简单的3D演示源程序

//uaiiadx.h

#include "stdafx.h"
#include <ddraw.h>
#include <d3d.h>
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file
#pragma message("linking with Microsoft's DirectX library ...")
#pragma comment(lib, "ddraw.lib")
#pragma comment(lib, "dxguid.lib")

class UAIIADX{
public:
 LPDIRECT3D     lpD3D;
 LPDIRECTDRAW4    lpDD;
 LPDIRECTDRAWSURFACE4  lpDDSPrimary;
 LPDIRECTDRAWSURFACE4  lpDDSBack;
 LPTSTR      lpBuffer;

 int       nlPitch;
 int       dwWidth;
 int       dwHeight;
 int       dwScreenWidth;
 int       dwScreenHeight;
 int       dwScreenColor;
public:
      UAIIADX   ();
      ~UAIIADX  ();
 BOOL    Init   ( HWND hWnd = GetActiveWindow() );
 BOOL    Init   ( int , int , HWND hWnd = GetActiveWindow() );
 BOOL    InitDDraw  ( HWND );
 void    FreeDDraw  ( void );
 BOOL    Text   ( int , int , COLORREF , COLORREF , LPTSTR , ... );
 BOOL    Lock   ( COLORREF );
 BOOL    Lock   ( void );
 BOOL    UnLock   ( void );
 BOOL    Backup   ( void );
 BOOL    Restore   ( void );
 BOOL    Fill   ( COLORREF );
 inline COLORREF GetPixel  ( int , int );
 inline COLORREF GetPixel  ( POINT );
 inline void  SetPixel  ( int , int , COLORREF );
 inline void  SetPixel  ( POINT , COLORREF );
 void    DrawLine  ( int , int , int , int , COLORREF );
 void    DrawLine  ( POINT , POINT , COLORREF ); 
};

 

//uaiia3d.h

#include "stdafx.h"
#include "uaiiaDX.h"


#define M_PAI        0.01745329251994329577

class UAIIA3D{
 typedef struct _tag_POINT3D{
  int  x;  
  int  y; 
  int  z; 
  int  tx;  
  int  ty; 
  int  tz; 
  POINT pt;
 } POINT3D;
 typedef struct _tag_POINT2X{
  DWORD  start;  
  DWORD  end; 
 } POINT2X;
public:
 UAIIADX      *lpDX;
 POINT3D      *lpPoint;
 POINT2X      *lpLine;
 DWORD      dwPoint,dwLine;
 DWORD      dwMaxPoint,dwMaxLine;
public:
    UAIIA3D   ();
    ~UAIIA3D  ();
 void  Bind   ( UAIIADX* );
 DWORD  SetPoint  ( int , int , int );
 DWORD  SetPoint  ( POINT3D );
 BOOL  SetLine   ( int , int , int , int , int , int );
 BOOL  SetLine   ( POINT3D , POINT3D );
 BOOL  SetBox   ( int , int , int , int , int , int );
 BOOL  FillBox   ( int , int , int , int , int , int );
 BOOL  SetAre   ( int , int , int , int , int n = 17 );
 void  Draw   ( COLORREF rgb = RGB(0,0,0) );
 void  Run3D   ( int x = 0 , int y = 0 , int z = 0 , double a = 0 , double b = 0 , double c = 0 );
 void  Run2D   ( int x = 0 , int y = 0 , int z = 0 , double a = 0 , double b = 0 , double c = 0 );
};

 

//uaiiadx.cpp


#include "stdafx.h"
#include "uaiiaDX.h"


UAIIADX::UAIIADX()
{
 
 dwScreenWidth  = 800;
 dwScreenHeight  = 600;
}

UAIIADX::~UAIIADX()

 FreeDDraw();
}

BOOL UAIIADX::Init( HWND hWnd )
{
 if ( !InitDDraw( hWnd )){
  MessageBox( hWnd , "初始化DirectDraw过程中出错!", "Error", MB_OK );
  FreeDDraw();
  return FALSE;
 }
 return TRUE;
}

