331 lines
6.9 KiB
C++
331 lines
6.9 KiB
C++
#include "blocktree.h"
|
|
#include "globals.h"
|
|
#include "intrin.h"
|
|
|
|
static const int m_iMaxBlockTrees= 16;
|
|
BlockTree g_BlockTrees[ m_iMaxBlockTrees ];
|
|
|
|
static const int m_iMaxTreeElements= 2 * 1024 * 128;
|
|
BlockTreeElement g_BlockElements[ m_iMaxTreeElements ];
|
|
int g_iBlockElementsUsed= 0;
|
|
|
|
static const int m_iMaxTreeBuilderElements= 512;
|
|
BlockTreeBuilder g_BuilderStack[ m_iMaxTreeBuilderElements ];
|
|
int g_iLastBuilderElement= 0;
|
|
|
|
static const int g_iMaxBlocksPerTree= 1024 * 2;
|
|
|
|
static float fMinSize;
|
|
|
|
void CreateBlockTree();
|
|
void MoveBTB( BlockTreeBuilder& btb, float fStep );
|
|
void ProcessTree( BlockTree* t );
|
|
BlockTreeElement* AddTreeBox( BlockTree* t, BlockTreeBuilder& btb );
|
|
void AddBuilderStack( BlockTreeBuilder& btb, int iLeafMode );
|
|
|
|
void BlockTree::Init()
|
|
{
|
|
m_pElements= NULL;
|
|
m_iElementcount= 0;
|
|
m_fBaseTime= 0.0f;
|
|
m_fLastChangeTime= -1.0f;
|
|
}
|
|
|
|
bool BlockTree::IsActive( float fTime )
|
|
{
|
|
if( fTime > m_fBaseTime )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void BlockTree::AddToScene( float fTime, int iObject )
|
|
{
|
|
if( fTime > m_fLastChangeTime )
|
|
{
|
|
return;
|
|
}
|
|
fTime-= m_fBaseTime;
|
|
|
|
g_Objects[ iObject ].Lock();
|
|
for( int i= 0; i < m_iElementcount; ++i )
|
|
{
|
|
BlockTreeElement& b= m_pElements[ i ];
|
|
float fElemTime= fTime - b.m_fTimeOffset;
|
|
if( fElemTime > 0.0f )
|
|
{
|
|
D3DXVECTOR3 Pos( b.m_v3Pos );
|
|
D3DXVECTOR3 Rot( b.m_v3Rot );
|
|
float fSize= b.m_fSize;
|
|
if( fElemTime < m_fTimeStep )
|
|
{
|
|
float fLerp= fElemTime / m_fTimeStep;
|
|
fSize*= fLerp;
|
|
if( b.m_ParentObject != NULL )
|
|
{
|
|
D3DXVec3Lerp( &Rot, &(b.m_ParentObject->m_v3Rot), &Rot, fLerp );
|
|
fLerp= 0.5f + 0.5f * fLerp;
|
|
D3DXVec3Lerp( &Pos, &(b.m_ParentObject->m_v3Pos), &Pos, fLerp );
|
|
}
|
|
}
|
|
D3DXVECTOR3 Size( fSize, fSize, fSize );
|
|
|
|
g_Objects[ iObject ].AddBox(
|
|
Pos,
|
|
Size,
|
|
Rot,
|
|
0xffffffff,
|
|
b.m_fColor, 0.0f );
|
|
}
|
|
}
|
|
g_Objects[ iObject ].Unlock();
|
|
}
|
|
|
|
void PrepareBlockTrees()
|
|
{
|
|
for( int i= OI_BlockTreeFirst; i <= OI_BlockTreeLast; ++i )
|
|
{
|
|
g_Objects[ i ].Create( 4 * 6 * g_iMaxBlocksPerTree, 6 * 6 * g_iMaxBlocksPerTree, true );
|
|
g_Objects[ i ].m_iUsedShader[ 0 ]= Rainbow;
|
|
g_Objects[ i ].m_iUsedPreShader= PreDepth;
|
|
}
|
|
for( int i= 0; i < m_iMaxBlockTrees; ++i )
|
|
{
|
|
g_BlockTrees[ i ].Init();
|
|
}
|
|
|
|
CreateBlockTree();
|
|
}
|
|
|
|
void AddBlockTreesToScene( float fTime )
|
|
{
|
|
for( int i= 0; i < m_iMaxBlockTrees; ++i )
|
|
{
|
|
if( g_BlockTrees[ i ].IsActive( fTime ) )
|
|
{
|
|
assert( OI_BlockTreeFirst + i < OI_BlockTreeLast );
|
|
g_BlockTrees[ i ].AddToScene( fTime, OI_BlockTreeFirst + i );
|
|
}
|
|
else
|
|
{
|
|
g_Objects[ OI_BlockTreeFirst + i ].HideVertexData();
|
|
}
|
|
}
|
|
}
|
|
|
|
void CreateBlockTree()
|
|
{
|
|
g_Random.setSeed( 17 );
|
|
fMinSize= 0.25f;
|
|
{
|
|
BlockTree* t= g_BlockTrees;
|
|
|
|
t->m_iElementcount= 0;
|
|
t->m_pElements= g_BlockElements + g_iBlockElementsUsed;
|
|
t->m_fTimeStep= 0.125f;
|
|
|
|
g_iLastBuilderElement= 1;
|
|
BlockTreeBuilder* btb= g_BuilderStack;
|
|
btb->m_v3Pos=D3DXVECTOR3( 0.0f,
|
|
-2.5f,
|
|
0.0f );
|
|
|
|
btb->m_v3Rot=D3DXVECTOR3( 0, 0, 0 );
|
|
btb->m_iWalkAxis= 2;
|
|
btb->m_fSize= 1.75f;
|
|
btb->m_fColor= 0.0f;
|
|
btb->m_fSizeChange= 119.0f / 128.0f;
|
|
btb->m_fRotOffset= 0.0f;
|
|
btb->m_fTimeOffset= 0.0f;
|
|
btb->m_iLevel= 0;
|
|
btb->m_pParent= NULL;
|
|
|
|
t->m_fBaseTime= 12.0f;
|
|
t->m_fLastChangeTime= t->m_fBaseTime + 5.0f;
|
|
|
|
ProcessTree(t);
|
|
|
|
g_iBlockElementsUsed+= t->m_iElementcount;
|
|
}
|
|
|
|
g_Random.setSeed( 43 );
|
|
fMinSize= 0.125f;
|
|
for( int i= 1; i < m_iMaxBlockTrees; ++i )
|
|
{
|
|
BlockTree* t= g_BlockTrees + i;
|
|
|
|
t->m_iElementcount= 0;
|
|
t->m_pElements= g_BlockElements + g_iBlockElementsUsed;
|
|
t->m_fTimeStep= 0.125f;
|
|
|
|
g_iLastBuilderElement= 1;
|
|
BlockTreeBuilder* btb= g_BuilderStack;
|
|
btb->m_v3Pos=D3DXVECTOR3( g_Random.genFloat( -18.0f, 18.0f ),
|
|
-1.5f,
|
|
g_Random.genFloat( -18.0f, 18.0f ) );
|
|
|
|
btb->m_v3Rot=D3DXVECTOR3( g_Random.genFloat( 0.0f, c_PI ), 0, 0 );
|
|
btb->m_iWalkAxis= 2;
|
|
btb->m_fSize= g_Random.genFloat( 0.7f, 1.0f );
|
|
btb->m_fColor= 0.0f;
|
|
btb->m_fSizeChange= 59.0f / 64.0f;
|
|
btb->m_fRotOffset= 0.0f;
|
|
btb->m_fTimeOffset= 0.0f;
|
|
btb->m_iLevel= 0;
|
|
btb->m_pParent= NULL;
|
|
|
|
t->m_fBaseTime= 34.0f - btb->m_v3Pos.z / 6.0f;
|
|
t->m_fLastChangeTime= t->m_fBaseTime + 5.0f;
|
|
|
|
ProcessTree(t);
|
|
|
|
g_iBlockElementsUsed+= t->m_iElementcount;
|
|
}
|
|
|
|
}
|
|
|
|
void MoveBTB( BlockTreeBuilder& btb, float fStep )
|
|
{
|
|
D3DXVECTOR3 Move( 0, 0, 0 );
|
|
D3DXVECTOR3 Rot( 0, 0, 0 );
|
|
|
|
switch( btb.m_iWalkAxis )
|
|
{
|
|
case 1:
|
|
Move.x+= fStep;
|
|
Rot.z+= c_PI;
|
|
break;
|
|
case 2:
|
|
Move.y+= fStep;
|
|
Rot.z+= c_PI;
|
|
break;
|
|
case 3:
|
|
Move.z+= fStep;
|
|
Rot.y-= c_PI;
|
|
break;
|
|
case -1:
|
|
Move.x-= fStep;
|
|
Rot.z-= c_PI;
|
|
break;
|
|
case -2:
|
|
Move.y-= fStep;
|
|
Rot.z+= c_PI;
|
|
break;
|
|
case -3:
|
|
Move.z-= fStep;
|
|
Rot.y+= c_PI;
|
|
break;
|
|
}
|
|
{
|
|
D3DXMATRIX m1;
|
|
D3DXMatrixRotationYawPitchRoll( &m1, btb.m_v3Rot.x, btb.m_v3Rot.y, btb.m_v3Rot.z );
|
|
D3DXVec3TransformCoord( &Move, &Move, &m1 );
|
|
}
|
|
|
|
btb.m_v3Pos+= Move;
|
|
btb.m_v3Rot+= Rot * btb.m_fRotOffset;
|
|
}
|
|
|
|
void ProcessTree( BlockTree* t )
|
|
{
|
|
while( g_iLastBuilderElement > 0 )
|
|
{
|
|
g_iLastBuilderElement--;
|
|
BlockTreeBuilder btb= g_BuilderStack[ g_iLastBuilderElement ];
|
|
|
|
int iLength= 0;
|
|
int iLeafMode= g_Random.genInteger( 0, 15 );
|
|
while( true )
|
|
{
|
|
float fStep= 2.0f * btb.m_fSize;
|
|
btb.m_fSize*= btb.m_fSizeChange;
|
|
btb.m_fColor+= 1.0f / 24.0f;
|
|
if( btb.m_fSize < fMinSize )
|
|
{
|
|
break;
|
|
}
|
|
|
|
MoveBTB(btb, fStep);
|
|
|
|
btb.m_pParent= AddTreeBox(t, btb);
|
|
btb.m_fTimeOffset+= t->m_fTimeStep;
|
|
|
|
if( btb.m_iLevel > 1 && g_Random.genInteger( 1, 6 ) == 1 )
|
|
{
|
|
btb.m_fRotOffset*= -1;
|
|
}
|
|
|
|
if( btb.m_iLevel == 0 )
|
|
{
|
|
if( iLength > 2 && iLength % 3 == 1 )
|
|
{
|
|
AddBuilderStack(btb, iLeafMode);
|
|
AddBuilderStack(btb, iLeafMode + 2);
|
|
}
|
|
iLeafMode++;
|
|
}
|
|
else if( g_Random.genInteger( 0, 8 ) < iLength - btb.m_iLevel )
|
|
{
|
|
if( btb.m_iLevel < 5 )
|
|
{
|
|
AddBuilderStack(btb, iLeafMode);
|
|
}
|
|
iLeafMode++;
|
|
}
|
|
|
|
iLength++;
|
|
}
|
|
}
|
|
}
|
|
|
|
BlockTreeElement* AddTreeBox( BlockTree* t, BlockTreeBuilder& btb )
|
|
{
|
|
// add box
|
|
assert( t->m_iElementcount < g_iMaxBlocksPerTree );
|
|
assert( g_iBlockElementsUsed + t->m_iElementcount < m_iMaxTreeElements );
|
|
BlockTreeElement* elem= t->m_pElements + t->m_iElementcount;
|
|
t->m_iElementcount++;
|
|
|
|
elem->m_fColor= btb.m_fColor;
|
|
elem->m_fSize= btb.m_fSize;
|
|
elem->m_fTimeOffset= btb.m_fTimeOffset;
|
|
elem->m_ParentObject= btb.m_pParent;
|
|
elem->m_v3Pos= btb.m_v3Pos;
|
|
elem->m_v3Rot= btb.m_v3Rot;
|
|
|
|
return elem;
|
|
}
|
|
|
|
void AddBuilderStack( BlockTreeBuilder& btb, int iLeafMode )
|
|
{
|
|
assert( g_iLastBuilderElement < m_iMaxTreeBuilderElements );
|
|
BlockTreeBuilder& btbNew= g_BuilderStack[ g_iLastBuilderElement ];
|
|
g_iLastBuilderElement++;
|
|
|
|
btbNew= btb;
|
|
int iSign= 1;
|
|
int iNewMode= 1 + iLeafMode % 4;
|
|
if( iNewMode > 2 )
|
|
{
|
|
iSign= -1;
|
|
iNewMode-= 2;
|
|
}
|
|
iNewMode+= abs( btb.m_iWalkAxis );
|
|
if( iNewMode > 3 )
|
|
{
|
|
iNewMode-= 3;
|
|
}
|
|
btbNew.m_iWalkAxis= iNewMode * iSign;
|
|
if( btbNew.m_fRotOffset >= 0.0f )
|
|
{
|
|
btbNew.m_fRotOffset+= 3.0f / 128.0f;
|
|
}
|
|
else
|
|
{
|
|
btbNew.m_fRotOffset-= 3.0f / 128.0f;
|
|
}
|
|
|
|
btbNew.m_iLevel++;
|
|
} |