为什么我用D3D(DirectX8)显示的.x文件会有很多凹陷的效果,我的模型在max4中没有这个现象,哪位大侠救我!

jzgenius 2001-08-15 01:56:28
为什么我用D3D(DirectX8)显示的.x文件会有很多凹陷的效果,我的模型在max4中没有这个现象,哪位大侠救我!

有人说是RenderState的问题,不过怎么改呢?
...全文
176 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
c_z_y 2001-08-15
  • 打赏
  • 举报
回复
微软的例子是不是用了凹凸纹理?
另外3ds->x会有损失的。
Kevin_qing 2001-08-15
  • 打赏
  • 举报
回复
是不是贴图看起来是扭曲的?
可能是因为你没有做透视矫正的缘故
davidlxm 2001-08-15
  • 打赏
  • 举报
回复
把觉得有问题的代码贴出来
jzgenius 2001-08-15
  • 打赏
  • 举报
回复
有问题的:
extern CMy3dXVView *g_3dView;

//-----------------------------------------------------------------------------
// Name: FullScreenWndProc()
// Desc: The WndProc funtion used when the app is in fullscreen mode. This is
// needed simply to trap the ESC key.
//-----------------------------------------------------------------------------
LRESULT CALLBACK FullScreenWndProc( HWND hWnd, UINT msg, WPARAM wParam,
LPARAM lParam )
{
if( msg == WM_CLOSE )
{
CWnd* pWnd=AfxGetMainWnd();
pWnd->PostMessage( WM_CLOSE, 0, 0 );

// User wants to exit, so go back to windowed mode and exit for real
//g_AppFormView->GoWindowed();
//g_D3DApp.GetMainWnd()->PostMessage( WM_CLOSE, 0, 0 );
}

if( msg == WM_SETCURSOR )
{
SetCursor( NULL );
}

if( msg == WM_KEYUP && wParam == VK_ESCAPE )
{
g_3dView->GoWindow();
// User wants to leave fullscreen mode
//g_AppFormView->GoWindowed();
}

if( g_bReady )
{
g_3dView->Render3DEnvironment();
}

g_3dView->FullScrKeyDown();

return DefWindowProc( hWnd, msg, wParam, lParam );
}

/////////////////////////////////////////////////////////////////////////////
// CMy3dXVView

IMPLEMENT_DYNCREATE(CMy3dXVView, CFormView)

BEGIN_MESSAGE_MAP(CMy3dXVView, CFormView)
//{{AFX_MSG_MAP(CMy3dXVView)
ON_WM_DESTROY()
ON_BN_CLICKED(IDC_CULL, OnCull)
ON_BN_CLICKED(IDC_WIRE, OnWire)
ON_BN_CLICKED(IDC_FLAT, OnFlat)
ON_WM_HSCROLL()
ON_EN_KILLFOCUS(IDC_EDIT_X, OnKillfocusEditX)
ON_EN_KILLFOCUS(IDC_EDIT_Y, OnKillfocusEditY)
ON_EN_KILLFOCUS(IDC_EDIT_Z, OnKillfocusEditZ)
ON_BN_CLICKED(IDC_BUTTON_XDOWN, OnButtonXdown)
ON_BN_CLICKED(IDC_BUTTON_XUP, OnButtonXup)
ON_BN_CLICKED(IDC_BUTTON_YDOWN, OnButtonYdown)
ON_BN_CLICKED(IDC_BUTTON_YUP, OnButtonYup)
ON_BN_CLICKED(IDC_BUTTON_ZDOWN, OnButtonZdown)
ON_BN_CLICKED(IDC_BUTTON_ZUP, OnButtonZup)
ON_BN_CLICKED(IDC_BUTTON_RESET, OnButtonReset)
ON_BN_CLICKED(IDC_FPS_CHECK, OnFpsCheck)
ON_EN_KILLFOCUS(IDC_FPS_EDIT, OnKillfocusFpsEdit)
ON_BN_CLICKED(IDC_BUTTON_FULLSCR, OnButtonFullscr)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMy3dXVView construction/destruction

CMy3dXVView::CMy3dXVView()
: CFormView(CMy3dXVView::IDD)
{
//{{AFX_DATA_INIT(CMy3dXVView)
//}}AFX_DATA_INIT
// TODO: add construction code here
g_3dView = this;
g_pDD = NULL;
g_pddsPrimary = NULL;
g_pddsBackBuffer = NULL;
g_pddsZBuffer = NULL; // Z-buffer surface
g_pD3D = NULL;
g_pd3dDevice = NULL;
//
m_pFileObject = NULL;
m_fObjectRadius = 0.0f;
m_fEyeDistance = 0.0f;
m_bCull = TRUE;
m_bFlat = FALSE;
m_bWire = FALSE;
m_fLMouseCapture = FALSE;
//
m_fXAxisAngle = 0.0f;
m_fYAxisAngle = 0.0f;
m_fXViewAngle = 0.0f;
m_fYViewAngle = 0.0f;
//
m_fModel_X = 0.0f;
m_fModel_Y = 0.0f;
m_fModel_Z = 0.0f;
//
m_IsWindow = TRUE;
}

CMy3dXVView::~CMy3dXVView()
{
}

void CMy3dXVView::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CMy3dXVView)
//}}AFX_DATA_MAP
}

BOOL CMy3dXVView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs

return CFormView::PreCreateWindow(cs);
}

void CMy3dXVView::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
GetParentFrame()->RecalcLayout();
ResizeParentToFit();
static BOOL firstTime = TRUE;
HRESULT r;
if(firstTime)
{
r = InitDirectX();
if( r==S_OK )
firstTime = FALSE;
else
PostMessage( WM_CLOSE );
}
//
((CButton*)GetDlgItem(IDC_FPS_CHECK))->SetCheck(g_FPS);
GetDlgItem(IDC_FPS_EDIT)->EnableWindow(g_FPS);
char msg[80];
sprintf(msg, "%d", g_FpsMax);
GetDlgItem(IDC_FPS_EDIT)->SetWindowText(msg);
//
m_bCull = TRUE;
m_bFlat = FALSE;
m_bWire = FALSE;
((CButton*)GetDlgItem(IDC_CULL))->SetCheck(m_bCull);
((CButton*)GetDlgItem(IDC_FLAT))->SetCheck(!m_bFlat);
((CButton*)GetDlgItem(IDC_WIRE))->SetCheck(m_bWire);
//
m_DirectionalLight = 1.0f;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_DLIGHT ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_DLIGHT ))->SetPos((int)(m_DirectionalLight*100));
m_AmbientLight = 0.0f;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_ALIGHT ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_ALIGHT ))->SetPos((int)(m_AmbientLight*100));
SetupLight();
//
m_fModel_X = 0.0f;
m_fModel_Y = 0.0f;
m_fModel_Z = 0.0f;
char buf[80];
sprintf(buf, "%7.2f", m_fModel_X);
GetDlgItem(IDC_EDIT_X)->SetWindowText(buf);
sprintf(buf, "%7.2f", m_fModel_Y);
GetDlgItem(IDC_EDIT_Y)->SetWindowText(buf);
sprintf(buf, "%7.2f", m_fModel_Z);
GetDlgItem(IDC_EDIT_Z)->SetWindowText(buf);
// 模块的转角
m_fXAxisAngle = 0.0f;
m_fYAxisAngle = 0.0f;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MX ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MX ))->SetPos(50);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MY ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MY ))->SetPos(50);
//Camera转角
m_fXViewAngle = 0.0f;
m_fYViewAngle = 0.0f;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CX ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CX ))->SetPos(50);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CY ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CY ))->SetPos(50);
//Camera距离
m_fEyeDistance = 0.0f;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CD ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CD ))->SetPos(30);

// Register a class for a fullscreen window
WNDCLASS wndClass = { CS_HREDRAW | CS_VREDRAW, FullScreenWndProc, 0, 0, NULL,
NULL, NULL, (HBRUSH)GetStockObject(WHITE_BRUSH), NULL,
TEXT("Fullscreen Window") };
RegisterClass( &wndClass );


}

/////////////////////////////////////////////////////////////////////////////
// CMy3dXVView diagnostics

#ifdef _DEBUG
void CMy3dXVView::AssertValid() const
{
CFormView::AssertValid();
}

void CMy3dXVView::Dump(CDumpContext& dc) const
{
CFormView::Dump(dc);
}

CMy3dXVDoc* CMy3dXVView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMy3dXVDoc)));
return (CMy3dXVDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMy3dXVView message handlers

BOOL CMy3dXVView::InitDirectX()
{
// 初始化Direct3D
// Cleanup any objects that might've been created before
if( FAILED( Cleanup3DEnvironment() ) )
return E_FAIL;

HWND hWnd;
m_hwndRenderWindow = GetDlgItem(IDC_FRAMEVIEW)->GetSafeHwnd();
hWnd = m_hwndRenderWindow;

// Create the D3D environment, at first, trying the HAL
if( SUCCEEDED( Initialize3DEnvironment( hWnd, NULL,
&IID_IDirect3DHALDevice ) ) )
return S_OK;

MessageBox( "使用硬件加速失败!\n现在尝试使用软件模式", "警告!", MB_OK|MB_ICONWARNING );
// Else, cleanup objects potentially created during the failed
// initialization attempt.
Cleanup3DEnvironment();

if( SUCCEEDED( Initialize3DEnvironment( hWnd, NULL,
&IID_IDirect3DRGBDevice ) ) )
return S_OK;

MessageBox( "尝试使用软件模式失败\n程序将退出", "错误!", MB_OK|MB_ICONERROR );
// Else, return failure. This simple tutorial will exit ungracefully.
return E_FAIL;
}

HRESULT CMy3dXVView::App_InitDeviceObjects(LPDIRECT3DDEVICE7 pd3dDevice)
{
// Setup a material
D3DMATERIAL7 mtrl;
D3DUtil_InitMaterial( mtrl, 1.0f, 1.0f, 1.0f );
g_pd3dDevice->SetMaterial( &mtrl );

// Setup the textures
D3DTextr_RestoreAllTextures( g_pd3dDevice );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTFN_LINEAR );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTFG_LINEAR );
g_pd3dDevice->SetRenderState( D3DRENDERSTATE_DITHERENABLE, TRUE );
g_pd3dDevice->SetRenderState( D3DRENDERSTATE_SPECULARENABLE, FALSE );
g_pd3dDevice->SetRenderState( D3DRENDERSTATE_ZENABLE, TRUE );
g_pd3dDevice->SetRenderState( D3DRENDERSTATE_NORMALIZENORMALS, TRUE );

// Set the projection matrix
D3DVIEWPORT7 vp;
g_pd3dDevice->GetViewport(&vp);
FLOAT fAspect = ((FLOAT)vp.dwHeight) / vp.dwWidth;

D3DMATRIX matProj;
D3DUtil_SetProjectionMatrix( matProj, g_PI/4, fAspect, 1.0f, m_fEyeDistance*10 );
g_pd3dDevice->SetTransform( D3DTRANSFORMSTATE_PROJECTION, &matProj );

// Set up the light
D3DLIGHT7 light;
D3DUtil_InitLight( light, D3DLIGHT_DIRECTIONAL, 0.0f, -2.0f, -2.0f );
g_pd3dDevice->SetLight( 0, &light );
g_pd3dDevice->LightEnable( 0, TRUE );
g_pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, TRUE );
g_pd3dDevice->SetRenderState( D3DRENDERSTATE_AMBIENT, 0x00000000 ); //环境光

return S_OK;
}

HRESULT CMy3dXVView::Render3DEnvironment()
{
// Call the app specific function to framemove (animate) the scene
App_FrameMove( g_pd3dDevice, ((FLOAT)clock())/CLOCKS_PER_SEC );

// Call the app specific function to render the scene
App_Render( g_pd3dDevice );

// Show the frame on the primary surface. Note: this is the best place to
// check for "lost" surfaces. Surfaces can be lost if something caused
// them to temporary lose their video memory. "Lost" surfaces simply
// need to be restored before continuing.
// 将帧显示到主表面。注意:这里是检测表面“丢失”的最好地方
if( DDERR_SURFACELOST == ShowFrame() )
RestoreSurfaces();

// Keep track of the frame rate, and output it every 500 milliseconds to
// the appropiate UI control.
static DWORD dwLastTime = 0;
static DWORD dwNumFrames = 0;
dwNumFrames++;

if( GetTickCount()-dwLastTime > 500 )
{
FLOAT fFPS = dwNumFrames*1000.0f/( GetTickCount() - dwLastTime );
dwLastTime = GetTickCount();
dwNumFrames=0;;
CHAR buffer[20];
sprintf(buffer,"%4.1f fps", fFPS );
GetDlgItem(IDC_FPS_TEXT)->SetWindowText(buffer);
// 控制刷新率
int FPS, d;
FPS = (int)fFPS;
d = (FPS-g_FpsMax)/2;
if( abs(d)>20 )
d = d/abs(d)*20;
g_FpsSec += d;
if( g_FpsSec > 1000)
g_FpsSec = 1000;
if( g_FpsSec < 1 )
g_FpsSec = 1;
}

return S_OK;
}

HRESULT CMy3dXVView::App_FrameMove(LPDIRECT3DDEVICE7 pd3dDevice, FLOAT fTimeKey)
{
// Set the object's world matrix
// g_pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &m_matRotate );

// Adjust the camera position
D3DVECTOR vEyePt = D3DVECTOR( 0.0f, 0.0f, 0.0f );
D3DVECTOR vLookatPt = D3DVECTOR( 0.0f, 0.0f, 0.0f );
D3DVECTOR vUpVec = D3DVECTOR( 0.0f, 1.0f, 0.0f );
FLOAT r;
//vEyePt.z += m_fObjectRadius*3.0f + m_fObjectRadius*m_fEyeDistance;
r = m_fObjectRadius*3.0f + m_fObjectRadius*m_fEyeDistance;
//Camena的位置
m_fYViewAngle = m_fYViewAngle>3.14159f/2 ? 3.14159f/2 : m_fYViewAngle;
m_fYViewAngle = m_fYViewAngle<-3.14159f/2 ? -3.14159f/2 : m_fYViewAngle;
vEyePt.z = r;
D3DMATRIX mX,mY;
D3DUtil_SetRotateYMatrix( mX, -m_fXViewAngle );
D3DUtil_SetRotateXMatrix( mY, m_fYViewAngle );
D3DMath_MatrixMultiply( m_matRotate, mY, mX );
UserUtil_xyz( m_matRotate, vEyePt.x, vEyePt.y, vEyePt.z );

// Set the view matrix
D3DMATRIX matView;
D3DUtil_SetViewMatrix( matView, vEyePt, vLookatPt, vUpVec );
g_pd3dDevice->SetTransform( D3DTRANSFORMSTATE_VIEW, &matView );

// Just for kicks, demonstrate the feature to find a frame and animate it.
// Here, if the user loads a file with a frame named "prop" (such as
// "triplane.x"), this code will find the matrix for that frame and
// animate it.
if( m_pFileObject )
{
CD3DFileObject* pObject = m_pFileObject->FindObject( "prop" );
if( pObject )
{
D3DMATRIX* pmat = pObject->GetMatrix();
D3DUtil_SetRotateZMatrix( *pmat, 5.0f*fTimeKey );
}
}

return S_OK;
}

HRESULT CMy3dXVView::App_Render(LPDIRECT3DDEVICE7 pd3dDevice)
{

// Clear the viewport
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
0x00009900, 1.0f, 0L );
//g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET,
// 0x00009900, 1.0f, 0L );

DWORD dwCullMode = m_bCull ? D3DCULL_CCW : D3DCULL_NONE;
DWORD dwShadeMode = m_bFlat ? D3DSHADE_FLAT : D3DSHADE_GOURAUD;
DWORD dwFillMode = m_bWire ? D3DFILL_WIREFRAME : D3DFILL_SOLID;
g_pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, dwCullMode );
g_pd3dDevice->SetRenderState( D3DRENDERSTATE_SHADEMODE, dwShadeMode );
g_pd3dDevice->SetRenderState( D3DRENDERSTATE_FILLMODE, dwFillMode );

// Begin the scene
D3DMATRIX matWorld, matSpinX, matSpinY;

if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{
if( m_pFileObject )
{
D3DUtil_SetRotateYMatrix( matSpinX, -m_fXAxisAngle ); //绕Y轴旋转矩阵
D3DUtil_SetRotateXMatrix( matSpinY, m_fYAxisAngle ); //绕X轴旋转矩阵
D3DUtil_SetTranslateMatrix( matWorld, m_fModel_X, m_fModel_Y, m_fModel_Z ); //平移矩阵
D3DMath_MatrixMultiply( matWorld, matSpinY, matWorld ); //混合两个矩阵
D3DMath_MatrixMultiply( matWorld, matSpinX, matWorld ); //混合两个矩阵
g_pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matWorld ); //移动
m_pFileObject->Render( g_pd3dDevice );
}

// End the scene.
g_pd3dDevice->EndScene();
//char msg[80];
//sprintf( msg, "模型半径%7.02f", m_fObjectRadius );
//OutputText( 5, 15, msg );
}

return S_OK;
}