BOOL UAIIADX::Init( int x , int y , HWND hWnd )
{
 dwScreenWidth  = x;
 dwScreenHeight  = y;
 return Init();
}
BOOL UAIIADX::InitDDraw( HWND hWnd )
{
 DDSURFACEDESC2             ddsd;
 LPDIRECTDRAW               pDD;
 DDSCAPS2       ddsCaps;
 
 if ( DirectDrawCreate( NULL, &pDD, NULL ) != DD_OK )
  return FALSE;
    if ( pDD->SetCooperativeLevel( hWnd,
                    DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN ) != DD_OK)
        return FALSE;
 if ( pDD->SetDisplayMode( dwScreenWidth, dwScreenHeight, 32 ) != DD_OK)
  return FALSE;
 if ( pDD->QueryInterface ( IID_IDirectDraw4, (LPVOID *) & lpDD) != DD_OK)
  return false;
 if (pDD->QueryInterface( IID_IDirect3D, (LPVOID*) &lpD3D) != DD_OK)
  return FALSE;
 
    UpdateWindow( hWnd );


 ZeroMemory( &ddsd, sizeof(ddsd) );
 ddsd.dwSize            = sizeof(ddsd);
 ddsd.dwFlags           = DDSD_BACKBUFFERCOUNT | DDSD_CAPS;
 ddsd.dwBackBufferCount = 1;
 ddsd.ddsCaps.dwCaps    = DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE;
 if ( lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL ) != DD_OK)
        return FALSE;
    ZeroMemory( &ddsCaps, sizeof(ddsCaps) );
 ddsCaps.dwCaps     = DDSCAPS_BACKBUFFER;
 if( lpDDSPrimary->GetAttachedSurface( &ddsCaps,&lpDDSBack ) != DD_OK )
    return FALSE;
 /*
 ZeroMemory ( &ddsd, sizeof ( ddsd ) );
    ddsd.dwSize       = sizeof( ddsd );
    ddsd.dwFlags      = DDSD_CAPS;
    ddsd.ddsCaps.dwCaps     = DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY;
 if ( lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL ) != DD_OK)
        return FALSE;

 ZeroMemory ( &ddsd, sizeof ( ddsd ) );
    ddsd.dwSize       = sizeof ( ddsd );
   ddsd.dwFlags      = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH;
   ddsd.ddsCaps.dwCaps     = DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY;
 ddsd.dwHeight      = dwScreenHeight;
 ddsd.dwWidth      = dwScreenWidth;
    if ( lpDD->CreateSurface( &ddsd, &lpDDSBack, NULL ) != DD_OK)
        return FALSE;
 /**/
    return TRUE;
}
void UAIIADX::FreeDDraw( void )
{
    if( lpDD != NULL ){
        if( lpDDSPrimary != NULL ){
            lpDDSPrimary->Release();
            lpDDSPrimary = NULL;
        }
        lpDD->Release();
        lpDD = NULL;
    }
}
BOOL UAIIADX::Text( int x , int y , COLORREF col , COLORREF bkcol , LPTSTR str , ... )
{
    char Buffer[300];
 HDC  hdc;
 va_list _list;
    va_start ( _list , str ); 
 wvsprintf(Buffer,str,_list);
 if ( lpDDSPrimary->GetDC(&hdc) != DD_OK)
  return FALSE;
    SetTextColor( hdc, col );
 ::SetBkColor( hdc, bkcol );
    TextOut( hdc, x, y, Buffer, lstrlen(Buffer));
    lpDDSPrimary->ReleaseDC(hdc);
 return TRUE;
}
BOOL UAIIADX::Lock( void )

 DDSURFACEDESC2   ddsd;
 //while(lpDDSBack->GetFlipStatus(DDGFS_ISFLIPDONE) == DDERR_WASSTILLDRAWING);
 ZeroMemory ( &ddsd, sizeof ( ddsd ) );
 ddsd.dwSize = sizeof ( ddsd );
 switch ( lpDDSBack->Lock ( NULL , &ddsd ,
  DDLOCK_READONLY|DDLOCK_WAIT , NULL) ){
  case DD_OK:
   lpBuffer = (LPTSTR)ddsd.lpSurface;
   nlPitch  = ddsd.lPitch;
   dwWidth  = ddsd.dwWidth;
   dwHeight = ddsd.dwHeight;
   return TRUE;
  case DDERR_INVALIDOBJECT:
  case DDERR_INVALIDPARAMS:
  case DDERR_OUTOFMEMORY:
  case DDERR_SURFACEBUSY:
  case DDERR_SURFACELOST:
   lpDDSBack->Restore();
   break;
  case DDERR_WASSTILLDRAWING:
   break;
  default:
   break;
 }
 if ( lpDDSBack->IsLost() )
  lpDDSBack->Restore();
 return FALSE;
}
BOOL UAIIADX::Lock( COLORREF rgb )
{
 DDBLTFX     ddbltfx;
 ddbltfx.dwSize   = sizeof(ddbltfx);
 ddbltfx.dwFillColor  = rgb;
 if ( lpDDSBack->Blt(NULL,NULL, NULL,DDBLT_COLORFILL, &ddbltfx) != DD_OK )
  return FALSE;
 return Lock();
}
BOOL UAIIADX::UnLock( void )
{
 lpDDSBack->Unlock( NULL );
 lpDDSPrimary->Flip( NULL, DDFLIP_WAIT );
 /*
 RECT rt;
 rt.left = 0;
 rt.top = 0;
 rt.right = dwScreenWidth;
 rt.bottom = dwScreenHeight;
 lpDDSBack->Unlock( NULL ); 
 if ( lpDDSPrimary->BltFast ( 0 , 0 , lpDDSBack ,&rt , false) != DD_OK ){
 //if ( lpDDSPrimary->Blt ( &rt , lpDDSBack ,&rt ,false,false) != DD_OK ){
  if (lpDDSBack->IsLost())
   lpDDSBack->Restore();
  if (lpDDSPrimary->IsLost())
   lpDDSPrimary->Restore();
  return FALSE;
 }
 */
 return TRUE;
}
BOOL UAIIADX::Backup( void )
{
 RECT rt;
 rt.left = 0;
 rt.top = 0;
 rt.right = dwScreenWidth;
 rt.bottom = dwScreenHeight;
 if ( lpDDSBack->BltFast ( 0 , 0 , lpDDSPrimary ,&rt , false) != DD_OK ){
  if (lpDDSBack->IsLost())
   lpDDSBack->Restore();
  if (lpDDSPrimary->IsLost())
   lpDDSPrimary->Restore();
  return FALSE;
 }
 return TRUE;
}
BOOL UAIIADX::Restore( void )
{
 RECT rt;
 rt.left = 0;
 rt.top = 0;
 rt.right = dwScreenWidth;
 rt.bottom = dwScreenHeight;
 if ( lpDDSPrimary->BltFast ( 0 , 0 , lpDDSBack ,&rt , false) != DD_OK ){
  if (lpDDSBack->IsLost())
   lpDDSBack->Restore();
  if (lpDDSPrimary->IsLost())
   lpDDSPrimary->Restore();
  return FALSE;
 }
 return TRUE;
}

