Passing 60.0f for the FOV to D3DXMatrixPerspectiveFovLH() gives you an upside-down scene
It took me about 45 minutes this morning to spot that bug. I was passing 60 degrees to a function that was expecting radians. I'm surprised it "worked" so well. Everything looked good, maybe the FOV was a little wide but I didn't notice that since I was only drawing 1 triangle. Oh yes, and it was flipped about the X axis...
In other news, 2d code is done (I think I said that before), and I'm working on 3D code now. I want to get some simple meshes working, which just spew out an indexed triangle list. I'm currently working on loading MD2 models for testing purposes.
I want to be able to add layers onto the model so I can add a bump map layer, a texture layer, a diffuse layer, etc. Should be pretty good if it all works.
I also like my vertex declaration class. I may as well post it in full here.
Header:
//==========================================================================// VetexDecl.h - Vertex declaration class//==========================================================================#ifndef __VERTEXDECL_H__#define __VERTEXDECL_H__#include #include struct IDirect3DVertexDeclaration9;class CVertexDecl{public: CVertexDecl(); ~CVertexDecl(); void Reset(); // Append types CVertexDecl& AppendPosition(); CVertexDecl& AppendNormal(); CVertexDecl& AppendDiffuse(); CVertexDecl& AppendSpecular(); CVertexDecl& AppendTextureCoords(); // Return the vertex declaration // Reference count is incremented - remember to Release() it! IDirect3DVertexDeclaration9* GetDecl();private: IDirect3DVertexDeclaration9* m_pDecl; std::vector m_vDecl;};#endif /* __VERTEXDECL_H__ */
Source:
//==========================================================================// VetexDecl.cpp - Vertex declaration class//==========================================================================#include #include #include "Common/mmgr.h"#include "VertexDecl.h"#include "Common/Log.h"#include "D3DDevice/D3DDevice.h"//==========================================================================// Used for comparing vertex elementsstatic const D3DVERTEXELEMENT9 s_streamEnd = D3DDECL_END();static bool operator==(const D3DVERTEXELEMENT9& a, const D3DVERTEXELEMENT9& b){ return memcmp(&a, &b, sizeof(a)) == 0;}//==========================================================================// Base class//==========================================================================CVertexDecl::CVertexDecl() : m_pDecl(NULL){}CVertexDecl::~CVertexDecl(){ if(m_pDecl) { m_pDecl->Release(); m_pDecl = NULL; }}void CVertexDecl::Reset(){ if(m_pDecl) { m_pDecl->Release(); m_pDecl = NULL; } m_vDecl.clear();}CVertexDecl& CVertexDecl::AppendPosition(){ if(!m_vDecl.empty() && m_vDecl.back() == s_streamEnd) m_vDecl.pop_back(); D3DVERTEXELEMENT9 theElement = { 0, // Stream 0, // Offset D3DDECLTYPE_FLOAT3, // Type / Size D3DDECLMETHOD_DEFAULT, // Method D3DDECLUSAGE_POSITION, // Usage 0 // Usage index }; m_vDecl.push_back(theElement); if(m_pDecl) { m_pDecl->Release(); m_pDecl = NULL; } return *this;}CVertexDecl& CVertexDecl::AppendNormal(){ if(!m_vDecl.empty() && m_vDecl.back() == s_streamEnd) m_vDecl.pop_back(); D3DVERTEXELEMENT9 theElement = { 0, // Stream 0, // Offset D3DDECLTYPE_FLOAT3, // Type / Size D3DDECLMETHOD_DEFAULT, // Method D3DDECLUSAGE_NORMAL, // Usage 0 // Usage index }; m_vDecl.push_back(theElement); if(m_pDecl) { m_pDecl->Release(); m_pDecl = NULL; } return *this;}CVertexDecl& CVertexDecl::AppendDiffuse(){ if(!m_vDecl.empty() && m_vDecl.back() == s_streamEnd) m_vDecl.pop_back(); D3DVERTEXELEMENT9 theElement = { 0, // Stream 0, // Offset D3DDECLTYPE_D3DCOLOR, // Type / Size D3DDECLMETHOD_DEFAULT, // Method D3DDECLUSAGE_COLOR, // Usage 0 // Usage index }; m_vDecl.push_back(theElement); if(m_pDecl) { m_pDecl->Release(); m_pDecl = NULL; } return *this;}CVertexDecl& CVertexDecl::AppendSpecular(){ if(!m_vDecl.empty() && m_vDecl.back() == s_streamEnd) m_vDecl.pop_back(); D3DVERTEXELEMENT9 theElement = { 0, // Stream 0, // Offset D3DDECLTYPE_D3DCOLOR, // Type / Size D3DDECLMETHOD_DEFAULT, // Method D3DDECLUSAGE_COLOR, // Usage 1 // Usage index }; m_vDecl.push_back(theElement); if(m_pDecl) { m_pDecl->Release(); m_pDecl = NULL; } return *this;}CVertexDecl& CVertexDecl::AppendTextureCoords(){ if(!m_vDecl.empty() && m_vDecl.back() == s_streamEnd) m_vDecl.pop_back(); D3DVERTEXELEMENT9 theElement = { 0, // Stream 0, // Offset D3DDECLTYPE_FLOAT2, // Type / Size D3DDECLMETHOD_DEFAULT, // Method D3DDECLUSAGE_TEXCOORD, // Usage 0 // Usage index }; m_vDecl.push_back(theElement); if(m_pDecl) { m_pDecl->Release(); m_pDecl = NULL; } return *this;}IDirect3DVertexDeclaration9* CVertexDecl::GetDecl(){ // If declaration is already valid, no need to regenerate it if(m_pDecl) { m_pDecl->AddRef(); return m_pDecl; } // Loop through the list, updating the offset and usage index DWORD dwOffset = 0; DWORD dwIndex[14]; for(int i=0; i<14; ++i) dwIndex = 0; for(size_t i=0; i { Assert(m_vDecl.Usage < 14); m_vDecl.Offset = (WORD)dwOffset; m_vDecl.UsageIndex = (BYTE)dwIndex[m_vDecl.Usage]; switch(m_vDecl.Type) { case D3DDECLTYPE_FLOAT1: dwOffset += sizeof(float); break; case D3DDECLTYPE_FLOAT2: dwOffset += sizeof(float)*2; break; case D3DDECLTYPE_FLOAT3: dwOffset += sizeof(float)*3; break; case D3DDECLTYPE_FLOAT4: dwOffset += sizeof(float)*4; break; case D3DDECLTYPE_D3DCOLOR: dwOffset += sizeof(DWORD); break; case D3DDECLTYPE_UBYTE4: dwOffset += sizeof(BYTE)*4; break; case D3DDECLTYPE_SHORT2: dwOffset += sizeof(SHORT)*2; break; case D3DDECLTYPE_SHORT4: dwOffset += sizeof(SHORT)*4; break; default: Assert(false); } ++dwIndex[m_vDecl.Usage]; } // Add the terminator m_vDecl.push_back(s_streamEnd); // Now create the declaration HRESULT hResult = CD3DDevice::Get().GetDevice()->CreateVertexDeclaration(&m_vDecl[0], &m_pDecl); if(FAILED(hResult)) { CLog::ErrorFormat("Failed to create vertex declaration. Error: %s\n", DXGetErrorString(hResult)); return NULL; } // Done m_pDecl->AddRef(); return m_pDecl;}
And the reason I like it; Example usage:
IDirect3DVertexDeclaration9* pDecl = CVertexDecl().AppendPosition().AppendDiffuse().AppendTextureCoords().GetDecl()
[smile]