HRESULT CMy3dXVView::RestoreSurfaces()
{
// Check/restore the primary surface
if( g_pddsPrimary )
if( g_pddsPrimary->IsLost() )
g_pddsPrimary->Restore();

// Check/restore the back buffer
if( g_pddsBackBuffer )
if( g_pddsBackBuffer->IsLost() )
g_pddsBackBuffer->Restore();

// Check/restore the z-buffer
if( g_pddsZBuffer )
if( g_pddsZBuffer->IsLost() )
g_pddsZBuffer->Restore();

return S_OK;
}

HRESULT CMy3dXVView::ShowFrame()
{
HRESULT hr;
if( NULL == g_pddsPrimary )
return E_FAIL;

if( m_IsWindow )
hr = g_pddsPrimary->Blt( &g_rcScreenRect, g_pddsBackBuffer,
NULL, DDBLT_WAIT, NULL );
else
hr = g_pddsPrimary->Flip( NULL, DDFLIP_WAIT );

return hr;
}

void CMy3dXVView::OnDestroy()
{
CFormView::OnDestroy();

// TODO: Add your message handler code here
Cleanup3DEnvironment();
}

VOID CMy3dXVView::App_DeleteDeviceObjects(LPDIRECT3DDEVICE7 pd3dDevice)
{
DeleteDeviceObjects();
// Release the material that was created earlier.
if( g_pmtrlObjectMtrl )
g_pmtrlObjectMtrl->Release();
g_pmtrlObjectMtrl = NULL;
}

void CMy3dXVView::WindowMove()
{
m_hwndRenderWindow = GetDlgItem(IDC_FRAMEVIEW)->GetSafeHwnd();
::GetClientRect( m_hwndRenderWindow, &g_rcScreenRect );
::ClientToScreen( m_hwndRenderWindow, (POINT*)&g_rcScreenRect.left );
::ClientToScreen( m_hwndRenderWindow, (POINT*)&g_rcScreenRect.right );
}

HRESULT CMy3dXVView::LoadFile( LPCTSTR lpszPathName )
{
CD3DFile* pFileObject = new CD3DFile();
if( FAILED( pFileObject->Load( (TCHAR*)lpszPathName ) ) )
{
char error[512];
strcpy(error, "不能打开指定的X文件\n");
strcat(error, lpszPathName);
MessageBox( error,
TEXT("错误!"), MB_OK|MB_ICONERROR );
g_bReady = FALSE;
return E_FAIL;
}

// If the file was successfully loaded, delete the old one and use this one
// instead.
SAFE_DELETE( m_pFileObject );
m_pFileObject = pFileObject;

// Get the new object position and size
m_fObjectRadius = 0.0f;
m_pFileObject->EnumObjects( CalcFileObjectSizeCB, NULL, (VOID*)&m_fObjectRadius );
//显示模型半径
CHAR buffer[20];
sprintf(buffer,"%4.2f", m_fObjectRadius );
GetDlgItem(IDC_RADIUS_TEXT)->SetWindowText(buffer);

// Set the projection matrix
D3DVIEWPORT7 vp;
g_pd3dDevice->GetViewport(&vp);
FLOAT fAspect = ((FLOAT)vp.dwHeight) / vp.dwWidth;

D3DMATRIX matProj;
D3DUtil_SetProjectionMatrix( matProj, g_PI/4, fAspect, 1.0f, m_fObjectRadius*10 );
g_pd3dDevice->SetTransform( D3DTRANSFORMSTATE_PROJECTION, &matProj );

// Restore the textures (if there's a device).
D3DTextr_RestoreAllTextures( g_pd3dDevice );

// Return successful
return S_OK;
}


HRESULT CMy3dXVView::Cleanup3DEnvironment()
{
// Cleanup any objects created for the scene
App_DeleteDeviceObjects( g_pd3dDevice );
FinalCleanup();

// Release the DDraw and D3D objects used by the app
if( g_pddsZBuffer ) g_pddsZBuffer->Release();
if( g_pD3D ) g_pD3D->Release();
if( g_pddsBackBuffer ) g_pddsBackBuffer->Release();
if( g_pddsPrimary ) g_pddsPrimary->Release();

// Do a safe check for releasing the D3DDEVICE. RefCount should be zero.
if( g_pd3dDevice )
if( 0 < g_pd3dDevice->Release() )
return E_FAIL;

// Do a safe check for releasing DDRAW. RefCount should be zero.
if( g_pDD )
if( 0 < g_pDD->Release() )
return E_FAIL;

g_pd3dDevice = NULL;
g_pD3D = NULL;
g_pddsBackBuffer = NULL;
g_pddsZBuffer = NULL;
g_pddsPrimary = NULL;
g_pDD = NULL;

return S_OK;
}

HRESULT CMy3dXVView::DeleteDeviceObjects()
{
D3DTextr_InvalidateAllTextures();

return S_OK;
}

HRESULT CMy3dXVView::FinalCleanup()
{
SAFE_DELETE( m_pFileObject );
//D3DTextr_DestroyTexture( "lake.bmp" );

return S_OK;
}

void CMy3dXVView::UserUtil_xyz(D3DMATRIX &m, FLOAT &x, FLOAT &y, FLOAT &z)
{
FLOAT x1, y1, z1;
x1 = m._11*x+m._21*y+m._31*z+m._41*1;
y1 = m._12*x+m._22*y+m._32*z+m._42*1;
z1 = m._13*x+m._23*y+m._33*z+m._43*1;
x = x1;
y = y1;
z = z1;
}

HRESULT CMy3dXVView::Initialize3DEnvironment(HWND hWnd, GUID *pDriverGUID, const GUID *pDeviceGUID)
{
HRESULT hr;

hr = DirectDrawCreateEx( pDriverGUID, (VOID**)&g_pDD, IID_IDirectDraw7,
NULL );
if( FAILED( hr ) )
return hr;

hr = g_pDD->SetCooperativeLevel( hWnd, DDSCL_NORMAL );
if( FAILED( hr ) )
return hr;

DDSURFACEDESC2 ddsd;
ZeroMemory( &ddsd, sizeof(DDSURFACEDESC2) );
ddsd.dwSize = sizeof(DDSURFACEDESC2);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

// Create the primary surface.
hr = g_pDD->CreateSurface( &ddsd, &g_pddsPrimary, NULL );
if( FAILED( hr ) )
return hr;

ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;

// Set the dimensions of the backbuffer. Note that if our window changes
// size, we need to destroy this surface and create a new one.
::GetClientRect( hWnd, &g_rcScreenRect );
::ClientToScreen( hWnd, (POINT*)&g_rcScreenRect.left );
::ClientToScreen( hWnd, (POINT*)&g_rcScreenRect.right );
ddsd.dwWidth = g_rcScreenRect.right - g_rcScreenRect.left;
ddsd.dwHeight = g_rcScreenRect.bottom - g_rcScreenRect.top;

// Create the backbuffer. The most likely reason for failure is running
// out of video memory. (A more sophisticated app should handle this.)
hr = g_pDD->CreateSurface( &ddsd, &g_pddsBackBuffer, NULL );
if( FAILED( hr ) )
return hr;

// Note: if using a z-buffer, the zbuffer surface creation would go around
// here. However, z-buffer usage is the topic of a subsequent tutorial.

// Create a clipper object which handles all our clipping for cases when
// our window is partially obscured by other windows. This is not needed
// for apps running in fullscreen mode.
LPDIRECTDRAWCLIPPER pcClipper;
hr = g_pDD->CreateClipper( 0, &pcClipper, NULL );
if( FAILED( hr ) )
return hr;

// Associate the clipper with our window. Note that, afterwards, the
// clipper is internally referenced by the primary surface, so it is safe
// to release our local reference to it.
pcClipper->SetHWnd( 0, hWnd );
g_pddsPrimary->SetClipper( pcClipper );
pcClipper->Release();

// Query DirectDraw for access to Direct3D
g_pDD->QueryInterface( IID_IDirect3D7, (VOID**)&g_pD3D );
if( FAILED( hr) )
return hr;

//-------------------------------------------------------------------------
// Create the z-buffer AFTER creating the backbuffer and BEFORE creating
// the d3ddevice.
//
// Note: before creating the z-buffer, apps may want to check the device
// caps for the D3DPRASTERCAPS_ZBUFFERLESSHSR flag. This flag is true for
// certain hardware that can do HSR (hidden-surface-removal) without a
// z-buffer. For those devices, there is no need to create a z-buffer.
//-------------------------------------------------------------------------

DDPIXELFORMAT ddpfZBuffer;
g_pD3D->EnumZBufferFormats( *pDeviceGUID,
EnumZBufferCallback, (VOID*)&ddpfZBuffer );

// If we found a good zbuffer format, then the dwSize field will be
// properly set during enumeration. Else, we have a problem and will exit.
if( sizeof(DDPIXELFORMAT) != ddpfZBuffer.dwSize )
return E_FAIL;

// Get z-buffer dimensions from the render target
// Setup the surface desc for the z-buffer.
ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
ddsd.dwWidth = g_rcScreenRect.right - g_rcScreenRect.left;
ddsd.dwHeight = g_rcScreenRect.bottom - g_rcScreenRect.top;
memcpy( &ddsd.ddpfPixelFormat, &ddpfZBuffer, sizeof(DDPIXELFORMAT) );

// For hardware devices, the z-buffer should be in video memory. For
// software devices, create the z-buffer in system memory
if( IsEqualIID( *pDeviceGUID, IID_IDirect3DHALDevice ) )
ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
else
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;

// Create and attach a z-buffer. Real apps should be able to handle an
// error here (DDERR_OUTOFVIDEOMEMORY may be encountered). For this
// tutorial, though, we are simply going to exit ungracefully.
if( FAILED( hr = g_pDD->CreateSurface( &ddsd, &g_pddsZBuffer, NULL ) ) )
return hr;

// Attach the z-buffer to the back buffer.
if( FAILED( hr = g_pddsBackBuffer->AddAttachedSurface( g_pddsZBuffer ) ) )
return hr;

//-------------------------------------------------------------------------
// End of z-buffer creation code.
//
// Before rendering, don't forget to enable the z-buffer with the
// appropiate D3DRENDERSTATE's.
//-------------------------------------------------------------------------

// Before creating the device, check that we are NOT in a palettized
// display. That case will cause CreateDevice() to fail, since this simple
// tutorial does not bother with palettes.
ddsd.dwSize = sizeof(DDSURFACEDESC2);
g_pDD->GetDisplayMode( &ddsd );
if( ddsd.ddpfPixelFormat.dwRGBBitCount <= 8 )
return DDERR_INVALIDMODE;

// Create the device. The device is created off of our back buffer, which
// becomes the render target for the newly created device. Note that the
// z-buffer must be created BEFORE the device

if( FAILED( hr = g_pD3D->CreateDevice( *pDeviceGUID, g_pddsBackBuffer,
&g_pd3dDevice ) ) )
{
// This call could fail for many reasons. The most likely cause is
// that we specifically requested a hardware device, without knowing
// whether there is even a 3D card installed in the system. Another
// possibility is the hardware is incompatible with the current display
// mode (the correct implementation would use enumeration for this.)
return hr;
}

// Create the viewport
DWORD dwRenderWidth = g_rcScreenRect.right - g_rcScreenRect.left;
DWORD dwRenderHeight = g_rcScreenRect.bottom - g_rcScreenRect.top;
D3DVIEWPORT7 vp = { 0, 0, dwRenderWidth, dwRenderHeight, 0.0f, 1.0f };
hr = g_pd3dDevice->SetViewport( &vp );
if( FAILED( hr ) )
return hr;

// Finish by setting up our scene
return App_InitDeviceObjects( g_pd3dDevice );
}


void CMy3dXVView::OnCull()
{
// TODO: Add your control notification handler code here
m_bCull = ((CButton*)GetDlgItem(IDC_CULL))->GetCheck();
}

void CMy3dXVView::OnWire()
{
// TODO: Add your control notification handler code here
m_bWire = ((CButton*)GetDlgItem(IDC_WIRE))->GetCheck();
}

void CMy3dXVView::OnFlat()
{
// TODO: Add your control notification handler code here
m_bFlat = !((CButton*)GetDlgItem(IDC_FLAT))->GetCheck();
}

void CMy3dXVView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
// 灯光亮度
m_AmbientLight = ((CSliderCtrl*)GetDlgItem(IDC_SLIDER_ALIGHT))->GetPos()/100.0f;
m_DirectionalLight = ((CSliderCtrl*)GetDlgItem(IDC_SLIDER_DLIGHT))->GetPos()/100.0f;
SetupLight();
// 模型绕轴的转角
int pos;
pos = ((CSliderCtrl*)GetDlgItem(IDC_SLIDER_MX))->GetPos()-50;
m_fXAxisAngle = pos*2*g_PI/50;
pos = ((CSliderCtrl*)GetDlgItem(IDC_SLIDER_MY))->GetPos()-50;
m_fYAxisAngle = pos*2*g_PI/50;
// Camera绕轴的转角
pos = ((CSliderCtrl*)GetDlgItem(IDC_SLIDER_CX))->GetPos()-50;
m_fXViewAngle = pos*2*g_PI/50;
pos = ((CSliderCtrl*)GetDlgItem(IDC_SLIDER_CY))->GetPos()-50;
m_fYViewAngle = pos*g_PI/100;
// Camera到原点的距离
pos = ((CSliderCtrl*)GetDlgItem(IDC_SLIDER_CD))->GetPos()-30;
m_fEyeDistance = (FLOAT)pos/10.0f;


CFormView::OnHScroll(nSBCode, nPos, pScrollBar);
}

void CMy3dXVView::SetupLight()
{
// Set up the light
// 直射光
D3DLIGHT7 light;
D3DUtil_InitLight( light, D3DLIGHT_DIRECTIONAL, 0.0f, -2.0f, -2.0f );
light.dcvDiffuse.r = m_DirectionalLight;
light.dcvDiffuse.g = m_DirectionalLight;
light.dcvDiffuse.b = m_DirectionalLight;
g_pd3dDevice->SetLight( 0, &light );
// 环境光
DWORD Ambient;
Ambient = (DWORD)(255*m_AmbientLight);
Ambient <<= 8;
Ambient += (DWORD)(255*m_AmbientLight);
Ambient <<= 8;
Ambient += (DWORD)(255*m_AmbientLight);
g_pd3dDevice->SetRenderState( D3DRENDERSTATE_AMBIENT, Ambient ); //环境光
}

void CMy3dXVView::OnKillfocusEditX()
{
// TODO: Add your control notification handler code here
CString buffer;
GetDlgItem(IDC_EDIT_X)->GetWindowText(buffer);
m_fModel_X = (float)atof( buffer );
char x[80];
sprintf(x, "%7.2f", m_fModel_X);
GetDlgItem(IDC_EDIT_X)->SetWindowText(x);
}

void CMy3dXVView::OnKillfocusEditY()
{
// TODO: Add your control notification handler code here
CString buffer;
GetDlgItem(IDC_EDIT_Y)->GetWindowText(buffer);
m_fModel_Y = (float)atof( buffer );
char y[80];
sprintf(y, "%7.2f", m_fModel_Y);
GetDlgItem(IDC_EDIT_Y)->SetWindowText(y);
}

void CMy3dXVView::OnKillfocusEditZ()
{
// TODO: Add your control notification handler code here
CString buffer;
GetDlgItem(IDC_EDIT_Z)->GetWindowText(buffer);
m_fModel_Z = (float)atof( buffer );
char z[80];
sprintf(z, "%7.2f", m_fModel_Z);
GetDlgItem(IDC_EDIT_Z)->SetWindowText(z);
}

void CMy3dXVView::OnButtonXdown()
{
// TODO: Add your control notification handler code here
m_fModel_X -= (FLOAT)fabs(m_fEyeDistance*m_fObjectRadius+m_fObjectRadius)/10.0f;
// 更新坐标显示
char buf[80];
sprintf(buf, "%7.2f", m_fModel_X);
GetDlgItem(IDC_EDIT_X)->SetWindowText(buf);
}

void CMy3dXVView::OnButtonXup()
{
// TODO: Add your control notification handler code here
m_fModel_X += (FLOAT)fabs(m_fEyeDistance*m_fObjectRadius+m_fObjectRadius)/10.0f;
// 更新坐标显示
char buf[80];
sprintf(buf, "%7.2f", m_fModel_X);
GetDlgItem(IDC_EDIT_X)->SetWindowText(buf);
}

void CMy3dXVView::OnButtonYdown()
{
// TODO: Add your control notification handler code here
m_fModel_Y -= (FLOAT)fabs(m_fEyeDistance*m_fObjectRadius+m_fObjectRadius)/10.0f;
// 更新坐标显示
char buf[80];
sprintf(buf, "%7.2f", m_fModel_Y);
GetDlgItem(IDC_EDIT_Y)->SetWindowText(buf);
}

void CMy3dXVView::OnButtonYup()
{
// TODO: Add your control notification handler code here
m_fModel_Y += (FLOAT)fabs(m_fEyeDistance*m_fObjectRadius+m_fObjectRadius)/10.0f;
char buf[80];
sprintf(buf, "%7.2f", m_fModel_Y);
GetDlgItem(IDC_EDIT_Y)->SetWindowText(buf);
}

void CMy3dXVView::OnButtonZdown()
{
// TODO: Add your control notification handler code here
m_fModel_Z -= (FLOAT)fabs(m_fEyeDistance*m_fObjectRadius+m_fObjectRadius)/10.0f;
char buf[80];
sprintf(buf, "%7.2f", m_fModel_Z);
GetDlgItem(IDC_EDIT_Z)->SetWindowText(buf);
}

