Files
bluflame/evoke-64k/bp10/blocktree.cpp
2026-04-18 22:31:51 +02:00

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++;
}