BOOL UAIIADX::Fill ( COLORREF rgb )
{
 DDBLTFX     ddbltfx;
 ddbltfx.dwSize   = sizeof(ddbltfx);
 ddbltfx.dwFillColor  = rgb;
 if ( lpDDSBack->Blt(NULL,NULL, NULL,DDBLT_COLORFILL, &ddbltfx) != DD_OK )
  return FALSE;
 return TRUE;
}
COLORREF UAIIADX::GetPixel  ( int x, int y )
{
 return * ( COLORREF * )( lpBuffer + y * nlPitch + x * 4 );
}
COLORREF UAIIADX::GetPixel  ( POINT pt )
{
 return * ( COLORREF * )( lpBuffer + pt.y * nlPitch + pt.x * 4 );
}
void UAIIADX::SetPixel  ( int x, int y, COLORREF rgb )
{
 if ( x < 0 || y < 0 || x >= dwWidth || y >= dwHeight )
  return;
 * ( COLORREF * )( lpBuffer + y * nlPitch + x * 4 ) = rgb;
}
void UAIIADX::SetPixel  ( POINT pt, COLORREF rgb )
{
 if ( pt.x < 0 || pt.y < 0 || pt.x >= dwWidth || pt.y >= dwHeight )
  return;
 * ( COLORREF * )( lpBuffer + pt.y * nlPitch + pt.x * 4 ) = rgb;
}
void UAIIADX::DrawLine  ( int x , int y , int x0 , int y0 , COLORREF rgb )
{
 register int l,sum;
 int dx,dy,dm,dn,m,n,u,v,k;
 dx=x0-x;
 dy=y0-y;
 if(dx==0){  
  if(dy<0) {u=y0;v=y;}
  else {u=y;v=y0;}
  for(l=u;l<=v;l++)
   SetPixel ( x , l , rgb );
  return;
 }
 if(dy==0){
  if(dx<0) {u=x0;v=x;}
  else {u=x;v=x0;}
  for(l=u;l<=v;l++)
   SetPixel ( l , y , rgb );
  return;
 }
 dm=1;
 dn=1;
 if(dx<0){ dx=-dx;dm=-1;}
 if(dy<0){ dy=-dy;dn=-1;}
 m=dx;n=dy;k=1;u=x;v=y;
 if(dx<dy){
  m=dy;n=dx;
  k=dm;dm=dn;dn=k;k=0;
  u=y;v=x;
 }
 l=0;sum=m;
 SetPixel ( x , y , rgb );
 while(sum!=0){
  sum=sum-1;l=l+n;u=u+dm;
  if(l>=m) {v=v+dn;l=l-m;}
  if(k==1)
   SetPixel ( u , v , rgb );
  else
   SetPixel ( v , u , rgb );
 }
 return;
 
}
void UAIIADX::DrawLine  ( POINT pt , POINT pt0 , COLORREF rgb )
{
 DrawLine ( pt.x , pt.y , pt0.x , pt0.y , rgb );
}

 

 

//uaiia3d.cpp

#include "stdafx.h"
#include "uaiia3D.h"
#include <stdio.h>
#include <math.h>

