/* 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 .
*
*/
/*
* 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 *g_poolRenderState = NULL;
cMemoryPool *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, (3000, NULL));
m_poolRenderNode = hplNew(cMemoryPool, (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(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(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 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; impTexture[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