void CMy3dXVView::OnButtonZup()
{
// TODO: Add your control notification handler code here
m_fModel_Z += (FLOAT)fabs(m_fEyeDistance*m_fObjectRadius+m_fObjectRadius)/10.0f;
char buf[80];
sprintf(buf, "%7.2f", m_fModel_Z);
GetDlgItem(IDC_EDIT_Z)->SetWindowText(buf);
}


void CMy3dXVView::OnButtonReset()
{
// TODO: Add your control notification handler code here
//
m_bCull = TRUE;
m_bFlat = FALSE;
m_bWire = FALSE;
((CButton*)GetDlgItem(IDC_CULL))->SetCheck(m_bCull);
((CButton*)GetDlgItem(IDC_FLAT))->SetCheck(!m_bFlat);
((CButton*)GetDlgItem(IDC_WIRE))->SetCheck(m_bWire);
//
m_DirectionalLight = 1.0f;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_DLIGHT ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_DLIGHT ))->SetPos((int)(m_DirectionalLight*100));
m_AmbientLight = 0.0f;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_ALIGHT ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_ALIGHT ))->SetPos((int)(m_AmbientLight*100));
SetupLight();
//
m_fModel_X = 0.0f;
m_fModel_Y = 0.0f;
m_fModel_Z = 0.0f;
char buf[80];
sprintf(buf, "%7.2f", m_fModel_X);
GetDlgItem(IDC_EDIT_X)->SetWindowText(buf);
sprintf(buf, "%7.2f", m_fModel_Y);
GetDlgItem(IDC_EDIT_Y)->SetWindowText(buf);
sprintf(buf, "%7.2f", m_fModel_Z);
GetDlgItem(IDC_EDIT_Z)->SetWindowText(buf);
// 模块的转角
m_fXAxisAngle = 0.0f;
m_fYAxisAngle = 0.0f;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MX ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MX ))->SetPos(50);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MY ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MY ))->SetPos(50);
//Camera转角
m_fXViewAngle = 0.0f;
m_fYViewAngle = 0.0f;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CX ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CX ))->SetPos(50);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CY ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CY ))->SetPos(50);
//Camera距离
m_fEyeDistance = 0.0f;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CD ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CD ))->SetPos(30);
}

void CMy3dXVView::Reset()
{
OnButtonReset();
}

void CMy3dXVView::OnFpsCheck()
{
// TODO: Add your control notification handler code here
g_FPS = ((CButton*)GetDlgItem(IDC_FPS_CHECK))->GetCheck();
GetDlgItem(IDC_FPS_EDIT)->EnableWindow(g_FPS);
char msg[80];
sprintf(msg, "%d", g_FpsMax);
GetDlgItem(IDC_FPS_EDIT)->SetWindowText(msg);
}

void CMy3dXVView::OnKillfocusFpsEdit()
{
// TODO: Add your control notification handler code here
CString buffer;
GetDlgItem(IDC_FPS_EDIT)->GetWindowText(buffer);
g_FpsMax = (UINT)atoi( buffer );
if(g_FpsMax == 0)
g_FpsMax = 1;
char x[80];
sprintf(x, "%d", g_FpsMax);
GetDlgItem(IDC_FPS_EDIT)->SetWindowText(x);
}

BOOL CMy3dXVView::KeyDown()
{
BOOL shift, ctrl;
shift = ctrl = FALSE;
BOOL left, right, up, down;
left = right = up = down = FALSE;
BOOL home, end;
home = end = FALSE;

if (GetAsyncKeyState(VK_RETURN))
{
// 取得Edit框中的值
OnKillfocusEditX();
OnKillfocusEditY();
OnKillfocusEditZ();
OnKillfocusFpsEdit();
}
if ( GetAsyncKeyState(VK_SHIFT) ) shift = TRUE;
if ( GetAsyncKeyState(VK_CONTROL) ) ctrl = TRUE;
if ( GetAsyncKeyState(VK_LEFT) ) left = TRUE;
if ( GetAsyncKeyState(VK_RIGHT) ) right = TRUE;
if ( GetAsyncKeyState(VK_UP) ) up = TRUE;
if ( GetAsyncKeyState(VK_DOWN) ) down = TRUE;
if ( GetAsyncKeyState(VK_HOME) ) home = TRUE;
if ( GetAsyncKeyState(VK_END) ) end = TRUE;

//转动模型
if ( ctrl && left )
{
GetDlgItem(IDC_FPS_EDIT)->SetFocus();
m_fXAxisAngle -= 0.03f;
if ( m_fXAxisAngle < -2*g_PI ) m_fXAxisAngle = 2*g_PI;
//
int pos;
pos = (int)(m_fXAxisAngle*50/2/g_PI)+50;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MX ))->SetPos(pos);
}
if ( ctrl && right )
{
GetDlgItem(IDC_FPS_EDIT)->SetFocus();
m_fXAxisAngle += 0.03f;
if ( m_fXAxisAngle > 2*g_PI ) m_fXAxisAngle = -2*g_PI;
//
int pos;
pos = (int)(m_fXAxisAngle*50/2/g_PI)+50;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MX ))->SetPos(pos);
}
if ( ctrl && up )
{
GetDlgItem(IDC_FPS_EDIT)->SetFocus();
m_fYAxisAngle -= 0.03f;
if ( m_fYAxisAngle < -2*g_PI ) m_fYAxisAngle = 2*g_PI;
//
int pos;
pos = (int)(m_fYAxisAngle*50/2/g_PI)+50;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MY ))->SetPos(pos);
}
if ( ctrl && down )
{
GetDlgItem(IDC_FPS_EDIT)->SetFocus();
m_fYAxisAngle += 0.03f;
if ( m_fYAxisAngle > 2*g_PI ) m_fYAxisAngle = -2*g_PI;
//
int pos;
pos = (int)(m_fYAxisAngle*50/2/g_PI)+50;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MY ))->SetPos(pos);
}
// 移动Camera
if ( shift && left )
{
GetDlgItem(IDC_FPS_EDIT)->SetFocus();
m_fXViewAngle -= 0.03f;
if ( m_fXViewAngle < -2*g_PI ) m_fXViewAngle = 2*g_PI;
//
int pos;
pos = (int)(m_fXViewAngle*50/2/g_PI)+50;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CX ))->SetPos(pos);
}
if ( shift && right )
{
GetDlgItem(IDC_FPS_EDIT)->SetFocus();
m_fXViewAngle += 0.03f;
if ( m_fXViewAngle > 2*g_PI ) m_fXViewAngle = -2*g_PI;
//
int pos;
pos = (int)(m_fXViewAngle*50/2/g_PI)+50;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CX ))->SetPos(pos);
}
if ( shift && up )
{
GetDlgItem(IDC_FPS_EDIT)->SetFocus();
m_fYViewAngle -= 0.03f;
if ( m_fYViewAngle < -g_PI ) m_fYViewAngle = -g_PI;
//
int pos;
pos = (int)(m_fYViewAngle*100/g_PI)+50;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CY ))->SetPos(pos);
}
if ( shift && down )
{
GetDlgItem(IDC_FPS_EDIT)->SetFocus();
m_fYViewAngle += 0.03f;
if ( m_fYViewAngle > g_PI ) m_fYViewAngle = g_PI;
//
int pos;
pos = (int)(m_fYViewAngle*100/g_PI)+50;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CY ))->SetPos(pos);
}
// Camera到原点的距离
if ( shift && home )
{
GetDlgItem(IDC_FPS_EDIT)->SetFocus();
m_fEyeDistance += 0.1f;
if( m_fEyeDistance > 7.0f ) m_fEyeDistance = 7.0f;
int pos;
pos = 30 + (int)(10.0f*m_fEyeDistance);
((CSliderCtrl*)GetDlgItem(IDC_SLIDER_CD))->SetPos(pos);
}
if ( shift && end )
{
GetDlgItem(IDC_FPS_EDIT)->SetFocus();
m_fEyeDistance -= 0.1f;
if( m_fEyeDistance < -3.0f ) m_fEyeDistance = -3.0f;
int pos;
pos = 30 + (int)(10.0f*m_fEyeDistance);
((CSliderCtrl*)GetDlgItem(IDC_SLIDER_CD))->SetPos(pos);
}

return TRUE;
}

BOOL CMy3dXVView::GoFullScreen()
{
// 创建一个全屏窗口
// Create a new fullscreen window
//RECT rc = { 0, 0, 100, 100 };
m_hwndFullScreen = CreateWindow( TEXT("Fullscreen Window"), NULL,
WS_POPUP|WS_VISIBLE, CW_USEDEFAULT,
CW_USEDEFAULT, 100, 100,
m_hwndRenderWindow, 0L, NULL, 0L );


if( m_hwndFullScreen == NULL )
{
AfxMessageBox( "CreateWindow failed" );
return FALSE;
}
m_IsWindow = FALSE; // 现在进入全屏幕
InitDirectXFullScreen();

return TRUE;

}

void CMy3dXVView::OnButtonFullscr()
{
// TODO: Add your control notification handler code here
g_bReady = FALSE;
GoFullScreen();
LoadFile( "teapot.x" );
g_bReady = TRUE;
}

BOOL CMy3dXVView::InitDirectXFullScreen()
{
// 初始化Direct3D,全屏幕模式
// Cleanup any objects that might've been created before
if( FAILED( Cleanup3DEnvironment() ) )
return E_FAIL;

// Create the D3D environment, at first, trying the HAL
if( SUCCEEDED( Initialize3DEnvFullScr( m_hwndFullScreen, NULL,
&IID_IDirect3DHALDevice ) ) )
return S_OK;

//MessageBox( "使用硬件加速失败!\n现在尝试使用软件模式", "警告!", MB_OK|MB_ICONWARNING );
// Else, cleanup objects potentially created during the failed
// initialization attempt.
Cleanup3DEnvironment();

if( SUCCEEDED( Initialize3DEnvFullScr( m_hwndFullScreen, NULL,
&IID_IDirect3DRGBDevice ) ) )
return S_OK;

//MessageBox( "尝试使用软件模式失败\n程序将退出", "错误!", MB_OK|MB_ICONERROR );
// Else, return failure. This simple tutorial will exit ungracefully.
return E_FAIL;
}

HRESULT CMy3dXVView::Initialize3DEnvFullScr(HWND hWnd, GUID *pDriverGUID, const GUID *pDeviceGUID)
{
HRESULT hr;

hr = DirectDrawCreateEx( pDriverGUID, (VOID**)&g_pDD, IID_IDirectDraw7,
NULL );
if( FAILED( hr ) )
return hr;

hr = g_pDD->SetCooperativeLevel( hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
if( FAILED( hr ) )
return hr;

// Initialize a surface description structure for the primary surface. The
// primary surface represents the entire display, with dimensions and a
// pixel format of the display. Therefore, none of that information needs
// to be specified in order to create the primary surface.

//
hr=g_pDD->SetDisplayMode(800, 600, 16, 0, 0);

if( FAILED( hr ) )
{
//DXError(r,"Create DirectX Surface failed\n请确定你已经安装了DirectX");
return hr;
}
// Create the primary surface.
DDSURFACEDESC2 ddsd;
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |
DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE;
ddsd.dwBackBufferCount = 1;

hr=g_pDD->CreateSurface(&ddsd, &g_pddsPrimary, 0);
if( FAILED( hr ) )
{
//DXError(r,"Create DirectX Surface failed\n请确定你已经安装了DirectX");
return hr;
}
//创建后台表面
DDSCAPS2 ddscaps = { DDSCAPS_BACKBUFFER, 0, 0, 0 };
hr =g_pddsPrimary->GetAttachedSurface(&ddscaps, &g_pddsBackBuffer);
if( FAILED( hr ) )
{
TRACE("Primary->GetAttachedSurface fialed\n");
return hr;
}
//
// Query DirectDraw for access to Direct3D
g_pDD->QueryInterface( IID_IDirect3D7, (VOID**)&g_pD3D );
if( FAILED( hr ) )
{
TRACE("QueryInterface D3D failed\n");
return hr;
}

//-------------------------------------------------------------------------
// Create the z-buffer AFTER creating the backbuffer and BEFORE creating
// the d3ddevice.
//
// Note: before creating the z-buffer, apps may want to check the device
// caps for the D3DPRASTERCAPS_ZBUFFERLESSHSR flag. This flag is true for
// certain hardware that can do HSR (hidden-surface-removal) without a
// z-buffer. For those devices, there is no need to create a z-buffer.
//-------------------------------------------------------------------------

DDPIXELFORMAT ddpfZBuffer;
g_pD3D->EnumZBufferFormats( *pDeviceGUID,
EnumZBufferCallback, (VOID*)&ddpfZBuffer );

// If we found a good zbuffer format, then the dwSize field will be
// properly set during enumeration. Else, we have a problem and will exit.
if( sizeof(DDPIXELFORMAT) != ddpfZBuffer.dwSize )
return E_FAIL;

// Get z-buffer dimensions from the render target
// Setup the surface desc for the z-buffer.
ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
ddsd.dwWidth = 800;
ddsd.dwHeight = 600;
memcpy( &ddsd.ddpfPixelFormat, &ddpfZBuffer, sizeof(DDPIXELFORMAT) );

// For hardware devices, the z-buffer should be in video memory. For
// software devices, create the z-buffer in system memory
if( IsEqualIID( *pDeviceGUID, IID_IDirect3DHALDevice ) )
ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
else
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;

// Create and attach a z-buffer. Real apps should be able to handle an
// error here (DDERR_OUTOFVIDEOMEMORY may be encountered). For this
// tutorial, though, we are simply going to exit ungracefully.
if( FAILED( hr = g_pDD->CreateSurface( &ddsd, &g_pddsZBuffer, NULL ) ) )
{
TRACE("Create ZBuffer failed");
return hr;
}

// Attach the z-buffer to the back buffer.
if( FAILED( hr = g_pddsBackBuffer->AddAttachedSurface( g_pddsZBuffer ) ) )
{
TRACE("BackBuffer->AddAttachedSurface failed\n");
return hr;
}

//-------------------------------------------------------------------------
// End of z-buffer creation code.
//
// Before rendering, don't forget to enable the z-buffer with the
// appropiate D3DRENDERSTATE's.
//-------------------------------------------------------------------------

// Before creating the device, check that we are NOT in a palettized
// display. That case will cause CreateDevice() to fail, since this simple
// tutorial does not bother with palettes.
ddsd.dwSize = sizeof(DDSURFACEDESC2);
g_pDD->GetDisplayMode( &ddsd );
if( ddsd.ddpfPixelFormat.dwRGBBitCount <= 8 )
return DDERR_INVALIDMODE;

// Create the device. The device is created off of our back buffer, which
// becomes the render target for the newly created device. Note that the
// z-buffer must be created BEFORE the device

if( FAILED( hr = g_pD3D->CreateDevice( *pDeviceGUID, g_pddsBackBuffer,
&g_pd3dDevice ) ) )
{
TRACE("D3D CreateDevice failed\n");
return hr;
}

// Create the viewport
DWORD dwRenderWidth = 800;
DWORD dwRenderHeight = 600;
D3DVIEWPORT7 vp = { 0, 0, dwRenderWidth, dwRenderHeight, 0.0f, 1.0f };
hr = g_pd3dDevice->SetViewport( &vp );
if( FAILED( hr ) )
return hr;

// Finish by setting up our scene
return App_InitDeviceObjects( g_pd3dDevice );
}

BOOL CMy3dXVView::FullScrKeyDown()
{
BOOL shift, ctrl;
shift = ctrl = FALSE;
BOOL left, right, up, down;
left = right = up = down = FALSE;
BOOL home, end;
home = end = FALSE;

if (GetAsyncKeyState(VK_RETURN))
{
// 取得Edit框中的值
OnKillfocusEditX();
OnKillfocusEditY();
OnKillfocusEditZ();
OnKillfocusFpsEdit();
}
if ( GetAsyncKeyState(VK_SHIFT) ) shift = TRUE;
if ( GetAsyncKeyState(VK_CONTROL) ) ctrl = TRUE;
if ( GetAsyncKeyState(VK_LEFT) ) left = TRUE;
if ( GetAsyncKeyState(VK_RIGHT) ) right = TRUE;
if ( GetAsyncKeyState(VK_UP) ) up = TRUE;
if ( GetAsyncKeyState(VK_DOWN) ) down = TRUE;
if ( GetAsyncKeyState(VK_HOME) ) home = TRUE;
if ( GetAsyncKeyState(VK_END) ) end = TRUE;

//转动模型
if ( ctrl && left )
{
m_fXAxisAngle -= 0.03f;
if ( m_fXAxisAngle < -2*g_PI ) m_fXAxisAngle = 2*g_PI;
//
int pos;
pos = (int)(m_fXAxisAngle*50/2/g_PI)+50;
}
if ( ctrl && right )
{
m_fXAxisAngle += 0.03f;
if ( m_fXAxisAngle > 2*g_PI ) m_fXAxisAngle = -2*g_PI;
//
int pos;
pos = (int)(m_fXAxisAngle*50/2/g_PI)+50;
}
if ( ctrl && up )
{
m_fYAxisAngle -= 0.03f;
if ( m_fYAxisAngle < -2*g_PI ) m_fYAxisAngle = 2*g_PI;
//
int pos;
pos = (int)(m_fYAxisAngle*50/2/g_PI)+50;
}
if ( ctrl && down )
{
m_fYAxisAngle += 0.03f;
if ( m_fYAxisAngle > 2*g_PI ) m_fYAxisAngle = -2*g_PI;
//
int pos;
pos = (int)(m_fYAxisAngle*50/2/g_PI)+50;
}
// 移动Camera
if ( shift && left )
{
m_fXViewAngle -= 0.03f;
if ( m_fXViewAngle < -2*g_PI ) m_fXViewAngle = 2*g_PI;
//
int pos;
pos = (int)(m_fXViewAngle*50/2/g_PI)+50;
}
if ( shift && right )
{
m_fXViewAngle += 0.03f;
if ( m_fXViewAngle > 2*g_PI ) m_fXViewAngle = -2*g_PI;
//
int pos;
pos = (int)(m_fXViewAngle*50/2/g_PI)+50;
}
if ( shift && up )
{
m_fYViewAngle -= 0.03f;
if ( m_fYViewAngle < -g_PI ) m_fYViewAngle = -g_PI;
//
int pos;
pos = (int)(m_fYViewAngle*100/g_PI)+50;
}
if ( shift && down )
{
m_fYViewAngle += 0.03f;
if ( m_fYViewAngle > g_PI ) m_fYViewAngle = g_PI;
//
int pos;
pos = (int)(m_fYViewAngle*100/g_PI)+50;
}
// Camera到原点的距离
if ( shift && home )
{
m_fEyeDistance += 0.1f;
if( m_fEyeDistance > 7.0f ) m_fEyeDistance = 7.0f;
int pos;
pos = 30 + (int)(10.0f*m_fEyeDistance);
}
if ( shift && end )
{
m_fEyeDistance -= 0.1f;
if( m_fEyeDistance < -3.0f ) m_fEyeDistance = -3.0f;
int pos;
pos = 30 + (int)(10.0f*m_fEyeDistance);
}

return TRUE;
}

BOOL CMy3dXVView::GoWindow()
{
g_bReady = FALSE;
// 初始化Direct3D
// Cleanup any objects that might've been created before
if( FAILED( Cleanup3DEnvironment() ) )
return E_FAIL;

HWND hWnd;
hWnd = m_hwndRenderWindow;

TRACE("GoWindow\n");
// Create the D3D environment, at first, trying the HAL
if( SUCCEEDED( Initialize3DEnvironment( hWnd, NULL,
&IID_IDirect3DHALDevice ) ) )
return S_OK;

// Else, cleanup objects potentially created during the failed
// initialization attempt.
Cleanup3DEnvironment();

if( SUCCEEDED( Initialize3DEnvironment( hWnd, NULL,
&IID_IDirect3DRGBDevice ) ) )
return S_OK;

LoadFile( "teapot.x" );
TRACE("DestroyWindow\n");
if( m_hwndFullScreen )
::DestroyWindow( m_hwndFullScreen );
TRACE("Destroied\n");

m_hwndFullScreen = NULL;
g_bReady = TRUE;

return TRUE;
}

我的,没有问题:
CGSD3DScreen::CGSD3DScreen(HWND hWnd)
{
ASSERT(hWnd);
_InitVars();

m_hWnd = hWnd;
::GetClientRect(m_hWnd, m_rectClient);

if (!_InitD3D())
{
throw -1;
}

D3DXQuaternionIdentity( &m_qDown );
D3DXQuaternionIdentity( &m_qNow );
D3DXMatrixIdentity( &m_matRotation );
D3DXMatrixIdentity( &m_matRotationDelta );
D3DXMatrixIdentity( &m_matTranslation );
D3DXMatrixIdentity( &m_matTranslationDelta );
}

CGSD3DScreen::~CGSD3DScreen()
{
_ReleaseAllResources();
_InitVars();
}

void CGSD3DScreen::_ReleaseAllResources()
{
CloseXFile();

SAFE_RELEASE(m_pD3DDevice);
SAFE_RELEASE(m_pD3D);
}

BOOL CGSD3DScreen::_InitD3D()
{
// Create the D3D object.
if( NULL == ( m_pD3D = Direct3DCreate8( D3D_SDK_VERSION ) ) )
{
return FALSE;
}

// Get the current desktop display mode, so we can set up a back
// buffer of the same format
D3DDISPLAYMODE d3ddm;
if( FAILED( m_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) )
{
return FALSE;
}

// Set up the structure used to create the D3DDevice. Since we are now
// using more complex geometry, we will create a device with a zbuffer.
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = d3ddm.Format;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

// Create the D3DDevice
if( FAILED( m_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &m_pD3DDevice ) ) )
{
if( FAILED( m_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, m_hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &m_pD3DDevice ) ) )
{
return FALSE;
}
else
{
m_fUsingHardwareAccelerate = FALSE;
TRACE(_T("抱歉,系统不能使用硬件加速,当前使用软件模拟加速模式。\n"));
}
}
else
{
m_fUsingHardwareAccelerate = TRUE;
TRACE(_T("恭喜!系统成功使用硬件加速性能。\n"));
}