#define MAXMEMPOINT 50
#define __FILL_LINE__ 20
UAIIA3D::UAIIA3D( )
{
 lpDX  = NULL;
 dwPoint  = 0;
 dwLine  = 0;
 dwMaxPoint = MAXMEMPOINT;
 dwMaxLine = MAXMEMPOINT;
 lpPoint  = new POINT3D[dwMaxPoint];
 lpLine  = new POINT2X[dwMaxLine];
}
UAIIA3D::~UAIIA3D()
{
 delete[] lpPoint;
 delete[] lpLine;
 lpPoint = NULL;
 lpLine = NULL;
}
void UAIIA3D::Bind(UAIIADX *uDX)
{
 lpDX = uDX;
 Run3D();
 Run2D();
}
DWORD UAIIA3D::SetPoint( POINT3D pt )

 for ( DWORD i = 0; i < dwPoint ; i ++ ){
  if ( pt.x == lpPoint[i].x &&  pt.y == lpPoint[i].y && pt.z == lpPoint[i].z ){
   return i;
  }
 }  
 lpPoint[dwPoint] = pt;
 dwPoint++;
 if ( dwPoint >= dwMaxPoint-1 ){
  POINT3D *lpTempPoint = lpPoint;
  dwMaxPoint += MAXMEMPOINT;
  lpPoint = new POINT3D[dwMaxPoint];
  for ( DWORD i = 0 ; i < dwPoint ; i ++ )
   lpPoint[i] = lpTempPoint[i];
  delete[] lpTempPoint;
 }
 return dwPoint - 1;
}
DWORD UAIIA3D::SetPoint( int x , int y ,int z )
{
 POINT3D pt;
 pt.x = x;
 pt.y = y;
 pt.z = z;
 return SetPoint(pt);
}
BOOL UAIIA3D::SetLine( POINT3D pt , POINT3D pt0 )
{
 DWORD i,t_start,t_end;
 t_start = SetPoint(pt);
 t_end   = SetPoint(pt0);
 for ( i = 0 ; i < dwLine ; i ++ ){
  if ( lpLine[i].start == t_start && lpLine[i].end == t_end )
   return TRUE;
  if ( lpLine[i].start == t_end && lpLine[i].end == t_start )
   return TRUE;
 }
 lpLine[dwLine].start = t_start;
 lpLine[dwLine].end   = t_end;
 dwLine++;
 if ( dwLine >= dwMaxLine - 1 ){
  POINT2X *lpTempPoint = lpLine;
  dwMaxLine += MAXMEMPOINT;
  lpLine = new POINT2X[dwMaxLine];
  for ( i = 0 ; i < dwLine ; i ++ )
   lpLine[i] = lpTempPoint[i];
  delete[] lpTempPoint;
 }
 return TRUE;
}
BOOL UAIIA3D::SetLine( int x , int y , int z ,int x0 , int y0 ,int z0 )
{
 POINT3D pt,pt0;
 pt.x = x;
 pt.y = y;
 pt.z = z;
 pt0.x = x0;
 pt0.y = y0;
 pt0.z = z0;
 return SetLine(pt,pt0);
}
BOOL UAIIA3D::SetBox( int x , int y , int z ,int width , int height ,int lz )
{
 SetLine(x,y,z,x+width,y,z);
 SetLine(x+width,y,z,x+width,y+height,z);
 SetLine(x+width,y+height,z,x,y+height,z);
 SetLine(x,y+height,z,x,y,z);
 
 SetLine(x,y,z+lz,x+width,y,z+lz);
 SetLine(x+width,y,z+lz,x+width,y+height,z+lz);
 SetLine(x+width,y+height,z+lz,x,y+height,z+lz);
 SetLine(x,y+height,z+lz,x,y,z+lz);
 
 SetLine(x,y,z,x,y,z+lz);
 SetLine(x+width,y,z,x+width,y,z+lz);
 SetLine(x+width,y+height,z,x+width,y+height,z+lz);
 SetLine(x,y+height,z,x,y+height,z+lz);
 return TRUE;
}
BOOL UAIIA3D::FillBox( int x , int y , int z ,int width , int height ,int lz )
{
 int i;
 for(i=0;i<=width;i+=__FILL_LINE__){
  SetLine(x+i,y,z,x+i,y+height,z);
  SetLine(x+i,y,z,x+i,y,z+lz);
  SetLine(x+i,y,z+lz,x+i,y+height,z+lz);
  SetLine(x+i,y+height,z,x+i,y+height,z+lz);
 } 
 if (i != width){
  i = width;
  SetLine(x+i,y,z,x+i,y+height,z);
  SetLine(x+i,y,z,x+i,y,z+lz);
  SetLine(x+i,y,z+lz,x+i,y+height,z+lz);
  SetLine(x+i,y+height,z,x+i,y+height,z+lz);
 } 
 for(i=0;i<=height;i+=__FILL_LINE__){
  SetLine(x,y+i,z,x+width,y+i,z);
  SetLine(x,y+i,z,x,y+i,z+lz);
  SetLine(x,y+i,z+lz,x+width,y+i,z+lz);
  SetLine(x+width,y+i,z,x+width,y+i,z+lz);
 }
 if(i!=height){
  i = height;
  SetLine(x,y+i,z,x+width,y+i,z);
  SetLine(x,y+i,z,x,y+i,z+lz);
  SetLine(x,y+i,z+lz,x+width,y+i,z+lz);
  SetLine(x+width,y+i,z,x+width,y+i,z+lz);
 }
 for(i=0;i<=lz;i+=__FILL_LINE__){
  SetLine(x,y,z+i,x+width,y,z+i);
  SetLine(x,y,z+i,x,y+height,z+i);  
  SetLine(x,y+height,z+i,x+width,y+height,z+i);
  SetLine(x+width,y,z+i,x+width,y+height,z+i);
 } 
 if(i!=lz){
  i=lz;
  SetLine(x,y,z+i,x+width,y,z+i);
  SetLine(x,y,z+i,x,y+height,z+i);  
  SetLine(x,y+height,z+i,x+width,y+height,z+i);
  SetLine(x+width,y,z+i,x+width,y+height,z+i);
 } 
 return TRUE;
}
BOOL UAIIA3D::SetAre( int x , int y , int z , int r , int n )
{
 POINT3D *xdx,*xd,x0;
 double  da;
 int     i,j;
 xd  = new POINT3D[n];
 xdx = new POINT3D[n*n];
 da = M_PAI * (double)360/(double)n;
 x0.x = r;
 x0.y = 0;
 x0.z = 0;
 for(i=0;i<n;i++){
  xd[i].x = (int)(x0.y*sin(da*i)+x0.x*cos(da*i));
  xd[i].y = (int)(x0.y*cos(da*i)-x0.x*sin(da*i));
  xd[i].z = 0;
 }
 for(j=0;j<n;j++){
  for(i=0;i<n;i++){
   xdx[j*n+i].x = (int)(xd[i].z*sin(da*j)+xd[i].x*cos(da*j)+x);
   xdx[j*n+i].y = xd[i].y+y;
   xdx[j*n+i].z = (int)(xd[i].z*cos(da*j)-xd[i].x*sin(da*j)+z);
  }
 }
 for(j=0;j<n;j++){
  for(i=1;i<n;i++){
   SetLine(xdx[j*n+i-1],xdx[j*n+i]);
  }
  SetLine(xdx[j*n+n-1],xdx[j*n]);
 }
 for(i=0;i<n;i++){
  for(j=1;j<n;j++){
   SetLine(xdx[(j-1)*n+i],xdx[j*n+i]);
  }
  SetLine(xdx[i],xdx[(n-1)*n+i]);
 }
 delete [] xd;
 delete [] xdx;
 return TRUE;
}
void UAIIA3D::Draw( COLORREF rgb)
{
 if ( lpDX == NULL )
  return;
 for ( DWORD i = 0; i < dwLine ; i ++ ){
  lpDX->DrawLine( lpPoint[lpLine[i].start].pt,
   lpPoint[lpLine[i].end].pt,
   rgb);
 }
}

