582 lines
13 KiB
C++
582 lines
13 KiB
C++
#include "meshviewer.h"
|
|
|
|
#include <windows.h>
|
|
#include <fstream>
|
|
|
|
#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 <std::string>& 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 <std::string>& 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();
|
|
} |