// Turn on the zbuffer
m_pD3DDevice->SetRenderState( D3DRS_ZENABLE, TRUE );

// Turn on ambient lighting
m_pD3DDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_XRGB(55, 55, 55) );

m_pD3DDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
m_pD3DDevice->SetRenderState( D3DRS_DITHERENABLE, TRUE );
m_pD3DDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
// m_pD3DDevice->SetRenderState( D3DRS_AMBIENT, 0x33333333 );
m_pD3DDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
m_pD3DDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );

// Setup the light
D3DLIGHT8 light;
_D3DUtil_InitLight( light, D3DLIGHT_DIRECTIONAL, 0.0f,-1.0f, 1.0f );
m_pD3DDevice->SetLight(0, &light );
m_pD3DDevice->LightEnable(0, TRUE );

return TRUE;
}

void CGSD3DScreen::Render()
{
static DWORD dwLastTickCount = 0;

if (m_pD3DDevice)
{
DWORD dwCurrentTickCount = GetTickCount();

if ((dwCurrentTickCount - dwLastTickCount) < m_nSleepTime)
{
return;
}
m_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
m_pD3DDevice->BeginScene();

SetupMatrices();
_FrameMove();

if (m_dwNumMaterials > 0)
{
for (int i = 0; i < (int)m_dwNumMaterials; i++)
{
// Set the material and texture for this subset
m_pD3DDevice->SetMaterial( &m_pMeshMaterials[i] );
m_pD3DDevice->SetTexture( 0, m_pMeshTextures[i] );

// Draw the mesh subset
m_pMeshXModel->DrawSubset( i );
}
}

m_pD3DDevice->EndScene();
m_pD3DDevice->Present(NULL, NULL, NULL, NULL);
dwLastTickCount = dwCurrentTickCount;
}
}

BOOL CGSD3DScreen::LoadXFile(LPSTR pszFileName)
{
LPD3DXBUFFER pD3DMtrlBuffer = NULL;
LPDIRECT3DVERTEXBUFFER8 pVB = NULL;
BYTE* pVertices = NULL;

//判断文件是否存在。。。
if (!PathFileExists(pszFileName))
{
TRACE(_T("指定的文件[%s]不存在\n"), pszFileName);
return FALSE;
}

CloseXFile(); //关闭已经打开的X文件资源
if ( FAILED( D3DXLoadMeshFromX(pszFileName, D3DXMESH_SYSTEMMEM, m_pD3DDevice, NULL,
&pD3DMtrlBuffer, &m_dwNumMaterials, &m_pMeshXModel) ) )
{
TRACE(_T("读取X文件失败。。。\n"));
return FALSE;
}
m_pMeshXModel->GetVertexBuffer(&pVB);
pVB->Lock( 0, 0, &pVertices, 0 );

LPD3DXMATERIAL pd3dxMaterials = (LPD3DXMATERIAL)pD3DMtrlBuffer->GetBufferPointer();
m_pMeshMaterials = new D3DMATERIAL8[m_dwNumMaterials];
m_pMeshTextures = new LPDIRECT3DTEXTURE8[m_dwNumMaterials];

for (int i = 0; i < (int)m_dwNumMaterials; i++)
{
//拷贝模型原料
m_pMeshMaterials[i] = pd3dxMaterials[i].MatD3D;

// Set the ambient color for the material (D3DX does not do this)
m_pMeshMaterials[i].Ambient = m_pMeshMaterials[i].Diffuse;

//Create a texture
if ( FAILED (D3DXCreateTextureFromFile(m_pD3DDevice,
pd3dxMaterials[i].pTextureFilename, &m_pMeshTextures[i]) ) )
{
m_pMeshTextures[i] = NULL;
}
}

D3DXComputeBoundingSphere( pVertices, m_pMeshXModel->GetNumVertices(),
m_pMeshXModel->GetFVF(), &m_vObjectCenter,
&m_fObjectRadius );

SAFE_RELEASE(pVB);
SAFE_RELEASE(pD3DMtrlBuffer);
m_fXFileOK = TRUE;

return TRUE;
}

void CGSD3DScreen::CloseXFile()
{
SAFE_DELETE(m_pMeshMaterials);

if( m_pMeshTextures )
{
for( int i = 0; i < (int)m_dwNumMaterials; i++ )
{
SAFE_RELEASE(m_pMeshTextures[i]);
}
SAFE_DELETE(m_pMeshTextures);
}
SAFE_RELEASE(m_pMeshXModel);

m_fXFileOK = FALSE;
}

void CGSD3DScreen::SetupMatrices()
{
// For our world matrix, we will just leave it as the identity
D3DXMATRIX matWorld;
D3DXMatrixRotationY( &matWorld, 0);
m_pD3DDevice->SetTransform( D3DTS_WORLD, &matWorld );

// Set up our view matrix. A view matrix can be defined given an eye point,
// a point to lookat, and a direction for which way is up. Here, we set the
// eye five units back along the z-axis and up three units, look at the
// origin, and define "up" to be in the y-direction.
D3DXMATRIX matView;
D3DXMatrixLookAtLH( &matView, &D3DXVECTOR3( 0.0f, 0.0f,-5.0f ),
&D3DXVECTOR3( 0.0f, 0.0f, .0f ),
&D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) );
m_pD3DDevice->SetTransform( D3DTS_VIEW, &matView );

// For the projection matrix, we set up a perspective transform (which
// transforms geometry from 3D view space to 2D viewport space, with
// a perspective divide making objects smaller in the distance). To build
// a perpsective transform, we need the field of view (1/4 pi is common),
// the aspect ratio, and the near and far clipping planes (which define at
// what distances geometry should be no longer be rendered).
D3DXMATRIX matProj;
D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f );
m_pD3DDevice->SetTransform( D3DTS_PROJECTION, &matProj );
}

//设置模型的显示模式:D3DFILL_POINT, D3DFILL_WIREFRAME, D3DFILL_SOLID
void CGSD3DScreen::SetFillMode(DWORD dwValue)
{
m_pD3DDevice->SetRenderState(D3DRS_FILLMODE, dwValue);
}

void CGSD3DScreen::SetRadius( FLOAT fRadius )
{
m_fRadius = fRadius;
}

void CGSD3DScreen::_D3DUtil_InitLight( D3DLIGHT8& light, D3DLIGHTTYPE ltType, FLOAT x, FLOAT y, FLOAT z )
{
ZeroMemory( &light, sizeof(D3DLIGHT8) );
light.Type = ltType;
light.Diffuse.r = 1.0f;
light.Diffuse.g = 1.0f;
light.Diffuse.b = 1.0f;
D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &D3DXVECTOR3(x, y, z) );
light.Position.x = x;
light.Position.y = y;
light.Position.z = z;
light.Range = 1000.0f;
}

D3DXVECTOR3 CGSD3DScreen::_ScreenToVector( int sx, int sy )
{
// Scale to screen
FLOAT x = (sx - m_rectClient.Width()/2) / (m_fRadius*m_rectClient.Width()/2);
FLOAT y = -(sy - m_rectClient.Height()/2) / (m_fRadius*m_rectClient.Height()/2);
FLOAT z = 0.0f;
FLOAT mag = x*x + y*y;

if( mag > 1.0f )
{
FLOAT scale = 1.0f/sqrtf(mag);
x *= scale;
y *= scale;
}
else
z = sqrtf( 1.0f - mag );

// Return vector
return D3DXVECTOR3( x, y, z );
}

HRESULT CGSD3DScreen::_FrameMove()
{
// Setup world matrix
D3DXMATRIX matWorld;
D3DXMATRIX matRotationInverse;
D3DXMatrixTranslation( &matWorld, -m_vObjectCenter.x,
-m_vObjectCenter.y,
-m_vObjectCenter.z );
D3DXMatrixInverse( &matRotationInverse, NULL, GetRotationMatrix() );
D3DXMatrixMultiply( &matWorld, &matWorld, &matRotationInverse );
D3DXMatrixMultiply( &matWorld, &matWorld, GetTranslationMatrix() );
m_pD3DDevice->SetTransform( D3DTS_WORLD, &matWorld );

D3DXMATRIX matView;
D3DXMatrixLookAtLH( &matView, &D3DXVECTOR3( 0, 0, -2*m_fObjectRadius ),
&D3DXVECTOR3( 0, 0, 0 ),
&D3DXVECTOR3( 0, 1, 0 ) );
m_pD3DDevice->SetTransform( D3DTS_VIEW, &matView );

return S_OK;
}

void CGSD3DScreen::StartRotation(CPoint ptMousePoint)
{
m_vDown = _ScreenToVector(ptMousePoint.x, ptMousePoint.y);
m_bDrag = TRUE;
}

void CGSD3DScreen::SetRotation(CPoint ptMousePoint, BOOL fLeft)
{
static CPoint ptLastMouse; //Saved mouse pointion
CPoint ptCurrentMouse = ptMousePoint;

if( fLeft )
{
if( m_bDrag )
{
D3DXVECTOR3 vPart;
D3DXVECTOR3 vCur = _ScreenToVector( ptCurrentMouse.x, ptCurrentMouse.y );
D3DXVec3Cross( &vPart, &m_vDown, &vCur );
m_qNow = m_qDown * D3DXQUATERNION( vPart.x, vPart.y, vPart.z,
D3DXVec3Dot( &m_vDown, &vCur ) );
}

D3DXQUATERNION qConj;
D3DXQuaternionConjugate( &qConj, &m_qNow );

D3DXMatrixRotationQuaternion( &m_matRotationDelta, &qConj );
D3DXMatrixTranspose( &m_matRotationDelta, &m_matRotationDelta );
D3DXMatrixMultiply( &m_matRotation, &m_matRotation, &m_matRotationDelta );

D3DXQuaternionIdentity( &m_qDown );
D3DXQuaternionIdentity( &m_qNow );
m_vDown = _ScreenToVector( ptCurrentMouse.x, ptCurrentMouse.y );
m_bDrag = TRUE;
}
else
{
// Normalize based on size of window and bounding sphere radius
FLOAT fDeltaX = ( ptLastMouse.x - ptCurrentMouse.x) * m_fRadius / m_rectClient.Width();
FLOAT fDeltaY = ( ptLastMouse.y - ptCurrentMouse.y) * m_fRadius / m_rectClient.Height();

if( TRUE )
{
D3DXMatrixTranslation( &m_matTranslationDelta, -2*fDeltaX, 2*fDeltaY, 0.0f );
D3DXMatrixMultiply( &m_matTranslation, &m_matTranslation, &m_matTranslationDelta );
}
else // wParam & MK_MBUTTON
{
D3DXMatrixTranslation( &m_matTranslationDelta, 0.0f, 0.0f, 5*fDeltaY );
D3DXMatrixMultiply( &m_matTranslation, &m_matTranslation, &m_matTranslationDelta );
}

// Store mouse coordinate
ptLastMouse = ptCurrentMouse;
}
}

void CGSD3DScreen::StopRotation(CPoint ptMousePoint)
{
m_qDown = m_qNow;
m_bDrag = FALSE;
}

void CGSD3DScreen::SetLight(BOOL fTurnOn)
{
if (fTurnOn)
{
m_pD3DDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_XRGB(255, 255, 255) );
}
else
{
m_pD3DDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_XRGB(55, 55, 55) );
}
}

void CGSD3DScreen::StartScale(CPoint ptMousePoint)
{
}

void CGSD3DScreen::StopScale(CPoint ptMousePoint)
{
}

void CGSD3DScreen::SetScale(CPoint ptMousePoint)
{
}
jzgenius 2001-08-15
  • 打赏
  • 举报
回复
我根椐书上的代码写的没有问题,可是一个范例却有问题,代码如下:
我的:
CGSD3DScreen::CGSD3DScreen(HWND hWnd)
{
ASSERT(hWnd);
_InitVars();

m_hWnd = hWnd;
::GetClientRect(m_hWnd, m_rectClient);

if (!_InitD3D())
{
throw -1;
}

D3DXQuaternionIdentity( &m_qDown );
D3DXQuaternionIdentity( &m_qNow );
D3DXMatrixIdentity( &m_matRotation );
D3DXMatrixIdentity( &m_matRotationDelta );
D3DXMatrixIdentity( &m_matTranslation );
D3DXMatrixIdentity( &m_matTranslationDelta );
}

CGSD3DScreen::~CGSD3DScreen()
{
_ReleaseAllResources();
_InitVars();
}

void CGSD3DScreen::_ReleaseAllResources()
{
CloseXFile();

SAFE_RELEASE(m_pD3DDevice);
SAFE_RELEASE(m_pD3D);
}