void UAIIA3D::Run3D( int x , int y , int z , double a , double b , double c )
{
 int dx,dy,dz;
 double da,db,dc;
 double SinA,SinB,SinC,CosA,CosB,CosC;
 double Mx1,Mx2,Mx3,My1,My2,My3,Mz1,Mz2,Mz3;
 
 da = M_PAI * (double)a;
 db = M_PAI * (double)b;
 dc = M_PAI * (double)c;

 SinA = sin(da);
 SinB = sin(db);
 SinC = sin(dc);
 CosA = cos(da);
 CosB = cos(db);
 CosC = cos(dc);

 Mx1 = CosA * CosB;
 Mx2 =-CosA * SinB * SinC - SinA * CosC;
 Mx3 = SinA * SinC - CosA * SinB * CosC;
 My1 = SinA * CosB;
 My2 = CosA * CosC - SinA * SinB * SinC;
 My3 = SinA * SinB * CosC +  CosA * SinC;
 Mz1 = SinB;
 Mz2 = CosB * SinC;
 Mz3 = CosB * CosC;

 for ( DWORD i = 0; i < dwPoint ; i ++ ){
  dx = lpPoint[i].x - x;
  dy = lpPoint[i].y - y;
  dz = lpPoint[i].z - z;   
 
   
  lpPoint[i].tx =  (int)(dx * Mx1 + dy * My1 + dz * Mz1 + x);
  lpPoint[i].ty =  (int)(dx * Mx2 + dy * My2 + dz * Mz2 + y);   
  lpPoint[i].tz =  (int)(dx * Mx3 - dy * My3 + dz * Mz3 + z);
 }
}
void UAIIA3D::Run2D( int x , int y , int z , double a , double b , double c )
{
 int dx,dy,dz,tx,ty,tz;
 double da,db,dc;
 double SinA,SinB,SinC,CosA,CosB,CosC;
 double Mx1,Mx2,Mx3,My1,My2,My3,Mz1,Mz2,Mz3;
 
 da = M_PAI * (double)a;
 db = M_PAI * (double)b;
 dc = M_PAI * (double)c;

 SinA = sin(da);
 SinB = sin(db);
 SinC = sin(dc);
 CosA = cos(da);
 CosB = cos(db);
 CosC = cos(dc);

 Mx1 = CosA * CosB;
 Mx2 =-CosA * SinB * SinC - SinA * CosC;
 Mx3 = SinA * SinC - CosA * SinB * CosC;
 My1 = SinA * CosB;
 My2 = CosA * CosC - SinA * SinB * SinC;
 My3 = SinA * SinB * CosC +  CosA * SinC;
 Mz1 = SinB;
 Mz2 = CosB * SinC;
 Mz3 = CosB * CosC;

 for ( DWORD i = 0; i < dwPoint ; i ++ ){
  dx = lpPoint[i].tx - x;
  dy = lpPoint[i].ty - y;
  dz = lpPoint[i].tz - z;   
 
   
  tx =  (int)(dx * Mx1 + dy * My1 + dz * Mz1);
  ty =  (int)(dx * Mx2 + dy * My2 + dz * Mz2);   
  tz =  (int)(dx * Mx3 - dy * My3 + dz * Mz3);

  
  if ( tz == 0 )
   tz = 1;
  if ( tz > 0 ){  
   lpPoint[i].pt.x = (tx*500)/tz+lpDX->dwWidth/2;
   lpPoint[i].pt.y = (ty*500)/tz+lpDX->dwHeight/2;  
  }
  else{
   lpPoint[i].pt.x = - ( (tx*500)/tz-lpDX->dwWidth/2 );
   lpPoint[i].pt.y = - ( (ty*500)/tz-lpDX->dwHeight/2 );  
  }
 }
}

 

// Screen.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "uaiia3d.h"

UAIIADX uaiiadx;
UAIIA3D uaiia3d1,uaiia3d2,uaiia3d3;


LRESULT CALLBACK WinProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );
BOOL InitWindow( HINSTANCE hInstance, int nCmdShow );

static double da = 0;
static double db = 0;
static double dc = 0;
static int  tdx = 0;
double tda[15] = {0.011,1.876,2.456,3.555,4.987,5.234,5.123,4.222,3.111,2.198,1.124,0.121,0.297,1.127,2.214};
double tdb[15] = {0.111,2.876,3.456,4.555,5.987,4.234,3.123,2.222,1.611,2.198,1.524,0.821,0.397,1.127,2.214};
double tdc[15] = {5.311,4.876,3.456,2.555,2.987,1.234,0.123,1.222,2.111,2.198,1.124,2.121,1.097,2.127,3.214};
int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
{
 MSG msg;
 if ( !InitWindow( hInstance, nCmdShow ) )
  return FALSE;
 if ( !uaiiadx.Init()){
  DestroyWindow(GetActiveWindow());
  return FALSE;
 }
 uaiia3d1.Bind(&uaiiadx);
 uaiia3d2.Bind(&uaiiadx);
 uaiia3d3.Bind(&uaiiadx);
 uaiia3d1.FillBox(100,300,300,500,100,300);
 uaiia3d2.SetAre(350,150,450,128,17);
 uaiia3d3.SetAre(350,450,350,128,19);

 /*
 uaiia3d1.Run3D();
 uaiia3d1.Run2D(); 
 uaiia3d2.Run3D();
 uaiia3d2.Run2D();
 uaiia3d3.Run3D();
 uaiia3d3.Run2D();
 */

 while (GetMessage(&msg, NULL, 0, 0)){
  TranslateMessage(&msg);
  DispatchMessage(&msg);
 }
 return msg.wParam;
}
//******************************************************************
//函数:InitWindow()
//功能:创建主窗口。
//******************************************************************
static BOOL InitWindow( HINSTANCE hInstance, int nCmdShow )
{
 HWND hwnd; //窗口句柄
 WNDCLASS wc; //窗口类结构
 //填充窗口类结构
 wc.style = 0;
 wc.lpfnWndProc = WinProc;
 wc.cbClsExtra = 0;
 wc.cbWndExtra = 0;
 wc.hInstance = hInstance;
 wc.hIcon = LoadIcon( hInstance, IDI_APPLICATION );
 wc.hCursor = LoadCursor( NULL, IDC_ARROW );
 wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
 wc.lpszMenuName = NULL;
 wc.lpszClassName = "dxuaiia";
 //注册窗口类
 RegisterClass( &wc );
 //创建主窗口
 hwnd = CreateWindowEx(0,wc.lpszClassName,"",WS_POPUP,0, 0,
  GetSystemMetrics( SM_CXSCREEN ),GetSystemMetrics( SM_CYSCREEN ),
  //0,0,
  NULL,NULL,hInstance,NULL );
 if( !hwnd )
  return FALSE;
 ShowWindow( hwnd, nCmdShow );
 UpdateWindow( hwnd );
 return TRUE;
}
//******************************************************************
//函数:WinProc()
//功能:处理主窗口消息
//******************************************************************
LRESULT CALLBACK WinProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )

 HDC hdc;
 switch( message ){
  case WM_KEYDOWN:
   {  
    //PostMessage(hWnd, WM_CLOSE, 0, 0);
    switch( wParam ){
     case VK_ESCAPE:
      PostMessage(hWnd, WM_CLOSE, 0, 0);
      break;
     case '1':
      uaiiadx.lpDDSPrimary->GetDC(&hdc);
      TextOut(hdc,2,2,"uaiia",5);
      uaiiadx.lpDDSPrimary->ReleaseDC(hdc);
      break;
     case '2':
      uaiiadx.lpDDSBack->GetDC(&hdc);
      TextOut(hdc,2,20,"XHX",3);
      uaiiadx.lpDDSBack->ReleaseDC(hdc);
      break;
     case '3':      
      uaiiadx.lpDDSPrimary->Flip(NULL,DDFLIP_WAIT);
      break;
    }
   }
   break;
  case WM_TIMER:
   {
    int r,g,b;
    int dz;
    int n;
    if ( uaiiadx.Lock(RGB(0,0,0)) == TRUE ){ 
     tdx++;     
     n = (tdx/900)%28;
     if (n>14)
      n = 28-n;
     da+=tda[n];
     db+=tdb[n];
     dc+=tdc[n];
     r = (int)(da/3+db/2)%300;
     g = (int)(db/3+db/2)%300;
     b = (int)(da/3+dc/2)%300;
     dz = (int)(da*3+db*7+dc*2)%8000;
     if ( dz > 4000 )
      dz = 8000 - dz;
     if ( r >= 150 )
      r = 300 - r;
     if ( g >= 150 )
      g = 300 - g;
     if ( b >= 150 )
      b = 300 - b;
     
     uaiia3d1.Run3D(350,150,450,db,dc,da);
     uaiia3d1.Run2D(350,150,-100);
     uaiia3d1.Draw(RGB(100+r,80+g,80+b));
     
     uaiia3d2.Run3D(350,150,450,da,db,dc);
     uaiia3d2.Run2D(uaiia3d1.lpPoint[11].pt.x-60,uaiia3d1.lpPoint[91].pt.y-150,100-dz/8);
     uaiia3d2.Draw(RGB(80+g,100+b,80+r)); 
     
     
     uaiia3d3.Run3D(uaiia3d2.lpPoint[6].x,uaiia3d2.lpPoint[7].y,uaiia3d1.lpPoint[62].z+500,dc,da,db);
     uaiia3d3.Run2D(uaiia3d1.lpPoint[62].pt.x-60,uaiia3d1.lpPoint[39].pt.y-150,-dz/7);
     uaiia3d3.Draw(RGB(80+b,80+r,100+g));
     
     uaiiadx.UnLock();
    }
   }
   break;
  case WM_MOUSEMOVE:
   //PostMessage(hWnd, WM_CLOSE, 0, 0);
   break;
  case WM_CREATE:
   ShowCursor(FALSE);
   SetTimer(hWnd,999,8,NULL);
   break;
  case WM_DESTROY:
   ShowCursor(TRUE);
   KillTimer(hWnd,999);
   PostQuitMessage( 0 );
   break;
 }
 return DefWindowProc(hWnd, message, wParam, lParam);
}

 

  • 1
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

