#include "meshviewer.h" #include #include #include "globals.h" extern float g_SunX; extern float g_SunY; extern float g_SunZ; #include "StringHelper.h" #include "TextFileReader.h" #include "Renderpipe.h" #include "camerahelper.h" #include "objmesh.h" #include "BinMeshData.h" #include "globals.h" extern int c_iScreenSizeX; extern int c_iScreenSizeY; extern ObjMesh g_objMesh; std::string g_strMeshPath= "3dmodel\\"; const int g_iMeshHelperObjectFirst= 0; const int g_iMeshHelperObjectLast= 15; const int g_iMeshMainObject= 16; HANDLE g_MeshNotification= NULL; bool bInstantQuit= false; std::string strBaseMeshName= "script"; std::string strObjName= ""; bool bLoadFlatten= false; int iFloatBits= 16; BinMesh g_BM; int g_IndexBytes; int g_VertexBytes; DWORD g_dwMeshColor; std::string g_strScriptCode; void ReadMeshviewerCommandLine() { std::string strAct( GetCommandLine() ); std::string strCommand; std::string strLastCommand; while( FrameWork::StringHelper::splitLoop( strAct, " ", strCommand ) ) { FrameWork::StringHelper::toUpper( strCommand ); if( strLastCommand == "/BASE" ) { strBaseMeshName= strCommand; } else if( strCommand == "/QUIT" ) { bInstantQuit= true; } strLastCommand= strCommand; } } void PrepareMeshViewer() { g_FullScreenQuad.InitFullScreenQuad(); Texture::Prepare1DTextures(); g_PSSM.m_iSplitCount = 6; //config g_PSSM.m_fRange = 240.0f; InitMeshViewerScene(); StartMeshFileWatch(); } void InitMeshViewerScene() { // Sky g_SkyBox.Create( 24, 36 ); g_SkyBox.m_iUsedPreShader= SkyDepth; g_SkyBox.m_iUsedShader[ 0 ]= Sky; g_SkyBox.Lock(); g_SkyBox.AddBox( D3DXVECTOR3( 0.0f, 0.0f, 0.0f), D3DXVECTOR3( 1.0f, 1.0f, 1.0f), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ), 0xff20b0f0); g_SkyBox.Unlock(); g_Objects[ g_iMeshHelperObjectFirst ].Create( 4 * 9, 6 * 9 ); g_Objects[ g_iMeshHelperObjectFirst ].m_iUsedPreShader= PreDepth; g_Objects[ g_iMeshHelperObjectFirst ].m_iUsedShader[ 0 ]= Text; g_Objects[ g_iMeshHelperObjectFirst ].Lock(); g_Objects[ g_iMeshHelperObjectFirst ].AddPlane( D3DXVECTOR3( 0.0f, -1.0f, 0.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ), 0xFFFFDCB5, // 0x8040ff40 D3DXVECTOR3( 100.0f, 1.0f, 100.0f ), D3DXVECTOR3( 400.0f, 1.0f, 400.0f ) ); g_Objects[ g_iMeshHelperObjectFirst ].Unlock(); LoadMeshViewerData(); } FrameWork::TextFileReader tfrMesh; void LoadMeshViewerScript() { std::string strFile= g_strMeshPath; strFile+= strBaseMeshName; strFile+= ".txt"; tfrMesh.read( strFile.c_str() ); } void PreParseScript( const std::vector & vecScript ) { for( size_t i= 0; i < vecScript.size(); ++i ) { std::string strAct= vecScript[ i ]; for( size_t j= 0; j < strAct.size(); ++j ) { if( strAct[ j ] == '\t' ) { strAct[ j ]= ' '; } } std::string strCommand; if( FrameWork::StringHelper::splitAt( strAct, " ", strCommand ) ) { FrameWork::StringHelper::trim( strCommand, FrameWork::StringHelper::getSpaceTab() ); } else { strAct= ""; } FrameWork::StringHelper::toUpper( strCommand ); if( strCommand == "FLATTEN" ) { bLoadFlatten= true; } else if( strCommand == "FILE" ) { strObjName= strAct; } else if( strCommand == "COLOR" ) { std::stringstream ss; ss << strAct; float fR; float fG; float fB; float fA; ss >> fR; ss >> fG; ss >> fB; ss >> fA; fR= min( 255.0f, fR ); fG= min( 255.0f, fG ); fB= min( 255.0f, fB ); fA= min( 255.0f, fA ); g_dwMeshColor= ( (int)fA << 24 ) | ( (int)fR << 16 ) | ( (int)fG << 8 ) | ( (int)fB ); } else if( strCommand == "FLOATBITS" ) { std::stringstream ss; ss << strAct; iFloatBits= 16; ss >> iFloatBits; if( iFloatBits < 10 ) { iFloatBits= 10; } } } } void ParseScript( const std::vector & vecScript ) { g_strScriptCode= ""; for( size_t i= 0; i < vecScript.size(); ++i ) { std::string strAct= vecScript[ i ]; for( size_t j= 0; j < strAct.size(); ++j ) { if( strAct[ j ] == '\t' ) { strAct[ j ]= ' '; } } std::string strCommand; if( FrameWork::StringHelper::splitAt( strAct, " ", strCommand ) ) { FrameWork::StringHelper::trim( strCommand, FrameWork::StringHelper::getSpaceTab() ); } else { strAct= ""; } FrameWork::StringHelper::toUpper( strCommand ); if( strCommand == "SUBDIVIDE" ) { g_objMesh.CatmullClarkSubdivide(); g_strScriptCode+= "\tg_objMesh.CatmullClarkSubdivide();\n"; } else if( strCommand == "UNINDEX" ) { g_objMesh.UnIndex(); g_strScriptCode+= "\tg_objMesh.UnIndex();\n"; } else if( strCommand == "EXTRUDE" ) { std::stringstream ss; ss << strAct; float fParam= 1.0f; ss >> fParam; fParam= ObjMesh::RoundFloat(fParam, iFloatBits); g_objMesh.Extrude( fParam ); g_strScriptCode+= "\tg_objMesh.Extrude( "; g_strScriptCode+= FloatToCodeString(fParam ); g_strScriptCode+= " );\n"; } else if( strCommand == "SUPER" ) { std::stringstream ss; ss << strAct; float fParam= 1.0f; ss >> fParam; fParam= ObjMesh::RoundFloat(fParam, iFloatBits); g_objMesh.SuperEllip( fParam ); g_strScriptCode+= "\tg_objMesh.SuperEllip( "; g_strScriptCode+= FloatToCodeString(fParam ); g_strScriptCode+= " );\n"; } } } void LoadMeshViewerData() { ObjMesh::m_fMaxRoundError= 0.0f; LoadMeshViewerScript(); PreParseScript( tfrMesh.getFileLines() ); std::string strObjFile= g_strMeshPath; strObjFile+= strObjName; g_objMesh.LoadMesh( strObjFile.c_str(), iFloatBits, bLoadFlatten, g_BM, g_IndexBytes, g_VertexBytes ); ParseScript( tfrMesh.getFileLines() ); g_objMesh.GenerateNormals(); g_Objects[ g_iMeshMainObject ].CreateObjMesh( &g_objMesh, g_dwMeshColor ); D3DXMATRIX mat; D3DXMatrixTranslation( &mat, 0.0f, 10.0f, 0.0f ); g_Objects[ g_iMeshMainObject ].SetTransformation( mat ); g_Objects[ g_iMeshMainObject ].m_iUsedPreShader= PreDepth; g_Objects[ g_iMeshMainObject ].m_iUsedShader[ 0 ]= Text; } void MeshViewerMainLoop() { g_dwTimeReplaceStart= timeGetTime(); /***********************************************************************************/ //Mainloop //int LastCamTick= 0; do { if( bInstantQuit ) { break; } g_dwSamplesPassed= (timeGetTime() - g_dwTimeReplaceStart ) * 441 / 10; DWORD dwNewSamples= g_dwSamplesPassed - g_dwSamples; g_dwSamples= g_dwSamplesPassed; EditorHelp::CheckKeys(); float fCamTime= (float)dwNewSamples / (float)g_iTempo * (float)g_iCamTickFactor; UserCam( (int)(fCamTime * 1.0f ) ); GetEditCam( g_Camera ); /***********************************************************************************/ // Sonne bewegen { D3DXMATRIX mSunRotX, mSunRotY, mSunRotZ, mSun; g_SunX= 1.0f; g_SunY= 2.75f - g_Camera.m_vec3Rot.x; g_SunZ= 0.0f; D3DXMatrixRotationX( &mSunRotX, g_SunX ); D3DXMatrixRotationY( &mSunRotY, g_SunY ); D3DXMatrixRotationZ( &mSunRotZ, g_SunZ ); mSun = mSunRotX * mSunRotY * mSunRotZ; g_LightDir.x = -mSun._21; g_LightDir.y = -mSun._22; g_LightDir.z = -mSun._23; D3DXVec3Normalize(&g_LightDir, &g_LightDir); } /***********************************************************************************/ //begin paint loop g_d3d_device->BeginScene(); /***********************************************************************************/ // normaler Renderdurchlauf // Projektion D3DXMATRIX& mat= g_matProjection; float zf= 1200.0f; float zn= 0.125f; float xScale = g_Camera.m_fFOV * g_Camera.m_fFOV; float yScale= xScale / (float)c_iScreenSizeY * (float)c_iScreenSizeX; mat._11= xScale; mat._12= 0; mat._13= 0; mat._14= 0; mat._21= 0; mat._22= yScale; mat._23= 0; mat._24= 0; mat._31= 0; mat._32= 0; mat._33= zf/(zf-zn); mat._34= 1; mat._41= 0; mat._42= 0; mat._43= -zn*zf/(zf-zn);mat._44= 0; FillCameraMatrix( g_Camera.m_vec3Pos, g_Camera.m_vec3Rot, &g_matView ); // Shadow splits aktualisieren g_PSSM.UpdateSplits(g_LightDir, g_matView, g_matProjection); g_d3d_device->SetTransform( D3DTS_PROJECTION, &g_matProjection ); g_d3d_device->SetTransform( D3DTS_VIEW, &g_matView ); Shader::SetConstants(); Shader::SetCamera(g_matView, g_matProjection, g_Camera.m_vec3Pos, g_CamFront); #ifndef DISABLEPOSTPROCESSING Renderpipe::FullRenderPass(); #else Renderpipe::SimpleRenderPass(); #endif /***********************************************************************************/ // Renderdurchlauf abschliessen //Shader aus Shader::Deactivate(); // Kinobalken //RenderBars(); DrawMeshText(); g_d3d_device->EndScene(); g_d3d_device->Present( NULL, NULL, NULL, NULL ); Sleep( 5 ); CheckMeshFileWatch(); // Allow the window to get focus when clicking in it or at the taskbar icon. MSG msg; if (PeekMessage(&msg, d3dpp.hDeviceWindow, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } bool bEsc= GetAsyncKeyState( VK_ESCAPE ) != 0; bool bCtrl= GetAsyncKeyState( VK_CONTROL ) != 0 || GetAsyncKeyState( VK_SHIFT) != 0; if( bEsc && bCtrl ) { break; } } while ( true ); WriteMeshHeader(); } void StopMeshFileWatch() { if (g_MeshNotification != INVALID_HANDLE_VALUE && g_MeshNotification != NULL) { FindCloseChangeNotification(g_MeshNotification); } g_MeshNotification= NULL; } void StartMeshFileWatch() { StopMeshFileWatch(); g_MeshNotification= FindFirstChangeNotification( g_strMeshPath.c_str(), FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE ); } bool CheckMeshFileWatch() { if (g_MeshNotification == INVALID_HANDLE_VALUE || g_MeshNotification == NULL) { return false; } DWORD dwRet= WaitForSingleObject( g_MeshNotification, 1 ); if( WAIT_OBJECT_0 == dwRet ) { FindNextChangeNotification( g_MeshNotification ); OnMeshFileChanged(); return true; } return false; } void OnMeshFileChanged() { LoadMeshViewerData(); } void DrawMeshText() { bool bHelp= EditorHelp::m_KeyDown[ VK_F1 ]; if( bHelp ) { int l= 0; EditorHelp::PrintDebug( l++,0, "F1 - Hilfeanzeige aktivieren" ); EditorHelp::PrintDebug( l++,0, "WASD - Kamera bewegen Mouse + mittlere oder rechte Taste - Kamera rotieren" ); EditorHelp::PrintDebug( l++,0, "FV - Kamera auf/ abbewegen Home - Kamera zuruecksetzen" ); EditorHelp::PrintDebug( l++,0, "QE - Kamera um Sichtachse rotieren Z - Reset" ); EditorHelp::PrintDebug( l++,0, "YH - Fov aendern TG - DOF Fokusebene" ); return; } if( EditorHelp::m_KeyPressed[ VK_F2 ] ) { EditorHelp::m_bShowDebugData= !EditorHelp::m_bShowDebugData; } char pcBuffer[ 1024 ]; pcBuffer[ 0 ]= 0; sprintf_s( pcBuffer, "compressed - VertexBytes: %d IndexBytes: %d total: %d", g_VertexBytes, g_IndexBytes, g_VertexBytes + g_IndexBytes ); EditorHelp::PrintDebug( 0,0, pcBuffer ); sprintf_s( pcBuffer, "final mesh - Vertex: %d Faces: %d", g_objMesh.GetVertexCount(), g_objMesh.GetFaceCount() ); EditorHelp::PrintDebug( 1,0, pcBuffer ); sprintf_s( pcBuffer, "float Bits: %d max rounding error: %7.7f", iFloatBits, ObjMesh::m_fMaxRoundError ); EditorHelp::PrintDebug( 2,0, pcBuffer ); sprintf_s( pcBuffer, "%30s", strObjName.c_str() ); EditorHelp::PrintDebug( 0,85, pcBuffer ); } void WriteMeshHeader() { std::string strBaseNameCamel= strBaseMeshName; FrameWork::StringHelper::toLower( strBaseNameCamel ); strBaseNameCamel[ 0 ]= toupper( strBaseNameCamel[ 0 ] ); std::string strFileName= "meshdata\\"; strFileName+= strBaseNameCamel; strFileName+= ".h"; std::ofstream ofs( strFileName.c_str() ); std::string strBytes; ofs << "#pragma once\n"; ofs << "#include \"objmesh.h\"\n"; ofs << "#include \"BinMeshData.h\"\n"; ofs << "#include \"renderjob.h\"\n"; ofs << "\n"; ofs << "unsigned char g_Vert" << strBaseNameCamel << "[]=\n"; strBytes= ""; CreateByteString( strBytes, (unsigned char*)g_BM.m_pVertex, g_VertexBytes ); ofs << strBytes; ofs << "\n"; ofs << "unsigned char g_Topology" << strBaseNameCamel << "[]=\n"; strBytes= ""; CreateByteString( strBytes, (unsigned char*)g_BM.m_pTopology, g_IndexBytes ); ofs << strBytes; ofs << "\n"; ofs << "void Create" << strBaseNameCamel << "( Renderjob& r )\n"; ofs << "{\n"; ofs << "\tBinMesh b;\n"; ofs << "\tb.Set( "<< g_BM.m_PrimitiveCount << ", g_Vert" << strBaseNameCamel << ", g_Topology" << strBaseNameCamel << " );\n"; ofs << "\tg_objMesh.LoadMesh(&b);\n"; ofs << g_strScriptCode; ofs << "\tg_objMesh.GenerateNormals();\n"; ofs << "\tr.CreateObjMesh( &g_objMesh, " << g_dwMeshColor << " );\n"; ofs << "}\n"; } std::string FloatToCodeString( float f ) { char pcSpecial[ 1024 ]; sprintf_s( pcSpecial, 1024, "%8.7ff", f ); return std::string( pcSpecial ); } std::string IntToCodeString( int d ) { char pcSpecial[ 1024 ]; sprintf_s( pcSpecial, 1024, "%d", d ); return std::string( pcSpecial ); } void CreateByteString( std::string& strOut, unsigned char* pData, int Count ) { strOut+= "{\n"; if( Count == 0 ) { strOut+= "\t0\n"; } else { int iEnterCount= 0; for( int i= 0; i < Count; ++i ) { if( iEnterCount == 0 ) { strOut+= "\t"; iEnterCount= 0; } strOut+= IntToCodeString( pData[ i ] ); strOut+= ", "; iEnterCount++; if( iEnterCount >= 20 && i + 1 < Count) { strOut+= "\n"; iEnterCount= 0; } } } strOut+= "\n};\n"; } bool IsInstantQuit() { return bInstantQuit; } void DoInstantQuit() { LoadMeshViewerData(); WriteMeshHeader(); }