895 lines
28 KiB
C++
895 lines
28 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2006-2010 - Frictional Games
|
|
*
|
|
* This file is part of HPL1 Engine.
|
|
*/
|
|
|
|
#include "hpl1/engine/graphics/RenderList.h"
|
|
#include "hpl1/engine/graphics/Graphics.h"
|
|
#include "hpl1/engine/graphics/Material.h"
|
|
#include "hpl1/engine/graphics/RenderState.h"
|
|
#include "hpl1/engine/graphics/Renderable.h"
|
|
#include "hpl1/engine/graphics/Renderer3D.h"
|
|
#include "hpl1/engine/graphics/RendererPostEffects.h"
|
|
#include "hpl1/engine/math/Math.h"
|
|
#include "hpl1/engine/scene/Camera3D.h"
|
|
#include "hpl1/engine/scene/MeshEntity.h"
|
|
|
|
namespace hpl {
|
|
|
|
int cRenderList::mlGlobalRenderCount = 0;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// MOTION BLUR OBJECT COMPARE
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
bool cMotionBlurObject_Compare::operator()(iRenderable *pObjectA,
|
|
iRenderable *pObjectB) const {
|
|
// TODO: perhaps Z here...
|
|
|
|
return pObjectA->GetVertexBuffer() < pObjectB->GetVertexBuffer();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// TRANSPERANT OBJECT COMPARE
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
bool cTransperantObject_Compare::operator()(iRenderable *pObjectA, iRenderable *pObjectB) const {
|
|
if (pObjectA->GetMaterial()->GetDepthTest() != pObjectA->GetMaterial()->GetDepthTest()) {
|
|
return pObjectA->GetMaterial()->GetDepthTest() < pObjectA->GetMaterial()->GetDepthTest();
|
|
}
|
|
|
|
return pObjectA->GetZ() < pObjectB->GetZ();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// QUERY COMPARE
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
bool cOcclusionQueryObject_Compare::operator()(const cOcclusionQueryObject *pObjectA,
|
|
const cOcclusionQueryObject *pObjectB) const {
|
|
if (pObjectA->mpVtxBuffer != pObjectB->mpVtxBuffer)
|
|
return pObjectA->mpVtxBuffer < pObjectB->mpVtxBuffer;
|
|
|
|
if (pObjectA->mpMatrix != pObjectB->mpMatrix)
|
|
return pObjectA->mpMatrix < pObjectB->mpMatrix;
|
|
|
|
return (int)pObjectA->mbDepthTest < (int)pObjectB->mbDepthTest;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// RENDER NODE
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
cMemoryPool<iRenderState> *g_poolRenderState = NULL;
|
|
cMemoryPool<cRenderNode> *g_poolRenderNode = NULL;
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
bool cRenderNodeCompare::operator()(cRenderNode *apNodeA, cRenderNode *apNodeB) const {
|
|
int val = apNodeA->mpState->Compare(apNodeB->mpState);
|
|
bool ret = val > 0 ? true : false;
|
|
return ret;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
void cRenderNode::DeleteChildren() {
|
|
tRenderNodeSetIt it = m_setNodes.begin();
|
|
for (; it != m_setNodes.end(); ++it) {
|
|
cRenderNode *pNode = *it;
|
|
|
|
pNode->DeleteChildren();
|
|
g_poolRenderNode->Release(pNode);
|
|
}
|
|
|
|
if (mpState)
|
|
g_poolRenderState->Release(mpState);
|
|
mpState = NULL;
|
|
m_setNodes.clear();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
void cRenderNode::Render(cRenderSettings *apSettings) {
|
|
tRenderNodeSetIt it = m_setNodes.begin();
|
|
for (; it != m_setNodes.end(); ++it) {
|
|
cRenderNode *pNode = *it;
|
|
|
|
pNode->mpState->SetMode(apSettings);
|
|
pNode->Render(apSettings);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// CONSTRUCTORS
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
cRenderList::cRenderList(cGraphics *apGraphics) {
|
|
mfFrameTime = 0;
|
|
mTempNode.mpState = hplNew(iRenderState, ());
|
|
|
|
mlRenderCount = 0;
|
|
mlLastRenderCount = 0;
|
|
|
|
mpGraphics = apGraphics;
|
|
|
|
m_poolRenderState = hplNew(cMemoryPool<iRenderState>, (3000, NULL));
|
|
m_poolRenderNode = hplNew(cMemoryPool<cRenderNode>, (3000, NULL));
|
|
|
|
g_poolRenderState = m_poolRenderState;
|
|
g_poolRenderNode = m_poolRenderNode;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
cRenderList::~cRenderList() {
|
|
Clear();
|
|
hplDelete(mTempNode.mpState);
|
|
|
|
hplDelete(m_poolRenderState);
|
|
hplDelete(m_poolRenderNode);
|
|
|
|
g_poolRenderState = NULL;
|
|
g_poolRenderNode = NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// PUBLIC METHODS
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
void cRenderList::Clear() {
|
|
++mlGlobalRenderCount;
|
|
|
|
// Clear containers.
|
|
m_setLights.clear();
|
|
m_setObjects.clear();
|
|
m_setQueries.clear();
|
|
m_setMotionBlurObjects.clear();
|
|
m_setTransperantObjects.clear();
|
|
|
|
mRootNodeDepth.DeleteChildren();
|
|
mRootNodeDiffuse.DeleteChildren();
|
|
mRootNodeTrans.DeleteChildren();
|
|
|
|
for (int i = 0; i < MAX_NUM_OF_LIGHTS; i++) {
|
|
mRootNodeLight[i].DeleteChildren();
|
|
}
|
|
|
|
mlLastRenderCount = mlRenderCount;
|
|
mlRenderCount++;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
void cRenderList::AddOcclusionQuery(cOcclusionQueryObject *apObject) {
|
|
m_setQueries.insert(apObject);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
cOcclusionQueryObjectIterator cRenderList::GetQueryIterator() {
|
|
return cOcclusionQueryObjectIterator(&m_setQueries);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
cMotionBlurObjectIterator cRenderList::GetMotionBlurIterator() {
|
|
return cMotionBlurObjectIterator(&m_setMotionBlurObjects);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
cTransperantObjectIterator cRenderList::GetTransperantIterator() {
|
|
return cTransperantObjectIterator(&m_setTransperantObjects);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
cLight3DIterator cRenderList::GetLightIt() {
|
|
return cLight3DIterator(&m_setLights);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
cRenderableIterator cRenderList::GetObjectIt() {
|
|
return cRenderableIterator(&m_setObjects);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
int cRenderList::GetLightNum() {
|
|
return (int)m_setLights.size();
|
|
}
|
|
|
|
int cRenderList::GetObjectNum() {
|
|
return (int)m_setObjects.size();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
cRenderNode *cRenderList::GetRootNode(eRenderListDrawType aObjectType, eMaterialRenderType aPassType, int alLightNum) {
|
|
if (aObjectType == eRenderListDrawType_Normal) {
|
|
if (aPassType == eMaterialRenderType_Z)
|
|
return &mRootNodeDepth;
|
|
if (aPassType == eMaterialRenderType_Diffuse)
|
|
return &mRootNodeDiffuse;
|
|
if (aPassType == eMaterialRenderType_Light)
|
|
return &mRootNodeLight[alLightNum];
|
|
return NULL;
|
|
} else {
|
|
return &mRootNodeTrans;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
void cRenderList::Compile() {
|
|
int lLightNum = (int)m_setLights.size();
|
|
if (lLightNum > MAX_NUM_OF_LIGHTS)
|
|
lLightNum = MAX_NUM_OF_LIGHTS;
|
|
|
|
for (int i = 0; i < lLightNum; ++i)
|
|
mvObjectsPerLight[i] = 0;
|
|
|
|
// Iterate the objects to be rendered and build trees with render states.
|
|
tRenderableSetIt it = m_setObjects.begin();
|
|
for (; it != m_setObjects.end(); ++it) {
|
|
iRenderable *pObject = *it;
|
|
iMaterial *pMat = pObject->GetMaterial();
|
|
|
|
// Skip meshes...
|
|
if (pObject->GetRenderType() == eRenderableType_Mesh)
|
|
continue;
|
|
|
|
// If the object is transparent add tot eh trans tree
|
|
if (pMat->IsTransperant()) {
|
|
// Use the set cotainer instead for now:
|
|
m_setTransperantObjects.insert(pObject);
|
|
/*for(int lPass=0; lPass< pMat->GetNumOfPasses(eMaterialRenderType_Diffuse, NULL);lPass++)
|
|
{
|
|
AddToTree(pObject,eRenderListDrawType_Trans,
|
|
eMaterialRenderType_Light,0,NULL, true,lPass);
|
|
}*/
|
|
}
|
|
// If object is not trans add to another tree.
|
|
else {
|
|
// If the object uses z pass add to z tree.
|
|
if (pMat->UsesType(eMaterialRenderType_Z)) {
|
|
for (int lPass = 0; lPass < pMat->GetNumOfPasses(eMaterialRenderType_Z, NULL); lPass++) {
|
|
AddToTree(pObject, eRenderListDrawType_Normal, eMaterialRenderType_Z,
|
|
0, NULL, false, lPass);
|
|
}
|
|
}
|
|
|
|
// If object uses light add the object to each light's tree.
|
|
if (pMat->UsesType(eMaterialRenderType_Light)) {
|
|
// Light trees that the object will belong to.
|
|
int lLightCount = 0;
|
|
|
|
tLight3DSetIt lightIt = m_setLights.begin();
|
|
for (; lightIt != m_setLights.end(); ++lightIt) {
|
|
iLight3D *pLight = *lightIt;
|
|
|
|
if ((pLight->GetOnlyAffectInSector() == false || pObject->IsInSector(pLight->GetCurrentSector())) &&
|
|
pLight->CheckObjectIntersection(pObject)) {
|
|
if (lLightCount >= MAX_NUM_OF_LIGHTS)
|
|
break;
|
|
|
|
++mvObjectsPerLight[lLightCount];
|
|
|
|
for (int lPass = 0; lPass < pMat->GetNumOfPasses(eMaterialRenderType_Light, pLight); ++lPass) {
|
|
AddToTree(pObject, eRenderListDrawType_Normal,
|
|
eMaterialRenderType_Light, lLightCount, pLight, false, lPass);
|
|
}
|
|
}
|
|
++lLightCount;
|
|
}
|
|
}
|
|
|
|
// If it has a diffuse pass, add to the diffuse tree.
|
|
if (pObject->GetMaterial()->UsesType(eMaterialRenderType_Diffuse)) {
|
|
for (int lPass = 0; lPass < pMat->GetNumOfPasses(eMaterialRenderType_Diffuse, NULL); lPass++) {
|
|
AddToTree(pObject, eRenderListDrawType_Normal,
|
|
eMaterialRenderType_Diffuse, 0, NULL, false, lPass);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
bool cRenderList::Add(iRenderable *apObject) {
|
|
if (apObject->IsVisible() == false)
|
|
return false;
|
|
|
|
// Check if the object is culled by fog.
|
|
cRenderer3D *pRenderer = mpGraphics->GetRenderer3D();
|
|
if (pRenderer->GetFogActive() && pRenderer->GetFogCulling()) {
|
|
if (cMath::CheckCollisionBV(*pRenderer->GetFogBV(), *apObject->GetBoundingVolume())) {
|
|
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Check if the object as already been added.
|
|
if (mlRenderCount == apObject->GetRenderCount())
|
|
return false;
|
|
apObject->SetRenderCount(mlRenderCount);
|
|
|
|
// Update the graphics of object.
|
|
apObject->UpdateGraphics(cRenderList::GetCamera(), mfFrameTime, this);
|
|
|
|
// Set that the object is to be rendered.
|
|
apObject->SetGlobalRenderCount(mlGlobalRenderCount);
|
|
|
|
switch (apObject->GetRenderType()) {
|
|
// Add a normal renderable
|
|
case eRenderableType_Normal:
|
|
case eRenderableType_ParticleSystem:
|
|
if (apObject->GetMaterial()->IsTransperant()) {
|
|
// Calculate the Z for the trans object
|
|
cVector3f vCameraPos = cMath::MatrixMul(cRenderList::GetCamera()->GetViewMatrix(),
|
|
apObject->GetBoundingVolume()->GetWorldCenter());
|
|
apObject->SetZ(vCameraPos.z);
|
|
|
|
m_setObjects.insert(apObject);
|
|
} else {
|
|
m_setObjects.insert(apObject);
|
|
|
|
// MotionBlur
|
|
if (mpGraphics->GetRendererPostEffects()->GetMotionBlurActive() || mpGraphics->GetRenderer3D()->GetRenderSettings()->mbFogActive || mpGraphics->GetRendererPostEffects()->GetDepthOfFieldActive()) {
|
|
m_setMotionBlurObjects.insert(apObject);
|
|
|
|
if (apObject->GetPrevRenderCount() != GetLastRenderCount()) {
|
|
cMatrixf *pMtx = apObject->GetModelMatrix(mpCamera);
|
|
if (pMtx) {
|
|
apObject->SetPrevMatrix(*pMtx);
|
|
}
|
|
}
|
|
apObject->SetPrevRenderCount(mlRenderCount);
|
|
}
|
|
}
|
|
|
|
break;
|
|
// Add all sub meshes of the mesh
|
|
case eRenderableType_Mesh: {
|
|
cMeshEntity *pMesh = static_cast<cMeshEntity *>(apObject);
|
|
for (int i = 0; i < pMesh->GetSubMeshEntityNum(); i++) {
|
|
Add(pMesh->GetSubMeshEntity(i));
|
|
}
|
|
break;
|
|
}
|
|
// Add a light to a special container
|
|
case eRenderableType_Light: {
|
|
iLight3D *pLight = static_cast<iLight3D *>(apObject);
|
|
|
|
m_setLights.insert(pLight);
|
|
} break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// PRIVATE METHODS
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
cRenderNode *cRenderList::InsertNode(cRenderNode *apListNode, cRenderNode *apTempNode) {
|
|
// Log("Searching for node... ");
|
|
// Create a node with the state.
|
|
|
|
tRenderNodeSetIt it = apListNode->m_setNodes.find(apTempNode);
|
|
|
|
if (it != apListNode->m_setNodes.end()) {
|
|
// Log("Node found!\n");
|
|
// node found, return it.
|
|
return *it;
|
|
} else {
|
|
// Log("Node NOT found, creating new.\n");
|
|
// no node found, create one and return it.
|
|
cRenderNode *pNode = m_poolRenderNode->Create();
|
|
pNode->mpState = m_poolRenderState->Create();
|
|
|
|
// Copy the relevant values to the state.
|
|
pNode->mpState->Set(apTempNode->mpState);
|
|
|
|
apListNode->m_setNodes.insert(pNode);
|
|
|
|
return pNode;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
/*cRenderNode* cRenderList::InsertNode(cRenderNode* apListNode, cRenderNode* apTempNode)
|
|
{
|
|
Std::pair<tRenderNodeSetIt, bool> ret = apListNode->m_setNodes.insert(apTempNode);
|
|
if(ret.second == false)
|
|
{
|
|
m_poolRenderState->Release(apTempNode->mpState);
|
|
m_poolRenderNode->Release(apTempNode);
|
|
return *ret.first;
|
|
}
|
|
|
|
return apTempNode;
|
|
}*/
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
void cRenderList::AddToTree(iRenderable *apObject, eRenderListDrawType aObjectType,
|
|
eMaterialRenderType aPassType, int alLightNum, iLight3D *apLight,
|
|
bool abUseDepth, int alPass) {
|
|
// Log("------ OBJECT ------------\n");
|
|
|
|
cRenderNode *pNode = GetRootNode(aObjectType, aPassType, alLightNum);
|
|
iMaterial *pMaterial = apObject->GetMaterial();
|
|
iRenderState *pTempState = mTempNode.mpState;
|
|
cRenderNode *pTempNode = &mTempNode;
|
|
|
|
//-------------- EXPLANATION ----------------------------------
|
|
// Go through each render state type and set the appropriate
|
|
// variables for each type. The most important states are set first.
|
|
// The state is then inserted to a tree structure, where each state type is a level.
|
|
// Example:
|
|
// |----------root--------|
|
|
// |---pass |-----pass----|
|
|
// depth-test depth-test depth-test
|
|
// ............etc......................
|
|
// After each insertion a pointer to the inserted or existing (if variables already existed)
|
|
// node is returned
|
|
// This is then passed on the next state, the state inserted (or exist found) there and so on.
|
|
// At each insertion, it is first checked if a state with variables exist, and if so, use that.
|
|
// if not, a new node is created and inserted.
|
|
// The temp node state is used as storage for the data to skip the overhead of deletion
|
|
// and creation when testing if state exist. Instead new data is only created if the state
|
|
// is new.
|
|
// Each Render state has the same class, but uses different var depending on type, this to
|
|
// skip the overhead of using inheritance.
|
|
//-------------------------------------------------------------
|
|
|
|
/////// SECTOR //////////////
|
|
if (aPassType == eMaterialRenderType_Z) {
|
|
// pTempNode = m_poolRenderNode->Create();
|
|
// pTempState = m_poolRenderState->Create();
|
|
// pTempNode->mpState = pTempState;
|
|
|
|
pTempState->mType = eRenderStateType_Sector;
|
|
pTempState->mpSector = apObject->GetCurrentSector();
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
|
|
/////// PASS //////////////
|
|
{
|
|
// pTempNode = m_poolRenderNode->Create();
|
|
// pTempState = m_poolRenderState->Create();
|
|
// pTempNode->mpState = pTempState;
|
|
|
|
pTempState->mType = eRenderStateType_Pass;
|
|
pTempState->mlPass = alPass;
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
/////// DEPTH TEST //////////////
|
|
{
|
|
// pTempNode = m_poolRenderNode->Create();
|
|
// pTempState = m_poolRenderState->Create();
|
|
// pTempNode->mpState = pTempState;
|
|
|
|
// Log("\nDepth level, Z: %f\n",apObject->GetZ());
|
|
|
|
pTempState->mType = eRenderStateType_DepthTest;
|
|
pTempState->mbDepthTest = pMaterial->GetDepthTest();
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
|
|
/////// DEPTH //////////////
|
|
if (abUseDepth) {
|
|
// Log("\nDepth level, Z: %f\n",apObject->GetZ());
|
|
// pTempNode = m_poolRenderNode->Create();
|
|
// pTempState = m_poolRenderState->Create();
|
|
// pTempNode->mpState = pTempState;
|
|
|
|
pTempState->mType = eRenderStateType_Depth;
|
|
pTempState->mfZ = apObject->GetZ();
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
|
|
/////// ALPHA MODE //////////////
|
|
{
|
|
// Log("\nAlpha level %d\n", pMaterial->GetAlphaMode(mType,alPass));
|
|
// pTempNode = m_poolRenderNode->Create();
|
|
// pTempState = m_poolRenderState->Create();
|
|
// pTempNode->mpState = pTempState;
|
|
|
|
pTempState->mType = eRenderStateType_AlphaMode;
|
|
pTempState->mAlphaMode = pMaterial->GetAlphaMode(aPassType, alPass, apLight);
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
|
|
/////// BLEND MODE //////////////
|
|
{
|
|
// Log("\nBlend level %d : %d\n",pMaterial->GetBlendMode(mType,alPass),pMaterial->GetChannelMode(mType,alPass));
|
|
// pTempNode = m_poolRenderNode->Create();
|
|
// pTempState = m_poolRenderState->Create();
|
|
// pTempNode->mpState = pTempState;
|
|
|
|
pTempState->mType = eRenderStateType_BlendMode;
|
|
|
|
pTempState->mBlendMode = pMaterial->GetBlendMode(aPassType, alPass, apLight);
|
|
pTempState->mChannelMode = pMaterial->GetChannelMode(aPassType, alPass, apLight);
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
|
|
/////// GPU PROGRAM //////////////
|
|
{
|
|
pTempState->mType = eRenderStateType_GpuProgram;
|
|
|
|
pTempState->gpuProgram = pMaterial->getGpuProgram(aPassType, alPass, apLight);
|
|
pTempState->gpuProgramSetup = pMaterial->getGpuProgramSetup(aPassType, alPass, apLight);
|
|
pTempState->mbUsesLight = pMaterial->VertexProgramUsesLight(aPassType, alPass, apLight);
|
|
pTempState->mbUsesEye = pMaterial->VertexProgramUsesEye(aPassType, alPass, apLight);
|
|
pTempState->mpLight = apLight;
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
#if 0
|
|
/////// VERTEX PROGRAM //////////////
|
|
{
|
|
// Log("\nVertex program level\n");
|
|
// pTempNode = m_poolRenderNode->Create();
|
|
// pTempState = m_poolRenderState->Create();
|
|
// pTempNode->mpState = pTempState;
|
|
|
|
pTempState->mType = eRenderStateType_VertexProgram;
|
|
|
|
pTempState->mpVtxProgram = pMaterial->GetVertexProgram(aPassType, alPass, apLight);
|
|
pTempState->mpVtxProgramSetup = pMaterial->GetVertexProgramSetup(aPassType, alPass, apLight);
|
|
pTempState->mbUsesLight = pMaterial->VertexProgramUsesLight(aPassType, alPass, apLight);
|
|
pTempState->mbUsesEye = pMaterial->VertexProgramUsesEye(aPassType, alPass, apLight);
|
|
pTempState->mpLight = apLight;
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
|
|
/////// FRAGMENT PROGRAM //////////////
|
|
{
|
|
// Log("\nFragment program level\n");
|
|
// pTempNode = m_poolRenderNode->Create();
|
|
// pTempState = m_poolRenderState->Create();
|
|
// pTempNode->mpState = pTempState;
|
|
|
|
pTempState->mType = eRenderStateType_FragmentProgram;
|
|
|
|
pTempState->mpFragProgram = pMaterial->GetFragmentProgram(aPassType, alPass, apLight);
|
|
pTempState->mpFragProgramSetup = pMaterial->GetFragmentProgramSetup(aPassType, alPass, apLight);
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
#endif
|
|
/////// TEXTURE //////////////
|
|
{
|
|
// Log("\nTexture level\n");
|
|
// pTempNode = m_poolRenderNode->Create();
|
|
// pTempState = m_poolRenderState->Create();
|
|
// pTempNode->mpState = pTempState;
|
|
|
|
pTempState->mType = eRenderStateType_Texture;
|
|
|
|
for (int i = 0; i < MAX_TEXTUREUNITS; i++) {
|
|
pTempState->mpTexture[i] = pMaterial->GetTexture(i, aPassType, alPass, apLight);
|
|
}
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
|
|
/////// VERTEX BUFFER //////////////
|
|
{
|
|
// Log("\nVertex buffer level\n");
|
|
// pTempNode = m_poolRenderNode->Create();
|
|
// pTempState = m_poolRenderState->Create();
|
|
// pTempNode->mpState = pTempState;
|
|
|
|
pTempState->mType = eRenderStateType_VertexBuffer;
|
|
|
|
pTempState->mpVtxBuffer = apObject->GetVertexBuffer();
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
|
|
/////// MATRIX //////////////
|
|
{
|
|
// Log("\nMatrix level\n");
|
|
// pTempNode = m_poolRenderNode->Create();
|
|
// pTempState = m_poolRenderState->Create();
|
|
// pTempNode->mpState = pTempState;
|
|
|
|
pTempState->mType = eRenderStateType_Matrix;
|
|
|
|
pTempState->mpModelMatrix = apObject->GetModelMatrix(mpCamera);
|
|
pTempState->mpInvModelMatrix = apObject->GetInvModelMatrix();
|
|
pTempState->mvScale = apObject->GetCalcScale();
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
|
|
/////// RENDER //////////////
|
|
{
|
|
// Log("\nRender leaf!\n");
|
|
// pTempNode = m_poolRenderNode->Create();
|
|
// pTempState = m_poolRenderState->Create();
|
|
// pTempNode->mpState = pTempState;
|
|
|
|
pTempState->mType = eRenderStateType_Render;
|
|
|
|
pTempState->mpObject = apObject;
|
|
|
|
InsertNode(pNode, pTempNode);
|
|
}
|
|
|
|
// Log("-------------------------\n");
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------
|
|
|
|
/*void cRenderList::AddToTree(iRenderable* apObject,eRenderListDrawType aObjectType,
|
|
eMaterialRenderType aPassType, int alLightNum,iLight3D* apLight,
|
|
bool abUseDepth, int alPass)
|
|
{
|
|
//Log("------ OBJECT ------------\n");
|
|
|
|
cRenderNode *pNode = GetRootNode(aObjectType,aPassType, alLightNum);
|
|
iMaterial *pMaterial = apObject->GetMaterial();
|
|
iRenderState *pTempState = NULL;//mTempNode.mpState;
|
|
cRenderNode *pTempNode = NULL;
|
|
|
|
//-------------- EXPLANATION ----------------------------------
|
|
// Go through each render state type and set the appropriate
|
|
// variables for each type. The most important states are set first.
|
|
// The state is then inserted to a tree structure, where each state type is a level.
|
|
// Example:
|
|
// |----------root--------|
|
|
// |---pass |-----pass----|
|
|
// depth-test depth-test depth-test
|
|
// ............etc......................
|
|
// After each insertion a pointer to the inserted or existing (if variables already existed)
|
|
// node is returned
|
|
// This is then passed on the next state, the state inserted (or exist found) there and so on.
|
|
// At each insertion, it is first checked if a state with variables exist, and if so, use that.
|
|
// if not, a new node is created and inserted.
|
|
// The temp node state is used as storage for the data to skip the overhead of deletion
|
|
// and creation when testing if state exist. Instead new data is only created if the state
|
|
// is new.
|
|
// Each Render state has the same class, but uses different var depending on type, this to
|
|
// skip the overhead of using inheritance.
|
|
//-------------------------------------------------------------
|
|
|
|
/////// SECTOR //////////////
|
|
if(aPassType == eMaterialRenderType_Z)
|
|
{
|
|
pTempNode = m_poolRenderNode->Create();
|
|
pTempState = m_poolRenderState->Create();
|
|
pTempNode->mpState = pTempState;
|
|
|
|
pTempState->mType = eRenderStateType_Sector;
|
|
pTempState->mpSector = apObject->GetCurrentSector();
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
|
|
/////// PASS //////////////
|
|
{
|
|
pTempNode = m_poolRenderNode->Create();
|
|
pTempState = m_poolRenderState->Create();
|
|
pTempNode->mpState = pTempState;
|
|
|
|
|
|
pTempState->mType = eRenderStateType_Pass;
|
|
pTempState->mlPass = alPass;
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
/////// DEPTH TEST //////////////
|
|
{
|
|
pTempNode = m_poolRenderNode->Create();
|
|
pTempState = m_poolRenderState->Create();
|
|
pTempNode->mpState = pTempState;
|
|
|
|
//Log("\nDepth level, Z: %f\n",apObject->GetZ());
|
|
|
|
pTempState->mType = eRenderStateType_DepthTest;
|
|
pTempState->mbDepthTest = pMaterial->GetDepthTest();
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
|
|
/////// DEPTH //////////////
|
|
if(abUseDepth)
|
|
{
|
|
//Log("\nDepth level, Z: %f\n",apObject->GetZ());
|
|
pTempNode = m_poolRenderNode->Create();
|
|
pTempState = m_poolRenderState->Create();
|
|
pTempNode->mpState = pTempState;
|
|
|
|
|
|
pTempState->mType = eRenderStateType_Depth;
|
|
pTempState->mfZ = apObject->GetZ();
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
|
|
/////// ALPHA MODE //////////////
|
|
{
|
|
//Log("\nAlpha level %d\n", pMaterial->GetAlphaMode(mType,alPass));
|
|
pTempNode = m_poolRenderNode->Create();
|
|
pTempState = m_poolRenderState->Create();
|
|
pTempNode->mpState = pTempState;
|
|
|
|
|
|
pTempState->mType = eRenderStateType_AlphaMode;
|
|
pTempState->mAlphaMode = pMaterial->GetAlphaMode(aPassType,alPass, apLight);
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
|
|
/////// BLEND MODE //////////////
|
|
{
|
|
//Log("\nBlend level %d : %d\n",pMaterial->GetBlendMode(mType,alPass),pMaterial->GetChannelMode(mType,alPass));
|
|
pTempNode = m_poolRenderNode->Create();
|
|
pTempState = m_poolRenderState->Create();
|
|
pTempNode->mpState = pTempState;
|
|
|
|
|
|
pTempState->mType = eRenderStateType_BlendMode;
|
|
|
|
pTempState->mBlendMode = pMaterial->GetBlendMode(aPassType,alPass,apLight);
|
|
pTempState->mChannelMode = pMaterial->GetChannelMode(aPassType,alPass,apLight);
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
|
|
/////// VERTEX PROGRAM //////////////
|
|
{
|
|
//Log("\nVertex program level\n");
|
|
pTempNode = m_poolRenderNode->Create();
|
|
pTempState = m_poolRenderState->Create();
|
|
pTempNode->mpState = pTempState;
|
|
|
|
pTempState->mType = eRenderStateType_VertexProgram;
|
|
|
|
pTempState->mpVtxProgram = pMaterial->GetVertexProgram(aPassType,alPass,apLight);
|
|
pTempState->mpVtxProgramSetup = pMaterial->GetVertexProgramSetup(aPassType,alPass,apLight);
|
|
pTempState->mbUsesLight = pMaterial->VertexProgramUsesLight(aPassType, alPass,apLight);
|
|
pTempState->mbUsesEye = pMaterial->VertexProgramUsesEye(aPassType, alPass,apLight);
|
|
pTempState->mpLight = apLight;
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
|
|
/////// FRAGMENT PROGRAM //////////////
|
|
{
|
|
//Log("\nFragment program level\n");
|
|
pTempNode = m_poolRenderNode->Create();
|
|
pTempState = m_poolRenderState->Create();
|
|
pTempNode->mpState = pTempState;
|
|
|
|
|
|
pTempState->mType = eRenderStateType_FragmentProgram;
|
|
|
|
pTempState->mpFragProgram = pMaterial->GetFragmentProgram(aPassType,alPass,apLight);
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
|
|
/////// TEXTURE //////////////
|
|
{
|
|
//Log("\nTexture level\n");
|
|
pTempNode = m_poolRenderNode->Create();
|
|
pTempState = m_poolRenderState->Create();
|
|
pTempNode->mpState = pTempState;
|
|
|
|
|
|
pTempState->mType = eRenderStateType_Texture;
|
|
|
|
for(int i=0; i<MAX_TEXTUREUNITS;i++)
|
|
{
|
|
pTempState->mpTexture[i] = pMaterial->GetTexture(i,aPassType, alPass,apLight);
|
|
}
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
|
|
/////// VERTEX BUFFER //////////////
|
|
{
|
|
//Log("\nVertex buffer level\n");
|
|
pTempNode = m_poolRenderNode->Create();
|
|
pTempState = m_poolRenderState->Create();
|
|
pTempNode->mpState = pTempState;
|
|
|
|
|
|
pTempState->mType = eRenderStateType_VertexBuffer;
|
|
|
|
pTempState->mpVtxBuffer = apObject->GetVertexBuffer();
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
|
|
/////// MATRIX //////////////
|
|
{
|
|
//Log("\nMatrix level\n");
|
|
pTempNode = m_poolRenderNode->Create();
|
|
pTempState = m_poolRenderState->Create();
|
|
pTempNode->mpState = pTempState;
|
|
|
|
|
|
pTempState->mType = eRenderStateType_Matrix;
|
|
|
|
pTempState->mpModelMatrix = apObject->GetModelMatrix(mpCamera);
|
|
pTempState->mpInvModelMatrix = apObject->GetInvModelMatrix();
|
|
pTempState->mvScale = apObject->GetCalcScale();
|
|
|
|
pNode = InsertNode(pNode, pTempNode);
|
|
}
|
|
|
|
/////// RENDER //////////////
|
|
{
|
|
//Log("\nRender leaf!\n");
|
|
pTempNode = m_poolRenderNode->Create();
|
|
pTempState = m_poolRenderState->Create();
|
|
pTempNode->mpState = pTempState;
|
|
|
|
|
|
pTempState->mType = eRenderStateType_Render;
|
|
|
|
pTempState->mpObject = apObject;
|
|
|
|
InsertNode(pNode, pTempNode);
|
|
}
|
|
|
|
//Log("-------------------------\n");
|
|
}*/
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
} // namespace hpl
|