前面几日我重新实现了迷宫自动生成方法,并且添加了迷宫自动寻路方法。有了一个独立于GUI迷宫库,我开始迫不及待地实现三维迷宫了! 下面是我在开发迷宫程序中遇到问题。 1、怎样将迷宫类行和列映射到真实三维坐标中?迷宫应该用哪个参考系来描述? 其实我在制作时候为了简化,将二维迷宫左上角与三维原点重合,二维迷宫右对应三维X轴正方向,迷宫下对应Z轴正方向。 2、迷宫“上、下、左、右”在三维中应该叫做什么? 在确定好迷宫位置后,我们将迷宫上对应Z轴负半轴,下对应Z轴正半轴,左对应X轴负半轴,右对应Y轴正半轴。 3、三维点绘制顺序以及OpenGL裁剪模式造成一些面不可见问题。 这个问题是我在编写二维迷宫没有想到。主要是因为二维迷宫中描述墙是用一条直线,而到了三维则是一个面。由于在OpenGL中有裁剪模式可以选择,我使用了 glFrontFace( GL_CW ); // 顺时针绘制为正面 glEnable( GL_CULL_FACE ); // 剔除不是正面面 进行设定,也就是说,所有在摄像机看来是逆时针绘制图形都无法显示。因此我不得不用同样顶点绘制两个面。下面是相关函数: void DrawInnerWall( Point3F& p1, Point3F& p2, Point3F& p3, Point3F& p4 ) { glTexCoord2f( 0.0f, 1.0f ); glVertex3fv( p1 ); glTexCoord2f( 1.0f, 1.0f ); glVertex3fv( p2 ); glTexCoord2f( 1.0f, 0.0f ); glVertex3fv( p3 ); glTexCoord2f( 0.0f, 0.0f ); glVertex3fv( p4 ); } void DrawOuterWall( Point3F& p1, Point3F& p2, Point3F& p3, Point3F& p4 ) { glTexCoord2f( 1.0f, 1.0f ); glVertex3fv( p1 ); glTexCoord2f( 0.0f, 1.0f ); glVertex3fv( p2 ); glTexCoord2f( 0.0f, 0.0f ); glVertex3fv( p3 ); glTexCoord2f( 1.0f, 0.0f ); glVertex3fv( p4 ); } 在编写这些函数时候尤其注意纹理坐标绘制顺序。可以在纸上绘制一个草图。下面是我调用代码: if ( Cell_UpWall( cell ) ) { DrawInnerWall( p8, p7, p3, p4 ); DrawOuterWall( p7, p8, p4, p3 ); } 4、怎样设置阻挡? 设置阻挡基本原则还是先检测后执行。首先我先尝试着执行走一步,再判断这一步是不是出现了越界问题。如果出现了越界问题,那么不执行这一步,否则执行这一步。为了不让我们无限地靠近墙,我设定了一个gap,即摄像机必须与墙保持gap距离。 下面是我相关代码: bool View3D::CanGo( Maze& maze, float step ) { static float gap = m_CellSize.w / 8.0f;// 摄像机与墙最近不能超过间隔 const Point3F& pos = m_Camera.Pos( ); Point3F tryPos; if ( pos.y > 0 && pos.y < m_CellSize.h )// 在一个墙高度之内 { m_Camera.TryMoveForward( tryPos, step ); unsigned short row = pos.z / m_CellSize.w + 1, column = pos.x / m_CellSize.w + 1; unsigned long cell = maze.Cell( row, column ); // 根据迷宫小房间墙来判断是否可行 bool ret = true; if ( Cell_UpWall( cell ) ) ret &= ( tryPos.z - gap > ( row - 1 ) * m_CellSize.w ); if ( Cell_DownWall( cell ) ) ret &= ( tryPos.z + gap < row * m_CellSize.w ); if ( Cell_LeftWall( cell ) ) ret &= ( tryPos.x - gap > ( column - 1 ) * m_CellSize.w ); if ( Cell_RightWall( cell ) ) ret &= ( tryPos.x + gap < column * m_CellSize.w ); return ret; } return true; } 但是这里还是出现了一点小Bug,摄像机在移动至一个墙角时再也无法移动了。我想可能是我设定gap有问题。暂时我还拿不出什么有效办法。 5、绘制二维视图问题。 这其中迷宫绘制环节与我上次写代码基本一致。关键在于箭头绘制。当摄像机移动时,我们需要更新二维视图中箭头角度。难点在于如何确定这个角度?二维中我们使用x-y坐标系,三维中我们需要重点关注是x-z坐标系。注意这一点,摄像机默认是向着(0,0,-1)看。设需要旋转角度为rotateAngle1,摄像机位置位CameraPos,那么有这样公式: rotateAngle1 = 90° + arctan( CameraPos.z / CameraPos.x ) 又由于glRotate()是沿着逆时针旋转,所以最终旋转角度 rotateAngle = 360° - ( rotateAngle1 ) = 270° - arctan( CameraPos.z / CameraPos.x ) math.h里面提供了atan2()函数,可以提供在(-π/2, π/2)范围内角度。把这个问题解决了,那么箭头绘制以及更新也就变得不那么困难了。
相关推荐
国际程序设计大赛作品欣赏 1、 先来第一个: 一段纯 3D DOS 动画,据说是获一等奖作品。虽然它不是最精美, 但是当你得知它只有 4K 时,会不会立刻疯死掉呢? 附件:3ddemo.com 2、 再来一个: 幽灵古堡 farb-rausche 64.0 KB (65,536 字节) 恰好 65536 字节,显然是参赛作品。它非常漂亮(利用了 Direct3D),更让人惊奇是只有 64K!而更让人震惊是,如果不压缩话它数据大小是 1.6G!再体会一次“奇迹”! 附件:castle.exe 3、 再来一个: 死亡阴影 64.0 KB (65,536 字节) 附件:death.exe 4、 火域幻境 73.0 KB (74,752 字节) 虽然大小超过了 64K 限制,但是它效果可称为程序中艺术品了! 附件:fire.exe 5、 fr-016 farb-rausche 16 字节 (16 字节) Let's rock hard!一个 DOS 里小动画。看上去似乎没有什么特别,但是如果看到它大小(16 字节),什么感觉????? 附件:fr-016.com 6、 第七天堂 Exceed 64.0 KB (65,536 字节) 由于参赛要求是在 64K 之内即可,不少参赛者未免会有不到 65536 字节就有吃亏感觉。 这是个 恰好 64K 作品,可能利用了 DirectX 引擎,效果很好。 附件:heaven7.exe 7、 金属迷城 6.00 KB (6,144 字节) 考虑到它大小时,你会不会体会到奇迹含义 附件:metal.exe 8、 我要重点推荐是这个作品fr-041_debris.exe(177K),效果是这所有作品之中最好,一般电脑无法流畅运行,我认为你买电脑时 可以把它带上运行一下作为一款测试工具。 附件:fr-041_debris.exe 9、 这个作品效果和以上作品比都可名列前矛(64K),效果很好 附件:kkino64.exe 10、 这个就是传说中25万倍压缩作品,prophecy《彗星撞地球》(63.5K)2000年时最经典力作!画面看着挺舒服。 附件:prophecy《彗星撞地球》.exe 11、 爱之记忆 12、 3D裸女 13、 卡通 14、 光影 15、 FAiRLiGHT 这是在《三角洲3大地勇士》光碟版中带有一个DEMO,发行组织FAiRLiGHT完全用原代码写出自己组织DEMO演示程序, 竟然才15K大小,画面也还行,对于他们技术我们只能感到折服!
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值