BOOL CGSD3DScreen::_InitD3D()
{
// Create the D3D object.
if( NULL == ( m_pD3D = Direct3DCreate8( D3D_SDK_VERSION ) ) )
{
return FALSE;
}

// Get the current desktop display mode, so we can set up a back
// buffer of the same format
D3DDISPLAYMODE d3ddm;
if( FAILED( m_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) )
{
return FALSE;
}

// Set up the structure used to create the D3DDevice. Since we are now
// using more complex geometry, we will create a device with a zbuffer.
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = d3ddm.Format;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

// Create the D3DDevice
if( FAILED( m_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &m_pD3DDevice ) ) )
{
if( FAILED( m_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, m_hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &m_pD3DDevice ) ) )
{
return FALSE;
}
else
{
m_fUsingHardwareAccelerate = FALSE;
TRACE(_T("抱歉,系统不能使用硬件加速,当前使用软件模拟加速模式。\n"));
}
}
else
{
m_fUsingHardwareAccelerate = TRUE;
TRACE(_T("恭喜!系统成功使用硬件加速性能。\n"));
}

// Turn on the zbuffer
m_pD3DDevice->SetRenderState( D3DRS_ZENABLE, TRUE );

// Turn on ambient lighting
m_pD3DDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_XRGB(55, 55, 55) );

m_pD3DDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
m_pD3DDevice->SetRenderState( D3DRS_DITHERENABLE, TRUE );
m_pD3DDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
// m_pD3DDevice->SetRenderState( D3DRS_AMBIENT, 0x33333333 );
m_pD3DDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
m_pD3DDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );

// Setup the light
D3DLIGHT8 light;
_D3DUtil_InitLight( light, D3DLIGHT_DIRECTIONAL, 0.0f,-1.0f, 1.0f );
m_pD3DDevice->SetLight(0, &light );
m_pD3DDevice->LightEnable(0, TRUE );

return TRUE;
}

void CGSD3DScreen::Render()
{
static DWORD dwLastTickCount = 0;

if (m_pD3DDevice)
{
DWORD dwCurrentTickCount = GetTickCount();

if ((dwCurrentTickCount - dwLastTickCount) < m_nSleepTime)
{
return;
}
m_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
m_pD3DDevice->BeginScene();

SetupMatrices();
_FrameMove();

if (m_dwNumMaterials > 0)
{
for (int i = 0; i < (int)m_dwNumMaterials; i++)
{
// Set the material and texture for this subset
m_pD3DDevice->SetMaterial( &m_pMeshMaterials[i] );
m_pD3DDevice->SetTexture( 0, m_pMeshTextures[i] );

// Draw the mesh subset
m_pMeshXModel->DrawSubset( i );
}
}

m_pD3DDevice->EndScene();
m_pD3DDevice->Present(NULL, NULL, NULL, NULL);
dwLastTickCount = dwCurrentTickCount;
}
}

BOOL CGSD3DScreen::LoadXFile(LPSTR pszFileName)
{
LPD3DXBUFFER pD3DMtrlBuffer = NULL;
LPDIRECT3DVERTEXBUFFER8 pVB = NULL;
BYTE* pVertices = NULL;

//判断文件是否存在。。。
if (!PathFileExists(pszFileName))
{
TRACE(_T("指定的文件[%s]不存在\n"), pszFileName);
return FALSE;
}

CloseXFile(); //关闭已经打开的X文件资源
if ( FAILED( D3DXLoadMeshFromX(pszFileName, D3DXMESH_SYSTEMMEM, m_pD3DDevice, NULL,
&pD3DMtrlBuffer, &m_dwNumMaterials, &m_pMeshXModel) ) )
{
TRACE(_T("读取X文件失败。。。\n"));
return FALSE;
}
m_pMeshXModel->GetVertexBuffer(&pVB);
pVB->Lock( 0, 0, &pVertices, 0 );

LPD3DXMATERIAL pd3dxMaterials = (LPD3DXMATERIAL)pD3DMtrlBuffer->GetBufferPointer();
m_pMeshMaterials = new D3DMATERIAL8[m_dwNumMaterials];
m_pMeshTextures = new LPDIRECT3DTEXTURE8[m_dwNumMaterials];

for (int i = 0; i < (int)m_dwNumMaterials; i++)
{
//拷贝模型原料
m_pMeshMaterials[i] = pd3dxMaterials[i].MatD3D;

// Set the ambient color for the material (D3DX does not do this)
m_pMeshMaterials[i].Ambient = m_pMeshMaterials[i].Diffuse;

//Create a texture
if ( FAILED (D3DXCreateTextureFromFile(m_pD3DDevice,
pd3dxMaterials[i].pTextureFilename, &m_pMeshTextures[i]) ) )
{
m_pMeshTextures[i] = NULL;
}
}

D3DXComputeBoundingSphere( pVertices, m_pMeshXModel->GetNumVertices(),
m_pMeshXModel->GetFVF(), &m_vObjectCenter,
&m_fObjectRadius );

SAFE_RELEASE(pVB);
SAFE_RELEASE(pD3DMtrlBuffer);
m_fXFileOK = TRUE;

return TRUE;
}

void CGSD3DScreen::CloseXFile()
{
SAFE_DELETE(m_pMeshMaterials);

if( m_pMeshTextures )
{
for( int i = 0; i < (int)m_dwNumMaterials; i++ )
{
SAFE_RELEASE(m_pMeshTextures[i]);
}
SAFE_DELETE(m_pMeshTextures);
}
SAFE_RELEASE(m_pMeshXModel);

m_fXFileOK = FALSE;
}

void CGSD3DScreen::SetupMatrices()
{
// For our world matrix, we will just leave it as the identity
D3DXMATRIX matWorld;
D3DXMatrixRotationY( &matWorld, 0);
m_pD3DDevice->SetTransform( D3DTS_WORLD, &matWorld );

// Set up our view matrix. A view matrix can be defined given an eye point,
// a point to lookat, and a direction for which way is up. Here, we set the
// eye five units back along the z-axis and up three units, look at the
// origin, and define "up" to be in the y-direction.
D3DXMATRIX matView;
D3DXMatrixLookAtLH( &matView, &D3DXVECTOR3( 0.0f, 0.0f,-5.0f ),
&D3DXVECTOR3( 0.0f, 0.0f, .0f ),
&D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) );
m_pD3DDevice->SetTransform( D3DTS_VIEW, &matView );

// For the projection matrix, we set up a perspective transform (which
// transforms geometry from 3D view space to 2D viewport space, with
// a perspective divide making objects smaller in the distance). To build
// a perpsective transform, we need the field of view (1/4 pi is common),
// the aspect ratio, and the near and far clipping planes (which define at
// what distances geometry should be no longer be rendered).
D3DXMATRIX matProj;
D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f );
m_pD3DDevice->SetTransform( D3DTS_PROJECTION, &matProj );
}

//设置模型的显示模式:D3DFILL_POINT, D3DFILL_WIREFRAME, D3DFILL_SOLID
void CGSD3DScreen::SetFillMode(DWORD dwValue)
{
m_pD3DDevice->SetRenderState(D3DRS_FILLMODE, dwValue);
}

void CGSD3DScreen::SetRadius( FLOAT fRadius )
{
m_fRadius = fRadius;
}

void CGSD3DScreen::_D3DUtil_InitLight( D3DLIGHT8& light, D3DLIGHTTYPE ltType, FLOAT x, FLOAT y, FLOAT z )
{
ZeroMemory( &light, sizeof(D3DLIGHT8) );
light.Type = ltType;
light.Diffuse.r = 1.0f;
light.Diffuse.g = 1.0f;
light.Diffuse.b = 1.0f;
D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &D3DXVECTOR3(x, y, z) );
light.Position.x = x;
light.Position.y = y;
light.Position.z = z;
light.Range = 1000.0f;
}

D3DXVECTOR3 CGSD3DScreen::_ScreenToVector( int sx, int sy )
{
// Scale to screen
FLOAT x = (sx - m_rectClient.Width()/2) / (m_fRadius*m_rectClient.Width()/2);
FLOAT y = -(sy - m_rectClient.Height()/2) / (m_fRadius*m_rectClient.Height()/2);
FLOAT z = 0.0f;
FLOAT mag = x*x + y*y;

if( mag > 1.0f )
{
FLOAT scale = 1.0f/sqrtf(mag);
x *= scale;
y *= scale;
}
else
z = sqrtf( 1.0f - mag );

// Return vector
return D3DXVECTOR3( x, y, z );
}

HRESULT CGSD3DScreen::_FrameMove()
{
// Setup world matrix
D3DXMATRIX matWorld;
D3DXMATRIX matRotationInverse;
D3DXMatrixTranslation( &matWorld, -m_vObjectCenter.x,
-m_vObjectCenter.y,
-m_vObjectCenter.z );
D3DXMatrixInverse( &matRotationInverse, NULL, GetRotationMatrix() );
D3DXMatrixMultiply( &matWorld, &matWorld, &matRotationInverse );
D3DXMatrixMultiply( &matWorld, &matWorld, GetTranslationMatrix() );
m_pD3DDevice->SetTransform( D3DTS_WORLD, &matWorld );

D3DXMATRIX matView;
D3DXMatrixLookAtLH( &matView, &D3DXVECTOR3( 0, 0, -2*m_fObjectRadius ),
&D3DXVECTOR3( 0, 0, 0 ),
&D3DXVECTOR3( 0, 1, 0 ) );
m_pD3DDevice->SetTransform( D3DTS_VIEW, &matView );

return S_OK;
}

void CGSD3DScreen::StartRotation(CPoint ptMousePoint)
{
m_vDown = _ScreenToVector(ptMousePoint.x, ptMousePoint.y);
m_bDrag = TRUE;
}

void CGSD3DScreen::SetRotation(CPoint ptMousePoint, BOOL fLeft)
{
static CPoint ptLastMouse; //Saved mouse pointion
CPoint ptCurrentMouse = ptMousePoint;

if( fLeft )
{
if( m_bDrag )
{
D3DXVECTOR3 vPart;
D3DXVECTOR3 vCur = _ScreenToVector( ptCurrentMouse.x, ptCurrentMouse.y );
D3DXVec3Cross( &vPart, &m_vDown, &vCur );
m_qNow = m_qDown * D3DXQUATERNION( vPart.x, vPart.y, vPart.z,
D3DXVec3Dot( &m_vDown, &vCur ) );
}

D3DXQUATERNION qConj;
D3DXQuaternionConjugate( &qConj, &m_qNow );

D3DXMatrixRotationQuaternion( &m_matRotationDelta, &qConj );
D3DXMatrixTranspose( &m_matRotationDelta, &m_matRotationDelta );
D3DXMatrixMultiply( &m_matRotation, &m_matRotation, &m_matRotationDelta );

D3DXQuaternionIdentity( &m_qDown );
D3DXQuaternionIdentity( &m_qNow );
m_vDown = _ScreenToVector( ptCurrentMouse.x, ptCurrentMouse.y );
m_bDrag = TRUE;
}
else
{
// Normalize based on size of window and bounding sphere radius
FLOAT fDeltaX = ( ptLastMouse.x - ptCurrentMouse.x) * m_fRadius / m_rectClient.Width();
FLOAT fDeltaY = ( ptLastMouse.y - ptCurrentMouse.y) * m_fRadius / m_rectClient.Height();

if( TRUE )
{
D3DXMatrixTranslation( &m_matTranslationDelta, -2*fDeltaX, 2*fDeltaY, 0.0f );
D3DXMatrixMultiply( &m_matTranslation, &m_matTranslation, &m_matTranslationDelta );
}
else // wParam & MK_MBUTTON
{
D3DXMatrixTranslation( &m_matTranslationDelta, 0.0f, 0.0f, 5*fDeltaY );
D3DXMatrixMultiply( &m_matTranslation, &m_matTranslation, &m_matTranslationDelta );
}

// Store mouse coordinate
ptLastMouse = ptCurrentMouse;
}
}

void CGSD3DScreen::StopRotation(CPoint ptMousePoint)
{
m_qDown = m_qNow;
m_bDrag = FALSE;
}

void CGSD3DScreen::SetLight(BOOL fTurnOn)
{
if (fTurnOn)
{
m_pD3DDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_XRGB(255, 255, 255) );
}
else
{
m_pD3DDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_XRGB(55, 55, 55) );
}
}

void CGSD3DScreen::StartScale(CPoint ptMousePoint)
{
}

void CGSD3DScreen::StopScale(CPoint ptMousePoint)
{
}

void CGSD3DScreen::SetScale(CPoint ptMousePoint)
{
}

他的:
extern CMy3dXVView *g_3dView;

//-----------------------------------------------------------------------------
// Name: FullScreenWndProc()
// Desc: The WndProc funtion used when the app is in fullscreen mode. This is
// needed simply to trap the ESC key.
//-----------------------------------------------------------------------------
LRESULT CALLBACK FullScreenWndProc( HWND hWnd, UINT msg, WPARAM wParam,
LPARAM lParam )
{
if( msg == WM_CLOSE )
{
CWnd* pWnd=AfxGetMainWnd();
pWnd->PostMessage( WM_CLOSE, 0, 0 );

// User wants to exit, so go back to windowed mode and exit for real
//g_AppFormView->GoWindowed();
//g_D3DApp.GetMainWnd()->PostMessage( WM_CLOSE, 0, 0 );
}

if( msg == WM_SETCURSOR )
{
SetCursor( NULL );
}

if( msg == WM_KEYUP && wParam == VK_ESCAPE )
{
g_3dView->GoWindow();
// User wants to leave fullscreen mode
//g_AppFormView->GoWindowed();
}

if( g_bReady )
{
g_3dView->Render3DEnvironment();
}

g_3dView->FullScrKeyDown();

return DefWindowProc( hWnd, msg, wParam, lParam );
}

/////////////////////////////////////////////////////////////////////////////
// CMy3dXVView

IMPLEMENT_DYNCREATE(CMy3dXVView, CFormView)

BEGIN_MESSAGE_MAP(CMy3dXVView, CFormView)
//{{AFX_MSG_MAP(CMy3dXVView)
ON_WM_DESTROY()
ON_BN_CLICKED(IDC_CULL, OnCull)
ON_BN_CLICKED(IDC_WIRE, OnWire)
ON_BN_CLICKED(IDC_FLAT, OnFlat)
ON_WM_HSCROLL()
ON_EN_KILLFOCUS(IDC_EDIT_X, OnKillfocusEditX)
ON_EN_KILLFOCUS(IDC_EDIT_Y, OnKillfocusEditY)
ON_EN_KILLFOCUS(IDC_EDIT_Z, OnKillfocusEditZ)
ON_BN_CLICKED(IDC_BUTTON_XDOWN, OnButtonXdown)
ON_BN_CLICKED(IDC_BUTTON_XUP, OnButtonXup)
ON_BN_CLICKED(IDC_BUTTON_YDOWN, OnButtonYdown)
ON_BN_CLICKED(IDC_BUTTON_YUP, OnButtonYup)
ON_BN_CLICKED(IDC_BUTTON_ZDOWN, OnButtonZdown)
ON_BN_CLICKED(IDC_BUTTON_ZUP, OnButtonZup)
ON_BN_CLICKED(IDC_BUTTON_RESET, OnButtonReset)
ON_BN_CLICKED(IDC_FPS_CHECK, OnFpsCheck)
ON_EN_KILLFOCUS(IDC_FPS_EDIT, OnKillfocusFpsEdit)
ON_BN_CLICKED(IDC_BUTTON_FULLSCR, OnButtonFullscr)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMy3dXVView construction/destruction

CMy3dXVView::CMy3dXVView()
: CFormView(CMy3dXVView::IDD)
{
//{{AFX_DATA_INIT(CMy3dXVView)
//}}AFX_DATA_INIT
// TODO: add construction code here
g_3dView = this;
g_pDD = NULL;
g_pddsPrimary = NULL;
g_pddsBackBuffer = NULL;
g_pddsZBuffer = NULL; // Z-buffer surface
g_pD3D = NULL;
g_pd3dDevice = NULL;
//
m_pFileObject = NULL;
m_fObjectRadius = 0.0f;
m_fEyeDistance = 0.0f;
m_bCull = TRUE;
m_bFlat = FALSE;
m_bWire = FALSE;
m_fLMouseCapture = FALSE;
//
m_fXAxisAngle = 0.0f;
m_fYAxisAngle = 0.0f;
m_fXViewAngle = 0.0f;
m_fYViewAngle = 0.0f;
//
m_fModel_X = 0.0f;
m_fModel_Y = 0.0f;
m_fModel_Z = 0.0f;
//
m_IsWindow = TRUE;
}

CMy3dXVView::~CMy3dXVView()
{
}

void CMy3dXVView::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CMy3dXVView)
//}}AFX_DATA_MAP
}

BOOL CMy3dXVView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs

return CFormView::PreCreateWindow(cs);
}

void CMy3dXVView::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
GetParentFrame()->RecalcLayout();
ResizeParentToFit();
static BOOL firstTime = TRUE;
HRESULT r;
if(firstTime)
{
r = InitDirectX();
if( r==S_OK )
firstTime = FALSE;
else
PostMessage( WM_CLOSE );
}
//
((CButton*)GetDlgItem(IDC_FPS_CHECK))->SetCheck(g_FPS);
GetDlgItem(IDC_FPS_EDIT)->EnableWindow(g_FPS);
char msg[80];
sprintf(msg, "%d", g_FpsMax);
GetDlgItem(IDC_FPS_EDIT)->SetWindowText(msg);
//
m_bCull = TRUE;
m_bFlat = FALSE;
m_bWire = FALSE;
((CButton*)GetDlgItem(IDC_CULL))->SetCheck(m_bCull);
((CButton*)GetDlgItem(IDC_FLAT))->SetCheck(!m_bFlat);
((CButton*)GetDlgItem(IDC_WIRE))->SetCheck(m_bWire);
//
m_DirectionalLight = 1.0f;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_DLIGHT ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_DLIGHT ))->SetPos((int)(m_DirectionalLight*100));
m_AmbientLight = 0.0f;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_ALIGHT ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_ALIGHT ))->SetPos((int)(m_AmbientLight*100));
SetupLight();
//
m_fModel_X = 0.0f;
m_fModel_Y = 0.0f;
m_fModel_Z = 0.0f;
char buf[80];
sprintf(buf, "%7.2f", m_fModel_X);
GetDlgItem(IDC_EDIT_X)->SetWindowText(buf);
sprintf(buf, "%7.2f", m_fModel_Y);
GetDlgItem(IDC_EDIT_Y)->SetWindowText(buf);
sprintf(buf, "%7.2f", m_fModel_Z);
GetDlgItem(IDC_EDIT_Z)->SetWindowText(buf);
// 模块的转角
m_fXAxisAngle = 0.0f;
m_fYAxisAngle = 0.0f;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MX ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MX ))->SetPos(50);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MY ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MY ))->SetPos(50);
//Camera转角
m_fXViewAngle = 0.0f;
m_fYViewAngle = 0.0f;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CX ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CX ))->SetPos(50);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CY ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CY ))->SetPos(50);
//Camera距离
m_fEyeDistance = 0.0f;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CD ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CD ))->SetPos(30);

// Register a class for a fullscreen window
WNDCLASS wndClass = { CS_HREDRAW | CS_VREDRAW, FullScreenWndProc, 0, 0, NULL,
NULL, NULL, (HBRUSH)GetStockObject(WHITE_BRUSH), NULL,
TEXT("Fullscreen Window") };
RegisterClass( &wndClass );


}

/////////////////////////////////////////////////////////////////////////////
// CMy3dXVView diagnostics

#ifdef _DEBUG
void CMy3dXVView::AssertValid() const
{
CFormView::AssertValid();
}

void CMy3dXVView::Dump(CDumpContext& dc) const
{
CFormView::Dump(dc);
}

CMy3dXVDoc* CMy3dXVView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMy3dXVDoc)));
return (CMy3dXVDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMy3dXVView message handlers

BOOL CMy3dXVView::InitDirectX()
{
// 初始化Direct3D
// Cleanup any objects that might've been created before
if( FAILED( Cleanup3DEnvironment() ) )
return E_FAIL;

HWND hWnd;
m_hwndRenderWindow = GetDlgItem(IDC_FRAMEVIEW)->GetSafeHwnd();
hWnd = m_hwndRenderWindow;

// Create the D3D environment, at first, trying the HAL
if( SUCCEEDED( Initialize3DEnvironment( hWnd, NULL,
&IID_IDirect3DHALDevice ) ) )
return S_OK;

MessageBox( "使用硬件加速失败!\n现在尝试使用软件模式", "警告!", MB_OK|MB_ICONWARNING );
// Else, cleanup objects potentially created during the failed
// initialization attempt.
Cleanup3DEnvironment();

if( SUCCEEDED( Initialize3DEnvironment( hWnd, NULL,
&IID_IDirect3DRGBDevice ) ) )
return S_OK;

MessageBox( "尝试使用软件模式失败\n程序将退出", "错误!", MB_OK|MB_ICONERROR );
// Else, return failure. This simple tutorial will exit ungracefully.
return E_FAIL;
}

HRESULT CMy3dXVView::App_InitDeviceObjects(LPDIRECT3DDEVICE7 pd3dDevice)
{
// Setup a material
D3DMATERIAL7 mtrl;
D3DUtil_InitMaterial( mtrl, 1.0f, 1.0f, 1.0f );
g_pd3dDevice->SetMaterial( &mtrl );

// Setup the textures
D3DTextr_RestoreAllTextures( g_pd3dDevice );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTFN_LINEAR );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTFG_LINEAR );
g_pd3dDevice->SetRenderState( D3DRENDERSTATE_DITHERENABLE, TRUE );
g_pd3dDevice->SetRenderState( D3DRENDERSTATE_SPECULARENABLE, FALSE );
g_pd3dDevice->SetRenderState( D3DRENDERSTATE_ZENABLE, TRUE );
g_pd3dDevice->SetRenderState( D3DRENDERSTATE_NORMALIZENORMALS, TRUE );

// Set the projection matrix
D3DVIEWPORT7 vp;
g_pd3dDevice->GetViewport(&vp);
FLOAT fAspect = ((FLOAT)vp.dwHeight) / vp.dwWidth;

D3DMATRIX matProj;
D3DUtil_SetProjectionMatrix( matProj, g_PI/4, fAspect, 1.0f, m_fEyeDistance*10 );
g_pd3dDevice->SetTransform( D3DTRANSFORMSTATE_PROJECTION, &matProj );

// Set up the light
D3DLIGHT7 light;
D3DUtil_InitLight( light, D3DLIGHT_DIRECTIONAL, 0.0f, -2.0f, -2.0f );
g_pd3dDevice->SetLight( 0, &light );
g_pd3dDevice->LightEnable( 0, TRUE );
g_pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, TRUE );
g_pd3dDevice->SetRenderState( D3DRENDERSTATE_AMBIENT, 0x00000000 ); //环境光

return S_OK;
}

HRESULT CMy3dXVView::Render3DEnvironment()
{
// Call the app specific function to framemove (animate) the scene
App_FrameMove( g_pd3dDevice, ((FLOAT)clock())/CLOCKS_PER_SEC );

// Call the app specific function to render the scene
App_Render( g_pd3dDevice );

// Show the frame on the primary surface. Note: this is the best place to
// check for "lost" surfaces. Surfaces can be lost if something caused
// them to temporary lose their video memory. "Lost" surfaces simply
// need to be restored before continuing.
// 将帧显示到主表面。注意:这里是检测表面“丢失”的最好地方
if( DDERR_SURFACELOST == ShowFrame() )
RestoreSurfaces();

// Keep track of the frame rate, and output it every 500 milliseconds to
// the appropiate UI control.
static DWORD dwLastTime = 0;
static DWORD dwNumFrames = 0;
dwNumFrames++;

if( GetTickCount()-dwLastTime > 500 )
{
FLOAT fFPS = dwNumFrames*1000.0f/( GetTickCount() - dwLastTime );
dwLastTime = GetTickCount();
dwNumFrames=0;;
CHAR buffer[20];
sprintf(buffer,"%4.1f fps", fFPS );
GetDlgItem(IDC_FPS_TEXT)->SetWindowText(buffer);
// 控制刷新率
int FPS, d;
FPS = (int)fFPS;
d = (FPS-g_FpsMax)/2;
if( abs(d)>20 )
d = d/abs(d)*20;
g_FpsSec += d;
if( g_FpsSec > 1000)
g_FpsSec = 1000;
if( g_FpsSec < 1 )
g_FpsSec = 1;
}

return S_OK;
}

HRESULT CMy3dXVView::App_FrameMove(LPDIRECT3DDEVICE7 pd3dDevice, FLOAT fTimeKey)
{
// Set the object's world matrix
// g_pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &m_matRotate );

// Adjust the camera position
D3DVECTOR vEyePt = D3DVECTOR( 0.0f, 0.0f, 0.0f );
D3DVECTOR vLookatPt = D3DVECTOR( 0.0f, 0.0f, 0.0f );
D3DVECTOR vUpVec = D3DVECTOR( 0.0f, 1.0f, 0.0f );
FLOAT r;
//vEyePt.z += m_fObjectRadius*3.0f + m_fObjectRadius*m_fEyeDistance;
r = m_fObjectRadius*3.0f + m_fObjectRadius*m_fEyeDistance;
//Camena的位置
m_fYViewAngle = m_fYViewAngle>3.14159f/2 ? 3.14159f/2 : m_fYViewAngle;
m_fYViewAngle = m_fYViewAngle<-3.14159f/2 ? -3.14159f/2 : m_fYViewAngle;
vEyePt.z = r;
D3DMATRIX mX,mY;
D3DUtil_SetRotateYMatrix( mX, -m_fXViewAngle );
D3DUtil_SetRotateXMatrix( mY, m_fYViewAngle );
D3DMath_MatrixMultiply( m_matRotate, mY, mX );
UserUtil_xyz( m_matRotate, vEyePt.x, vEyePt.y, vEyePt.z );

// Set the view matrix
D3DMATRIX matView;
D3DUtil_SetViewMatrix( matView, vEyePt, vLookatPt, vUpVec );
g_pd3dDevice->SetTransform( D3DTRANSFORMSTATE_VIEW, &matView );

// Just for kicks, demonstrate the feature to find a frame and animate it.
// Here, if the user loads a file with a frame named "prop" (such as
// "triplane.x"), this code will find the matrix for that frame and
// animate it.
if( m_pFileObject )
{
CD3DFileObject* pObject = m_pFileObject->FindObject( "prop" );
if( pObject )
{
D3DMATRIX* pmat = pObject->GetMatrix();
D3DUtil_SetRotateZMatrix( *pmat, 5.0f*fTimeKey );
}
}

return S_OK;
}

HRESULT CMy3dXVView::App_Render(LPDIRECT3DDEVICE7 pd3dDevice)
{

// Clear the viewport
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
0x00009900, 1.0f, 0L );
//g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET,
// 0x00009900, 1.0f, 0L );

DWORD dwCullMode = m_bCull ? D3DCULL_CCW : D3DCULL_NONE;
DWORD dwShadeMode = m_bFlat ? D3DSHADE_FLAT : D3DSHADE_GOURAUD;
DWORD dwFillMode = m_bWire ? D3DFILL_WIREFRAME : D3DFILL_SOLID;
g_pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, dwCullMode );
g_pd3dDevice->SetRenderState( D3DRENDERSTATE_SHADEMODE, dwShadeMode );
g_pd3dDevice->SetRenderState( D3DRENDERSTATE_FILLMODE, dwFillMode );

// Begin the scene
D3DMATRIX matWorld, matSpinX, matSpinY;

if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{
if( m_pFileObject )
{
D3DUtil_SetRotateYMatrix( matSpinX, -m_fXAxisAngle ); //绕Y轴旋转矩阵
D3DUtil_SetRotateXMatrix( matSpinY, m_fYAxisAngle ); //绕X轴旋转矩阵
D3DUtil_SetTranslateMatrix( matWorld, m_fModel_X, m_fModel_Y, m_fModel_Z ); //平移矩阵
D3DMath_MatrixMultiply( matWorld, matSpinY, matWorld ); //混合两个矩阵
D3DMath_MatrixMultiply( matWorld, matSpinX, matWorld ); //混合两个矩阵
g_pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matWorld ); //移动
m_pFileObject->Render( g_pd3dDevice );
}

// End the scene.
g_pd3dDevice->EndScene();
//char msg[80];
//sprintf( msg, "模型半径%7.02f", m_fObjectRadius );
//OutputText( 5, 15, msg );
}

return S_OK;
}

HRESULT CMy3dXVView::RestoreSurfaces()
{
// Check/restore the primary surface
if( g_pddsPrimary )
if( g_pddsPrimary->IsLost() )
g_pddsPrimary->Restore();

// Check/restore the back buffer
if( g_pddsBackBuffer )
if( g_pddsBackBuffer->IsLost() )
g_pddsBackBuffer->Restore();

// Check/restore the z-buffer
if( g_pddsZBuffer )
if( g_pddsZBuffer->IsLost() )
g_pddsZBuffer->Restore();

return S_OK;
}

HRESULT CMy3dXVView::ShowFrame()
{
HRESULT hr;
if( NULL == g_pddsPrimary )
return E_FAIL;

if( m_IsWindow )
hr = g_pddsPrimary->Blt( &g_rcScreenRect, g_pddsBackBuffer,
NULL, DDBLT_WAIT, NULL );
else
hr = g_pddsPrimary->Flip( NULL, DDFLIP_WAIT );

return hr;
}

void CMy3dXVView::OnDestroy()
{
CFormView::OnDestroy();

// TODO: Add your message handler code here
Cleanup3DEnvironment();
}

VOID CMy3dXVView::App_DeleteDeviceObjects(LPDIRECT3DDEVICE7 pd3dDevice)
{
DeleteDeviceObjects();
// Release the material that was created earlier.
if( g_pmtrlObjectMtrl )
g_pmtrlObjectMtrl->Release();
g_pmtrlObjectMtrl = NULL;
}

void CMy3dXVView::WindowMove()
{
m_hwndRenderWindow = GetDlgItem(IDC_FRAMEVIEW)->GetSafeHwnd();
::GetClientRect( m_hwndRenderWindow, &g_rcScreenRect );
::ClientToScreen( m_hwndRenderWindow, (POINT*)&g_rcScreenRect.left );
::ClientToScreen( m_hwndRenderWindow, (POINT*)&g_rcScreenRect.right );
}

HRESULT CMy3dXVView::LoadFile( LPCTSTR lpszPathName )
{
CD3DFile* pFileObject = new CD3DFile();
if( FAILED( pFileObject->Load( (TCHAR*)lpszPathName ) ) )
{
char error[512];
strcpy(error, "不能打开指定的X文件\n");
strcat(error, lpszPathName);
MessageBox( error,
TEXT("错误!"), MB_OK|MB_ICONERROR );
g_bReady = FALSE;
return E_FAIL;
}

// If the file was successfully loaded, delete the old one and use this one
// instead.
SAFE_DELETE( m_pFileObject );
m_pFileObject = pFileObject;

// Get the new object position and size
m_fObjectRadius = 0.0f;
m_pFileObject->EnumObjects( CalcFileObjectSizeCB, NULL, (VOID*)&m_fObjectRadius );
//显示模型半径
CHAR buffer[20];
sprintf(buffer,"%4.2f", m_fObjectRadius );
GetDlgItem(IDC_RADIUS_TEXT)->SetWindowText(buffer);

// Set the projection matrix
D3DVIEWPORT7 vp;
g_pd3dDevice->GetViewport(&vp);
FLOAT fAspect = ((FLOAT)vp.dwHeight) / vp.dwWidth;

D3DMATRIX matProj;
D3DUtil_SetProjectionMatrix( matProj, g_PI/4, fAspect, 1.0f, m_fObjectRadius*10 );
g_pd3dDevice->SetTransform( D3DTRANSFORMSTATE_PROJECTION, &matProj );

// Restore the textures (if there's a device).
D3DTextr_RestoreAllTextures( g_pd3dDevice );

// Return successful
return S_OK;
}


HRESULT CMy3dXVView::Cleanup3DEnvironment()
{
// Cleanup any objects created for the scene
App_DeleteDeviceObjects( g_pd3dDevice );
FinalCleanup();

// Release the DDraw and D3D objects used by the app
if( g_pddsZBuffer ) g_pddsZBuffer->Release();
if( g_pD3D ) g_pD3D->Release();
if( g_pddsBackBuffer ) g_pddsBackBuffer->Release();
if( g_pddsPrimary ) g_pddsPrimary->Release();

// Do a safe check for releasing the D3DDEVICE. RefCount should be zero.
if( g_pd3dDevice )
if( 0 < g_pd3dDevice->Release() )
return E_FAIL;

// Do a safe check for releasing DDRAW. RefCount should be zero.
if( g_pDD )
if( 0 < g_pDD->Release() )
return E_FAIL;

g_pd3dDevice = NULL;
g_pD3D = NULL;
g_pddsBackBuffer = NULL;
g_pddsZBuffer = NULL;
g_pddsPrimary = NULL;
g_pDD = NULL;

return S_OK;
}

HRESULT CMy3dXVView::DeleteDeviceObjects()
{
D3DTextr_InvalidateAllTextures();

return S_OK;
}

HRESULT CMy3dXVView::FinalCleanup()
{
SAFE_DELETE( m_pFileObject );
//D3DTextr_DestroyTexture( "lake.bmp" );

return S_OK;
}

void CMy3dXVView::UserUtil_xyz(D3DMATRIX &m, FLOAT &x, FLOAT &y, FLOAT &z)
{
FLOAT x1, y1, z1;
x1 = m._11*x+m._21*y+m._31*z+m._41*1;
y1 = m._12*x+m._22*y+m._32*z+m._42*1;
z1 = m._13*x+m._23*y+m._33*z+m._43*1;
x = x1;
y = y1;
z = z1;
}

