// EMERGENT GAME TECHNOLOGIES PROPRIETARY INFORMATION // // This software is supplied under the terms of a license agreement or // nondisclosure agreement with Emergent Game Technologies and may not // be copied or disclosed except in accordance with the terms of that // agreement. // // Copyright (c) 1996-2007 Emergent Game Technologies. // All Rights Reserved. // // Emergent Game Technologies, Chapel Hill, North Carolina 27517 // http://www.emergent.net #include "stdafx.h" #include "Renderers.h" #include "EntryDef.h" #include "Terrain.h" #include "QuadTree.h" #include "LayerFog.h" #include "MRT_ColorDepthMaterial.h" #include "NiTextureTransformController.h" #include "NiLinFloatKey.h" #include "NiFloatData.h" #include "NiFloatInterpolator.h" #define NIMATERIALTOOLKIT_IMPORT //#include #include #include #ifndef _LIB #define _LIB #endif // Include the header files for the shader libraries & parsers #include #include #include #include #include #include #include #include #include #include "C3DSExportor.h" #if defined(WIN32) #include #include #endif using namespace SceneCore; //--------------------------------------------------------------------------- NiApplication* NiApplication::Create() { return NiNew Renderers; } //--------------------------------------------------------------------------- Renderers::Renderers() : NiSample("TEST: terrain", 800, 600, false), m_kBackgroundColor( 0.0f, .2f, 0.25f), m_pTerrain(NULL) { SetMediaPath("D:\\Program Files\\Emergent\\Gamebryo 2.3 Source\\Samples\\Data"); m_bUseFixedTime = false; //__super::m_bRendererDialog = false; //m_bUseNavSystem = false; } //--------------------------------------------------------------------------- bool Renderers::CreateShaderSystem() { NiShaderFactory::RegisterErrorCallback(ShaderErrorCallback); char* pcShaderDir = getenv("EGB_SHADER_LIBRARY_PATH"); //char* pcShaderDir = "E:\\mux\\Developer\\PlatformTools\\Bin\\scenedesigner\\shaders"; char szShaderPath[MAX_PATH]; strcpy( szShaderPath, pcShaderDir); strcat( szShaderPath, "\\Data\\Dx9" ); NiShaderFactory::AddShaderProgramFileDirectory(szShaderPath); NiShaderFactory::AddShaderProgramFileDirectory(pcShaderDir); if (!RunShaderParsers(pcShaderDir)) { NiMessageBox("Failed to run shader parsers!", "ERROR"); return false; } if (!RunShaderLibraries(pcShaderDir)) { NiMessageBox("Failed to load shader libraries!", "ERROR"); return false; } return true; } bool Renderers::RunShaderParsers(const char* pcShaderDir) { NiShaderFactory::RegisterRunParserCallback(ShaderCallback_RunParser); const char* pcLibName = NULL; NiShaderFactory::LoadAndRunParserLibrary(pcLibName, pcShaderDir, true); return true; } //--------------------------------------------------------------------------- bool Renderers::RunShaderLibraries(const char* pcShaderDir) { NiShaderFactory::RegisterClassCreationCallback( ShaderCallback_LibraryClassCreate); unsigned int uiCount = 1; char* apcDirectories[1]; apcDirectories[0] = (char*)pcShaderDir; const char* pcLibName = NULL; if (!NiShaderFactory::LoadAndRegisterShaderLibrary(pcLibName, uiCount, apcDirectories, true)) { NiMessageBox("Failed to load shader library!", "ERROR"); return false; } return true; } //--------------------------------------------------------------------------- bool Renderers::ShaderCallback_LibraryClassCreate(const char* pcLibFile, NiRenderer* pkRenderer, int iDirectoryCount, char* apcDirectories[], bool bRecurseSubFolders, NiShaderLibrary** ppkLibrary) { *ppkLibrary = NULL; if (!NSBShaderLib_LoadShaderLibrary(pkRenderer, iDirectoryCount, apcDirectories, bRecurseSubFolders, ppkLibrary)) { return false; } return true; } //--------------------------------------------------------------------------- unsigned int Renderers::ShaderCallback_RunParser(const char* pcLibFile, NiRenderer* pkRenderer, const char* pcDirectory, bool bRecurseSubFolders) { return NSFParserLib_RunShaderParser(pcDirectory, bRecurseSubFolders); } //--------------------------------------------------------------------------- unsigned int Renderers::ShaderCallback_Errors(const char* pcError, NiShaderError eError, bool bRecoverable) { NiOutputDebugString("ERROR: "); NiOutputDebugString(pcError); return 0; } // //bool SaveTexture( NiSourceTexturePtr pkTexture, const char *pszFile ) //{ // if ( !pkTexture ) return false; // // CImage image; // image.Create( pkTexture->GetWidth(), pkTexture->GetHeight(), 32, CImage::createAlphaChannel ); // // NiPixelData *pPixelData = pkTexture->GetSourcePixelData(); // // unsigned char *pPtr = (*pPixelData)( 0, 0 ); // // unsigned char *pData = ( unsigned char *)image.GetBits(); // for ( int y = 0; y < BLENDTEX_SIZE; y++) // { // memcpy( pData, pPtr, BLENDTEX_SIZE * 4 ); // // pPtr = (*pPixelData)( 0, y); // pData += image.GetPitch(); // } // // HRESULT h = image.Save( pszFile ); // return true; //} bool Renderers::CreateUIElements() { NiSample::CreateUIElements(); // The Log is a text output used by all NiSample derived classes AddLogEntry("Press ESC or Start + Select to quit"); return true; } bool Renderers::CreateScene() { __super::CreateScene(); NiStream kStream; if (!kStream.Load("e:\\test\\plane.nif")) { return false; } NiAVObject* pkAvObj = (NiAVObject*)(kStream.GetObjectAt(0)); NiNode* pkNode; if (NiIsKindOf(NiNode, pkAvObj)) { pkNode = (NiNode*)pkAvObj; } NiGeometry* pkGeom = (NiGeometry*)pkNode->GetAt(0); NiMaterial* pkWaterMtl = NiSingleShaderMaterial::Create("AdvanceWater"); NIASSERT(pkWaterMtl); pkGeom->ApplyAndSetActiveMaterial(pkWaterMtl); NiTimeSyncController* pkTimeController = NiNew NiTimeSyncController(); pkTimeController->SetTarget(pkGeom); pkTimeController->Start(); pkAvObj->UpdateEffects(); pkAvObj->UpdateProperties(); pkAvObj->Update(0.0f); this->m_spScene->AttachChild(pkAvObj); pkNode->SetSelectiveUpdate(true); m_spScene->SetSelectiveUpdate(true); return true; } bool Renderers::CreateCamera() { __super::CreateCamera(); m_spCamera->SetTranslate( 0, 50, 5 ); m_spCamera->LookAtWorldPoint( NiPoint3(0,0,0), NiPoint3( 0,0,1 ) ); //m_spCamera->SetMaxFarNearRatio(10000000.0f); //m_spCamera->SetMaxFarNearRatio(0.5f); m_spCamera->Update(0.0f); return true; } bool Renderers::CreateFrame() { bool bResult = __super::CreateFrame(); return bResult; } bool Renderers::CreateUISystem(){ //bool bResult = __super::CreateUISystem(); //return bResult; NiUIManager::Create(); NiUIManager* pkUIManager = NiUIManager::GetUIManager(); if (pkUIManager == NULL) return false; NiInputSystem* pkInputSys = GetInputSystem(); if (!pkUIManager->Initialize(GetInputSystem(), "D:\\Program Files\\Emergent\\Gamebryo 2.3 Source\\Samples\\Data\\UISkinFull.dds", m_spCursor)) { return false; } m_fUIElementHeight = pkUIManager->GetMaxCharHeightInNSC() * 3.0f; m_fUIElementWidth = NiMin(0.40f, pkUIManager->GetMaxCharWidthInNSC() * 25.0f); m_fUIGroupHeaderHeight = pkUIManager->GetMaxCharHeightInNSC() * 2.75f; m_kUIElementGroupOffset.x = pkUIManager->GetMaxCharWidthInNSC() * 1.5f; m_kUIElementGroupOffset.y = pkUIManager->GetMaxCharHeightInNSC() * 0.5f + m_fUIGroupHeaderHeight; if (m_bUseNavSystem) { if (!NiNavManager::Create()) return false; } NiUIManager::GetUIManager()->ReserveGamePadButton( NiInputGamePad::NIGP_A, &m_kHideAll, NiUIManager::WASPRESSED); NiUIManager::GetUIManager()->ReserveKeyboardButton( NiInputKeyboard::KEY_Z, &m_kHideAll, NiUIManager::WASPRESSED); return true; } bool Renderers::CreateNavigationControllers(){ bool bResult = __super::CreateNavigationControllers(); return bResult; } bool Renderers::CompleteUISystem(){ bool bResult = __super::CompleteUISystem(); return bResult; } void Renderers::UpdateFrame() { __super::UpdateFrame(); //if ( m_pTerrain ) // m_pTerrain->Update( .0f, .0f ); m_spScene->Update(0.03f); m_spScene->UpdateControllers(0.03f); m_spScene->DoSelectedUpdate(0.03f); m_spCamera->Update( .0f ); NiInputKeyboard* pkKeyboard = GetInputSystem()->GetKeyboard(); if ( pkKeyboard->KeyIsDown( NiInputKeyboard::KEY_M ) ) { CEventManager::GetInstance()->PostEvent( NiNew CMyEvent ); } if ( pkKeyboard->KeyIsDown( NiInputKeyboard::KEY_Y ) ) { CEventManager::GetInstance()->PostEvent( NiNew CYourEvent ); } CEventManager::GetInstance()->ProcessEvent(); } void Renderers::OnIdle(void) { // MeasureTime returns false if the frame rate is over the pre-set limit if (!MeasureTime()) return; ResetFrameTimings(); BeginUpdate(); UpdateFrame(); EndUpdate(); BeginFrame(); RenderFrame(); EndFrame(); DisplayFrame(); UpdateVisualTrackers(); UpdateMetrics(); m_iClicks++; if ((m_fAccumTime >= m_fAppEndTime) && (m_fAppEndTime != NI_INFINITY)) { QuitApplication(); } } void Renderers::RenderFrame() { if (m_bUseFrameSystem) { NiApplication::RenderFrame(); } else { m_spRenderer->BeginUsingDefaultRenderTargetGroup( NiRenderer::CLEAR_ALL); BeginRender(); if ( m_pTerrain ) m_pTerrain->Render( m_spCamera, m_spCuller, &m_kVisible ); CullFrame(); NiDrawVisibleArray(m_spCamera, m_kVisible); RenderScreenItems(); RenderUIElements(); EndRender(); RenderVisualTrackers(); m_spRenderer->EndUsingRenderTargetGroup(); } } void Renderers::Terminate() { SAFE_DELETE( m_pTerrain ); __super::Terminate(); } void Renderers::EventTest() { /*TEventListener< CMyEventDisposal > *pListener1 = new TEventListener< CMyEventDisposal >; TEventListener< CYourEventDisposal > *pListener2 = new TEventListener< CYourEventDisposal >; pListener1->RegisterEventProcessor( MYEVENTID, &CMyEventDisposal::OnMyEvent ); pListener2->RegisterEventProcessor( YOUREVENTID, &CYourEventDisposal::OnYourEvent );*/ // CEventManager::GetInstance()->AddEventListener() CMyEventDisposal *pListener1 = new CMyEventDisposal; pListener1->RegisterEventProcessor( MYEVENTID, &CMyEventDisposal::OnMyEvent ); CYourEventDisposal *pListener2 = new CYourEventDisposal; pListener2->RegisterEventProcessor( YOUREVENTID, &CYourEventDisposal::OnYourEvent ); //CEventManager::GetInstance()->AddEventListener( new CMyEventDisposal ); //CEventManager::GetInstance()->AddEventListener( new CYourEventDisposal ); //CEventManager::GetInstance()->SendEvent( NiNew CMyEvent ); //CEventManager::GetInstance()->SendEvent( NiNew CYourEvent ); } // old create scene //m_pTerrain = new CTerrain(); //bool b = false; //m_pTerrain->Create( 2,2,"e:/test/Test_0.BMP" ); // //CTerrain::stChunk* pChunks = m_pTerrain->GetChunks(); //pChunks->pChunkMtl->SetTexture("e:/test/BRICK01_0.BMP", b ); //m_pTerrain->ExportBlendTexture("e:/test/"); //// 先导出一个Chunk的纹理测试 //NiSourceTexturePtr pkBlendResult = pChunks->pChunkMtl->GetTextureBlendResult(); /***************************************** * 3、获取 LPDIRECT3DBASETEXTURE9 并转换到 * 压缩格式,保存文件。 * D3DXLoadSurfaceFromSurface ******************************************/ //NiDX9Renderer* pkDX9Renderer = NiDynamicCast(NiDX9Renderer, this->m_spRenderer); //LPDIRECT3DBASETEXTURE9 PrepareTextureForRendering(NiTexture* pNewTexIm, bool &bChanged, bool &bMipmap, bool &bNonPow2) // This function takes the NiTexture that is passed in and ensures that it is ready to be rendered. // It returns a pointer to the DX texture that can be used with a NiD3DRenderState::SetTexture call, // and three Boolean values indicating whether the texture needs to be updated, whether the texture // contains mipmaps, and whether it has one or both dimensions that are not round powers of two. //bool bChanged = false; //bool bMipmap = false; //bool bNonPow2 = false; // 获取源纹理 surface //LPDIRECT3DBASETEXTURE9 pD3D9Tex = pkDX9Renderer->GetTextureManager()->PrepareTextureForRendering(pkBlendResult, bChanged, bMipmap, bNonPow2); //pD3D9Tex->GenerateMipSubLevels(); //DWORD count = pD3D9Tex->GetLOD(); //LPDIRECT3DSURFACE9 pSurSource = NULL; //((LPDIRECT3DTEXTURE9)pD3D9Tex)->GetSurfaceLevel(0, &pSurSource); //int w = pSurSource->Width; //int h = pSurSource->Height; //// 创建目标 纹理 //LPDIRECT3DTEXTURE9 pTexDest = NULL; //LPDIRECT3DSURFACE9 pSurDest = NULL; //if (FAILED(pkDX9Renderer->GetD3DDevice()->CreateTexture( // 256, // 256, // 1, D3DUSAGE_DYNAMIC, D3DFMT_DXT5, // D3DPOOL_SYSTEMMEM, &pTexDest, NULL))) //{ // return false; //} //pTexDest->GetSurfaceLevel(0, &pSurDest); // //D3DLOCKED_RECT rect; //pSurDest->LockRect(&rect, NULL, 0); //// 源纹理拷贝到目标纹理 //if (FAILED(D3DXLoadSurfaceFromSurface(pSurDest, NULL, NULL, pSurSource, NULL, NULL, D3DX_FILTER_NONE, 0))) //{ // return false; //} //pSurDest->UnlockRect(); //pTexDest->AddDirtyRect(NULL); //pSurSource->Width //HRESULT hr = D3DXSaveTextureToFileA( // "e:\\test\\blendResult.dds", // D3DXIFF_DDS, // pD3D9Tex, // NULL // ); //if (FAILED(hr)) //{ // return false; //} //system("dxtex e:\\test\\blendResult.dds DXT5 e:\\test\\blendResult.dds "); /*********************************** * QuadTree Test ************************************/ //CQuadTree* pQuadTree = new CQuadTree(m_pTerrain); //NiStream kStream; //bool bSuccess = kStream.Load( "e:/test/Medium_MMMM.nif" ); //if (!bSuccess) //{ // NiMessageBox("WORLD.NIF file could not be loaded!", "NIF Error"); // return false; //} ////m_spScene = NiNew NiNode; //m_spScene = (NiNode*) kStream.GetObjectAt(0); //NIASSERT(NiIsKindOf(NiNode, m_spScene)); //m_spScene->SetTranslate( rand()%1024, rand()%1024, 0 ); //m_spScene->SetScale(0.1f); //m_spScene->Update(0.0f); // stQuadNode* pQuadNode = pQuadTree->AttachObject(m_spScene); //int iCount = m_spScene->GetChildCount(); //m_spScene->AttachChild( m_spCamera ); //NiNode* pkNewSceneGraph = pQuadTree->BuildSceneGraph(); // //pkNewSceneGraph->Update(0.0f); //NiStream kOutStream; //kOutStream.InsertObject(pkNewSceneGraph); //kOutStream.Save("e:/test/MYFILE.NIF"); /* m_pTerrain->SetActiveCamera( m_spCamera ); float x = float( rand() % 101 ) / 100.0f * 4; float y = float( rand() % 101 ) / 100.0f * 4; //srand( timeGetTime() ); for ( int i = 0; i < 5; ++i ) { float x = float( rand() % 101 ) / 100.0f * 512; float y = float( rand() % 101 ) / 100.0f * 512; float h = float( rand() % 101 ) / 100.0f * 20; float r = float( rand() % 101 ) / 100.0f * 20; float R = float( rand() % 101 ) / 100.0f * 10 + r; //m_pTerrain->AdjustHeight( NiPoint3(x,y,0), h, r, R, true ); } //m_pTerrain->SetBaseTexture( "c:/Shader/yello.bmp" ); //m_pTerrain->SetTexture( "c:/Shader/yello.bmp", NiPoint3(64,0,0), 0.8, 0.0f, 64 ); //m_pTerrain->SetTexture( "c:/Shader/blue.bmp", NiPoint3( 32,10,0), 0.8, 15, 18 ); //m_pTerrain->SetTexture( "c:/Shader/red.bmp", NiPoint3(64,64,0), 0.6, 32.0f, 33 ); //m_pTerrain->SetTexture( "c:/Shader/green.bmp", NiPoint3(64,64,0), 0.6, 20.0f, 20 ); vector< vector > vPoints; NiStream kStream; bool bSuccess = kStream.Load( "../../../../data/teapot.nif" ); if (!bSuccess) { NiMessageBox("WORLD.NIF file could not be loaded!", "NIF Error"); return false; } CTerrainMaterial mtl; if ( mtl.CreateBlendTexture() ) { //mtl.SetBlendDataB( NiPoint2(50,50), 0.6, 40, 50, false ); //mtl.SetBlendDataG( NiPoint2(60,200), 0.6, 100, 120, false ); //mtl.SetBlendDataR( NiPoint2(250,50), 0.9, 100, 150, false ); //mtl.SaveBlendTexture( "c:/T5.png" ); } //m_spScene = NiNew NiNode; m_spScene = (NiNode*) kStream.GetObjectAt(0); NIASSERT(NiIsKindOf(NiNode, m_spScene)); m_spScene->SetTranslate( 0, 0, 0 ); m_spScene->Update(0.0f); m_spScene->AttachChild( m_spCamera ); //EventTest(); m_pTerrain->ExportTerrainToServer( "c:/场景1.Map" ); int iTotalX, iTotalY, iGridX, iGridY; m_pTerrain->ReadTerrainFile( "c:/场景1.map", iTotalX, iTotalY, iGridX, iGridY ); int *pBlockInfo = new int[ iGridX*iGridY ]; m_pTerrain->ReadDataFromTerrainFile( "c:/场景1.map", pBlockInfo ); */ //return true; //return __super::CreateScene();