Files
FC1/Cry3DEngine/SaveCFG.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

492 lines
12 KiB
C++

////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
// File name: savecfg.cpp
// Version: v1.00
// Created: 28/5/2002 by Andrey
// Compilers: Visual Studio.NET
// Description: cgf file writer
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "3dEngine.h"
#include "CryStaticModel.h"
#include "statobj.h"
#include "MeshIdx.h"
bool C3DEngine::WriteMaterials(TArray<CHUNK_HEADER>& Chunks, TArray<IShader *>& Shaders, FILE *out, int &MatChunk)
{
CHUNK_HEADER ch;
// the type and version of the material chunk
typedef MTL_CHUNK_DESC_0745 MTL_CHUNK_TYPE;
MTL_CHUNK_TYPE chunk;
memset (&chunk, 0, sizeof(chunk));
int Offs = ftell(out);
ch.ChunkType = ChunkType_Mtl;
ch.ChunkID = Chunks.Num();
MatChunk = ch.ChunkID;
ch.ChunkVersion = MTL_CHUNK_TYPE::VERSION;
ch.FileOffset = Offs;
Offs += sizeof(chunk) + sizeof(int) * Shaders.Num();
Chunks.AddElem(ch);
int i=0;
for (i=0; i<Shaders.Num(); i++)
{
ch.ChunkType = ChunkType_Mtl;
ch.ChunkID = Chunks.Num();
ch.ChunkVersion = MTL_CHUNK_TYPE::VERSION;
ch.FileOffset = Offs;
Offs += sizeof(chunk);
Chunks.AddElem(ch);
}
chunk.chdr = Chunks[MatChunk];
chunk.MtlType = MTL_MULTI;
strcpy(chunk.name, "Multi");
chunk.nChildren = Shaders.Num();
fwrite(&chunk, 1, sizeof(chunk), out);
for (i=0; i<Shaders.Num(); i++)
{
int nn = MatChunk+i;
fwrite(&nn, 1, sizeof(int), out);
}
/*for (i=0; i<Shaders.Num(); i++)
{
memset(&chunk, 0, sizeof(chunk));
chunk.chdr = Chunks[MatChunk+i+1];
chunk.MtlType = MTL_STANDARD;
IShader *sh = Shaders[i];
strcpy(chunk.name, sh->GetName());
if (sh->GetTemplates())
{
SEfTemplates *eft = sh->GetTemplates();
for (int j=0; j<16; j++)
{
if (!eft->m_TexInfo[j].m_Name.empty())
{
switch (j)
{
case EFTT_DECAL:
strcpy(chunk.tex_d.name, eft->m_TexInfo[j].m_Name);
break;
case EFTT_BUMP:
case EFTT_DSDTBUMP:
strcpy(chunk.tex_b.name, eft->m_TexInfo[j].m_Name);
break;
case EFTT_GLOSS:
strcpy(chunk.tex_g.name, eft->m_TexInfo[j].m_Name);
break;
case EFTT_OPACITY:
strcpy(chunk.tex_o.name, eft->m_TexInfo[j].m_Name);
break;
case EFTT_ENVIRONMENT:
case EFTT_REFLECTION:
strcpy(chunk.tex_rl.name, eft->m_TexInfo[j].m_Name);
break;
case EFTT_REFRACTION:
strcpy(chunk.tex_rr.name, eft->m_TexInfo[j].m_Name);
break;
case EFTT_CUBEMAP:
strcpy(chunk.tex_c.name, eft->m_TexInfo[j].m_Name);
break;
case EFTT_SPECULAR:
strcpy(chunk.tex_s.name, eft->m_TexInfo[j].m_Name);
break;
case EFTT_DETAIL:
strcpy(chunk.tex_det.name, eft->m_TexInfo[j].m_Name);
break;
}
}
}
}
else
strcpy(chunk.tex_d.name, chunk.name);
chunk.Dyn_Bounce = 1;
chunk.Dyn_StaticFriction = 1;
chunk.Dyn_SlidingFriction = 1;
chunk.nChildren = -1;
fwrite(&chunk, 1, sizeof(chunk), out);
}*/
return true;
}
struct SNodeInfo
{
int bGlobals;
int Sector;
CStatObj *pObj;
char name[64];
};
bool C3DEngine::WriteNodes(TArray<CHUNK_HEADER>& Chunks, TArray<NODE_CHUNK_DESC>& Nodes, FILE *out, TArray<SNodeInfo>& NI, int& MatChunk, int& ExpFrame, std::vector<IStatObj *>& pObjs)
{
CHUNK_HEADER ch;
int numMeshs = 0;
NODE_CHUNK_DESC nd;
SNodeInfo ni;
int i;
NI.Free();
ExpFrame++;
int nChildren;
std::vector<IStatObj*>::iterator n;
for (n=pObjs.begin();n!=pObjs.end();n++)
{
IStatObj *io = (*n);
CStatObj *co = (CStatObj *)io;
memset(&nd, 0, sizeof(NODE_CHUNK_DESC));
strcpy(nd.name, co->m_szGeomName);
nd.tm.SetIdentity();
nd.scl = Vec3(1.0,1.0,1.0);
nd.MatID = MatChunk;
nd.ObjectID = numMeshs++;
int nnd = Nodes.Num();
Nodes.AddElem(nd);
ni.bGlobals = 1;
ni.pObj = co;
strcpy(ni.name, nd.name);
NI.AddElem(ni);
nChildren = 0;
Nodes[nnd].nChildren = nChildren;
}
memset(&ch, 0, sizeof(CHUNK_HEADER));
int no = Chunks.Num() + Nodes.Num();
for (i=0; i<Nodes.Num(); i++)
{
Nodes[i].ObjectID += no;
ch.ChunkType = ChunkType_Node;
ch.ChunkID = Chunks.Num();
ch.ChunkVersion = NODE_CHUNK_DESC_VERSION;
ch.FileOffset = ftell(out);
Nodes[i].chdr = ch;
Chunks.AddElem(ch);
fwrite(&Nodes[i], sizeof(NODE_CHUNK_DESC), 1, out);
for (int j=0; j<Nodes[i].nChildren; j++)
{
int nn = Nodes[i].chdr.ChunkID+1+j;
fwrite(&nn, sizeof(int), 1, out);
}
}
return true;
}
bool C3DEngine::WriteNodeMesh(int nNode, MESH_CHUNK_DESC *chunk, FILE *out, TArray<IShader *>& Shaders, TArray<SNodeInfo>& NI, CStatObj *pObj)
{
TArray<CryVertex> Verts;
TArray<CryFace> Faces;
TArray<CryUV> UVs;
TArray<CryTexFace> TFaces;
TArray<CryIRGB> Colors;
int i, j;
SNodeInfo *ni = &NI[nNode];
CIndexedMesh *pMesh = pObj->GetTriData();
for (i=0; i<pMesh->m_nFaceCount; i++)
{
CryFace fc;
CryTexFace tf;
fc.v0 = pMesh->m_pFaces[i].v[0];
fc.v1 = pMesh->m_pFaces[i].v[1];
fc.v2 = pMesh->m_pFaces[i].v[2];
tf.t0 = pMesh->m_pFaces[i].t[0];
tf.t1 = pMesh->m_pFaces[i].t[1];
tf.t2 = pMesh->m_pFaces[i].t[2];
int ns = pMesh->m_pFaces[i].shader_id;
IShader *sh = pMesh->m_lstMatTable[ns].shaderItem.m_pShader;
for (j=0; j<Shaders.Num(); j++)
{
if (!stricmp(sh->GetName(), Shaders[j]->GetName()))
break;
}
assert (j != Shaders.Num());
fc.MatID = j;
fc.SmGroup = 0;
Faces.AddElem(fc);
TFaces.AddElem(tf);
}
for (i=0; i<pMesh->m_nVertCount; i++)
{
CryVertex vr;
CryIRGB rgb;
vr.p[0] = pMesh->m_pVerts[i].x * 100.0f;
vr.p[1] = pMesh->m_pVerts[i].y * 100.0f;
vr.p[2] = pMesh->m_pVerts[i].z * 100.0f;
vr.n[0] = pMesh->m_pNorms[i].x;
vr.n[1] = pMesh->m_pNorms[i].y;
vr.n[2] = pMesh->m_pNorms[i].z;
rgb.r = pMesh->m_pColor[i].r;
rgb.g = pMesh->m_pColor[i].g;
rgb.b = pMesh->m_pColor[i].b;
Verts.AddElem(vr);
Colors.AddElem(rgb);
}
for (i=0; i<pMesh->m_nCoorCount; i++)
{
CryUV uv;
uv.u = pMesh->m_pCoors[i].s;
uv.v = pMesh->m_pCoors[i].t;
UVs.AddElem(uv);
}
chunk->nFaces = Faces.Num();
chunk->nTVerts = UVs.Num();
chunk->nVerts = Verts.Num();
chunk->VertAnimID = 0;
if (Colors.Num())
chunk->HasVertexCol = 1;
else
chunk->HasVertexCol = 0;
fwrite(chunk, 1, sizeof(MESH_CHUNK_DESC), out);
fwrite(&Verts[0], sizeof(CryVertex), chunk->nVerts, out);
fwrite(&Faces[0], sizeof(CryFace), chunk->nFaces, out);
fwrite(&UVs[0], sizeof(CryUV), chunk->nTVerts, out);
fwrite(&TFaces[0], sizeof(CryTexFace), chunk->nFaces, out);
if (chunk->HasVertexCol)
fwrite(&Colors[0], sizeof(CryIRGB), chunk->nVerts, out);
return true;
}
bool C3DEngine::WriteMesh(TArray<CHUNK_HEADER>& Chunks, TArray<NODE_CHUNK_DESC>& Nodes, TArray<IShader *>& Shaders, FILE *out, TArray<SNodeInfo>& NI, int& MatChunk, int& ExpFrame)
{
MESH_CHUNK_DESC chunk;
CHUNK_HEADER ch;
ExpFrame++;
for (int i=0; i<Nodes.Num(); i++)
{
NODE_CHUNK_DESC *nd = &Nodes[i];
SNodeInfo *ni = &NI[i];
ch.ChunkType = ChunkType_Mesh;
ch.ChunkID = Chunks.Num();
ch.ChunkVersion = GeomFileVersion;
ch.FileOffset = ftell(out);
Chunks.AddElem(ch);
chunk.chdr = ch;
chunk.HasBoneInfo = 0;
chunk.HasVertexCol = 0;
WriteNodeMesh(i, &chunk, out, Shaders, NI, ni->pObj);
}
return true;
}
bool C3DEngine::WriteLights(TArray<CHUNK_HEADER>& Chunks, TArray<NODE_CHUNK_DESC>& Nodes, FILE *out, std::vector<IStatObj *>& pObjs)
{
LIGHT_CHUNK_DESC lcd;
CHUNK_HEADER ch;
NODE_CHUNK_DESC nd;
std::vector<IStatObj*>::iterator n;
for (n=pObjs.begin();n!=pObjs.end();n++)
{
IStatObj *io = (*n);
CStatObj *co = (CStatObj *)io;
// CIndexedMesh *im = co->GetTriData();
for (int j=0; j<co->m_lstLSources.Count(); j++)
{
CDLight *dl = &co->m_lstLSources[j];
memset(&lcd, 0, sizeof(LIGHT_CHUNK_DESC));
memset(&ch, 0, sizeof(CHUNK_HEADER));
memset(&nd, 0, sizeof(NODE_CHUNK_DESC));
int no = Chunks.Num();
ch.ChunkType = ChunkType_Node;
ch.ChunkID = Chunks.Num();
ch.ChunkVersion = NODE_CHUNK_DESC_VERSION;
ch.FileOffset = ftell(out);
Chunks.AddElem(ch);
nd.chdr = ch;
nd.ObjectID = Chunks.Num();
if (dl->m_Name)
strcpy(nd.name, dl->m_Name);
else
nd.name[0] = 0;
Vec3d Org;
/* if (dl->m_OrigLight)
Org = dl->m_OrigLight->m_Origin;
else
Org = dl->m_Origin;
*/ nd.pos.x = Org[0] * 100.0f;
nd.pos.y = Org[1] * 100.0f;
nd.pos.z = Org[2] * 100.0f;
nd.tm.SetIdentity();
nd.tm[3][0] = nd.pos.x;
nd.tm[3][1] = nd.pos.y;
nd.tm[3][2] = nd.pos.z;
nd.scl = Vec3(1.0f, 1.0f, 1.0f);
fwrite(&nd, sizeof(NODE_CHUNK_DESC), 1, out);
// Light
ch.ChunkType = ChunkType_Light;
ch.ChunkID = Chunks.Num();
ch.ChunkVersion = LIGHT_CHUNK_DESC_VERSION;
ch.FileOffset = ftell(out);
Chunks.AddElem(ch);
lcd.chdr = ch;
lcd.intens = dl->m_fRadius * 100.0f;
if (lcd.intens <= 0)
lcd.intens = 500;
lcd.attenEnd = lcd.intens;
UCol col;
col.dcolor = dl->m_Color.GetTrue();
lcd.color.r = col.bcolor[0];
lcd.color.g = col.bcolor[1];
lcd.color.b = col.bcolor[2];
lcd.vDirection = dl->m_ProjAngles;
lcd.fallsize = dl->m_fLightFrustumAngle;
if (dl->m_pLightImage)
{
strcpy(lcd.szLightImage, dl->m_pLightImage->GetName());
lcd.type = LT_OMNI;
}
else
if (dl->m_Flags & DLF_DIRECTIONAL)
lcd.type = LT_DIRECT;
else
if (dl->m_Flags & DLF_POINT)
{
lcd.useAtten = true;
lcd.type = LT_OMNI;
}
fwrite(&lcd, sizeof(LIGHT_CHUNK_DESC), 1, out);
}
}
return true;
}
bool C3DEngine::SaveCGF(std::vector<IStatObj *>& pObjs)
{
TArray<CHUNK_HEADER> Chunks;
TArray<NODE_CHUNK_DESC> Nodes;
TArray<IShader *> Shaders;
TArray<SNodeInfo> NI;
int ExpFrame = 0;
char fName[1024];
int res;
int i, j;
int MatChunk;
if (pObjs.empty())
return false;
IStatObj *io = pObjs.front();
CStatObj *so = (CStatObj *)io;
// Remove extension
char *in = so->m_szFileName;
char *o = fName;
char c;
while (*in)
{
if (*in=='.')
{
c = in[1];
if (c!='.' && c!='/' && c!='\\')
break;
}
*o++ = *in++;
}
*o = 0;
// Add default extension
strcat(fName, ".cgf");
FILE *out = fxopen(fName, "wb");
if (!out)
return false;
FILE_HEADER hd;
strcpy(hd.Signature, FILE_SIGNATURE);
hd.Version = GeomFileVersion;
hd.FileType = FileType_Geom;
//write the header
res = fwrite(&hd, sizeof(hd), 1, out);
if(res != 1)
return false;
std::vector<IStatObj*>::iterator n;
for (n=pObjs.begin();n!=pObjs.end();n++)
{
IStatObj *io = (*n);
CStatObj *co = (CStatObj *)io;
CLeafBuffer *lb = co->GetLeafBuffer();
// Prepare shaders for write
for (i=0; i<lb->m_pMats->Count(); i++)
{
IShader *e = (*lb->m_pMats)[i].shaderItem.m_pShader;
if (!e)
continue;
for (j=0; j<Shaders.Num(); j++)
{
if (!stricmp(e->GetName(), Shaders[j]->GetName()))
break;
}
if (j == Shaders.Num())
Shaders.AddElem(e);
}
}
WriteMaterials(Chunks, Shaders, out, MatChunk);
WriteNodes(Chunks, Nodes, out, NI, MatChunk, ExpFrame, pObjs);
WriteMesh(Chunks, Nodes, Shaders, out, NI, MatChunk, ExpFrame);
Nodes.Free();
WriteLights(Chunks, Nodes, out, pObjs);
hd.ChunkTableOffset = ftell(out);
int nn = Chunks.Num();
fwrite(&nn, sizeof(int), 1, out);
for (i=0; i<Chunks.Num(); i++)
{
fwrite(&Chunks[i], sizeof(CHUNK_HEADER), 1, out);
}
fseek(out, 0, SEEK_SET);
fwrite(&hd, sizeof(hd), 1, out);
fclose (out);
return true;
}
//============================================================================================