HRESULT CMy3dXVView::Initialize3DEnvironment(HWND hWnd, GUID *pDriverGUID, const GUID *pDeviceGUID)
{
HRESULT hr;

hr = DirectDrawCreateEx( pDriverGUID, (VOID**)&g_pDD, IID_IDirectDraw7,
NULL );
if( FAILED( hr ) )
return hr;

hr = g_pDD->SetCooperativeLevel( hWnd, DDSCL_NORMAL );
if( FAILED( hr ) )
return hr;

DDSURFACEDESC2 ddsd;
ZeroMemory( &ddsd, sizeof(DDSURFACEDESC2) );
ddsd.dwSize = sizeof(DDSURFACEDESC2);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

// Create the primary surface.
hr = g_pDD->CreateSurface( &ddsd, &g_pddsPrimary, NULL );
if( FAILED( hr ) )
return hr;

ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;

// Set the dimensions of the backbuffer. Note that if our window changes
// size, we need to destroy this surface and create a new one.
::GetClientRect( hWnd, &g_rcScreenRect );
::ClientToScreen( hWnd, (POINT*)&g_rcScreenRect.left );
::ClientToScreen( hWnd, (POINT*)&g_rcScreenRect.right );
ddsd.dwWidth = g_rcScreenRect.right - g_rcScreenRect.left;
ddsd.dwHeight = g_rcScreenRect.bottom - g_rcScreenRect.top;

// Create the backbuffer. The most likely reason for failure is running
// out of video memory. (A more sophisticated app should handle this.)
hr = g_pDD->CreateSurface( &ddsd, &g_pddsBackBuffer, NULL );
if( FAILED( hr ) )
return hr;

// Note: if using a z-buffer, the zbuffer surface creation would go around
// here. However, z-buffer usage is the topic of a subsequent tutorial.

// Create a clipper object which handles all our clipping for cases when
// our window is partially obscured by other windows. This is not needed
// for apps running in fullscreen mode.
LPDIRECTDRAWCLIPPER pcClipper;
hr = g_pDD->CreateClipper( 0, &pcClipper, NULL );
if( FAILED( hr ) )
return hr;

// Associate the clipper with our window. Note that, afterwards, the
// clipper is internally referenced by the primary surface, so it is safe
// to release our local reference to it.
pcClipper->SetHWnd( 0, hWnd );
g_pddsPrimary->SetClipper( pcClipper );
pcClipper->Release();

// Query DirectDraw for access to Direct3D
g_pDD->QueryInterface( IID_IDirect3D7, (VOID**)&g_pD3D );
if( FAILED( hr) )
return hr;

//-------------------------------------------------------------------------
// Create the z-buffer AFTER creating the backbuffer and BEFORE creating
// the d3ddevice.
//
// Note: before creating the z-buffer, apps may want to check the device
// caps for the D3DPRASTERCAPS_ZBUFFERLESSHSR flag. This flag is true for
// certain hardware that can do HSR (hidden-surface-removal) without a
// z-buffer. For those devices, there is no need to create a z-buffer.
//-------------------------------------------------------------------------

DDPIXELFORMAT ddpfZBuffer;
g_pD3D->EnumZBufferFormats( *pDeviceGUID,
EnumZBufferCallback, (VOID*)&ddpfZBuffer );

// If we found a good zbuffer format, then the dwSize field will be
// properly set during enumeration. Else, we have a problem and will exit.
if( sizeof(DDPIXELFORMAT) != ddpfZBuffer.dwSize )
return E_FAIL;

// Get z-buffer dimensions from the render target
// Setup the surface desc for the z-buffer.
ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
ddsd.dwWidth = g_rcScreenRect.right - g_rcScreenRect.left;
ddsd.dwHeight = g_rcScreenRect.bottom - g_rcScreenRect.top;
memcpy( &ddsd.ddpfPixelFormat, &ddpfZBuffer, sizeof(DDPIXELFORMAT) );

// For hardware devices, the z-buffer should be in video memory. For
// software devices, create the z-buffer in system memory
if( IsEqualIID( *pDeviceGUID, IID_IDirect3DHALDevice ) )
ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
else
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;

// Create and attach a z-buffer. Real apps should be able to handle an
// error here (DDERR_OUTOFVIDEOMEMORY may be encountered). For this
// tutorial, though, we are simply going to exit ungracefully.
if( FAILED( hr = g_pDD->CreateSurface( &ddsd, &g_pddsZBuffer, NULL ) ) )
return hr;

// Attach the z-buffer to the back buffer.
if( FAILED( hr = g_pddsBackBuffer->AddAttachedSurface( g_pddsZBuffer ) ) )
return hr;

//-------------------------------------------------------------------------
// End of z-buffer creation code.
//
// Before rendering, don't forget to enable the z-buffer with the
// appropiate D3DRENDERSTATE's.
//-------------------------------------------------------------------------

// Before creating the device, check that we are NOT in a palettized
// display. That case will cause CreateDevice() to fail, since this simple
// tutorial does not bother with palettes.
ddsd.dwSize = sizeof(DDSURFACEDESC2);
g_pDD->GetDisplayMode( &ddsd );
if( ddsd.ddpfPixelFormat.dwRGBBitCount <= 8 )
return DDERR_INVALIDMODE;

// Create the device. The device is created off of our back buffer, which
// becomes the render target for the newly created device. Note that the
// z-buffer must be created BEFORE the device

if( FAILED( hr = g_pD3D->CreateDevice( *pDeviceGUID, g_pddsBackBuffer,
&g_pd3dDevice ) ) )
{
// This call could fail for many reasons. The most likely cause is
// that we specifically requested a hardware device, without knowing
// whether there is even a 3D card installed in the system. Another
// possibility is the hardware is incompatible with the current display
// mode (the correct implementation would use enumeration for this.)
return hr;
}

// Create the viewport
DWORD dwRenderWidth = g_rcScreenRect.right - g_rcScreenRect.left;
DWORD dwRenderHeight = g_rcScreenRect.bottom - g_rcScreenRect.top;
D3DVIEWPORT7 vp = { 0, 0, dwRenderWidth, dwRenderHeight, 0.0f, 1.0f };
hr = g_pd3dDevice->SetViewport( &vp );
if( FAILED( hr ) )
return hr;

// Finish by setting up our scene
return App_InitDeviceObjects( g_pd3dDevice );
}


void CMy3dXVView::OnCull()
{
// TODO: Add your control notification handler code here
m_bCull = ((CButton*)GetDlgItem(IDC_CULL))->GetCheck();
}

void CMy3dXVView::OnWire()
{
// TODO: Add your control notification handler code here
m_bWire = ((CButton*)GetDlgItem(IDC_WIRE))->GetCheck();
}

void CMy3dXVView::OnFlat()
{
// TODO: Add your control notification handler code here
m_bFlat = !((CButton*)GetDlgItem(IDC_FLAT))->GetCheck();
}

void CMy3dXVView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
// 灯光亮度
m_AmbientLight = ((CSliderCtrl*)GetDlgItem(IDC_SLIDER_ALIGHT))->GetPos()/100.0f;
m_DirectionalLight = ((CSliderCtrl*)GetDlgItem(IDC_SLIDER_DLIGHT))->GetPos()/100.0f;
SetupLight();
// 模型绕轴的转角
int pos;
pos = ((CSliderCtrl*)GetDlgItem(IDC_SLIDER_MX))->GetPos()-50;
m_fXAxisAngle = pos*2*g_PI/50;
pos = ((CSliderCtrl*)GetDlgItem(IDC_SLIDER_MY))->GetPos()-50;
m_fYAxisAngle = pos*2*g_PI/50;
// Camera绕轴的转角
pos = ((CSliderCtrl*)GetDlgItem(IDC_SLIDER_CX))->GetPos()-50;
m_fXViewAngle = pos*2*g_PI/50;
pos = ((CSliderCtrl*)GetDlgItem(IDC_SLIDER_CY))->GetPos()-50;
m_fYViewAngle = pos*g_PI/100;
// Camera到原点的距离
pos = ((CSliderCtrl*)GetDlgItem(IDC_SLIDER_CD))->GetPos()-30;
m_fEyeDistance = (FLOAT)pos/10.0f;


CFormView::OnHScroll(nSBCode, nPos, pScrollBar);
}

void CMy3dXVView::SetupLight()
{
// Set up the light
// 直射光
D3DLIGHT7 light;
D3DUtil_InitLight( light, D3DLIGHT_DIRECTIONAL, 0.0f, -2.0f, -2.0f );
light.dcvDiffuse.r = m_DirectionalLight;
light.dcvDiffuse.g = m_DirectionalLight;
light.dcvDiffuse.b = m_DirectionalLight;
g_pd3dDevice->SetLight( 0, &light );
// 环境光
DWORD Ambient;
Ambient = (DWORD)(255*m_AmbientLight);
Ambient <<= 8;
Ambient += (DWORD)(255*m_AmbientLight);
Ambient <<= 8;
Ambient += (DWORD)(255*m_AmbientLight);
g_pd3dDevice->SetRenderState( D3DRENDERSTATE_AMBIENT, Ambient ); //环境光
}

void CMy3dXVView::OnKillfocusEditX()
{
// TODO: Add your control notification handler code here
CString buffer;
GetDlgItem(IDC_EDIT_X)->GetWindowText(buffer);
m_fModel_X = (float)atof( buffer );
char x[80];
sprintf(x, "%7.2f", m_fModel_X);
GetDlgItem(IDC_EDIT_X)->SetWindowText(x);
}

void CMy3dXVView::OnKillfocusEditY()
{
// TODO: Add your control notification handler code here
CString buffer;
GetDlgItem(IDC_EDIT_Y)->GetWindowText(buffer);
m_fModel_Y = (float)atof( buffer );
char y[80];
sprintf(y, "%7.2f", m_fModel_Y);
GetDlgItem(IDC_EDIT_Y)->SetWindowText(y);
}

void CMy3dXVView::OnKillfocusEditZ()
{
// TODO: Add your control notification handler code here
CString buffer;
GetDlgItem(IDC_EDIT_Z)->GetWindowText(buffer);
m_fModel_Z = (float)atof( buffer );
char z[80];
sprintf(z, "%7.2f", m_fModel_Z);
GetDlgItem(IDC_EDIT_Z)->SetWindowText(z);
}

void CMy3dXVView::OnButtonXdown()
{
// TODO: Add your control notification handler code here
m_fModel_X -= (FLOAT)fabs(m_fEyeDistance*m_fObjectRadius+m_fObjectRadius)/10.0f;
// 更新坐标显示
char buf[80];
sprintf(buf, "%7.2f", m_fModel_X);
GetDlgItem(IDC_EDIT_X)->SetWindowText(buf);
}

void CMy3dXVView::OnButtonXup()
{
// TODO: Add your control notification handler code here
m_fModel_X += (FLOAT)fabs(m_fEyeDistance*m_fObjectRadius+m_fObjectRadius)/10.0f;
// 更新坐标显示
char buf[80];
sprintf(buf, "%7.2f", m_fModel_X);
GetDlgItem(IDC_EDIT_X)->SetWindowText(buf);
}

void CMy3dXVView::OnButtonYdown()
{
// TODO: Add your control notification handler code here
m_fModel_Y -= (FLOAT)fabs(m_fEyeDistance*m_fObjectRadius+m_fObjectRadius)/10.0f;
// 更新坐标显示
char buf[80];
sprintf(buf, "%7.2f", m_fModel_Y);
GetDlgItem(IDC_EDIT_Y)->SetWindowText(buf);
}

void CMy3dXVView::OnButtonYup()
{
// TODO: Add your control notification handler code here
m_fModel_Y += (FLOAT)fabs(m_fEyeDistance*m_fObjectRadius+m_fObjectRadius)/10.0f;
char buf[80];
sprintf(buf, "%7.2f", m_fModel_Y);
GetDlgItem(IDC_EDIT_Y)->SetWindowText(buf);
}

void CMy3dXVView::OnButtonZdown()
{
// TODO: Add your control notification handler code here
m_fModel_Z -= (FLOAT)fabs(m_fEyeDistance*m_fObjectRadius+m_fObjectRadius)/10.0f;
char buf[80];
sprintf(buf, "%7.2f", m_fModel_Z);
GetDlgItem(IDC_EDIT_Z)->SetWindowText(buf);
}

void CMy3dXVView::OnButtonZup()
{
// TODO: Add your control notification handler code here
m_fModel_Z += (FLOAT)fabs(m_fEyeDistance*m_fObjectRadius+m_fObjectRadius)/10.0f;
char buf[80];
sprintf(buf, "%7.2f", m_fModel_Z);
GetDlgItem(IDC_EDIT_Z)->SetWindowText(buf);
}


void CMy3dXVView::OnButtonReset()
{
// TODO: Add your control notification handler code here
//
m_bCull = TRUE;
m_bFlat = FALSE;
m_bWire = FALSE;
((CButton*)GetDlgItem(IDC_CULL))->SetCheck(m_bCull);
((CButton*)GetDlgItem(IDC_FLAT))->SetCheck(!m_bFlat);
((CButton*)GetDlgItem(IDC_WIRE))->SetCheck(m_bWire);
//
m_DirectionalLight = 1.0f;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_DLIGHT ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_DLIGHT ))->SetPos((int)(m_DirectionalLight*100));
m_AmbientLight = 0.0f;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_ALIGHT ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_ALIGHT ))->SetPos((int)(m_AmbientLight*100));
SetupLight();
//
m_fModel_X = 0.0f;
m_fModel_Y = 0.0f;
m_fModel_Z = 0.0f;
char buf[80];
sprintf(buf, "%7.2f", m_fModel_X);
GetDlgItem(IDC_EDIT_X)->SetWindowText(buf);
sprintf(buf, "%7.2f", m_fModel_Y);
GetDlgItem(IDC_EDIT_Y)->SetWindowText(buf);
sprintf(buf, "%7.2f", m_fModel_Z);
GetDlgItem(IDC_EDIT_Z)->SetWindowText(buf);
// 模块的转角
m_fXAxisAngle = 0.0f;
m_fYAxisAngle = 0.0f;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MX ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MX ))->SetPos(50);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MY ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MY ))->SetPos(50);
//Camera转角
m_fXViewAngle = 0.0f;
m_fYViewAngle = 0.0f;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CX ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CX ))->SetPos(50);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CY ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CY ))->SetPos(50);
//Camera距离
m_fEyeDistance = 0.0f;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CD ))->SetRange(0,100,TRUE);
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CD ))->SetPos(30);
}

void CMy3dXVView::Reset()
{
OnButtonReset();
}

void CMy3dXVView::OnFpsCheck()
{
// TODO: Add your control notification handler code here
g_FPS = ((CButton*)GetDlgItem(IDC_FPS_CHECK))->GetCheck();
GetDlgItem(IDC_FPS_EDIT)->EnableWindow(g_FPS);
char msg[80];
sprintf(msg, "%d", g_FpsMax);
GetDlgItem(IDC_FPS_EDIT)->SetWindowText(msg);
}

void CMy3dXVView::OnKillfocusFpsEdit()
{
// TODO: Add your control notification handler code here
CString buffer;
GetDlgItem(IDC_FPS_EDIT)->GetWindowText(buffer);
g_FpsMax = (UINT)atoi( buffer );
if(g_FpsMax == 0)
g_FpsMax = 1;
char x[80];
sprintf(x, "%d", g_FpsMax);
GetDlgItem(IDC_FPS_EDIT)->SetWindowText(x);
}

