Files
bluflame/evoke-64k/trunk/ev10/meshviewer.cpp
2026-04-18 22:31:51 +02:00

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();
}