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