BOOL CMy3dXVView::KeyDown()
{
BOOL shift, ctrl;
shift = ctrl = FALSE;
BOOL left, right, up, down;
left = right = up = down = FALSE;
BOOL home, end;
home = end = FALSE;

if (GetAsyncKeyState(VK_RETURN))
{
// 取得Edit框中的值
OnKillfocusEditX();
OnKillfocusEditY();
OnKillfocusEditZ();
OnKillfocusFpsEdit();
}
if ( GetAsyncKeyState(VK_SHIFT) ) shift = TRUE;
if ( GetAsyncKeyState(VK_CONTROL) ) ctrl = TRUE;
if ( GetAsyncKeyState(VK_LEFT) ) left = TRUE;
if ( GetAsyncKeyState(VK_RIGHT) ) right = TRUE;
if ( GetAsyncKeyState(VK_UP) ) up = TRUE;
if ( GetAsyncKeyState(VK_DOWN) ) down = TRUE;
if ( GetAsyncKeyState(VK_HOME) ) home = TRUE;
if ( GetAsyncKeyState(VK_END) ) end = TRUE;

//转动模型
if ( ctrl && left )
{
GetDlgItem(IDC_FPS_EDIT)->SetFocus();
m_fXAxisAngle -= 0.03f;
if ( m_fXAxisAngle < -2*g_PI ) m_fXAxisAngle = 2*g_PI;
//
int pos;
pos = (int)(m_fXAxisAngle*50/2/g_PI)+50;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MX ))->SetPos(pos);
}
if ( ctrl && right )
{
GetDlgItem(IDC_FPS_EDIT)->SetFocus();
m_fXAxisAngle += 0.03f;
if ( m_fXAxisAngle > 2*g_PI ) m_fXAxisAngle = -2*g_PI;
//
int pos;
pos = (int)(m_fXAxisAngle*50/2/g_PI)+50;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MX ))->SetPos(pos);
}
if ( ctrl && up )
{
GetDlgItem(IDC_FPS_EDIT)->SetFocus();
m_fYAxisAngle -= 0.03f;
if ( m_fYAxisAngle < -2*g_PI ) m_fYAxisAngle = 2*g_PI;
//
int pos;
pos = (int)(m_fYAxisAngle*50/2/g_PI)+50;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MY ))->SetPos(pos);
}
if ( ctrl && down )
{
GetDlgItem(IDC_FPS_EDIT)->SetFocus();
m_fYAxisAngle += 0.03f;
if ( m_fYAxisAngle > 2*g_PI ) m_fYAxisAngle = -2*g_PI;
//
int pos;
pos = (int)(m_fYAxisAngle*50/2/g_PI)+50;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_MY ))->SetPos(pos);
}
// 移动Camera
if ( shift && left )
{
GetDlgItem(IDC_FPS_EDIT)->SetFocus();
m_fXViewAngle -= 0.03f;
if ( m_fXViewAngle < -2*g_PI ) m_fXViewAngle = 2*g_PI;
//
int pos;
pos = (int)(m_fXViewAngle*50/2/g_PI)+50;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CX ))->SetPos(pos);
}
if ( shift && right )
{
GetDlgItem(IDC_FPS_EDIT)->SetFocus();
m_fXViewAngle += 0.03f;
if ( m_fXViewAngle > 2*g_PI ) m_fXViewAngle = -2*g_PI;
//
int pos;
pos = (int)(m_fXViewAngle*50/2/g_PI)+50;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CX ))->SetPos(pos);
}
if ( shift && up )
{
GetDlgItem(IDC_FPS_EDIT)->SetFocus();
m_fYViewAngle -= 0.03f;
if ( m_fYViewAngle < -g_PI ) m_fYViewAngle = -g_PI;
//
int pos;
pos = (int)(m_fYViewAngle*100/g_PI)+50;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CY ))->SetPos(pos);
}
if ( shift && down )
{
GetDlgItem(IDC_FPS_EDIT)->SetFocus();
m_fYViewAngle += 0.03f;
if ( m_fYViewAngle > g_PI ) m_fYViewAngle = g_PI;
//
int pos;
pos = (int)(m_fYViewAngle*100/g_PI)+50;
((CSliderCtrl*)GetDlgItem( IDC_SLIDER_CY ))->SetPos(pos);
}
// Camera到原点的距离
if ( shift && home )
{
GetDlgItem(IDC_FPS_EDIT)->SetFocus();
m_fEyeDistance += 0.1f;
if( m_fEyeDistance > 7.0f ) m_fEyeDistance = 7.0f;
int pos;
pos = 30 + (int)(10.0f*m_fEyeDistance);
((CSliderCtrl*)GetDlgItem(IDC_SLIDER_CD))->SetPos(pos);
}
if ( shift && end )
{
GetDlgItem(IDC_FPS_EDIT)->SetFocus();
m_fEyeDistance -= 0.1f;
if( m_fEyeDistance < -3.0f ) m_fEyeDistance = -3.0f;
int pos;
pos = 30 + (int)(10.0f*m_fEyeDistance);
((CSliderCtrl*)GetDlgItem(IDC_SLIDER_CD))->SetPos(pos);
}

return TRUE;
}

BOOL CMy3dXVView::GoFullScreen()
{
// 创建一个全屏窗口
// Create a new fullscreen window
//RECT rc = { 0, 0, 100, 100 };
m_hwndFullScreen = CreateWindow( TEXT("Fullscreen Window"), NULL,
WS_POPUP|WS_VISIBLE, CW_USEDEFAULT,
CW_USEDEFAULT, 100, 100,
m_hwndRenderWindow, 0L, NULL, 0L );


if( m_hwndFullScreen == NULL )
{
AfxMessageBox( "CreateWindow failed" );
return FALSE;
}
m_IsWindow = FALSE; // 现在进入全屏幕
InitDirectXFullScreen();

return TRUE;

}

void CMy3dXVView::OnButtonFullscr()
{
// TODO: Add your control notification handler code here
g_bReady = FALSE;
GoFullScreen();
LoadFile( "teapot.x" );
g_bReady = TRUE;
}

BOOL CMy3dXVView::InitDirectXFullScreen()
{
// 初始化Direct3D,全屏幕模式
// Cleanup any objects that might've been created before
if( FAILED( Cleanup3DEnvironment() ) )
return E_FAIL;

// Create the D3D environment, at first, trying the HAL
if( SUCCEEDED( Initialize3DEnvFullScr( m_hwndFullScreen, NULL,
&IID_IDirect3DHALDevice ) ) )
return S_OK;

//MessageBox( "使用硬件加速失败!\n现在尝试使用软件模式", "警告!", MB_OK|MB_ICONWARNING );
// Else, cleanup objects potentially created during the failed
// initialization attempt.
Cleanup3DEnvironment();

if( SUCCEEDED( Initialize3DEnvFullScr( m_hwndFullScreen, NULL,
&IID_IDirect3DRGBDevice ) ) )
return S_OK;

//MessageBox( "尝试使用软件模式失败\n程序将退出", "错误!", MB_OK|MB_ICONERROR );
// Else, return failure. This simple tutorial will exit ungracefully.
return E_FAIL;
}

HRESULT CMy3dXVView::Initialize3DEnvFullScr(HWND hWnd, GUID *pDriverGUID, const GUID *pDeviceGUID)
{
HRESULT hr;

hr = DirectDrawCreateEx( pDriverGUID, (VOID**)&g_pDD, IID_IDirectDraw7,
NULL );
if( FAILED( hr ) )
return hr;

hr = g_pDD->SetCooperativeLevel( hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
if( FAILED( hr ) )
return hr;

// Initialize a surface description structure for the primary surface. The
// primary surface represents the entire display, with dimensions and a
// pixel format of the display. Therefore, none of that information needs
// to be specified in order to create the primary surface.

//
hr=g_pDD->SetDisplayMode(800, 600, 16, 0, 0);

if( FAILED( hr ) )
{
//DXError(r,"Create DirectX Surface failed\n请确定你已经安装了DirectX");
return hr;
}
// Create the primary surface.
DDSURFACEDESC2 ddsd;
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |
DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE;
ddsd.dwBackBufferCount = 1;

hr=g_pDD->CreateSurface(&ddsd, &g_pddsPrimary, 0);
if( FAILED( hr ) )
{
//DXError(r,"Create DirectX Surface failed\n请确定你已经安装了DirectX");
return hr;
}
//创建后台表面
DDSCAPS2 ddscaps = { DDSCAPS_BACKBUFFER, 0, 0, 0 };
hr =g_pddsPrimary->GetAttachedSurface(&ddscaps, &g_pddsBackBuffer);
if( FAILED( hr ) )
{
TRACE("Primary->GetAttachedSurface fialed\n");
return hr;
}
//
// Query DirectDraw for access to Direct3D
g_pDD->QueryInterface( IID_IDirect3D7, (VOID**)&g_pD3D );
if( FAILED( hr ) )
{
TRACE("QueryInterface D3D failed\n");
return hr;
}

//-------------------------------------------------------------------------
// Create the z-buffer AFTER creating the backbuffer and BEFORE creating
// the d3ddevice.
//
// Note: before creating the z-buffer, apps may want to check the device
// caps for the D3DPRASTERCAPS_ZBUFFERLESSHSR flag. This flag is true for
// certain hardware that can do HSR (hidden-surface-removal) without a
// z-buffer. For those devices, there is no need to create a z-buffer.
//-------------------------------------------------------------------------

DDPIXELFORMAT ddpfZBuffer;
g_pD3D->EnumZBufferFormats( *pDeviceGUID,
EnumZBufferCallback, (VOID*)&ddpfZBuffer );

// If we found a good zbuffer format, then the dwSize field will be
// properly set during enumeration. Else, we have a problem and will exit.
if( sizeof(DDPIXELFORMAT) != ddpfZBuffer.dwSize )
return E_FAIL;

// Get z-buffer dimensions from the render target
// Setup the surface desc for the z-buffer.
ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
ddsd.dwWidth = 800;
ddsd.dwHeight = 600;
memcpy( &ddsd.ddpfPixelFormat, &ddpfZBuffer, sizeof(DDPIXELFORMAT) );

// For hardware devices, the z-buffer should be in video memory. For
// software devices, create the z-buffer in system memory
if( IsEqualIID( *pDeviceGUID, IID_IDirect3DHALDevice ) )
ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
else
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;

// Create and attach a z-buffer. Real apps should be able to handle an
// error here (DDERR_OUTOFVIDEOMEMORY may be encountered). For this
// tutorial, though, we are simply going to exit ungracefully.
if( FAILED( hr = g_pDD->CreateSurface( &ddsd, &g_pddsZBuffer, NULL ) ) )
{
TRACE("Create ZBuffer failed");
return hr;
}

// Attach the z-buffer to the back buffer.
if( FAILED( hr = g_pddsBackBuffer->AddAttachedSurface( g_pddsZBuffer ) ) )
{
TRACE("BackBuffer->AddAttachedSurface failed\n");
return hr;
}

//-------------------------------------------------------------------------
// End of z-buffer creation code.
//
// Before rendering, don't forget to enable the z-buffer with the
// appropiate D3DRENDERSTATE's.
//-------------------------------------------------------------------------

// Before creating the device, check that we are NOT in a palettized
// display. That case will cause CreateDevice() to fail, since this simple
// tutorial does not bother with palettes.
ddsd.dwSize = sizeof(DDSURFACEDESC2);
g_pDD->GetDisplayMode( &ddsd );
if( ddsd.ddpfPixelFormat.dwRGBBitCount <= 8 )
return DDERR_INVALIDMODE;

// Create the device. The device is created off of our back buffer, which
// becomes the render target for the newly created device. Note that the
// z-buffer must be created BEFORE the device

if( FAILED( hr = g_pD3D->CreateDevice( *pDeviceGUID, g_pddsBackBuffer,
&g_pd3dDevice ) ) )
{
TRACE("D3D CreateDevice failed\n");
return hr;
}

// Create the viewport
DWORD dwRenderWidth = 800;
DWORD dwRenderHeight = 600;
D3DVIEWPORT7 vp = { 0, 0, dwRenderWidth, dwRenderHeight, 0.0f, 1.0f };
hr = g_pd3dDevice->SetViewport( &vp );
if( FAILED( hr ) )
return hr;

// Finish by setting up our scene
return App_InitDeviceObjects( g_pd3dDevice );
}

BOOL CMy3dXVView::FullScrKeyDown()
{
BOOL shift, ctrl;
shift = ctrl = FALSE;
BOOL left, right, up, down;
left = right = up = down = FALSE;
BOOL home, end;
home = end = FALSE;

if (GetAsyncKeyState(VK_RETURN))
{
// 取得Edit框中的值
OnKillfocusEditX();
OnKillfocusEditY();
OnKillfocusEditZ();
OnKillfocusFpsEdit();
}
if ( GetAsyncKeyState(VK_SHIFT) ) shift = TRUE;
if ( GetAsyncKeyState(VK_CONTROL) ) ctrl = TRUE;
if ( GetAsyncKeyState(VK_LEFT) ) left = TRUE;
if ( GetAsyncKeyState(VK_RIGHT) ) right = TRUE;
if ( GetAsyncKeyState(VK_UP) ) up = TRUE;
if ( GetAsyncKeyState(VK_DOWN) ) down = TRUE;
if ( GetAsyncKeyState(VK_HOME) ) home = TRUE;
if ( GetAsyncKeyState(VK_END) ) end = TRUE;

//转动模型
if ( ctrl && left )
{
m_fXAxisAngle -= 0.03f;
if ( m_fXAxisAngle < -2*g_PI ) m_fXAxisAngle = 2*g_PI;
//
int pos;
pos = (int)(m_fXAxisAngle*50/2/g_PI)+50;
}
if ( ctrl && right )
{
m_fXAxisAngle += 0.03f;
if ( m_fXAxisAngle > 2*g_PI ) m_fXAxisAngle = -2*g_PI;
//
int pos;
pos = (int)(m_fXAxisAngle*50/2/g_PI)+50;
}
if ( ctrl && up )
{
m_fYAxisAngle -= 0.03f;
if ( m_fYAxisAngle < -2*g_PI ) m_fYAxisAngle = 2*g_PI;
//
int pos;
pos = (int)(m_fYAxisAngle*50/2/g_PI)+50;
}
if ( ctrl && down )
{
m_fYAxisAngle += 0.03f;
if ( m_fYAxisAngle > 2*g_PI ) m_fYAxisAngle = -2*g_PI;
//
int pos;
pos = (int)(m_fYAxisAngle*50/2/g_PI)+50;
}
// 移动Camera
if ( shift && left )
{
m_fXViewAngle -= 0.03f;
if ( m_fXViewAngle < -2*g_PI ) m_fXViewAngle = 2*g_PI;
//
int pos;
pos = (int)(m_fXViewAngle*50/2/g_PI)+50;
}
if ( shift && right )
{
m_fXViewAngle += 0.03f;
if ( m_fXViewAngle > 2*g_PI ) m_fXViewAngle = -2*g_PI;
//
int pos;
pos = (int)(m_fXViewAngle*50/2/g_PI)+50;
}
if ( shift && up )
{
m_fYViewAngle -= 0.03f;
if ( m_fYViewAngle < -g_PI ) m_fYViewAngle = -g_PI;
//
int pos;
pos = (int)(m_fYViewAngle*100/g_PI)+50;
}
if ( shift && down )
{
m_fYViewAngle += 0.03f;
if ( m_fYViewAngle > g_PI ) m_fYViewAngle = g_PI;
//
int pos;
pos = (int)(m_fYViewAngle*100/g_PI)+50;
}
// Camera到原点的距离
if ( shift && home )
{
m_fEyeDistance += 0.1f;
if( m_fEyeDistance > 7.0f ) m_fEyeDistance = 7.0f;
int pos;
pos = 30 + (int)(10.0f*m_fEyeDistance);
}
if ( shift && end )
{
m_fEyeDistance -= 0.1f;
if( m_fEyeDistance < -3.0f ) m_fEyeDistance = -3.0f;
int pos;
pos = 30 + (int)(10.0f*m_fEyeDistance);
}

return TRUE;
}

BOOL CMy3dXVView::GoWindow()
{
g_bReady = FALSE;
// 初始化Direct3D
// Cleanup any objects that might've been created before
if( FAILED( Cleanup3DEnvironment() ) )
return E_FAIL;

HWND hWnd;
hWnd = m_hwndRenderWindow;

TRACE("GoWindow\n");
// Create the D3D environment, at first, trying the HAL
if( SUCCEEDED( Initialize3DEnvironment( hWnd, NULL,
&IID_IDirect3DHALDevice ) ) )
return S_OK;

// Else, cleanup objects potentially created during the failed
// initialization attempt.
Cleanup3DEnvironment();

if( SUCCEEDED( Initialize3DEnvironment( hWnd, NULL,
&IID_IDirect3DRGBDevice ) ) )
return S_OK;

LoadFile( "teapot.x" );
TRACE("DestroyWindow\n");
if( m_hwndFullScreen )
::DestroyWindow( m_hwndFullScreen );
TRACE("Destroied\n");

m_hwndFullScreen = NULL;
g_bReady = TRUE;

return TRUE;
}
包含 for 3DS MAX3 for 3DS MAX4 0 for 3DS MAX4 0+ CS3 1 for 3DS MAX4 2 CS3 2+ or MAX 5 0 for 3DS Max 6 0+ CS4 2 and 3DS Max 7 0 for 3DS Max 8 0 for 3DS Max 9 0 Panda Directx Exporter x64 5 9 67 0 for 3DS Max 9 64 bit Panda Directx Exporter x64 5 2008 67 0 for 3DS Max 2008 64 bit Panda Directx Exporter x64 5 2009 67 0 for 3DS Max 2009 64 bit Panda Directx Exporter x64 6 9 72 0 for 3DS Max 9 64 bit Panda Directx Exporter x64 6 2008 71 0 for 3DS Max 2008 64 bit Panda Directx Exporter x64 6 2009 72 0 for 3DS Max 2009 64 bit Panda Directx Exporter x64 6 2010 72 0 for 3DS Max 2010 64 bit Panda Directx Exporter x64 6 2011 72 0 for 3DS Max 2011 64 bit Panda Directx Exporter x64 6 2012 72 0 for 3DS Max 2012 64 bit Panda Directx Exporter x86 5 8 66 0 for 3DS Max 8 32 bit Panda Directx Exporter x86 5 9 67 0 for 3DS Max 9 32 bit Panda Directx Exporter x86 5 2008 67 0 for 3DS Max 2008 32 bit Panda Directx Exporter x86 5 2009 67 0 for 3DS Max 2009 32 bit Panda Directx Exporter x86 6 9 72 0 for 3DS Max 9 32 bit Panda Directx Exporter x86 6 2008 71 0 for 3DS Max 2008 32 bit Panda Directx Exporter x86 6 2009 72 0 for 3DS Max 2009 32 bit Panda Directx Exporter x86 6 2010 72 0 for 3DS Max 2010 32 bit Panda Directx Exporter x86 6 2011 72 0 for 3DS Max 2011 32 bit Panda Directx Exporter x86 6 2012 72 0 for 3DS Max 2012 32 bit ">包含 for 3DS MAX3 for 3DS MAX4 0 for 3DS MAX4 0+ CS3 1 for 3DS MAX4 2 CS3 2+ or MAX 5 0 for 3DS Max 6 0+ CS4 2 and 3DS Max 7 0 for 3DS Max 8 0 for 3DS Max 9 0 Panda Directx Exporter x64 5 9 67 0 for 3DS Max 9 64 bit Panda Directx Exporter x64 5 2008 67 0 for 3DS Max 2008 64 bit Panda Direc [更多]

8,303

社区成员

发帖
与我相关
我的任务
社区描述
游戏开发相关内容讨论专区
社区管理员
  • 游戏开发
  • 呆呆敲代码的小Y
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