📄 scenegraph.cpp
字号:
int* CSceneItem::OBBMin()
{
return m_OBBMin;
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
int* CSceneItem::OBBMax()
{
return m_OBBMax;
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
void CSceneItem::SetEnvMapMode(byte jEnvMapMode)
{
m_jEnvMapMode = jEnvMapMode;
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
byte CSceneItem::EnvMapMode()
{
return m_jEnvMapMode;
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
CSceneGraph::CSceneGraph(CEngine* pEngine)
{
m_pEngine = pEngine;
m_pRoot = new CSceneItem();
m_pRoot->SetNode(TRUE);
m_wModelCount = 0;
m_pModelLibrary = NULL;
m_wTextureCount = 0;
m_pTextureLibrary = NULL;
for (byte x=0; x<6; x++) m_pSkyBox[x] = NULL;
m_bSkyBoxLoaded = FALSE;
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
CSceneGraph::~CSceneGraph()
{
WORD x;
if (m_pModelLibrary)
{
for (x=0; x<m_wModelCount; x++)
delete m_pModelLibrary[x];
FREE(m_pModelLibrary);
}
if (m_pTextureLibrary)
{
for (x=0; x<m_wTextureCount; x++)
delete m_pTextureLibrary[x];
FREE(m_pTextureLibrary);
}
for (x=0; x<6; x++)
if (m_pSkyBox[x]) delete m_pSkyBox[x];
delete m_pRoot;
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
void CSceneGraph::AddItem(CSceneItem* pNode, CSceneItem* pItem)
{
// start from specified node
CSceneItem* pLeaf = pNode;
// find last item
while (pLeaf->Next()) pLeaf = pLeaf->Next();
// add new item
pLeaf->SetNext(pItem);
// setup new item
pItem->SetNode(FALSE);
pItem->SetPrevious(pLeaf);
pItem->SetNext(NULL);
pItem->SetParent(NULL);
pItem->SetChild(NULL);
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
void CSceneGraph::RemoveItem(CSceneItem* pItem)
{
if (pItem->IsNode())
{
// remove node
pItem->Parent()->SetChild(pItem->Child());
pItem->SetParent(NULL);
}
else
{
// remove item
if (pItem->Next()) pItem->Next()->SetPrevious(pItem->Previous());
pItem->Previous()->SetNext(pItem->Next());
pItem->SetPrevious(NULL);
}
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
void CSceneGraph::AddChild(CSceneItem* pNode, CSceneItem* pItem)
{
// start from specified node
CSceneItem* pLeaf = pNode;
// find last child node
while (pLeaf->Child()) pLeaf = pLeaf->Child();
// add new item
pLeaf->SetChild(pItem);
// setup new item
pItem->SetNode(TRUE);
pItem->SetParent(pLeaf);
pItem->SetChild(NULL);
pItem->SetPrevious(NULL);
pItem->SetNext(NULL);
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
void CSceneGraph::RemoveNode(CSceneItem* pItem)
{
RemoveItem(pItem);
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
CSceneItem* CSceneGraph::Root()
{
return m_pRoot;
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
void CSceneGraph::Render(CSceneItem* pItem, CCamera* pCam, boolean bFrustum)
{
// load camera projection view matrix
glMatrixMode(GL_PROJECTION);
glLoadMatrixx(pCam->ProjectionMatrix().m);
// switch back to model view matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// rotate world in camera space
vec3_t r; VectorCopy(pCam->Rotation(), r);
glRotatex(-r[0], 1,0,0);
glRotatex(-r[1], 0,1,0);
glRotatex(-r[2], 0,0,1);
vec3_t p; VectorCopy(pCam->Position(), p);
// render skybox before translation
// (skybox always at 0,0,0)
if (m_bSkyBoxLoaded)
{
glDisable(GL_DEPTH_TEST);
for (byte x=0; x<6; x++)
{
VectorCopy(p, m_pSkyBox[x]->Position());
m_pSkyBox[x]->Render(this);
}
glEnable(GL_DEPTH_TEST);
}
// translate world in camera space
glTranslatex(-p[0], -p[1], -p[2]);
// render recursively
RecursiveRender(pItem, pCam, bFrustum);
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
void CSceneGraph::RecursiveRender(CSceneItem* pItem, CCamera* pCam, boolean bFrustum)
{
//
// render the hierarchical scenegraph
//
while (pItem)
{
glPushMatrix();
// translate and rotate item
vec3_t v; VectorCopy(pItem->Position(), v);
vec3_t r; VectorCopy(pItem->Rotation(), r);
glTranslatex(v[0], v[1], v[2]);
glRotatex(r[0], 1, 0, 0);
glRotatex(r[1], 0, 1, 0);
glRotatex(r[2], 0, 0, 1);
// render item
if (pItem->ModelIndex() > -1)
{
vec3_t BBMin;
VectorAdd(pItem->OBBMin(), pItem->Position(), BBMin);
vec3_t BBMax;
VectorAdd(pItem->OBBMax(), pItem->Position(), BBMax);
if (!bFrustum || pCam->IsBoxVisible(BBMin, BBMax))
pItem->Render(this);
}
// recursively render item's childrens
if (pItem->Child())
RecursiveRender(pItem->Child(), pCam);
glPopMatrix();
// jump to next item on the current level
pItem = pItem->Next();
}
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
CMobModel* CSceneGraph::AddEmptyModel()
{
if (!m_wModelCount)
m_pModelLibrary = (CMobModel**)MALLOC(sizeof(CMobModel*));
else
m_pModelLibrary = (CMobModel**)REALLOC(m_pModelLibrary, sizeof(CMobModel*) * (m_wModelCount+1));
if (!m_pModelLibrary) return NULL;
m_pModelLibrary[m_wModelCount] = new CMobModel();
CMobModel* pModel = m_pModelLibrary[m_wModelCount];
m_wModelCount++;
return pModel;
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
boolean CSceneGraph::LoadModel(char *szFile, float fXScale, float fYScale, float fZScale)
{
CMobModel* pModel = AddEmptyModel();
if (!pModel) return FALSE;
boolean ok = pModel->Load(m_pEngine->Applet(), "game.dat", szFile, fXScale, fYScale, fZScale);
return ok;
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
unsigned short CSceneGraph::ModelCount()
{
return m_wModelCount;
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
CMobModel* CSceneGraph::Model(unsigned short wModel)
{
return m_pModelLibrary[wModel];
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
CTexture* CSceneGraph::CreateTexture(void)
{
if (!m_wTextureCount)
m_pTextureLibrary = (CTexture**)MALLOC(sizeof(CTexture*));
else
m_pTextureLibrary = (CTexture**)REALLOC(m_pTextureLibrary, sizeof(CTexture*) * (m_wTextureCount+1));
if (!m_pTextureLibrary) return NULL;
m_pTextureLibrary[m_wTextureCount] = new CTexture();
CTexture* pTex = m_pTextureLibrary[m_wTextureCount];
m_wTextureCount++;
return pTex;
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
boolean CSceneGraph::LoadTexture(char *szFile, boolean bGenMipMap)
{
CTexture* pTex = CreateTexture();
boolean ok = pTex->Load(m_pEngine->Applet(), "game.dat", szFile, bGenMipMap);
return ok;
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
unsigned short CSceneGraph::TextureCount()
{
return m_wTextureCount;
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
CTexture* CSceneGraph::Texture(unsigned short wTexture)
{
return m_pTextureLibrary[wTexture];
}
// ----------------------------------------------------------------------------------------------------------
//
//
//
// ----------------------------------------------------------------------------------------------------------
boolean CSceneGraph::GenSkyBox(char *szFile, int32 iSize)
{
word wmod = m_wModelCount;
word wtex = m_wTextureCount;
// make a copy of the file name
char szName[64];
STRCPY(szName, szFile);
// get a pointer to the extension
char* szExt = &szName[STRLEN(szName)-3];
// cut the filename upto the dot.
szName[STRLEN(szName)-4] = '\0';
// define suffixes for the textures
const char szSuffixes[6][3] = { "ft", "up", "lf", "rt", "bk", "dn"};
char szTex[64];
// define sky box coordinates and uv mapping
int32 iBoxData[6][12] =
{
// front plane
-iSize,iSize,-iSize, -iSize,-iSize,-iSize, iSize,-iSize,-iSize, iSize,iSize,-iSize,
// up plane
iSize,iSize,iSize, -iSize,iSize,iSize, -iSize,iSize,-iSize, iSize,iSize,-iSize,
// left plane (engine's right)
iSize,iSize,-iSize, iSize,-iSize,-iSize, iSize,-iSize,iSize, iSize,iSize,iSize,
// right plane (engine's left)
-iSize,iSize,iSize, -iSize,-iSize,iSize, -iSize,-iSize,-iSize, -iSize,iSize,-iSize,
// back plane
iSize,iSize,iSize, iSize,-iSize,iSize, -iSize,-iSize,iSize, -iSize,iSize,iSize,
// down plane
-iSize,-iSize,iSize, iSize,-iSize,iSize, iSize,-iSize,-iSize, -iSize,-iSize,-iSize
};
int iuv[8] = { ITOX(0),ITOX(0), ITOX(0),ITOX(1), ITOX(1),ITOX(1), ITOX(1),ITOX(0) };
byte x;
// batch load box textures and procedurally create sky box planes as individual models
for (x=0; x<6; x++)
{
STRCPY(szTex, szName);
STRCAT(szTex, szSuffixes[x]);
STRCAT(szTex, ".");
STRCAT(szTex, szExt);
if (!LoadTexture(szTex)) return FALSE;
// generate a new mob model for the sky box plane
CMobModel* pModel = AddEmptyModel();
if (!pModel) return FALSE;
pModel->SetZWrite(FALSE);
pModel->SetBackCull(FALSE);
pModel->AllocSpace(4, 2);
byte y;
for (y=0; y<12; y++) pModel->Vertices()[y] = iBoxData[x][y];
for (y=0; y<8; y++) pModel->TexCoords()[y] = iuv[y];
pModel->Faces()[0] = 0;
pModel->Faces()[1] = 1;
pModel->Faces()[2] = 2;
pModel->Faces()[3] = 0;
pModel->Faces()[4] = 2;
pModel->Faces()[5] = 3;
#if INC_NORMALS
pModel->RecalculateNormals();
#endif
}
for (x=0; x<6; x++)
{
// create the item but do not add the sky box plane to the scenegraph
// (it is a special entity)
m_pSkyBox[x] = new CSceneItem(this, wmod+x, wtex+x);
}
m_bSkyBoxLoaded = TRUE;
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -