123
This commit is contained in:
42
ResourceCompilerPC/StatCGFCompiler/BaseObj.h
Normal file
42
ResourceCompilerPC/StatCGFCompiler/BaseObj.h
Normal file
@@ -0,0 +1,42 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: baseobj.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_BASEOBJ_H__2D817DB5_34FA_4C73_8588_867E88C9CFB3__INCLUDED_)
|
||||
#define AFX_BASEOBJ_H__2D817DB5_34FA_4C73_8588_867E88C9CFB3__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
class CBaseObj
|
||||
{
|
||||
public:
|
||||
CHUNK_HEADER m_ChunkHeader;
|
||||
bool m_bBinded;
|
||||
int m_nUsers;
|
||||
|
||||
CBaseObj()
|
||||
{
|
||||
memset(&m_ChunkHeader,0,sizeof(m_ChunkHeader));
|
||||
m_bBinded = false;
|
||||
m_nUsers = 0;
|
||||
}
|
||||
|
||||
virtual ~CBaseObj(){};
|
||||
virtual bool Load(class CXFile *f, int pos) { return false; }
|
||||
virtual void Bind(CBaseObj **all_objects, int n_obj){}
|
||||
};
|
||||
|
||||
#endif // !defined(AFX_BASEOBJ_H__2D817DB5_34FA_4C73_8588_867E88C9CFB3__INCLUDED_)
|
||||
498
ResourceCompilerPC/StatCGFCompiler/CryStaticModel.cpp
Normal file
498
ResourceCompilerPC/StatCGFCompiler/CryStaticModel.cpp
Normal file
@@ -0,0 +1,498 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: crystaticmodel.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: load cgf file
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "CryStaticModel.h"
|
||||
|
||||
#include "baseobj.h"
|
||||
#include "node.h"
|
||||
#include "geom.h"
|
||||
#include "helper.h"
|
||||
#include "light.h"
|
||||
|
||||
#include "file.h"
|
||||
#include "IRCLog.h"
|
||||
|
||||
CryStaticModel::CryStaticModel()
|
||||
{
|
||||
memset( this,0,sizeof(*this) );
|
||||
}
|
||||
|
||||
CryStaticModel::~CryStaticModel()
|
||||
{
|
||||
for( int i=0; i<m_nNewObjs; i++)
|
||||
{
|
||||
CNodeCGF * pNode = (CNodeCGF*)m_ppNewObjs[i];
|
||||
delete pNode;
|
||||
}
|
||||
|
||||
if(m_ppNewObjs)
|
||||
free(m_ppNewObjs);
|
||||
m_ppNewObjs=0;
|
||||
}
|
||||
|
||||
void CryStaticModel::LoadMaterials(CXFile*f, int pos)
|
||||
{
|
||||
if(f->FSeek(pos,SEEK_SET))
|
||||
return;
|
||||
|
||||
CHUNK_HEADER ch;
|
||||
int res = f->FRead(&ch,1,sizeof(ch));
|
||||
if (ch.ChunkVersion == MTL_CHUNK_DESC_0746::VERSION)
|
||||
{
|
||||
f->FSeek(pos,SEEK_SET);
|
||||
MTL_CHUNK_DESC_0746 chunk;
|
||||
int res=f->FRead(&chunk,1,sizeof(chunk));
|
||||
if(res!=sizeof(chunk))
|
||||
return;
|
||||
|
||||
MAT_ENTITY me;
|
||||
memset(&me, 0, sizeof(MAT_ENTITY));
|
||||
me.opacity = 1.0f;
|
||||
me.alpharef = 0;
|
||||
me.m_New = 2;
|
||||
strcpy(me.name, chunk.name);
|
||||
switch (chunk.MtlType)
|
||||
{
|
||||
case MTL_STANDARD:
|
||||
me.IsStdMat = true;
|
||||
me.col_d = chunk.col_d;
|
||||
me.col_a = chunk.col_a;
|
||||
me.col_s = chunk.col_s;
|
||||
|
||||
me.specLevel = chunk.specLevel;
|
||||
me.specShininess = chunk.specShininess*100;
|
||||
me.opacity = chunk.opacity;
|
||||
me.selfIllum = chunk.selfIllum;
|
||||
me.flags = chunk.flags;
|
||||
if (me.flags & MTLFLAG_CRYSHADER)
|
||||
me.alpharef = chunk.alphaTest;
|
||||
|
||||
me.Dyn_Bounce = chunk.Dyn_Bounce;
|
||||
me.Dyn_StaticFriction = chunk.Dyn_StaticFriction;
|
||||
me.Dyn_SlidingFriction = chunk.Dyn_SlidingFriction;
|
||||
/* //Timur[10/24/2001]
|
||||
strcpy(me.map_a, chunk.tex_a.name);
|
||||
strcpy(me.map_d, chunk.tex_d.name);
|
||||
strcpy(me.map_o, chunk.tex_o.name);
|
||||
strcpy(me.map_b, chunk.tex_b.name);
|
||||
strcpy(me.map_s, chunk.tex_s.name);
|
||||
strcpy(me.map_g, chunk.tex_g.name);
|
||||
strcpy(me.map_c, chunk.tex_c.name);
|
||||
strcpy(me.map_e, chunk.tex_rl.name);
|
||||
strcpy(me.map_rr, chunk.tex_rr.name);
|
||||
strcpy(me.map_det, chunk.tex_det.name);
|
||||
*/
|
||||
me.map_a = chunk.tex_a;
|
||||
me.map_d = chunk.tex_d;
|
||||
me.map_o = chunk.tex_o;
|
||||
me.map_b = chunk.tex_b;
|
||||
me.map_s = chunk.tex_s;
|
||||
me.map_g = chunk.tex_g;
|
||||
me.map_detail = chunk.tex_fl;
|
||||
me.map_e = chunk.tex_rl;
|
||||
me.map_subsurf = chunk.tex_subsurf;
|
||||
me.map_displ = chunk.tex_det;
|
||||
|
||||
me.nChildren = chunk.nChildren;
|
||||
|
||||
m_lstMaterials.Add(me);
|
||||
break;
|
||||
|
||||
/* case MTL_MULTI:
|
||||
me.IsStdMat = 0;
|
||||
me.nChildren = chunk.nChildren;
|
||||
me.children = new int [chunk.nChildren];
|
||||
int res=f->FRead(me.children,sizeof(int),chunk.nChildren);
|
||||
if (res != chunk.nChildren)
|
||||
return;*/
|
||||
}
|
||||
}
|
||||
else
|
||||
if (ch.ChunkVersion == MTL_CHUNK_DESC_0745::VERSION)
|
||||
{
|
||||
f->FSeek(pos,SEEK_SET);
|
||||
MTL_CHUNK_DESC_0745 chunk;
|
||||
int res=f->FRead(&chunk,1,sizeof(chunk));
|
||||
if(res!=sizeof(chunk))
|
||||
return;
|
||||
|
||||
MAT_ENTITY me;
|
||||
memset(&me, 0, sizeof(MAT_ENTITY));
|
||||
me.opacity = 1.0f;
|
||||
me.alpharef = 0;
|
||||
me.m_New = 1;
|
||||
strcpy(me.name, chunk.name);
|
||||
switch (chunk.MtlType)
|
||||
{
|
||||
case MTL_STANDARD:
|
||||
me.IsStdMat = true;
|
||||
me.col_d = chunk.col_d;
|
||||
me.col_a = chunk.col_a;
|
||||
me.col_s = chunk.col_s;
|
||||
|
||||
me.specLevel = chunk.specLevel;
|
||||
me.specShininess = chunk.specShininess*100;
|
||||
me.opacity = chunk.opacity;
|
||||
me.selfIllum = chunk.selfIllum;
|
||||
me.flags = chunk.flags;
|
||||
|
||||
me.Dyn_Bounce = chunk.Dyn_Bounce;
|
||||
me.Dyn_StaticFriction = chunk.Dyn_StaticFriction;
|
||||
me.Dyn_SlidingFriction = chunk.Dyn_SlidingFriction;
|
||||
/* //Timur[10/24/2001]
|
||||
strcpy(me.map_a, chunk.tex_a.name);
|
||||
strcpy(me.map_d, chunk.tex_d.name);
|
||||
strcpy(me.map_o, chunk.tex_o.name);
|
||||
strcpy(me.map_b, chunk.tex_b.name);
|
||||
strcpy(me.map_s, chunk.tex_s.name);
|
||||
strcpy(me.map_g, chunk.tex_g.name);
|
||||
strcpy(me.map_c, chunk.tex_c.name);
|
||||
strcpy(me.map_e, chunk.tex_rl.name);
|
||||
strcpy(me.map_rr, chunk.tex_rr.name);
|
||||
strcpy(me.map_det, chunk.tex_det.name);
|
||||
*/
|
||||
me.map_a = chunk.tex_a;
|
||||
me.map_d = chunk.tex_d;
|
||||
me.map_o = chunk.tex_o;
|
||||
me.map_b = chunk.tex_b;
|
||||
me.map_s = chunk.tex_s;
|
||||
me.map_g = chunk.tex_g;
|
||||
me.map_detail = chunk.tex_c;
|
||||
me.map_e = chunk.tex_rl;
|
||||
me.map_subsurf = chunk.tex_subsurf;
|
||||
me.map_displ = chunk.tex_det;
|
||||
|
||||
me.nChildren = chunk.nChildren;
|
||||
|
||||
m_lstMaterials.Add(me);
|
||||
break;
|
||||
|
||||
/* case MTL_MULTI:
|
||||
me.IsStdMat = 0;
|
||||
me.nChildren = chunk.nChildren;
|
||||
me.children = new int [chunk.nChildren];
|
||||
int res=f->FRead(me.children,sizeof(int),chunk.nChildren);
|
||||
if (res != chunk.nChildren)
|
||||
return;*/
|
||||
}
|
||||
}
|
||||
else
|
||||
if (ch.ChunkVersion == MTL_CHUNK_DESC_0744::VERSION)
|
||||
{
|
||||
f->FSeek(pos,SEEK_SET);
|
||||
MTL_CHUNK_DESC_0744 chunk;
|
||||
int res=f->FRead(&chunk,1,sizeof(chunk));
|
||||
if(res!=sizeof(chunk))
|
||||
return;
|
||||
|
||||
MAT_ENTITY me;
|
||||
memset(&me, 0, sizeof(MAT_ENTITY));
|
||||
me.opacity = 1.0f;
|
||||
me.alpharef = 0;
|
||||
strcpy(me.name, chunk.name);
|
||||
switch (chunk.MtlType)
|
||||
{
|
||||
case MTL_STANDARD:
|
||||
me.IsStdMat = true;
|
||||
me.col_d = chunk.col_d;
|
||||
me.col_a = chunk.col_a;
|
||||
me.col_s = chunk.col_s;
|
||||
me.Dyn_Bounce = chunk.Dyn_Bounce;
|
||||
me.Dyn_StaticFriction = chunk.Dyn_StaticFriction;
|
||||
me.Dyn_SlidingFriction = chunk.Dyn_SlidingFriction;
|
||||
strcpy(me.map_d.name, chunk.tex_d.name);
|
||||
strcpy(me.map_o.name, chunk.tex_o.name);
|
||||
strcpy(me.map_b.name, chunk.tex_b.name);
|
||||
me.nChildren = chunk.nChildren;
|
||||
|
||||
m_lstMaterials.Add(me);
|
||||
break;
|
||||
|
||||
case MTL_MULTI:
|
||||
me.IsStdMat = 0;
|
||||
me.nChildren = chunk.nChildren;
|
||||
me.m_pMaterialChildren = new int [chunk.nChildren];//leak
|
||||
int res=f->FRead(me.m_pMaterialChildren,sizeof(int),chunk.nChildren);
|
||||
if (res != chunk.nChildren)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CryStaticModel::OnLoadgeom(char * FileName, const char * szGeomName, bool bLoadMats, bool bKeepInLocalSpace)
|
||||
{
|
||||
CXFile * f = new CXFile();
|
||||
|
||||
// preload all data
|
||||
if(!f->FLoad(FileName))
|
||||
{
|
||||
delete f; return 0;
|
||||
}
|
||||
|
||||
//read the file header
|
||||
FILE_HEADER fh;
|
||||
int res = f->FRead(&fh,sizeof(fh),1);
|
||||
if(res!=1)
|
||||
return 0;
|
||||
|
||||
if(fh.Version != GeomFileVersion)
|
||||
{
|
||||
f->FClose(); delete f; f=0;
|
||||
m_pLog->LogError("CryStaticModel::OnLoadgeom: CGF file version error: %s", FileName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(fh.FileType != FileType_Geom)
|
||||
{
|
||||
f->FClose(); delete f; f=0;
|
||||
m_pLog->LogError("OnLoadgeom: CGF file type error: %s", FileName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//read the chunk table
|
||||
f->FSeek(fh.ChunkTableOffset,SEEK_SET);
|
||||
int n_chunks=100000;
|
||||
res = f->FRead(&n_chunks,sizeof(n_chunks),1);
|
||||
if(res!=1)
|
||||
return 0;
|
||||
|
||||
if(n_chunks>=100000)
|
||||
{
|
||||
f->FClose(); delete f; f=0;
|
||||
m_pLog->LogError("CryStaticModel::OnLoadgeom: File corrupted: %s, (n_chunks>=100000)", FileName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CHUNK_HEADER * pChunks;
|
||||
pChunks=(CHUNK_HEADER *)malloc(sizeof(CHUNK_HEADER)*n_chunks);
|
||||
assert(pChunks);
|
||||
res = f->FRead(pChunks,sizeof(CHUNK_HEADER),n_chunks);
|
||||
if(res!=n_chunks)
|
||||
return 0;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Create and load objects
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
m_ppNewObjs = (CBaseObj **)malloc(n_chunks*sizeof(CBaseObj*));
|
||||
memset(m_ppNewObjs,0,n_chunks*sizeof(CBaseObj*));
|
||||
|
||||
assert(m_ppNewObjs);
|
||||
m_nNewObjs=0;
|
||||
|
||||
int nGeomToLoadID = -1;
|
||||
|
||||
int i;
|
||||
for(i=0;i<n_chunks;i++)
|
||||
{
|
||||
switch(pChunks[i].ChunkType)
|
||||
{
|
||||
case ChunkType_Node:
|
||||
m_ppNewObjs[m_nNewObjs]=new CNodeCGF();
|
||||
break;
|
||||
|
||||
case ChunkType_Mesh:
|
||||
if(!szGeomName || nGeomToLoadID == i)
|
||||
m_ppNewObjs[m_nNewObjs]=new CGeom();
|
||||
break;
|
||||
|
||||
case ChunkType_Helper:
|
||||
m_ppNewObjs[m_nNewObjs]=new CHelper();
|
||||
break;
|
||||
|
||||
case ChunkType_Light:
|
||||
m_ppNewObjs[m_nNewObjs]=new CLight();
|
||||
break;
|
||||
|
||||
case ChunkType_Mtl:
|
||||
if(bLoadMats)
|
||||
LoadMaterials(f,pChunks[i].FileOffset);
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_ppNewObjs[m_nNewObjs])
|
||||
{
|
||||
m_ppNewObjs[m_nNewObjs]->Load(f,pChunks[i].FileOffset);
|
||||
|
||||
// find chunk id of needed geom
|
||||
if(pChunks[i].ChunkType == ChunkType_Node)
|
||||
if(szGeomName && strcmp(szGeomName,((CNodeCGF*)m_ppNewObjs[m_nNewObjs])->m_Chunk.name)==0)
|
||||
nGeomToLoadID = ((CNodeCGF*)m_ppNewObjs[m_nNewObjs])->m_Chunk.ObjectID;
|
||||
|
||||
m_nNewObjs++;
|
||||
}
|
||||
}
|
||||
|
||||
//Do pointer and name list bindings
|
||||
for(i=0;i<m_nNewObjs;i++)
|
||||
{
|
||||
if(!m_ppNewObjs[i])
|
||||
continue;
|
||||
m_ppNewObjs[i]->Bind(m_ppNewObjs, m_nNewObjs);
|
||||
}
|
||||
|
||||
f->FClose(); delete f; f=0;
|
||||
|
||||
if(pChunks)
|
||||
free(pChunks);
|
||||
pChunks=0;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Make objects
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
list2<NAME_ENTITY> lstOtherNames;
|
||||
|
||||
for( i=0; i<m_nNewObjs; i++)
|
||||
{
|
||||
CNodeCGF * pNode = (CNodeCGF*)m_ppNewObjs[i];
|
||||
|
||||
if(pNode->m_ChunkHeader.ChunkType != ChunkType_Node)
|
||||
continue;
|
||||
|
||||
// make list of mesh names
|
||||
NAME_ENTITY geomname;
|
||||
strcpy(geomname.name, pNode->m_Chunk.name);
|
||||
lstOtherNames.Add(geomname);
|
||||
|
||||
if(!pNode->m_pObj)
|
||||
continue;
|
||||
|
||||
if(pNode->m_pObj->m_nUsers>1)
|
||||
m_pLog->Log("WARNING: loading of instances from cgf not supported, geom skipped: %s, %s",FileName, pNode->GetName());
|
||||
|
||||
// Accumulate this and all parent nodes transformations
|
||||
// TODO: get rid of the obsolete CryMatrix here
|
||||
|
||||
//CHANGED_BY_IVO
|
||||
//CryMatrix matNodeMatrix = pNode->m_Chunk.tm;
|
||||
Matrix44 matNodeMatrix = pNode->m_Chunk.tm;
|
||||
|
||||
for(CNodeCGF * pCurNode = pNode->m_pParent; pCurNode; pCurNode = pCurNode->m_pParent)
|
||||
//CHANGED_BY_IVO
|
||||
//matNodeMatrix = matNodeMatrix * (CryMatrix&)(pCurNode->m_Chunk.tm);
|
||||
matNodeMatrix = matNodeMatrix * (pCurNode->m_Chunk.tm);
|
||||
|
||||
if(pNode->m_pObj->m_ChunkHeader.ChunkType == ChunkType_Mesh)
|
||||
if(pNode->m_pObj->m_nUsers<=1)
|
||||
{ // geoms
|
||||
// make list of mesh names
|
||||
NAME_ENTITY geomname;
|
||||
strcpy(geomname.name, pNode->m_Chunk.name);
|
||||
m_lstGeomNames.Add(geomname);
|
||||
lstOtherNames.DeleteLast();
|
||||
|
||||
CGeom * pGeom = (CGeom*)pNode->m_pObj;
|
||||
|
||||
// transform geometry from this node space into CGFs space
|
||||
if(!bKeepInLocalSpace)
|
||||
for(int v=0; v<pGeom->m_Chunk.nVerts; v++)
|
||||
{
|
||||
//CHANGED_BY_IVO
|
||||
//pGeom->m_pVertices[v].p = matNodeMatrix*pGeom->m_pVertices[v].p;
|
||||
//pGeom->m_pVertices[v].n = matNodeMatrix/pGeom->m_pVertices[v].n;
|
||||
pGeom->m_pVertices[v].p = matNodeMatrix.TransformPointOLD(pGeom->m_pVertices[v].p);
|
||||
pGeom->m_pVertices[v].n = matNodeMatrix.TransformVectorOLD(pGeom->m_pVertices[v].n);
|
||||
}
|
||||
|
||||
if(!szGeomName || strcmp(pNode->GetName(),szGeomName)==0)
|
||||
m_lstGeoms.Add(pGeom);
|
||||
}
|
||||
|
||||
if(pNode->m_pObj->m_ChunkHeader.ChunkType == ChunkType_Light)
|
||||
{ // make light
|
||||
CLight * pLight = (CLight*)pNode->m_pObj;
|
||||
|
||||
LightInstance inst;
|
||||
memcpy(&inst.Chunk,&pLight->m_Chunk,sizeof(LIGHT_CHUNK_DESC));
|
||||
inst.Chunk = pLight->m_Chunk;
|
||||
|
||||
if(bKeepInLocalSpace)
|
||||
|
||||
//inst.vPos.Set(&pNode->m_Chunk.pos.x);
|
||||
inst.vPos.Set(pNode->m_Chunk.pos[0],pNode->m_Chunk.pos[1],pNode->m_Chunk.pos[2]);
|
||||
|
||||
else
|
||||
//CHANGED_BY_IVO
|
||||
//inst.vPos = Vec3d(matNodeMatrix.data[3]);
|
||||
inst.vPos = matNodeMatrix.GetTranslationOLD();
|
||||
|
||||
if(!pNode->m_pParent)
|
||||
assert( IsEquivalent(pNode->m_Chunk.pos,inst.vPos,VEC_EPSILON) );
|
||||
|
||||
strncpy(inst.szName,pNode->m_Chunk.name, sizeof(inst.szName));
|
||||
|
||||
// load proj texture
|
||||
if(inst.Chunk.szLightImage[0])
|
||||
{
|
||||
assert(0);
|
||||
inst.pLightImage = 0;//GetRenderer()->EF_LoadTexture(inst.Chunk.szLightImage, FT_CLAMP, FT2_FORCECUBEMAP, eTT_Cubemap);
|
||||
if (!inst.pLightImage->IsTextureLoaded())
|
||||
inst.pLightImage = NULL;
|
||||
}
|
||||
else
|
||||
inst.pLightImage = NULL;
|
||||
|
||||
m_lstLights.Add(inst);
|
||||
}
|
||||
|
||||
if(pNode->m_pObj->m_ChunkHeader.ChunkType == ChunkType_Helper)
|
||||
{ // make helper
|
||||
CHelper * pHelper = (CHelper*)pNode->m_pObj;
|
||||
|
||||
HelperInstance inst;
|
||||
inst.Chunk = pHelper->m_Chunk;
|
||||
|
||||
if(bKeepInLocalSpace)
|
||||
inst.tMat.SetIdentity();
|
||||
else
|
||||
//CHANGED_BY_IVO
|
||||
//inst.tMat = Matrix(matNodeMatrix.matrix);
|
||||
inst.tMat = matNodeMatrix;
|
||||
|
||||
/*
|
||||
if(!pNode->m_pParent)
|
||||
{
|
||||
assert(inst.vPos == pNode->m_Chunk.pos);
|
||||
float dot = inst.qRot.Dot(pNode->m_Chunk.rot);
|
||||
dot=dot;
|
||||
}
|
||||
*/
|
||||
strncpy(inst.szName,pNode->m_Chunk.name, sizeof(inst.szName));
|
||||
m_lstHelpers.Add(inst);
|
||||
}
|
||||
}
|
||||
|
||||
m_lstGeomNames.AddList (lstOtherNames);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
CHelperInstance * CryStaticModel::GetHelper(const char * name)
|
||||
{
|
||||
for(int i=0; i<m_Helpers.Count(); i++)
|
||||
{
|
||||
if(!strcmp(m_Helpers[i].name,name))
|
||||
return &m_Helpers[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
// this timer measures the time spent in the CGF Loader
|
||||
//double g_dTimeLoadCGF;
|
||||
69
ResourceCompilerPC/StatCGFCompiler/CryStaticModel.h
Normal file
69
ResourceCompilerPC/StatCGFCompiler/CryStaticModel.h
Normal file
@@ -0,0 +1,69 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: crystaticmodel.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: cgf file loader
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CryStaticModel_H
|
||||
#define CryStaticModel_H
|
||||
|
||||
class CBaseObj;
|
||||
class CGeom;
|
||||
|
||||
#include "list2.h"
|
||||
|
||||
struct LightInstance
|
||||
{
|
||||
LIGHT_CHUNK_DESC Chunk;
|
||||
Vec3d vPos;
|
||||
char szName[64];
|
||||
struct ITexPic * pLightImage;
|
||||
};
|
||||
|
||||
struct HelperInstance
|
||||
{
|
||||
HELPER_CHUNK_DESC Chunk;
|
||||
char szName[64];
|
||||
Matrix44 tMat;
|
||||
};
|
||||
|
||||
class CXFile;
|
||||
|
||||
struct CryStaticModel
|
||||
{
|
||||
CryStaticModel();
|
||||
~CryStaticModel();
|
||||
|
||||
char m_FileName[256];
|
||||
|
||||
list2<CGeom*> m_lstGeoms;
|
||||
list2<MAT_ENTITY> m_lstMaterials;
|
||||
list2<NAME_ENTITY> m_lstGeomNames;
|
||||
list2<LightInstance> m_lstLights;
|
||||
list2<HelperInstance> m_lstHelpers;
|
||||
|
||||
bool OnLoadgeom(char * filename, const char * geom_name, bool bLoadMats, bool bKeepInLocalSpace);
|
||||
|
||||
float m_fBoundingRadius;
|
||||
float m_fCenterZ;
|
||||
|
||||
void LoadMaterials(CXFile*f, int pos);
|
||||
int m_nNewObjs;
|
||||
CBaseObj ** m_ppNewObjs;
|
||||
ILog * m_pLog;
|
||||
};
|
||||
|
||||
// timers that are used for precision very low cost profiling of load times
|
||||
// this timer measures the time spent in the CGF Loader
|
||||
//extern double g_dTimeLoadCGF;
|
||||
|
||||
#endif // CryStaticModel_H
|
||||
306
ResourceCompilerPC/StatCGFCompiler/File.cpp
Normal file
306
ResourceCompilerPC/StatCGFCompiler/File.cpp
Normal file
@@ -0,0 +1,306 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: file.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: ceached file access
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#ifndef GAMECUBE
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#ifndef _XBOX
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include "windows.h"
|
||||
#endif
|
||||
#else
|
||||
#include <xtl.h>
|
||||
#endif
|
||||
|
||||
#include "File.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
CXFile::CXFile()
|
||||
{
|
||||
m_szFileStart=NULL;
|
||||
m_nFileSize=0;
|
||||
m_pCurrPos=0;
|
||||
m_pEndOfFile=NULL;
|
||||
m_sLoadedFileName[0]=0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int CXFile::FRead(void *pDest,int nSize,int nNumElems)
|
||||
{
|
||||
int nTotSize=nSize*nNumElems;
|
||||
char *pTest=m_pCurrPos+nTotSize;
|
||||
if (pTest>m_pEndOfFile)
|
||||
return (0);
|
||||
|
||||
memcpy(pDest,m_pCurrPos,nTotSize);
|
||||
m_pCurrPos+=nTotSize;
|
||||
return (nNumElems);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int CXFile::FSeek(int nOff,int nFrom)
|
||||
{
|
||||
if (nFrom==SEEK_SET)
|
||||
{
|
||||
m_pCurrPos=m_szFileStart+nOff;
|
||||
if (m_pCurrPos>m_pEndOfFile)
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void CXFile::FClose()
|
||||
{
|
||||
if (m_szFileStart)
|
||||
{
|
||||
delete [] m_szFileStart;
|
||||
m_szFileStart=NULL;
|
||||
}
|
||||
|
||||
m_pCurrPos=NULL;
|
||||
m_nFileSize=0;
|
||||
m_pEndOfFile=NULL;
|
||||
m_sLoadedFileName[0]=0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int CXFile::FLoad(const char * filename)
|
||||
{
|
||||
if(!m_szFileStart || strcmp(m_sLoadedFileName,filename)!=0)
|
||||
{
|
||||
FClose();
|
||||
m_nFileSize=LoadInMemory(filename,(void**)&m_szFileStart);
|
||||
strncpy(m_sLoadedFileName,filename,sizeof(m_sLoadedFileName));
|
||||
}
|
||||
|
||||
m_pCurrPos=m_szFileStart;
|
||||
m_pEndOfFile=m_szFileStart+m_nFileSize;
|
||||
return (m_nFileSize);
|
||||
}
|
||||
|
||||
//get filename's extension
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
char *CXFile::GetExtension(const char *filename)
|
||||
{
|
||||
char *src = (char *)filename+strlen(filename)-1;
|
||||
while (*src)
|
||||
{
|
||||
if (*src == '.')
|
||||
{
|
||||
return (++src);
|
||||
}
|
||||
src--;
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
//remove extension from filename
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void CXFile::RemoveExtension(char *path)
|
||||
{
|
||||
char *src = path+strlen(path)-1;
|
||||
while (*src)
|
||||
{
|
||||
if (*src == '.')
|
||||
{
|
||||
*src = 0; // remove extension
|
||||
return;
|
||||
}
|
||||
src--;
|
||||
}
|
||||
}
|
||||
|
||||
//replace filename extension
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void CXFile::ReplaceExtension(char *path, const char *new_ext)
|
||||
{
|
||||
RemoveExtension(path);
|
||||
strcat(path,".");
|
||||
strcat(path,new_ext);
|
||||
}
|
||||
|
||||
//check if file exist
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
bool CXFile::IsFileExist(const char *filename)
|
||||
{
|
||||
return FileExist(filename);
|
||||
}
|
||||
|
||||
//check if file exist
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
bool CXFile::FileExist(const char *filename)
|
||||
{
|
||||
FILE *fp=fopen(filename,"rb");
|
||||
if (!fp) return (false);
|
||||
fclose(fp);
|
||||
return (true);
|
||||
}
|
||||
|
||||
//get length of the file
|
||||
//return (-1) if error
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int CXFile::GetLength(const char *filename)
|
||||
{
|
||||
FILE *fp=fopen(filename,"rb");
|
||||
if (!fp) return (-1);
|
||||
|
||||
int pos;
|
||||
int end;
|
||||
|
||||
pos = ftell(fp);
|
||||
fseek(fp, 0, SEEK_END);
|
||||
end = ftell(fp);
|
||||
fseek(fp, pos, SEEK_SET);
|
||||
|
||||
fclose(fp);
|
||||
return (end);
|
||||
}
|
||||
|
||||
//tell if filename1 is older than masterfile
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
bool CXFile::IsOutOfDate(const char *pFileName1,const char *pMasterFile)
|
||||
{
|
||||
|
||||
FILE *f=fopen(pMasterFile,"rb");
|
||||
if (f)
|
||||
fclose(f);
|
||||
else
|
||||
return (false);
|
||||
|
||||
f=fopen(pFileName1,"rb");
|
||||
if (f)
|
||||
fclose(f);
|
||||
else
|
||||
return (true);
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
HANDLE status1 = CreateFile(pFileName1,GENERIC_READ,FILE_SHARE_READ,
|
||||
NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);
|
||||
|
||||
HANDLE status2 = CreateFile(pMasterFile,GENERIC_READ,FILE_SHARE_READ,
|
||||
NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);
|
||||
|
||||
FILETIME writetime1,writetime2;
|
||||
|
||||
GetFileTime(status1,NULL,NULL,&writetime1);
|
||||
GetFileTime(status2,NULL,NULL,&writetime2);
|
||||
|
||||
CloseHandle(status1);
|
||||
CloseHandle(status2);
|
||||
|
||||
if (CompareFileTime(&writetime1,&writetime2)==-1)
|
||||
return(true);
|
||||
|
||||
return (false);
|
||||
#else
|
||||
|
||||
return (false);
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int CXFile::GetWriteTime(const char *pFileName1)
|
||||
{
|
||||
FILE *f=fopen(pFileName1,"rb");
|
||||
if (f)
|
||||
fclose(f);
|
||||
else
|
||||
return (0);
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
HANDLE status1 = CreateFile(pFileName1,GENERIC_READ,FILE_SHARE_READ,
|
||||
NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);
|
||||
|
||||
FILETIME writetime1;
|
||||
memset(&writetime1,0,sizeof(writetime1));
|
||||
|
||||
GetFileTime(status1,NULL,NULL,&writetime1);
|
||||
|
||||
CloseHandle(status1);
|
||||
|
||||
return (writetime1.dwHighDateTime + writetime1.dwLowDateTime);
|
||||
#else
|
||||
|
||||
return (0);
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int CXFile::GetLength(FILE *f)
|
||||
{
|
||||
int pos;
|
||||
int end;
|
||||
|
||||
pos = ftell(f);
|
||||
fseek(f, 0, SEEK_END);
|
||||
end = ftell(f);
|
||||
fseek(f, pos, SEEK_SET);
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void CXFile::SafeRead(FILE *f, void *buffer, int count)
|
||||
{
|
||||
(fread(buffer, 1, count, f) != (unsigned)count);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int CXFile::LoadInMemory(const char *filename, void **bufferptr)
|
||||
{
|
||||
FILE *f = fopen(filename,"rb");
|
||||
if (!f)
|
||||
return (0);
|
||||
int length = CXFile::GetLength(f);
|
||||
void *buffer = new char[length+1];
|
||||
|
||||
SafeRead(f, buffer, length);
|
||||
fclose(f);
|
||||
|
||||
char *bbp=(char *)buffer;
|
||||
bbp[length]=0; //null terminated
|
||||
*bufferptr = buffer;
|
||||
return (length);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void CXFile::GetPath(char *path)
|
||||
{
|
||||
char *src = path+strlen(path)-1;
|
||||
while (*src)
|
||||
{
|
||||
if (*src == '\\')
|
||||
{
|
||||
src++;
|
||||
*src = 0; // remove extension
|
||||
return;
|
||||
}
|
||||
src--;
|
||||
}
|
||||
}
|
||||
68
ResourceCompilerPC/StatCGFCompiler/File.h
Normal file
68
ResourceCompilerPC/StatCGFCompiler/File.h
Normal file
@@ -0,0 +1,68 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: file.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: cecahed file access
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PS2
|
||||
#ifndef FILE_H
|
||||
#define FILE_H
|
||||
|
||||
#define MAX_PATH_LENGTH 512
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
class CXFile
|
||||
{
|
||||
public:
|
||||
|
||||
CXFile();
|
||||
~CXFile() { FClose(); }
|
||||
|
||||
int FRead(void *pDest,int nSize,int nNumElems);
|
||||
static void SafeRead(FILE *f, void *buffer, int count);
|
||||
int FSeek(int nOff,int nFrom);
|
||||
int FLoad(const char *filename);
|
||||
void FClose();
|
||||
|
||||
static bool FileExist(const char *filename);
|
||||
static bool IsFileExist(const char *filename);
|
||||
//-1 if file does not exist
|
||||
static int GetLength(const char *filename);
|
||||
static int GetLength(FILE *f);
|
||||
static int LoadInMemory(const char *filename, void **bufferptr);
|
||||
|
||||
static bool IsOutOfDate(const char *pFileName1,const char *pMasterFile);
|
||||
static int GetWriteTime(const char *pFileName1);
|
||||
|
||||
//utils
|
||||
static void RemoveExtension (char *path);
|
||||
static void ReplaceExtension(char *path, const char *new_ext);
|
||||
static char *GetExtension (const char *filename);
|
||||
static char *GetString (FILE *fp,const char *key);
|
||||
static void GetPath(char *path);
|
||||
|
||||
//Tim code
|
||||
static void SetLanguage (const char *command=NULL);
|
||||
static char *ConvertFilename(const char *filename);
|
||||
|
||||
private:
|
||||
|
||||
char *m_szFileStart,*m_pCurrPos,*m_pEndOfFile;
|
||||
int m_nFileSize;
|
||||
char m_sLoadedFileName[512];
|
||||
};
|
||||
|
||||
#endif
|
||||
#else //PS2
|
||||
#include "..\CryCommon\File.h"
|
||||
#endif
|
||||
148
ResourceCompilerPC/StatCGFCompiler/Geom.cpp
Normal file
148
ResourceCompilerPC/StatCGFCompiler/Geom.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: geom.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: loading geometry from cgf
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Geom.h"
|
||||
#include "file.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CGeom::CGeom() : CBaseObj()
|
||||
{
|
||||
memset(&m_Chunk,0,sizeof(m_Chunk));
|
||||
m_pVertices =NULL;
|
||||
m_pFaces =NULL;
|
||||
// m_pLinks =NULL;
|
||||
m_pUVs =NULL;
|
||||
m_sPropstr =NULL;
|
||||
// bones =NULL;
|
||||
m_pTexFaces =NULL;
|
||||
// m_pNumLinks =NULL;
|
||||
// links =NULL;
|
||||
m_pVcols =NULL;
|
||||
// BoneNames =NULL;
|
||||
}
|
||||
|
||||
CGeom::~CGeom()
|
||||
{
|
||||
/* if(links)
|
||||
{
|
||||
for(int i=0;i<m_Chunk.nVerts;i++) if(links[i]) free(links[i]);
|
||||
free(links);
|
||||
}*/
|
||||
|
||||
// if(bones) free(bones);
|
||||
if(m_pFaces) free(m_pFaces);
|
||||
if(m_pVertices)free(m_pVertices);
|
||||
if(m_pUVs) free(m_pUVs);
|
||||
if(m_sPropstr) free(m_sPropstr);
|
||||
// if(nLinks) free(nLinks);
|
||||
if(m_pVcols) free(m_pVcols);
|
||||
if(m_pTexFaces)free(m_pTexFaces);
|
||||
}
|
||||
|
||||
bool CGeom::Load(CXFile *f, int pos)
|
||||
{
|
||||
if(f->FSeek(pos,SEEK_SET)) return true;
|
||||
|
||||
int res=f->FRead(&m_Chunk,sizeof(m_Chunk),1);
|
||||
if(res!=1) return true;
|
||||
|
||||
m_ChunkHeader=m_Chunk.chdr;
|
||||
|
||||
if(m_ChunkHeader.ChunkType != ChunkType_Mesh || m_ChunkHeader.ChunkVersion != MESH_CHUNK_DESC_VERSION)
|
||||
{
|
||||
memset(&m_Chunk,0,sizeof(m_Chunk));
|
||||
return true;
|
||||
}
|
||||
|
||||
//read verts
|
||||
m_pVertices=(CryVertex*)malloc(sizeof(CryVertex)*m_Chunk.nVerts);
|
||||
assert(m_pVertices);
|
||||
res=f->FRead(m_pVertices,sizeof(CryVertex),m_Chunk.nVerts);
|
||||
if(res!=m_Chunk.nVerts) return true;
|
||||
|
||||
//read m_pFaces
|
||||
m_pFaces=(CryFace*)malloc(sizeof(CryFace)*m_Chunk.nFaces);
|
||||
assert(m_pFaces);
|
||||
res=f->FRead(m_pFaces,sizeof(CryFace),m_Chunk.nFaces);
|
||||
if(res!=m_Chunk.nFaces) return true;
|
||||
|
||||
//read tverts
|
||||
if(m_Chunk.nTVerts)
|
||||
{
|
||||
m_pUVs=(CryUV*)malloc(sizeof(CryUV)*m_Chunk.nTVerts);
|
||||
assert(m_pUVs);
|
||||
res=f->FRead(m_pUVs,sizeof(CryUV),m_Chunk.nTVerts);
|
||||
if(res!=m_Chunk.nTVerts) return true;
|
||||
|
||||
// flip tex coords (since it was flipped in max?)
|
||||
for(int t=0; t<m_Chunk.nTVerts; t++)
|
||||
m_pUVs[t].v = 1.f-m_pUVs[t].v;
|
||||
|
||||
//read Tfaces
|
||||
//if(m_Chunk.nVerts != m_Chunk.nTVerts)
|
||||
if(m_Chunk.nVerts != 12 || pos != 692)//hack to make old grass objects working
|
||||
{
|
||||
m_pTexFaces=(CryTexFace*)malloc(sizeof(CryTexFace)*m_Chunk.nFaces);
|
||||
assert(m_pTexFaces);
|
||||
|
||||
res=f->FRead(m_pTexFaces,sizeof(CryTexFace),m_Chunk.nFaces);
|
||||
if(res!=m_Chunk.nFaces) return true;
|
||||
}
|
||||
}
|
||||
|
||||
//read Vertex Colors
|
||||
if(m_Chunk.HasVertexCol)
|
||||
{
|
||||
m_pVcols=(CryIRGB *)malloc(m_Chunk.nVerts*sizeof(CryIRGB));
|
||||
assert(m_pVcols);
|
||||
|
||||
int res=f->FRead(m_pVcols, sizeof(CryIRGB), m_Chunk.nVerts);
|
||||
|
||||
/*
|
||||
for (int k=0;k<m_Chunk.nVerts;k++)
|
||||
{
|
||||
m_pVcols[k].r=255;
|
||||
m_pVcols[k].g=0;
|
||||
m_pVcols[k].b=0;
|
||||
} //k
|
||||
*/
|
||||
|
||||
|
||||
if (res!=m_Chunk.nVerts)
|
||||
return (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pVcols=0;
|
||||
/*
|
||||
m_pVcols=(CryIRGB *)malloc(m_Chunk.nVerts*sizeof(CryIRGB));
|
||||
assert(m_pVcols);
|
||||
|
||||
for (int k=0;k<m_Chunk.nVerts;k++)
|
||||
{
|
||||
m_pVcols[k].r=255;
|
||||
m_pVcols[k].g=0;
|
||||
m_pVcols[k].b=0;
|
||||
} //k
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
return (false);
|
||||
}
|
||||
51
ResourceCompilerPC/StatCGFCompiler/Geom.h
Normal file
51
ResourceCompilerPC/StatCGFCompiler/Geom.h
Normal file
@@ -0,0 +1,51 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: geom.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_GEOM_H__D90B8CB0_DAA4_49C7_8D72_4A73FA38E640__INCLUDED_)
|
||||
#define AFX_GEOM_H__D90B8CB0_DAA4_49C7_8D72_4A73FA38E640__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "baseobj.h"
|
||||
|
||||
class CGeom : public CBaseObj
|
||||
{
|
||||
public:
|
||||
CryVertex *m_pVertices;
|
||||
CryFace *m_pFaces;
|
||||
CryUV *m_pUVs;
|
||||
CryTexFace *m_pTexFaces;
|
||||
CryIRGB *m_pVcols;
|
||||
// int *m_pNumLinks;
|
||||
// CryLink ** m_pLinks;
|
||||
|
||||
char * m_sPropstr;
|
||||
MESH_CHUNK_DESC m_Chunk;
|
||||
|
||||
CGeom();
|
||||
virtual ~CGeom();
|
||||
|
||||
//from BaseObj
|
||||
bool Load(CXFile *f, int pos);
|
||||
|
||||
MESH_CHUNK_DESC * GetChunk() { return &m_Chunk; }
|
||||
|
||||
//CGeom methods
|
||||
void Deform();
|
||||
};
|
||||
|
||||
#endif // !defined(AFX_GEOM_H__D90B8CB0_DAA4_49C7_8D72_4A73FA38E640__INCLUDED_)
|
||||
49
ResourceCompilerPC/StatCGFCompiler/Helper.cpp
Normal file
49
ResourceCompilerPC/StatCGFCompiler/Helper.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: helper.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: loading helper from cgf
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Helper.h"
|
||||
#include "file.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CHelper::CHelper() : CBaseObj()
|
||||
{
|
||||
memset(&m_Chunk,0,sizeof(m_Chunk));
|
||||
}
|
||||
|
||||
CHelper::~CHelper()
|
||||
{
|
||||
}
|
||||
|
||||
bool CHelper::Load(CXFile *f, int pos)
|
||||
{
|
||||
if(f->FSeek(pos,SEEK_SET)) return true;
|
||||
|
||||
int res=f->FRead(&m_Chunk,sizeof(m_Chunk),1);
|
||||
if(res!=1) return true;
|
||||
|
||||
if(m_Chunk.chdr.ChunkType != ChunkType_Helper || m_Chunk.chdr.ChunkVersion != HELPER_CHUNK_DESC_VERSION)
|
||||
{
|
||||
memset(&m_Chunk,0,sizeof(m_Chunk));
|
||||
return true;
|
||||
}
|
||||
|
||||
m_ChunkHeader=m_Chunk.chdr;
|
||||
|
||||
return false;
|
||||
}
|
||||
36
ResourceCompilerPC/StatCGFCompiler/Helper.h
Normal file
36
ResourceCompilerPC/StatCGFCompiler/Helper.h
Normal file
@@ -0,0 +1,36 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: helper.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_HELPER_H__3A967DC3_988F_4A67_BC33_AC26573B86FA__INCLUDED_)
|
||||
#define AFX_HELPER_H__3A967DC3_988F_4A67_BC33_AC26573B86FA__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "BaseObj.h"
|
||||
|
||||
class CHelper : public CBaseObj
|
||||
{
|
||||
public:
|
||||
HELPER_CHUNK_DESC m_Chunk;
|
||||
|
||||
CHelper();
|
||||
virtual ~CHelper();
|
||||
|
||||
virtual bool Load(CXFile *f, int pos);
|
||||
};
|
||||
|
||||
#endif // !defined(AFX_HELPER_H__3A967DC3_988F_4A67_BC33_AC26573B86FA__INCLUDED_)
|
||||
49
ResourceCompilerPC/StatCGFCompiler/Light.cpp
Normal file
49
ResourceCompilerPC/StatCGFCompiler/Light.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: light.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: loading light source from cgf
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Light.h"
|
||||
#include "file.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CLight::CLight()
|
||||
{
|
||||
memset(&m_Chunk,0,sizeof(m_Chunk));
|
||||
}
|
||||
|
||||
CLight::~CLight()
|
||||
{
|
||||
}
|
||||
|
||||
bool CLight::Load(CXFile *f, int pos)
|
||||
{
|
||||
if(f->FSeek(pos,SEEK_SET)) return true;
|
||||
|
||||
int res=f->FRead(&m_Chunk,sizeof(m_Chunk),1);
|
||||
if(res!=1) return true;
|
||||
|
||||
if(m_Chunk.chdr.ChunkType != ChunkType_Light || m_Chunk.chdr.ChunkVersion != LIGHT_CHUNK_DESC_VERSION)
|
||||
{
|
||||
memset(&m_Chunk,0,sizeof(m_Chunk));
|
||||
return true;
|
||||
}
|
||||
|
||||
m_ChunkHeader=m_Chunk.chdr;
|
||||
|
||||
return false;
|
||||
}
|
||||
36
ResourceCompilerPC/StatCGFCompiler/Light.h
Normal file
36
ResourceCompilerPC/StatCGFCompiler/Light.h
Normal file
@@ -0,0 +1,36 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: light.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_LIGHT_H__ACF97045_6471_4C13_BC9F_F26C16A0590E__INCLUDED_)
|
||||
#define AFX_LIGHT_H__ACF97045_6471_4C13_BC9F_F26C16A0590E__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "BaseObj.h"
|
||||
|
||||
class CLight : public CBaseObj
|
||||
{
|
||||
public:
|
||||
LIGHT_CHUNK_DESC m_Chunk;
|
||||
|
||||
CLight();
|
||||
virtual ~CLight();
|
||||
|
||||
virtual bool Load(CXFile *f, int pos);
|
||||
};
|
||||
|
||||
#endif // !defined(AFX_LIGHT_H__ACF97045_6471_4C13_BC9F_F26C16A0590E__INCLUDED_)
|
||||
1224
ResourceCompilerPC/StatCGFCompiler/Meshidx.cpp
Normal file
1224
ResourceCompilerPC/StatCGFCompiler/Meshidx.cpp
Normal file
File diff suppressed because it is too large
Load Diff
125
ResourceCompilerPC/StatCGFCompiler/Node.cpp
Normal file
125
ResourceCompilerPC/StatCGFCompiler/Node.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: node.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: loading node info from cgf
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "Node.h"
|
||||
#include "Geom.h"
|
||||
#include "file.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CNodeCGF::CNodeCGF() : CBaseObj()
|
||||
{
|
||||
m_pObj = NULL;
|
||||
// m_sPropStr = NULL;
|
||||
// m_ppChildren = NULL;
|
||||
// m_pnChildrenIds= NULL;
|
||||
m_pParent = NULL;
|
||||
// m_pMtl = NULL;
|
||||
// m_pConRot = NULL;
|
||||
// m_pConPos = NULL;
|
||||
// m_pConScl = NULL;
|
||||
memset(&m_Chunk,0,sizeof(m_Chunk));
|
||||
}
|
||||
|
||||
CNodeCGF::~CNodeCGF()
|
||||
{
|
||||
// if(m_ppChildren) free(m_ppChildren);
|
||||
// if(m_pnChildrenIds) free(m_pnChildrenIds);
|
||||
// if(m_sPropStr) free(m_sPropStr);
|
||||
}
|
||||
|
||||
bool CNodeCGF::Load(CXFile *f, int pos)
|
||||
{
|
||||
if(f->FSeek(pos,SEEK_SET)) return true;
|
||||
|
||||
int res=f->FRead(&m_Chunk,sizeof(m_Chunk),1);
|
||||
if(res!=1) return true;
|
||||
|
||||
if(m_Chunk.chdr.ChunkType != ChunkType_Node || m_Chunk.chdr.ChunkVersion != NODE_CHUNK_DESC_VERSION)
|
||||
{
|
||||
memset(&m_Chunk,0,sizeof(m_Chunk));
|
||||
return true;
|
||||
}
|
||||
|
||||
m_ChunkHeader=m_Chunk.chdr;
|
||||
// m_NodeMatrix = m_Chunk.tm;
|
||||
|
||||
//read propstr
|
||||
/* if(m_Chunk.PropStrLen)
|
||||
{
|
||||
m_sPropStr=(char*)malloc(m_Chunk.PropStrLen+1);
|
||||
assert(m_sPropStr);
|
||||
res=f->FRead(m_sPropStr,m_Chunk.PropStrLen,1);
|
||||
m_sPropStr[m_Chunk.PropStrLen]=0;
|
||||
if(res!=1) return true;
|
||||
}*/
|
||||
|
||||
//read m_ppChildren
|
||||
/* if(m_Chunk.nChildren)
|
||||
{
|
||||
m_pnChildrenIds = (int*) malloc(m_Chunk.nChildren*sizeof(int));
|
||||
assert(m_pnChildrenIds);
|
||||
|
||||
m_ppChildren = (CNodeCGF **) malloc(m_Chunk.nChildren*sizeof(CNodeCGF*));
|
||||
assert(m_pnChildrenIds);
|
||||
memset(m_ppChildren,0,m_Chunk.nChildren*sizeof(CNodeCGF*));
|
||||
|
||||
int res=f->FRead(m_pnChildrenIds,sizeof(int),m_Chunk.nChildren);
|
||||
if(res!=m_Chunk.nChildren) return true;
|
||||
}*/
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CNodeCGF::Bind(CBaseObj ** all_objects, int n_obj)
|
||||
{
|
||||
if(m_bBinded)
|
||||
return;
|
||||
|
||||
for(int i=0;i<n_obj;i++)
|
||||
{
|
||||
CBaseObj * o = all_objects[i];
|
||||
if(!o || o->m_ChunkHeader.ChunkID == -1)
|
||||
continue;
|
||||
|
||||
if(o->m_ChunkHeader.ChunkID == m_Chunk.ObjectID)
|
||||
{
|
||||
m_pObj = o;
|
||||
o->m_nUsers++;
|
||||
}
|
||||
else if(o->m_ChunkHeader.ChunkID == m_Chunk.ParentID)
|
||||
m_pParent=(CNodeCGF *)o; /*
|
||||
else if(o->m_ChunkHeader.ChunkID == m_Chunk.MatID)
|
||||
m_pMtl=o;
|
||||
else if(o->m_ChunkHeader.ChunkID == m_Chunk.pos_cont_id)
|
||||
m_pConPos=(Controller *)o;
|
||||
else if(o->m_ChunkHeader.ChunkID == m_Chunk.rot_cont_id)
|
||||
m_pConRot=(Controller *)o;
|
||||
else if(o->m_ChunkHeader.ChunkID == m_Chunk.scl_cont_id)
|
||||
m_pConScl=(Controller *)o;
|
||||
|
||||
for(int j=0;j<m_Chunk.nChildren;j++)
|
||||
{
|
||||
if(o->m_ChunkHeader.ChunkID == m_pnChildrenIds[j])
|
||||
m_ppChildren[j]=(CNodeCGF *)o;
|
||||
}*/
|
||||
}
|
||||
|
||||
m_bBinded = true;
|
||||
}
|
||||
51
ResourceCompilerPC/StatCGFCompiler/Node.h
Normal file
51
ResourceCompilerPC/StatCGFCompiler/Node.h
Normal file
@@ -0,0 +1,51 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: node.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_NODE_H__8DFD8741_DBA1_4357_9F50_8E37EA039BCB__INCLUDED_)
|
||||
#define AFX_NODE_H__8DFD8741_DBA1_4357_9F50_8E37EA039BCB__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "BaseObj.h"
|
||||
|
||||
class Controller;
|
||||
|
||||
class CNodeCGF : public CBaseObj
|
||||
{
|
||||
public:
|
||||
NODE_CHUNK_DESC m_Chunk;
|
||||
// int *m_pnChildrenIds;
|
||||
|
||||
CBaseObj *m_pObj;
|
||||
/* char *m_sPropStr;
|
||||
CNodeCGF ** m_ppChildren;*/
|
||||
CNodeCGF *m_pParent;
|
||||
/*CBaseObj *m_pMtl;
|
||||
Controller *m_pConPos,*m_pConRot,*m_pConScl;*/
|
||||
// CryMatrix m_NodeMatrix;
|
||||
|
||||
CNodeCGF();
|
||||
virtual ~CNodeCGF();
|
||||
|
||||
virtual bool Load(CXFile *f, int pos);
|
||||
virtual void Bind(CBaseObj **all_objects, int n_obj);
|
||||
|
||||
char * GetName() { return m_Chunk.name; }
|
||||
float * GetMatrixData() { return m_Chunk.tm.GetData(); }
|
||||
};
|
||||
|
||||
#endif // !defined(AFX_NODE_H__8DFD8741_DBA1_4357_9F50_8E37EA039BCB__INCLUDED_)
|
||||
362
ResourceCompilerPC/StatCGFCompiler/StatCGFCompiler.cpp
Normal file
362
ResourceCompilerPC/StatCGFCompiler/StatCGFCompiler.cpp
Normal file
@@ -0,0 +1,362 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: StatCGFCompiler.cpp
|
||||
// Version: v1.00
|
||||
// Created: 5/11/2002 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
#include <DbgHelp.h>
|
||||
#include "ConvertContext.h"
|
||||
#include "iconfig.h"
|
||||
#include "StatCGFCompiler.h"
|
||||
#define ISystem IRCLog
|
||||
#include "meshidx.h"
|
||||
#include "statcgfshadvol.h"
|
||||
|
||||
CStatCFGCompiler::CStatCFGCompiler(void)
|
||||
{
|
||||
}
|
||||
|
||||
CStatCFGCompiler::~CStatCFGCompiler(void)
|
||||
{
|
||||
}
|
||||
|
||||
// function for creating this from outside (without including StatCGFCompiler.h)
|
||||
IConvertor* NewStatCGFCompiler()
|
||||
{
|
||||
return new CStatCFGCompiler();
|
||||
}
|
||||
|
||||
void CStatCFGCompiler::FindDependencies( CIndexedMesh * pIndexedMesh, ConvertContext &cc )
|
||||
{
|
||||
cc.pLog->Log("Finding dependencies");
|
||||
|
||||
for(int m=0; m<pIndexedMesh->m_lstMatTable.Count(); m++)
|
||||
{
|
||||
CMatInfo &ref=pIndexedMesh->m_lstMatTable[m];
|
||||
|
||||
const char *szMatName=ref.GetName();
|
||||
const char *szScriptName=ref.sScriptMaterial;
|
||||
|
||||
CString sourceFile = cc.getSourcePath();
|
||||
|
||||
cc.pRC->AddDependencyMaterial(sourceFile.GetString(),szMatName,szScriptName); // material name
|
||||
|
||||
if(!ref.pMatEnt)continue;
|
||||
|
||||
// texture path names
|
||||
#define ADD_MAP(MAP) if (ref.pMatEnt->map_##MAP.name[0]) cc.pRC->AddDependencyFile(sourceFile.GetString(),ref.pMatEnt->map_##MAP.name);
|
||||
ADD_MAP(a);
|
||||
ADD_MAP(d);
|
||||
ADD_MAP(o);
|
||||
ADD_MAP(b);
|
||||
ADD_MAP(s);
|
||||
ADD_MAP(g);
|
||||
ADD_MAP(detail);
|
||||
ADD_MAP(e);
|
||||
ADD_MAP(subsurf);
|
||||
ADD_MAP(displ);
|
||||
#undef ADD_MAP
|
||||
}
|
||||
}
|
||||
|
||||
FILETIME UnixTimeToFileTime(time_t t)
|
||||
{
|
||||
// Note that LONGLONG is a 64-bit value
|
||||
LONGLONG ll = Int32x32To64(t, 10000000) + 116444736000000000;
|
||||
return (FILETIME&)ll;
|
||||
}
|
||||
|
||||
|
||||
// returns the file modification time
|
||||
FILETIME GetModificationTime(FILE* hFile)
|
||||
{
|
||||
struct _stat st;
|
||||
_fstat(_fileno(hFile), &st);
|
||||
#ifdef _DEBUG
|
||||
const char* szTest = ctime (&st.st_mtime);
|
||||
#endif
|
||||
return UnixTimeToFileTime (st.st_mtime);
|
||||
}
|
||||
|
||||
|
||||
bool CStatCFGCompiler::GetSourceFileTime(const char * szFileName, FILETIME & fileTime)
|
||||
{
|
||||
FILE* f = fopen (szFileName, "rb");
|
||||
if (!f)
|
||||
return false;
|
||||
|
||||
fileTime = GetModificationTime(f);
|
||||
fclose (f);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CStatCFGCompiler::GetFileParams( ConvertContext &cc, CString & sGeomName,
|
||||
bool & bStripify, bool & bLoadAdditinalInfo, bool & bKeepInLocalSpace)
|
||||
{
|
||||
cc.config->Get("GeomName",sGeomName); // subobject name
|
||||
cc.config->Get("Stripify",bStripify); // sort for vertex ceache
|
||||
cc.config->Get("LoadAdditinalInfo",bLoadAdditinalInfo); // load geom names, helpers, lightsources
|
||||
cc.config->Get("KeepInLocalSpace",bKeepInLocalSpace); // do not transform vertices by node matrix
|
||||
}
|
||||
|
||||
bool CStatCFGCompiler::Process( ConvertContext &cc )
|
||||
{
|
||||
try
|
||||
{
|
||||
CString sGeomName;
|
||||
bool bStripify=0, bLoadAdditinalInfo=0, bKeepInLocalSpace=0;
|
||||
GetFileParams( cc, sGeomName, bStripify, bLoadAdditinalInfo, bKeepInLocalSpace);
|
||||
if (!cc.bQuiet)
|
||||
{
|
||||
cc.pLog->Log("Conversion params:");
|
||||
cc.pLog->Log(" GeomName = %s", sGeomName[0] ? sGeomName : "None");
|
||||
cc.pLog->Log(" Stripify = %s", bStripify ? "Yes" : "No");
|
||||
cc.pLog->Log(" LoadAdditinalInfo = %s", bLoadAdditinalInfo ? "Yes" : "No");
|
||||
cc.pLog->Log(" KeepInLocalSpace = %s", bKeepInLocalSpace ? "Yes" : "No");
|
||||
}
|
||||
|
||||
CString sourceFile = cc.getSourcePath();
|
||||
CString outputFile = cc.getOutputPath();
|
||||
|
||||
const char *sInFile = sourceFile.GetString();
|
||||
|
||||
FILETIME fileTime;
|
||||
if(!GetSourceFileTime( sourceFile.GetString(), fileTime))
|
||||
{
|
||||
remove( outputFile.GetString() );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if .cga.
|
||||
if (stricmp(Path::GetExt(cc.sourceFile).GetString(),"cga") == 0)
|
||||
{
|
||||
// Load CGA.
|
||||
ProcessCGA( cc,sourceFile,outputFile,fileTime,bStripify );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load Normal CGF.
|
||||
ProcessCGF( cc,sourceFile,outputFile,fileTime,sGeomName,bStripify,bLoadAdditinalInfo,bKeepInLocalSpace );
|
||||
}
|
||||
}
|
||||
catch(char*)
|
||||
{
|
||||
Beep(1000,1000);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CStatCFGCompiler::ProcessCGA( ConvertContext &cc,CString &sourceFile,CString &outputFile,FILETIME fileTime,bool bStripify )
|
||||
{
|
||||
CString outputFileNoExt = Path::RemoveExtension(cc.sourceFile);
|
||||
CString outputGeomFile;
|
||||
|
||||
int nLoadedTrisCount=0;
|
||||
CIndexedMesh * pIndexedMesh = new CIndexedMesh( cc.pLog,sourceFile.GetString(),0,&nLoadedTrisCount,true,true );
|
||||
if (pIndexedMesh)
|
||||
{
|
||||
for (int i = 0; i < (int)pIndexedMesh->m_lstGeomNames.size(); i++)
|
||||
{
|
||||
CString sOrgGeomName = pIndexedMesh->m_lstGeomNames[i];
|
||||
CString sGeomName = sOrgGeomName;
|
||||
sGeomName.Replace( '\\','_' );
|
||||
sGeomName.Replace( '/','_' );
|
||||
outputGeomFile.Format( "%s_%s_%d_%d_%d.ccgf",outputFileNoExt.GetString(), sGeomName.GetString(),(int)bStripify,1,1 );
|
||||
cc.outputFile = outputGeomFile;
|
||||
outputGeomFile = cc.getOutputPath();
|
||||
const char *sgeom = outputGeomFile.GetString();
|
||||
ProcessCGF( cc,sourceFile,outputGeomFile,fileTime,sOrgGeomName,bStripify,true,true );
|
||||
}
|
||||
}
|
||||
delete pIndexedMesh;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CStatCFGCompiler::ProcessCGF( ConvertContext &cc,CString &sourceFile,CString &outputFile,FILETIME fileTime,CString sGeomName,
|
||||
bool bStripify, bool bLoadAdditinalInfo, bool bKeepInLocalSpace )
|
||||
{
|
||||
// load source cgf
|
||||
int nLoadedTrisCount=0;
|
||||
CIndexedMesh * pIndexedMesh = new CIndexedMesh( cc.pLog, sourceFile.GetString(), sGeomName[0] ? sGeomName.GetString() : 0,
|
||||
&nLoadedTrisCount, bLoadAdditinalInfo, bKeepInLocalSpace);
|
||||
pIndexedMesh->CalcTangentSpace();
|
||||
|
||||
// if geom name was specified - save empty file to let the engine know that this geom does not exits
|
||||
// since passing wrong geom name is valid operation
|
||||
if(!nLoadedTrisCount && !sGeomName[0])
|
||||
cc.pLog->ThrowError(" No faces found");
|
||||
|
||||
// find dependencies (material names, texture path names)
|
||||
FindDependencies( pIndexedMesh, cc );
|
||||
|
||||
// compile data
|
||||
CSimpleStatObj StatObj( cc.pLog, pIndexedMesh, sourceFile.GetString() );
|
||||
CSimpleLeafBuffer LeafBuffer(cc.pLog, pIndexedMesh, bStripify,
|
||||
pIndexedMesh->m_lstGeomNames.Count()>0 && strstr(pIndexedMesh->m_lstGeomNames[0],"cloth")!=0);
|
||||
CStatCGFShadVol StatCGFShadVol(cc.pLog, pIndexedMesh);
|
||||
|
||||
int nPos = 0;
|
||||
|
||||
// get data size
|
||||
if(nLoadedTrisCount)
|
||||
{
|
||||
StatObj.Serialize(nPos, 0, true);
|
||||
LeafBuffer.Serialize(nPos, 0, true, outputFile.GetString() );
|
||||
StatCGFShadVol.Serialize(nPos, 0, true);
|
||||
}
|
||||
|
||||
// allocate mem buffer
|
||||
uchar * pData = new uchar[nPos+sizeof(CCGFHeader)];
|
||||
|
||||
// make header
|
||||
CCGFHeader fileHeader;
|
||||
fileHeader.nDataSize = nPos;
|
||||
fileHeader.nFacesInCGFNum = nLoadedTrisCount;
|
||||
fileHeader.SourceFileTime = fileTime;
|
||||
fileHeader.vBoxMin = pIndexedMesh->m_vBoxMin;
|
||||
fileHeader.vBoxMax = pIndexedMesh->m_vBoxMax;
|
||||
strcpy(fileHeader.szVersion,CCGF_FILE_VERSION);
|
||||
if(StatObj.IsPhysicsExist())
|
||||
fileHeader.dwFlags |= CCGFHF_PHYSICS_EXIST;
|
||||
|
||||
memcpy(pData,&fileHeader,sizeof(CCGFHeader));
|
||||
|
||||
nPos = sizeof(fileHeader);
|
||||
|
||||
// save to new file
|
||||
if(nLoadedTrisCount)
|
||||
{
|
||||
StatObj.Serialize(nPos, pData, true);
|
||||
LeafBuffer.Serialize(nPos, pData, true, outputFile.GetString() );
|
||||
StatCGFShadVol.Serialize(nPos, pData, true);
|
||||
}
|
||||
|
||||
// create folder for object
|
||||
CString srtDirName = cc.getOutputFolderPath();
|
||||
int nFind = -1;
|
||||
while(1)
|
||||
{
|
||||
nFind = srtDirName.Find('\\', nFind+1);
|
||||
if(nFind<0)
|
||||
break;
|
||||
|
||||
CString strSubDirName = srtDirName.Left(nFind);
|
||||
CreateDirectory(strSubDirName.GetString(),NULL);
|
||||
}
|
||||
|
||||
cc.pLog->Log("Writing CCGF: %s", outputFile.GetString() );
|
||||
FILE * f = fopen(outputFile.GetString(),"wb");
|
||||
if(f)
|
||||
{
|
||||
size_t nWriten = fwrite(pData,1,nPos,f);
|
||||
fclose(f);
|
||||
if(nWriten == nPos)
|
||||
cc.pLog->Log(" %d bytes saved", nPos);
|
||||
else
|
||||
cc.pLog->ThrowError(" Error writing output file");
|
||||
}
|
||||
else
|
||||
cc.pLog->ThrowError(" Error opening output file");
|
||||
|
||||
delete pIndexedMesh;
|
||||
delete pData;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// !!! PLZ NEVER CHANGE THIS FILE WITHOUT ASKING VLAD !!!
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
bool CStatCFGCompiler::GetOutputFile( ConvertContext &cc )
|
||||
{
|
||||
bool bStripify=0, bLoadAdditinalInfo=0, bKeepInLocalSpace=0; CString sGeomName;
|
||||
GetFileParams( cc, sGeomName, bStripify, bLoadAdditinalInfo, bKeepInLocalSpace);
|
||||
|
||||
CString outputFileNoExt = Path::ReplaceExtension( cc.sourceFile, "" );
|
||||
|
||||
char szCurDir[MAX_PATH]="";
|
||||
GetCurrentDirectory(MAX_PATH,szCurDir);
|
||||
CString curFolderName = szCurDir;
|
||||
|
||||
cc.outputFolder = cc.masterFolder + CString(CCGF_CACHE_DIR_NAME) + "\\" + cc.outputFolder;
|
||||
//CString outputDirName=Path::ReplacePath(curFolderName, curFolderName + "\\" + CCGF_CACHE_DIR_NAME, outputFileNoExt);
|
||||
|
||||
char szOutputFileName[1024];
|
||||
sprintf(szOutputFileName,
|
||||
"%s_%s_%d_%d_%d.ccgf",
|
||||
outputFileNoExt.GetString(), sGeomName.GetString(),
|
||||
(int)bStripify, (int)bLoadAdditinalInfo, (int)bKeepInLocalSpace);
|
||||
|
||||
//specify output path
|
||||
cc.outputFile = szOutputFileName;
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CStatCFGCompiler::GetNumPlatforms() const
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Platform CStatCFGCompiler::GetPlatform( int index ) const
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0: return PLATFORM_PC;
|
||||
case 1: return PLATFORM_XBOX;
|
||||
//case 2: return PLATFORM_PS2;
|
||||
//case 3: return PLATFORM_GAMECUBE;
|
||||
};
|
||||
//assert(0);
|
||||
return PLATFORM_UNKNOWN;
|
||||
}
|
||||
|
||||
DWORD CStatCFGCompiler::GetTimestamp() const
|
||||
{
|
||||
return GetTimestampForLoadedLibrary(g_hInst);
|
||||
}
|
||||
|
||||
CStatCFGCompiler::Error::Error (const char* szFormat, ...)
|
||||
{
|
||||
char szBuffer[0x800];
|
||||
va_list arg;
|
||||
va_start(arg,szFormat);
|
||||
_vsnprintf (szBuffer, sizeof(szBuffer), szFormat, arg);
|
||||
va_end(arg);
|
||||
this->m_strReason = szBuffer;
|
||||
}
|
||||
|
||||
CStatCFGCompiler::Error::Error (int nCode)
|
||||
{
|
||||
char szBuffer[36];
|
||||
sprintf (szBuffer, "Generic Error #%d", nCode);
|
||||
this->m_strReason = szBuffer;
|
||||
}
|
||||
|
||||
int CStatCFGCompiler::SetTexType(TextureMap3 *tm)
|
||||
{
|
||||
if (tm->type == TEXMAP_CUBIC)
|
||||
return eTT_Cubemap;
|
||||
else
|
||||
if (tm->type == TEXMAP_AUTOCUBIC)
|
||||
return eTT_AutoCubemap;
|
||||
return eTT_Base;
|
||||
}
|
||||
299
ResourceCompilerPC/StatCGFCompiler/StatCGFCompiler.h
Normal file
299
ResourceCompilerPC/StatCGFCompiler/StatCGFCompiler.h
Normal file
@@ -0,0 +1,299 @@
|
||||
#ifndef STAT_CGF_COMPILER
|
||||
#define STAT_CGF_COMPILER
|
||||
|
||||
#include "IConvertor.h"
|
||||
|
||||
struct ConvertContext;
|
||||
class CStatCFGCompiler : public IConvertor
|
||||
{
|
||||
public:
|
||||
class Error
|
||||
{
|
||||
public:
|
||||
Error (int nCode);
|
||||
Error (const char* szFormat, ...);
|
||||
const char* c_str()const {return m_strReason.c_str();}
|
||||
protected:
|
||||
string m_strReason;
|
||||
};
|
||||
|
||||
CStatCFGCompiler(void);
|
||||
~CStatCFGCompiler(void);
|
||||
bool Process( ConvertContext &cc );
|
||||
void Release() { delete this; };
|
||||
bool GetOutputFile( ConvertContext &cc );
|
||||
int GetNumPlatforms() const;
|
||||
Platform GetPlatform( int index ) const;
|
||||
virtual int GetNumExt() const { return 2; };
|
||||
virtual const char* GetExt( int index ) const { return index ? "cga" : "cgf"; };
|
||||
DWORD GetTimestamp() const;
|
||||
bool GetSourceFileTime(const char * szFileName, FILETIME & fileTime);
|
||||
|
||||
protected:
|
||||
int SetTexType(struct TextureMap3 *tm);
|
||||
bool PrepareTexSpaceBasis();
|
||||
void FindDependencies( CIndexedMesh * pIndexedMesh, ConvertContext &cc );
|
||||
void GetFileParams( ConvertContext &cc, CString & sGeomName,
|
||||
bool & bStripify, bool & bLoadAdditinalInfo, bool & bKeepInLocalSpace);
|
||||
void ProcessCGA( ConvertContext &cc,CString &sourceFile,CString &outputFile,FILETIME fileTime,bool bStripify );
|
||||
void ProcessCGF( ConvertContext &cc,CString &sourceFile,CString &outputFile,FILETIME fileTime,CString sGeomName,
|
||||
bool bStripify, bool bLoadAdditinalInfo, bool bKeepInLocalSpace );
|
||||
};
|
||||
|
||||
struct CSimpleREOcLeaf
|
||||
{
|
||||
TArray<SMeshFace> * m_Faces;
|
||||
CMatInfo * m_pChunk;
|
||||
class CSimpleLeafBuffer * m_pBuffer;
|
||||
|
||||
CSimpleREOcLeaf() {memset(this,0,sizeof(CSimpleREOcLeaf));}
|
||||
~CSimpleREOcLeaf()
|
||||
{
|
||||
delete m_Faces;
|
||||
}
|
||||
};
|
||||
|
||||
struct CBasis
|
||||
{
|
||||
CBasis()
|
||||
{
|
||||
tangent(0,0,0);
|
||||
binormal(0,0,0);
|
||||
tnormal(0,0,0);
|
||||
}
|
||||
Vec3d tangent, binormal, tnormal;
|
||||
};
|
||||
|
||||
class CSimpleLeafBuffer
|
||||
{
|
||||
public:
|
||||
CSimpleLeafBuffer(IRCLog * pLog, CIndexedMesh * pIndexedMesh, bool bStripifyAndShareVerts, bool bKeepRemapTable=false);
|
||||
~CSimpleLeafBuffer();
|
||||
bool Serialize(int & nPos, uchar * pSerBuf, bool bSave, const char * szFolderName);
|
||||
// CBasis * m_pBasises;
|
||||
|
||||
protected:
|
||||
void CreateLeafBuffer( CIndexedMesh * pTriData, int Stripify, bool bShareVerts, bool bKeepRemapTable=false );
|
||||
Vec3d *m_TempNormals;
|
||||
SMRendTexVert *m_TempTexCoords;
|
||||
UCol *m_TempColors;
|
||||
int m_SecVertCount;
|
||||
list2<CMatInfo> * m_pMats;
|
||||
|
||||
IRCLog * m_pLog;
|
||||
|
||||
bool compute_tangent( const float * v0, const float * v1, const float * v2,
|
||||
const float * t0, const float * t1, const float * t2,
|
||||
Vec3d & tangent, Vec3d & binormal, Vec3d & tnormal, Vec3d & face_normal);
|
||||
|
||||
void CompactBuffer(struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F * _vbuff, int * _vcount,
|
||||
list2<unsigned short> * pindices, bool bShareVerts[128], uint *uiInfo, CBasis * pBasises);
|
||||
|
||||
list2<unsigned short> *m_pIndices, *m_pIndicesPreStrip;
|
||||
void *m_pD3DIndBuf;
|
||||
list2<unsigned short> & GetIndices() { return *m_pIndices; }
|
||||
CVertexBuffer * m_pSecVertBuffer;
|
||||
void StripifyMesh(int StripType, CBasis *pTangNonStrip);
|
||||
void CalcFaceNormals();
|
||||
bool CreateTangBuffer(CBasis * pBasises);
|
||||
Vec3d * m_pLoadedColors;
|
||||
Vec3d m_vBoxMin, m_vBoxMax;
|
||||
int FindInBuffer(struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F &opt, CBasis &origBasis, uint nMatInfo, uint *uiInfo, struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F* _vbuff, CBasis *_vbasis, int _vcount, list2<unsigned short> * pHash, TArray<uint>& ShareNewInfo);
|
||||
uint * m_arrVertStripMap;
|
||||
int m_nPrimetiveType;
|
||||
bool PrepareTexSpaceBasis();
|
||||
void CorrectTangentBasisesForPolyBump( TangData * pDuplTangData = 0);
|
||||
|
||||
CSimpleLeafBuffer *m_pVertexContainer;
|
||||
CVertexBuffer * m_pVertexBuffer;
|
||||
uint * m_arrVtxMap; //!< [Anton] mapping table leaf buffer vertex idx->original vertex idx
|
||||
|
||||
_inline CSimpleLeafBuffer *GetVertexContainer(void)
|
||||
{
|
||||
if (m_pVertexContainer)
|
||||
return m_pVertexContainer;
|
||||
return this;
|
||||
}
|
||||
|
||||
byte *GetNormalPtr(int& Stride, int Id=0, bool bSys=true)
|
||||
{
|
||||
CSimpleLeafBuffer *lb = GetVertexContainer();
|
||||
byte *pData;
|
||||
SBufInfoTable * pOffs;
|
||||
if (bSys)
|
||||
{
|
||||
pData = (byte *)lb->m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData;
|
||||
pOffs = &gBufInfoTable[lb->m_pSecVertBuffer->m_vertexformat];
|
||||
Stride = m_VertexSize[lb->m_pSecVertBuffer->m_vertexformat];
|
||||
}
|
||||
else
|
||||
{
|
||||
pData = (byte *)lb->m_pVertexBuffer->m_VS[VSF_GENERAL].m_VData;
|
||||
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
||||
Stride = m_VertexSize[lb->m_pVertexBuffer->m_vertexformat];
|
||||
}
|
||||
if (pOffs->OffsNormal)
|
||||
{
|
||||
return &pData[Id*Stride+pOffs->OffsNormal];
|
||||
}
|
||||
|
||||
Stride = sizeof(Vec3d);
|
||||
return (byte*)&lb->m_TempNormals[Id];
|
||||
}
|
||||
|
||||
byte *GetPosPtr(int& Stride, int Id=0, bool bSys=true)
|
||||
{
|
||||
CSimpleLeafBuffer *lb = GetVertexContainer();
|
||||
byte *pData;
|
||||
if (bSys)
|
||||
{
|
||||
pData = (byte *)lb->m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData;
|
||||
Stride = m_VertexSize[lb->m_pSecVertBuffer->m_vertexformat];
|
||||
}
|
||||
else
|
||||
{
|
||||
pData = (byte *)lb->m_pVertexBuffer->m_VS[VSF_GENERAL].m_VData;
|
||||
Stride = m_VertexSize[lb->m_pVertexBuffer->m_vertexformat];
|
||||
}
|
||||
return &pData[Id*Stride];
|
||||
}
|
||||
|
||||
byte *GetBinormalPtr(int& Stride, int Id=0, bool bSys=true)
|
||||
{
|
||||
CSimpleLeafBuffer *lb = GetVertexContainer();
|
||||
byte *pData;
|
||||
if (bSys)
|
||||
{
|
||||
pData = (byte *)lb->m_pSecVertBuffer->m_VS[VSF_TANGENTS].m_VData;
|
||||
}
|
||||
else
|
||||
{
|
||||
pData = (byte *)lb->m_pVertexBuffer->m_VS[VSF_TANGENTS].m_VData;
|
||||
}
|
||||
Stride = sizeof(SPipTangents);
|
||||
return &pData[Id*Stride+12];
|
||||
}
|
||||
byte *GetTangentPtr(int& Stride, int Id=0, bool bSys=true)
|
||||
{
|
||||
CSimpleLeafBuffer *lb = GetVertexContainer();
|
||||
byte *pData;
|
||||
if (bSys)
|
||||
{
|
||||
pData = (byte *)lb->m_pSecVertBuffer->m_VS[VSF_TANGENTS].m_VData;
|
||||
}
|
||||
else
|
||||
{
|
||||
pData = (byte *)lb->m_pVertexBuffer->m_VS[VSF_TANGENTS].m_VData;
|
||||
}
|
||||
Stride = sizeof(SPipTangents);
|
||||
return &pData[Id*Stride];
|
||||
}
|
||||
byte *GetTNormalPtr(int& Stride, int Id=0, bool bSys=true)
|
||||
{
|
||||
CSimpleLeafBuffer *lb = GetVertexContainer();
|
||||
byte *pData;
|
||||
if (bSys)
|
||||
{
|
||||
pData = (byte *)lb->m_pSecVertBuffer->m_VS[VSF_TANGENTS].m_VData;
|
||||
}
|
||||
else
|
||||
{
|
||||
pData = (byte *)lb->m_pVertexBuffer->m_VS[VSF_TANGENTS].m_VData;
|
||||
}
|
||||
Stride = sizeof(SPipTangents);
|
||||
return &pData[Id*Stride+24];
|
||||
}
|
||||
|
||||
byte *GetColorPtr(int & Stride, int Id=0, bool bSys=true)
|
||||
{
|
||||
CSimpleLeafBuffer *lb = GetVertexContainer();
|
||||
SBufInfoTable * pOffs;
|
||||
byte *pData;
|
||||
if (bSys)
|
||||
{
|
||||
pData = (byte *)lb->m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData;
|
||||
pOffs = &gBufInfoTable[lb->m_pSecVertBuffer->m_vertexformat];
|
||||
Stride = m_VertexSize[lb->m_pSecVertBuffer->m_vertexformat];
|
||||
}
|
||||
else
|
||||
{
|
||||
pData = (byte *)lb->m_pVertexBuffer->m_VS[VSF_GENERAL].m_VData;
|
||||
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
||||
Stride = m_VertexSize[lb->m_pVertexBuffer->m_vertexformat];
|
||||
}
|
||||
if (pOffs->OffsColor)
|
||||
{
|
||||
return &pData[Id*Stride+pOffs->OffsColor];
|
||||
}
|
||||
|
||||
Stride = sizeof(UCol);
|
||||
return (byte*)&lb->m_TempColors[Id];
|
||||
}
|
||||
|
||||
byte *GetUVPtr(int & Stride, int Id=0, bool bSys=true)
|
||||
{
|
||||
CSimpleLeafBuffer *lb = GetVertexContainer();
|
||||
SBufInfoTable * pOffs;
|
||||
byte *pData;
|
||||
if (bSys)
|
||||
{
|
||||
pData = (byte *)lb->m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData;
|
||||
pOffs = &gBufInfoTable[lb->m_pSecVertBuffer->m_vertexformat];
|
||||
Stride = m_VertexSize[m_pSecVertBuffer->m_vertexformat];
|
||||
}
|
||||
else
|
||||
{
|
||||
pData = (byte *)lb->m_pVertexBuffer->m_VS[VSF_GENERAL].m_VData;
|
||||
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
||||
Stride = m_VertexSize[m_pVertexBuffer->m_vertexformat];
|
||||
}
|
||||
if (pOffs->OffsTC)
|
||||
{
|
||||
return &pData[Id*Stride+pOffs->OffsTC];
|
||||
}
|
||||
|
||||
Stride = sizeof(SMRendTexVert);
|
||||
return (byte*)&lb->m_TempTexCoords[Id];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CSimpleStatObj
|
||||
{
|
||||
public:
|
||||
CSimpleStatObj(IRCLog * pLog, CIndexedMesh * pTriData, const char*pGeomName)
|
||||
{
|
||||
memset(this,0,sizeof(CSimpleStatObj));
|
||||
m_pLog = pLog;
|
||||
m_pTriData = pTriData;
|
||||
m_pGeomName = (char *)pGeomName;
|
||||
Physicalize();
|
||||
InitGeometry();
|
||||
}
|
||||
void Serialize(int & nPos, uchar * pSerBuf, bool bSave);
|
||||
bool IsPhysicsExist();
|
||||
|
||||
protected:
|
||||
int FindInPosBuffer(const Vec3d & opt, Vec3d * _vbuff, int _vcount, list2<int> * pHash);
|
||||
void CompactPosBuffer(Vec3d * _vbuff, int * _vcount, list2<int> * pindices);
|
||||
|
||||
void Physicalize();
|
||||
void InitGeometry();
|
||||
IRCLog * m_pLog;
|
||||
CIndexedMesh * m_pTriData;
|
||||
char * m_pGeomName;
|
||||
|
||||
// output
|
||||
list2<Vec3d> m_lstProxyVerts[3];
|
||||
list2<int> m_lstProxyInds[3];
|
||||
Vec3d m_vProxyBoxMin[3];
|
||||
Vec3d m_vProxyBoxMax[3];
|
||||
list2<unsigned char> m_lstProxyFaceMaterials[3];
|
||||
|
||||
Vec3d m_vBoxMin, m_vBoxMax;
|
||||
|
||||
list2<struct StatHelperInfo> m_lstHelpers;
|
||||
list2<CDLight> m_lstLSources;
|
||||
};
|
||||
|
||||
#endif
|
||||
913
ResourceCompilerPC/StatCGFCompiler/StatCGFCompilerLB.cpp
Normal file
913
ResourceCompilerPC/StatCGFCompiler/StatCGFCompilerLB.cpp
Normal file
@@ -0,0 +1,913 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: StatCGFCompiler.cpp
|
||||
// Version: v1.00
|
||||
// Created: 5/11/2002 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Dbghelp.h"
|
||||
#include "FileUtil.h"
|
||||
#include "PathUtil.h"
|
||||
#include "..\ResourceCompilerPC.h"
|
||||
|
||||
#include "StatCGFCompiler.h"
|
||||
#include "CryChunkedFile.h"
|
||||
#include "CryHeaders.h"
|
||||
|
||||
#include "NvTriStrip\NvTriStrip.h"
|
||||
|
||||
#include "meshidx.h"
|
||||
#include <IShader.h>
|
||||
#include "Cry_Geo.h"
|
||||
|
||||
CSimpleLeafBuffer::CSimpleLeafBuffer(IRCLog * pLog, CIndexedMesh * pIndexedMesh, bool bStripifyAndShareVerts,bool bKeepRemapTable)
|
||||
{
|
||||
memset(this,0,sizeof(CSimpleLeafBuffer));
|
||||
m_pIndices = new list2<unsigned short>;
|
||||
m_pIndicesPreStrip = new list2<unsigned short>;
|
||||
m_pLog = pLog;
|
||||
|
||||
CreateLeafBuffer(pIndexedMesh,bStripifyAndShareVerts,bStripifyAndShareVerts,bKeepRemapTable);
|
||||
}
|
||||
|
||||
CSimpleLeafBuffer::~CSimpleLeafBuffer()
|
||||
{
|
||||
for (int i=0; m_pMats && i<m_pMats->Count(); i++)
|
||||
{
|
||||
delete (CSimpleREOcLeaf*)(m_pMats->Get(i)->pRE);
|
||||
m_pMats->Get(i)->pRE = 0;
|
||||
delete m_pMats->Get(i)->pMatEnt;
|
||||
m_pMats->Get(i)->pMatEnt=0;
|
||||
delete [] m_pMats->Get(i)->m_pPrimitiveGroups;
|
||||
m_pMats->Get(i)->m_pPrimitiveGroups=0;
|
||||
}
|
||||
|
||||
delete m_pIndices;
|
||||
delete m_pIndicesPreStrip;
|
||||
|
||||
delete m_TempNormals;
|
||||
delete m_TempTexCoords;
|
||||
delete m_TempColors;
|
||||
delete m_pMats;
|
||||
|
||||
delete m_pD3DIndBuf;
|
||||
delete m_pLoadedColors;
|
||||
delete m_arrVertStripMap;
|
||||
|
||||
if (m_pVertexBuffer)
|
||||
{
|
||||
delete m_pVertexBuffer->m_VS[VSF_GENERAL].m_VData;
|
||||
delete m_pVertexBuffer->m_VS[VSF_TANGENTS].m_VData;
|
||||
}
|
||||
|
||||
if (m_pSecVertBuffer)
|
||||
{
|
||||
delete m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData;
|
||||
delete m_pSecVertBuffer->m_VS[VSF_TANGENTS].m_VData;
|
||||
}
|
||||
|
||||
delete m_pVertexContainer;
|
||||
delete m_pVertexBuffer;
|
||||
delete m_pSecVertBuffer;
|
||||
|
||||
if (m_arrVtxMap)
|
||||
delete[] m_arrVtxMap;
|
||||
}
|
||||
|
||||
|
||||
void CSimpleLeafBuffer::CreateLeafBuffer( CIndexedMesh * pTriData, int Stripify, bool bShareVerts, bool bKeepRemapTable )
|
||||
{
|
||||
m_pLog->Log("Processing geometry");
|
||||
|
||||
int max_vert_num = pTriData->m_nFaceCount*3;
|
||||
|
||||
int i;
|
||||
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F * pVBuff = new struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F[max_vert_num];
|
||||
CBasis * pTmpTangBasis = new CBasis[max_vert_num];
|
||||
|
||||
int buff_vert_count = 0;
|
||||
uint *uiInfo = new uint[max_vert_num];
|
||||
|
||||
uint *piVtxIdx = 0; // [Anton] need this to build the mapping table leafbuffer vtx idx->original vtx idx
|
||||
if (bKeepRemapTable)
|
||||
piVtxIdx = new uint[max_vert_num];
|
||||
m_arrVtxMap = 0;
|
||||
|
||||
// . Sort|Group faces by materials
|
||||
// For each shader (designated by shader_id of an element of m_pFaces)
|
||||
// there is one list2 in this table. Each list will contain
|
||||
// set of faces belonging to this shader.
|
||||
list2<CObjFace*> _hash_table[512];
|
||||
bool bShareVertsArr[512];
|
||||
|
||||
m_pMats = new list2<CMatInfo>;
|
||||
m_pMats->PreAllocate(pTriData->m_lstMatTable.Count(),pTriData->m_lstMatTable.Count());
|
||||
*m_pMats = pTriData->m_lstMatTable;
|
||||
|
||||
{ // fill the table: one list of faces per one shader
|
||||
for(int i=0; i<pTriData->m_nFaceCount; i++)
|
||||
{
|
||||
CObjFace * pFace = &pTriData->m_pFaces[i];
|
||||
|
||||
char szMatName[128];
|
||||
strncpy(szMatName, m_pMats->GetAt(pFace->shader_id).pMatEnt->name, 128);
|
||||
strlwr(szMatName);
|
||||
if(strstr(szMatName,"(nodraw)") || strstr(szMatName,"(no_draw)"))
|
||||
continue;
|
||||
|
||||
assert(pFace->shader_id>=0 && pFace->shader_id<512);
|
||||
|
||||
if(pFace->shader_id>=m_pMats->Count())
|
||||
{
|
||||
pFace->shader_id=0;
|
||||
m_pLog->Log("CLeafBuffer::CreateBuffer shader_id of face is out of range");
|
||||
}
|
||||
|
||||
_hash_table[pFace->shader_id].Add(pFace);
|
||||
}
|
||||
}
|
||||
|
||||
// . Create vertex buffer with sequence of (possibly non-unique) vertices, 3 verts per face
|
||||
// for each shader..
|
||||
for (int t = 0; t < m_pMats->Count(); t++)
|
||||
{
|
||||
// memorize the starting index of this material's face range
|
||||
(*m_pMats)[t].nFirstIndexId = buff_vert_count;
|
||||
|
||||
// scan through all the faces using the shader #t
|
||||
for(int i=0; i<_hash_table[t].Count(); ++i)
|
||||
{
|
||||
CObjFace * pFace = _hash_table[t][i];
|
||||
|
||||
assert(pFace->shader_id == t);
|
||||
|
||||
for (int v = 0; v < 3; ++v)
|
||||
{
|
||||
if(pTriData->m_pColor)
|
||||
{ // if color exported - copy from pTriData
|
||||
pVBuff[buff_vert_count].color.bcolor[0] = pTriData->m_pColor[pFace->v[v]].r;
|
||||
pVBuff[buff_vert_count].color.bcolor[1] = pTriData->m_pColor[pFace->v[v]].g;
|
||||
pVBuff[buff_vert_count].color.bcolor[2] = pTriData->m_pColor[pFace->v[v]].b;
|
||||
pVBuff[buff_vert_count].color.bcolor[3] = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
pVBuff[buff_vert_count].color.dcolor = -1;
|
||||
}
|
||||
|
||||
// base tex coord
|
||||
int tid = pFace->t[v];
|
||||
if(tid>=0 && tid<pTriData->m_nCoorCount)
|
||||
{
|
||||
pVBuff[buff_vert_count].st[0] = pTriData->m_pCoors[pFace->t[v]].s;
|
||||
pVBuff[buff_vert_count].st[1] = pTriData->m_pCoors[pFace->t[v]].t;
|
||||
}
|
||||
else
|
||||
{
|
||||
pVBuff[buff_vert_count].st[0] = 0;
|
||||
pVBuff[buff_vert_count].st[1] = 0;
|
||||
}
|
||||
|
||||
// normal
|
||||
pVBuff[buff_vert_count].normal = pTriData->m_pNorms[pFace->n[v]];
|
||||
uiInfo[buff_vert_count] = 0;
|
||||
|
||||
// position
|
||||
pVBuff[buff_vert_count].xyz = pTriData->m_pVerts[pFace->v[v]];
|
||||
|
||||
// remember shader id per face to prevent vertex sharing between materials during recompacting
|
||||
uiInfo[buff_vert_count] |= pFace->shader_id;
|
||||
bShareVertsArr[pFace->shader_id] = bShareVerts;
|
||||
|
||||
// [Anton] keep index list to build mapping table later
|
||||
if (piVtxIdx)
|
||||
piVtxIdx[buff_vert_count] = pFace->v[v];
|
||||
|
||||
// tang basis
|
||||
pTmpTangBasis[buff_vert_count] = pTriData->m_pTangBasis[pFace->b[v]];
|
||||
|
||||
buff_vert_count++;
|
||||
}
|
||||
}
|
||||
|
||||
// there are faces belonging to this material(shader) #t, if number of indices > 0
|
||||
(*m_pMats)[t].nNumIndices = buff_vert_count - (*m_pMats)[t].nFirstIndexId;
|
||||
_hash_table[t].Reset();
|
||||
}
|
||||
|
||||
// make REs
|
||||
for (i=0; i<(*m_pMats).Count(); i++)
|
||||
{
|
||||
if((*m_pMats)[i].nNumIndices)
|
||||
{
|
||||
CSimpleREOcLeaf *re = new CSimpleREOcLeaf; // (CRE OcLeaf *)gRenDev->EF_CreateRE(eDATA_OcLeaf);
|
||||
re->m_pChunk = &(*m_pMats)[i];
|
||||
re->m_pBuffer = this;
|
||||
assert (re->m_pChunk->nNumIndices < 60000);
|
||||
re->m_pChunk->pRE = (CREOcLeaf*)re;
|
||||
|
||||
// always enable sharing if there is 'flareproc' in shader/material name
|
||||
if (!bShareVertsArr[i] && (*m_pMats)[i].nNumIndices == 6)
|
||||
{
|
||||
char nameSh[128];
|
||||
strncpy(nameSh, (*m_pMats)[i].pMatEnt->name,sizeof(nameSh));
|
||||
strlwr(nameSh);
|
||||
bShareVertsArr[i] = strstr(nameSh, "flareproc")!=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// . For each (non-unique) vertex calculate the tangent base
|
||||
/* m_pBasises = buff_vert_count ? new CBasis[buff_vert_count] : 0;
|
||||
for (int n=0; n<buff_vert_count; n+=3)
|
||||
{
|
||||
Vec3d *vN0 = (Vec3d *)(&pVBuff[n+0].nx);
|
||||
Vec3d *vN1 = (Vec3d *)(&pVBuff[n+1].nx);
|
||||
Vec3d *vN2 = (Vec3d *)(&pVBuff[n+2].nx);
|
||||
Vec3d vFaceNormal = *vN0 + *vN1 + *vN2;
|
||||
vFaceNormal.Normalize();
|
||||
|
||||
float *v[3] =
|
||||
{
|
||||
(float *)&pVBuff[n+0].x,
|
||||
(float *)&pVBuff[n+1].x,
|
||||
(float *)&pVBuff[n+2].x,
|
||||
};
|
||||
|
||||
float *tc[3] =
|
||||
{
|
||||
(float *)&pVBuff[n+0].s,
|
||||
(float *)&pVBuff[n+1].s,
|
||||
(float *)&pVBuff[n+2].s,
|
||||
};
|
||||
|
||||
compute_tangent(v[0], v[1], v[2], tc[0], tc[1], tc[2], m_pBasises[n+0].tangent, m_pBasises[n+0].binormal, m_pBasises[n+0].tnormal, vFaceNormal);
|
||||
compute_tangent(v[1], v[2], v[0], tc[1], tc[2], tc[0], m_pBasises[n+1].tangent, m_pBasises[n+1].binormal, m_pBasises[n+1].tnormal, vFaceNormal);
|
||||
compute_tangent(v[2], v[0], v[1], tc[2], tc[0], tc[1], m_pBasises[n+2].tangent, m_pBasises[n+2].binormal, m_pBasises[n+2].tnormal, vFaceNormal);
|
||||
}*/
|
||||
|
||||
// . Index the mesh (Compact Vertices): detect and delete duplicate vertices
|
||||
// remove duplicates
|
||||
if(buff_vert_count)
|
||||
CompactBuffer(pVBuff, &buff_vert_count, &GetIndices(), bShareVertsArr, uiInfo, pTmpTangBasis );
|
||||
|
||||
delete [] uiInfo;
|
||||
uiInfo=0;
|
||||
|
||||
for( i=0; i<GetIndices().Count(); i++ )
|
||||
{
|
||||
if(GetIndices()[i]<buff_vert_count)
|
||||
continue;
|
||||
|
||||
m_pLog->ThrowError("CLeafBuffer::CreateBuffer: Indices out of range");
|
||||
}
|
||||
|
||||
if (bKeepRemapTable) // [Anton] build the mapping table leaf buffer vertex index -> original vertex index
|
||||
{
|
||||
m_arrVtxMap = new uint[buff_vert_count];
|
||||
for( i=0; i<GetIndices().Count(); i++ )
|
||||
m_arrVtxMap[GetIndices()[i]] = piVtxIdx[i];
|
||||
delete[] piVtxIdx;
|
||||
}
|
||||
|
||||
if(buff_vert_count>65535)
|
||||
m_pLog->ThrowError("CLeafBuffer::CreateBuffer: Number of vertices in object is more than 65535");
|
||||
|
||||
// . Remove degenerated triangles in the generated mesh (GetIndices())
|
||||
// FIXME: For some reason this optimization doesn't work for Animated objects (Assertion in CryModelState::GenerateRenderArrays)
|
||||
/*if (!m_sSource || strcmp(m_sSource, "CryModelArray") != 0)
|
||||
{
|
||||
// Remove degenerated triangles
|
||||
list2<ushort> NewIndexes;
|
||||
for (i=0; i<(*m_pMats).Count(); i++) // each material..
|
||||
{
|
||||
CMatInfo *mi = &(*m_pMats)[i];
|
||||
if (!mi->pRE)
|
||||
continue;
|
||||
int nFirstInd = NewIndexes.Count();
|
||||
for (int j=mi->nFirstIndexId; j<mi->nFirstIndexId+mi->nNumIndices; j+=3)
|
||||
{
|
||||
// the face in material #i consists of vertices i0,i1,i2:
|
||||
int i0 = GetIndices()[j+0];
|
||||
int i1 = GetIndices()[j+1];
|
||||
int i2 = GetIndices()[j+2];
|
||||
// if the face is not degenerated, then add it; otherwise skip and finally it'll be deleted
|
||||
if (i0!=i1 && i0!=i2 && i1!=i2)
|
||||
{
|
||||
NewIndexes.Add(i0);
|
||||
NewIndexes.Add(i1);
|
||||
NewIndexes.Add(i2);
|
||||
}
|
||||
}
|
||||
mi->nFirstIndexId = nFirstInd;
|
||||
mi->nNumIndices = NewIndexes.Count() - nFirstInd;
|
||||
if (!mi->nNumIndices)
|
||||
{
|
||||
mi->pRE->Release();
|
||||
mi->pRE = NULL;
|
||||
}
|
||||
}
|
||||
GetIndices().Free();
|
||||
GetIndices().AddList(NewIndexes);
|
||||
NewIndexes.Free();
|
||||
}*/
|
||||
|
||||
// . Find vertex range (both index and spacial ranges) for each material (needed for rendering)
|
||||
for (i=0; i<(*m_pMats).Count(); i++)
|
||||
{
|
||||
CMatInfo *mi = &(*m_pMats)[i];
|
||||
if (!mi->pRE)
|
||||
continue;
|
||||
if (mi->nNumIndices+mi->nFirstIndexId > GetIndices().Count())
|
||||
{ assert(0); continue; }
|
||||
int nMin = 999999;
|
||||
int nMax = -999999;
|
||||
Vec3d vMin;
|
||||
Vec3d vMax;
|
||||
vMin=SetMaxBB();
|
||||
vMax=SetMinBB();
|
||||
for (int j=mi->nFirstIndexId; j<mi->nNumIndices+mi->nFirstIndexId; j++)
|
||||
{
|
||||
int ind = GetIndices()[j];
|
||||
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F *pV = &pVBuff[ind];
|
||||
Vec3d v = pV->xyz;
|
||||
vMin.CheckMin(v);
|
||||
vMax.CheckMax(v);
|
||||
nMin = min(nMin, ind);
|
||||
nMax = max(nMax, ind);
|
||||
}
|
||||
mi->m_vCenter = (vMin + vMax) * 0.5f;
|
||||
mi->m_fRadius = (vMin - mi->m_vCenter).Length();
|
||||
mi->nFirstVertId = nMin;
|
||||
mi->nNumVerts = nMax-nMin+1;
|
||||
}
|
||||
|
||||
// store resulting vertex buffer in system memory
|
||||
m_SecVertCount = buff_vert_count;
|
||||
m_pSecVertBuffer = new CVertexBuffer;
|
||||
m_pSecVertBuffer->m_vertexformat = VERTEX_FORMAT_P3F_N_COL4UB_TEX2F;
|
||||
if(m_SecVertCount)
|
||||
m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData = new struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F[m_SecVertCount];
|
||||
memcpy(m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData, pVBuff, m_SecVertCount*sizeof(struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F));
|
||||
|
||||
delete [] pVBuff;
|
||||
pVBuff=0;
|
||||
|
||||
*m_pIndicesPreStrip = GetIndices();
|
||||
|
||||
if(m_SecVertCount)
|
||||
{
|
||||
if (Stripify!=STRIPTYPE_NONE && !bKeepRemapTable)
|
||||
StripifyMesh(Stripify,pTmpTangBasis);
|
||||
CalcFaceNormals();
|
||||
CreateTangBuffer(pTmpTangBasis);
|
||||
}
|
||||
|
||||
delete [] pTmpTangBasis;
|
||||
pTmpTangBasis=0;
|
||||
|
||||
// if colors was loaded - remember for later use
|
||||
if(pTriData->m_pColor)
|
||||
{
|
||||
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F * pSecBuff = (struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F *)m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData;
|
||||
m_pLoadedColors = new Vec3d[m_SecVertCount];
|
||||
for(int i=0; i<m_SecVertCount; i++)
|
||||
{
|
||||
m_pLoadedColors[i].x = pSecBuff[i].color.bcolor[0];
|
||||
m_pLoadedColors[i].y = pSecBuff[i].color.bcolor[1];
|
||||
m_pLoadedColors[i].z = pSecBuff[i].color.bcolor[2];
|
||||
}
|
||||
}
|
||||
m_vBoxMin = pTriData->m_vBoxMin;
|
||||
m_vBoxMax = pTriData->m_vBoxMax;
|
||||
}
|
||||
|
||||
|
||||
void CSimpleLeafBuffer::CompactBuffer(struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F * _vbuff, int * _vcount,
|
||||
list2<unsigned short> * pindices, bool bShareVerts[128], uint *uiInfo,
|
||||
CBasis * pBasises)
|
||||
{
|
||||
assert(*_vcount);
|
||||
if(!*_vcount)
|
||||
m_pLog->ThrowError("CLeafBuffer::CompactBuffer error");
|
||||
|
||||
int vert_num_before = *_vcount;
|
||||
|
||||
CBasis *tmp_basis = new CBasis[*_vcount];
|
||||
SMRendTexVert *tmp_lmtc = NULL;
|
||||
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F * tmp_buff = new struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F[*_vcount];
|
||||
unsigned int tmp_count = 0;
|
||||
pindices->Clear();
|
||||
TArray<uint> ShareNewInfo;
|
||||
|
||||
list2<unsigned short> hash_table[256];//[256];
|
||||
|
||||
for(unsigned int v=0; v<(unsigned int)(*_vcount); v++)
|
||||
{
|
||||
int nHashInd = (unsigned char)(_vbuff[v].xyz.x*100);
|
||||
uint nMInfo = uiInfo[v];
|
||||
uint nMatId = nMInfo & 255;
|
||||
int find = bShareVerts[nMatId] ? FindInBuffer( _vbuff[v], pBasises[v], nMInfo, uiInfo, tmp_buff, tmp_basis, tmp_count, &hash_table[nHashInd], ShareNewInfo/*[(unsigned char)(_vbuff[v].pos.y*100)]*/) : -1;
|
||||
if(find<0)
|
||||
{ // not found
|
||||
tmp_buff[tmp_count] = _vbuff[v];
|
||||
tmp_basis[tmp_count] = pBasises[v];
|
||||
pindices->Add(tmp_count);
|
||||
ShareNewInfo.AddElem(uiInfo[v]);
|
||||
|
||||
hash_table[(unsigned char)(_vbuff[v].xyz.x*100)]/*[(unsigned char)(_vbuff[v].pos.y*100)]*/.Add(tmp_count);
|
||||
|
||||
tmp_count++;
|
||||
}
|
||||
else
|
||||
{ // found
|
||||
pindices->Add(find);
|
||||
}
|
||||
}
|
||||
|
||||
* _vcount = tmp_count;
|
||||
memcpy( _vbuff, tmp_buff, tmp_count*sizeof(struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F));
|
||||
delete [] tmp_buff;
|
||||
|
||||
// pBasises will contain recompacted tangents now
|
||||
memcpy( pBasises, tmp_basis, tmp_count*sizeof(CBasis) );
|
||||
delete [] tmp_basis;
|
||||
|
||||
// SAFE_DELETE_ARRAY(pBasises);
|
||||
|
||||
int ratio = 100*(*_vcount)/vert_num_before;
|
||||
m_pLog->Log(" Vert buffer size after compression = %d %s ( %d -> %d )", ratio, "%", vert_num_before, *_vcount);
|
||||
}
|
||||
|
||||
#include "NvTriStrip/NVTriStrip.h"
|
||||
|
||||
void CSimpleLeafBuffer::StripifyMesh(int StripType, CBasis *pTangNonStrip)
|
||||
{
|
||||
int i;
|
||||
unsigned int n;
|
||||
|
||||
//Log("Stripify mesh...");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Stripping stuff
|
||||
|
||||
if (StripType == STRIPTYPE_DEFAULT)
|
||||
StripType = STRIPTYPE_ONLYLISTS;//CRenderer::CV_r_stripmesh;
|
||||
|
||||
if (StripType == STRIPTYPE_NONE)
|
||||
return;
|
||||
|
||||
m_pLog->Log(" Sorting vertices for GPU cache");
|
||||
|
||||
// if (gRenDev->GetFeatures() & RFT_HW_GF3)
|
||||
SetCacheSize(CACHESIZE_GEFORCE3);
|
||||
// else
|
||||
// SetCacheSize(CACHESIZE_GEFORCE1_2);
|
||||
if (StripType == STRIPTYPE_SINGLESTRIP)
|
||||
SetStitchStrips(true);
|
||||
else
|
||||
SetStitchStrips(false);
|
||||
SetMinStripSize(0);
|
||||
if (StripType == STRIPTYPE_ONLYLISTS)
|
||||
{
|
||||
SetListsOnly(true);
|
||||
SetStitchStrips(false);
|
||||
}
|
||||
else
|
||||
SetListsOnly(false);
|
||||
|
||||
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F *pVBOld = (struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F *)m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData;
|
||||
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F *pVBNew = new struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F [m_SecVertCount];
|
||||
|
||||
CBasis *pTangOld = pTangNonStrip;
|
||||
CBasis *pTangNew = new CBasis[m_SecVertCount];
|
||||
|
||||
m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData = pVBNew;
|
||||
|
||||
// remember remapping
|
||||
m_arrVertStripMap = new uint [m_SecVertCount];
|
||||
memset(m_arrVertStripMap,256,sizeof(uint)*m_SecVertCount);
|
||||
|
||||
int vertFirst = 0;
|
||||
|
||||
list2<ushort> NewIndexes;
|
||||
|
||||
//stripify!
|
||||
for (i=0; i<(*m_pMats).Count(); i++)
|
||||
{
|
||||
CMatInfo *mi = &(*m_pMats)[i];
|
||||
if (!mi->pRE)
|
||||
continue;
|
||||
PrimitiveGroup* pOldPG;
|
||||
GenerateStrips(&GetIndices()[mi->nFirstIndexId], mi->nNumIndices, &pOldPG, (unsigned short*)&mi->m_dwNumSections);
|
||||
|
||||
//remap!
|
||||
PrimitiveGroup *pg;
|
||||
RemapIndices(pOldPG, mi->m_dwNumSections, m_SecVertCount, &pg);
|
||||
mi->m_pPrimitiveGroups = new SPrimitiveGroup[mi->m_dwNumSections];
|
||||
|
||||
int nMin = 999999;
|
||||
int nMax = -999999;
|
||||
|
||||
//loop through all indices, copying from oldVB -> newVB
|
||||
//note that this will do numIndices copies, instead of numVerts copies,
|
||||
// which is extraneous. Deal with it! ;-)
|
||||
int nFirstIndex = 0;
|
||||
mi->nFirstIndexId = NewIndexes.Count();
|
||||
for(int groupCtr = 0; groupCtr < mi->m_dwNumSections; groupCtr++)
|
||||
{
|
||||
mi->m_pPrimitiveGroups[groupCtr].type = pg[groupCtr].type;
|
||||
mi->m_pPrimitiveGroups[groupCtr].numIndices = pg[groupCtr].numIndices;
|
||||
mi->m_pPrimitiveGroups[groupCtr].offsIndex = nFirstIndex;
|
||||
mi->m_pPrimitiveGroups[groupCtr].numTris = 0;
|
||||
for(unsigned int indexCtr = 0; indexCtr < mi->m_pPrimitiveGroups[groupCtr].numIndices; indexCtr++)
|
||||
{
|
||||
//grab old index
|
||||
int oldVertex = pOldPG[groupCtr].indices[indexCtr];
|
||||
|
||||
//grab new index
|
||||
int newVertex = pg[groupCtr].indices[indexCtr] + vertFirst;
|
||||
NewIndexes.Add(newVertex);
|
||||
|
||||
nMin = min(nMin, newVertex);
|
||||
nMax = max(nMax, newVertex);
|
||||
|
||||
//copy from old -> new vertex buffer
|
||||
memcpy(&pVBNew[newVertex], &pVBOld[oldVertex], sizeof(struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F));
|
||||
|
||||
//copy from old -> new tang buffer
|
||||
memcpy(&pTangNew[newVertex], &pTangOld[oldVertex], sizeof(CBasis));
|
||||
// if (pVBLMOld)
|
||||
// memcpy(&pVBLMNew[newVertex], &pVBLMOld[oldVertex], sizeof(SMRendTexVert));
|
||||
|
||||
// remember remaping
|
||||
m_arrVertStripMap[oldVertex] = newVertex;
|
||||
}
|
||||
nFirstIndex += mi->m_pPrimitiveGroups[groupCtr].numIndices;
|
||||
|
||||
SPrimitiveGroup *pgn = &mi->m_pPrimitiveGroups[groupCtr];
|
||||
int incr;
|
||||
switch (pgn->type)
|
||||
{
|
||||
case PT_LIST:
|
||||
incr = 3;
|
||||
break;
|
||||
case PT_STRIP:
|
||||
case PT_FAN:
|
||||
incr = 1;
|
||||
break;
|
||||
}
|
||||
int offs = pgn->offsIndex;
|
||||
for (n=0; n<pgn->numIndices-2; n+=incr)
|
||||
{
|
||||
int i0, i1, i2;
|
||||
switch (pgn->type)
|
||||
{
|
||||
case PT_LIST:
|
||||
i0 = pg[groupCtr].indices[offs+n];
|
||||
i1 = pg[groupCtr].indices[offs+n+1];
|
||||
i2 = pg[groupCtr].indices[offs+n+2];
|
||||
break;
|
||||
case PT_STRIP:
|
||||
i0 = pg[groupCtr].indices[offs+n];
|
||||
i1 = pg[groupCtr].indices[offs+n+1];
|
||||
i2 = pg[groupCtr].indices[offs+n+2];
|
||||
break;
|
||||
case PT_FAN:
|
||||
i0 = pg[groupCtr].indices[offs+0];
|
||||
i1 = pg[groupCtr].indices[offs+n+1];
|
||||
i2 = pg[groupCtr].indices[offs+n+2];
|
||||
break;
|
||||
}
|
||||
// ignore degenerate triangle
|
||||
if (i0==i1 || i0==i2 || i1==i2)
|
||||
continue;
|
||||
pgn->numTris++;
|
||||
}
|
||||
}
|
||||
mi->nNumIndices = nFirstIndex;
|
||||
mi->nFirstVertId = nMin;
|
||||
mi->nNumVerts = nMax-nMin+1;
|
||||
vertFirst += mi->nNumVerts;
|
||||
}
|
||||
m_nPrimetiveType = R_PRIMV_MULTI_GROUPS;
|
||||
|
||||
GetIndices().Free();
|
||||
GetIndices().AddList(NewIndexes);
|
||||
|
||||
delete [] pVBOld;
|
||||
|
||||
memcpy(pTangOld,pTangNew,sizeof(CBasis)*m_SecVertCount);
|
||||
delete [] pTangNew;
|
||||
}
|
||||
|
||||
void CSimpleLeafBuffer::CalcFaceNormals()
|
||||
{
|
||||
int i, j;
|
||||
|
||||
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F *pV = (struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F *)m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData;
|
||||
|
||||
if (m_nPrimetiveType != R_PRIMV_MULTI_GROUPS)
|
||||
{
|
||||
for (i=0; i<m_pMats->Count(); i++)
|
||||
{
|
||||
CMatInfo *mi = m_pMats->Get(i);
|
||||
CSimpleREOcLeaf * re = (CSimpleREOcLeaf *)mi->pRE;
|
||||
if (!re)
|
||||
continue;
|
||||
if (!re->m_Faces)
|
||||
re->m_Faces = new TArray<SMeshFace>;
|
||||
re->m_Faces->Free();
|
||||
int nOffs = mi->nFirstIndexId;
|
||||
for(j=0; j<mi->nNumIndices-2; j+=3)
|
||||
{
|
||||
unsigned short * face = &GetIndices()[j+nOffs];
|
||||
|
||||
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F *p0 = &pV[face[0]];
|
||||
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F *p1 = &pV[face[1]];
|
||||
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F *p2 = &pV[face[2]];
|
||||
Vec3d v0 = p0->xyz;
|
||||
Vec3d v1 = p1->xyz;
|
||||
Vec3d v2 = p2->xyz;
|
||||
Vec3d face_normal = (v0-v1) ^ (v0-v2);
|
||||
face_normal.Normalize();
|
||||
SMeshFace fn;
|
||||
fn.m_Normal = face_normal;
|
||||
fn.m_Middle = (v0 + v1 + v2) / 3.0f;
|
||||
re->m_Faces->AddElem(fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// assert(0);
|
||||
|
||||
unsigned int n;
|
||||
for (i=0; i<m_pMats->Count(); i++)
|
||||
{
|
||||
CMatInfo *mi = m_pMats->Get(i);
|
||||
CSimpleREOcLeaf *re = (CSimpleREOcLeaf*)mi->pRE;
|
||||
if (!re)
|
||||
continue;
|
||||
if (!re->m_Faces)
|
||||
re->m_Faces = new TArray<SMeshFace>;
|
||||
re->m_Faces->Free();
|
||||
int nOffs = mi->nFirstIndexId;
|
||||
for (j=0; j<mi->m_dwNumSections; j++)
|
||||
{
|
||||
SPrimitiveGroup *g = &mi->m_pPrimitiveGroups[j];
|
||||
g->nFirstFace = re->m_Faces->Num();
|
||||
int incr;
|
||||
switch (g->type)
|
||||
{
|
||||
case PT_LIST:
|
||||
incr = 3;
|
||||
break;
|
||||
case PT_STRIP:
|
||||
case PT_FAN:
|
||||
incr = 1;
|
||||
break;
|
||||
}
|
||||
int offs = g->offsIndex + nOffs;
|
||||
for (n=0; n<g->numIndices-2; n+=incr)
|
||||
{
|
||||
int i0, i1, i2;
|
||||
switch (g->type)
|
||||
{
|
||||
case PT_LIST:
|
||||
i0 = GetIndices()[offs+n];
|
||||
i1 = GetIndices()[offs+n+1];
|
||||
i2 = GetIndices()[offs+n+2];
|
||||
break;
|
||||
case PT_STRIP:
|
||||
i0 = GetIndices()[offs+n];
|
||||
i1 = GetIndices()[offs+n+1];
|
||||
i2 = GetIndices()[offs+n+2];
|
||||
break;
|
||||
case PT_FAN:
|
||||
i0 = GetIndices()[offs+0];
|
||||
i1 = GetIndices()[offs+n+1];
|
||||
i2 = GetIndices()[offs+n+2];
|
||||
break;
|
||||
}
|
||||
// ignore degenerate triangle
|
||||
if (i0==i1 || i0==i2 || i1==i2)
|
||||
continue;
|
||||
|
||||
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F *p0 = &pV[i0];
|
||||
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F *p1 = &pV[i1];
|
||||
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F *p2 = &pV[i2];
|
||||
Vec3d v0 = p0->xyz;
|
||||
Vec3d v1 = p1->xyz;
|
||||
Vec3d v2 = p2->xyz;
|
||||
Vec3d face_normal = (v0-v1) ^ (v0-v2);
|
||||
face_normal.Normalize();
|
||||
|
||||
SMeshFace fn;
|
||||
fn.m_Normal = face_normal;
|
||||
fn.m_Middle = (v0 + v1 + v2) / 3.0f;
|
||||
re->m_Faces->AddElem(fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CSimpleLeafBuffer::CreateTangBuffer(CBasis * pBasises)
|
||||
{
|
||||
// if (!m_pBasises)
|
||||
// PrepareTexSpaceBasis();
|
||||
assert(pBasises);
|
||||
|
||||
SAFE_DELETE_ARRAY(m_pSecVertBuffer->m_VS[VSF_TANGENTS].m_VData);
|
||||
// if (!m_pBasises)
|
||||
// return false;
|
||||
m_pSecVertBuffer->m_VS[VSF_TANGENTS].m_VData = new SPipTangents[m_SecVertCount];
|
||||
SPipTangents *tn = (SPipTangents *)m_pSecVertBuffer->m_VS[VSF_TANGENTS].m_VData;
|
||||
for (int i=0; i<m_SecVertCount; i++)
|
||||
{
|
||||
tn[i].m_Tangent[0] = pBasises[i].tangent[0];
|
||||
tn[i].m_Tangent[1] = pBasises[i].tangent[1];
|
||||
tn[i].m_Tangent[2] = pBasises[i].tangent[2];
|
||||
|
||||
tn[i].m_Binormal[0] = pBasises[i].binormal[0];
|
||||
tn[i].m_Binormal[1] = pBasises[i].binormal[1];
|
||||
tn[i].m_Binormal[2] = pBasises[i].binormal[2];
|
||||
|
||||
tn[i].m_TNormal[0] = pBasises[i].tnormal[0];
|
||||
tn[i].m_TNormal[1] = pBasises[i].tnormal[1];
|
||||
tn[i].m_TNormal[2] = pBasises[i].tnormal[2];
|
||||
}
|
||||
|
||||
// CorrectTangentBasisesForPolyBump();
|
||||
|
||||
// Temporary basis vectors
|
||||
// delete [] m_pBasises;
|
||||
// m_pBasises = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
#define PIP_TEX_EPS 0.001f
|
||||
#define PIP_VER_EPS 0.001f
|
||||
|
||||
bool struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F::operator == (struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F & other)
|
||||
{
|
||||
assert(this != &other);
|
||||
|
||||
return fabs(xyz.x-other.xyz.x)<PIP_VER_EPS && fabs(xyz.y-other.xyz.y)<PIP_VER_EPS && fabs(xyz.z-other.xyz.z)<PIP_VER_EPS &&
|
||||
fabs(normal.x-other.normal.x)<PIP_VER_EPS && fabs(normal.y-other.normal.y)<PIP_VER_EPS && fabs(normal.z-other.normal.z)<PIP_VER_EPS &&
|
||||
fabs(st[0]-other.st[0])<PIP_TEX_EPS && fabs(st[1]-other.st[1])<PIP_TEX_EPS &&
|
||||
(color.dcolor&0xffffff) == (other.color.dcolor&0xffffff);
|
||||
}
|
||||
|
||||
int CSimpleLeafBuffer::FindInBuffer(struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F &opt, CBasis &origBasis, uint nMatInfo, uint *uiInfo, struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F* _vbuff, CBasis *_vbasis, int _vcount, list2<unsigned short> * pHash, TArray<uint>& ShareNewInfo)
|
||||
{
|
||||
for(int i=0; i<pHash->Count(); i++)
|
||||
{
|
||||
int id = (*pHash)[i];
|
||||
if(_vbuff[id] == opt)
|
||||
{
|
||||
if (ShareNewInfo[id] != nMatInfo)
|
||||
continue;
|
||||
if (origBasis.binormal.Dot(_vbasis[id].binormal) > 0.5f && origBasis.tangent.Dot(_vbasis[id].tangent) > 0.5f)
|
||||
return (*pHash)[i];
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CSimpleLeafBuffer::CorrectTangentBasisesForPolyBump( TangData * pDuplTangData )
|
||||
{
|
||||
TArray <bool> bUsedVerts;
|
||||
|
||||
int nBinormalStride=0, nTangentStride=0, nTNormalStride=0;
|
||||
byte * pBinormal = GetBinormalPtr(nBinormalStride, 0, true);
|
||||
byte * pTangent = GetTangentPtr(nTangentStride, 0, true);
|
||||
byte * pTNormal = GetTNormalPtr(nTNormalStride, 0, true);
|
||||
|
||||
bUsedVerts.Reserve(GetIndices().Count());
|
||||
|
||||
for(int m=0; m<m_pMats->Count(); m++)
|
||||
{
|
||||
CMatInfo *pMI = m_pMats->Get(m);
|
||||
if(!(pMI->m_Flags & MIF_POLYBUMP))
|
||||
continue; // not polybump
|
||||
|
||||
bool bCloneSpace = false;
|
||||
if (pMI->shaderItem.m_pShaderResources)
|
||||
{
|
||||
SRenderShaderResources *sr = pMI->shaderItem.m_pShaderResources;
|
||||
if (sr->m_Textures[EFTT_BUMP] && sr->m_Textures[EFTT_BUMP]->m_TU.m_ITexPic && bCloneSpace)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_nPrimetiveType != R_PRIMV_MULTI_GROUPS)
|
||||
{
|
||||
int nStart = pMI->nFirstIndexId;
|
||||
int nEnd = nStart + pMI->nNumIndices;
|
||||
|
||||
assert(nEnd <= GetIndices().Count());
|
||||
|
||||
for( int i = nStart; i<nEnd; i++ )
|
||||
{
|
||||
int nVertId = GetIndices()[i];
|
||||
if (bUsedVerts[nVertId])
|
||||
continue;
|
||||
bUsedVerts[nVertId] = true;
|
||||
|
||||
Vec3d vBin, vTan, vTnor;
|
||||
if(pMI->m_Flags & MIF_INVPOLYBUMP)
|
||||
{
|
||||
vTan = Vec3d(1,0,0);
|
||||
vBin = Vec3d(0,1,0);
|
||||
vTnor = vTan.Cross(vBin);
|
||||
}
|
||||
else
|
||||
{
|
||||
vTan = Vec3d(-1,0,0);
|
||||
vBin = Vec3d(0,1,0);
|
||||
vTnor = vBin.Cross(vTan);
|
||||
}
|
||||
if ((UINT_PTR)pBinormal>256 && (UINT_PTR)pTangent>256)
|
||||
{
|
||||
Vec3d * vBinorm = (Vec3d *)&pBinormal[nBinormalStride*nVertId];
|
||||
Vec3d * vTang = (Vec3d *)&pTangent [nTangentStride*nVertId];
|
||||
Vec3d * vTNormal = (Vec3d *)&pTNormal [nTNormalStride*nVertId];
|
||||
|
||||
*vBinorm = vBin;
|
||||
*vTang = vTan;
|
||||
*vTNormal = vTnor;
|
||||
}
|
||||
|
||||
if (pDuplTangData)
|
||||
{
|
||||
// int sn = pGeomInfo->m_rDupVertToNorVert[nVertId];
|
||||
// assert(nVertId<pGeomInfo->m_nAllocatedTangNum);
|
||||
pDuplTangData[nVertId].binormal = vBin;
|
||||
pDuplTangData[nVertId].tangent = vTan;
|
||||
pDuplTangData[nVertId].tnormal = vTnor;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j=0; j<pMI->m_dwNumSections; j++)
|
||||
{
|
||||
SPrimitiveGroup *g = &pMI->m_pPrimitiveGroups[j];
|
||||
int offs = g->offsIndex+pMI->nFirstIndexId;
|
||||
for (uint n=0; n<g->numIndices; n++)
|
||||
{
|
||||
int nVertId = GetIndices()[n+offs];
|
||||
if (bUsedVerts[nVertId])
|
||||
continue;
|
||||
bUsedVerts[nVertId] = true;
|
||||
|
||||
Vec3d vBin, vTan, vTnor;
|
||||
if(pMI->m_Flags & MIF_INVPOLYBUMP)
|
||||
{
|
||||
vTan = Vec3d(1,0,0);
|
||||
vBin = Vec3d(0,1,0);
|
||||
vTnor = vTan.Cross(vBin);
|
||||
}
|
||||
else
|
||||
{
|
||||
vTan = Vec3d(-1,0,0);
|
||||
vBin = Vec3d(0,1,0);
|
||||
vTnor = vBin.Cross(vTan);
|
||||
}
|
||||
if ((UINT_PTR)pBinormal>256 && (UINT_PTR)pTangent>256)
|
||||
{
|
||||
Vec3d * vBinorm = (Vec3d *)&pBinormal[nBinormalStride*nVertId];
|
||||
Vec3d * vTang = (Vec3d *)&pTangent [nTangentStride*nVertId];
|
||||
Vec3d * vTNormal = (Vec3d *)&pTNormal [nTNormalStride*nVertId];
|
||||
|
||||
*vBinorm = vBin;
|
||||
*vTang = vTan;
|
||||
*vTNormal = vTnor;
|
||||
}
|
||||
|
||||
if (pDuplTangData)
|
||||
{
|
||||
// int sn = pGeomInfo->m_rDupVertToNorVert[nVertId];
|
||||
// assert(nVertId<pGeomInfo->m_nAllocatedTangNum);
|
||||
pDuplTangData[nVertId].binormal = vBin;
|
||||
pDuplTangData[nVertId].tangent = vTan;
|
||||
pDuplTangData[nVertId].tnormal = vTnor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bUsedVerts.Free();
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: LeafBufferSerialize.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/8/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: LeafBuffer serialization
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Dbghelp.h"
|
||||
#include "FileUtil.h"
|
||||
#include "PathUtil.h"
|
||||
#include "..\ResourceCompilerPC.h"
|
||||
|
||||
#include "StatCGFCompiler.h"
|
||||
#include "CryChunkedFile.h"
|
||||
#include "CryHeaders.h"
|
||||
|
||||
#include "meshidx.h"
|
||||
#include "IShader.h"
|
||||
#include "NvTriStrip\NvTriStrip.h"
|
||||
|
||||
#include "SerializeBuffer.h"
|
||||
|
||||
CryIRGB CF2IRGB(CFColor in)
|
||||
{
|
||||
CryIRGB out;
|
||||
out.r = uchar(in.r*255);
|
||||
out.g = uchar(in.g*255);
|
||||
out.b = uchar(in.b*255);
|
||||
return out;
|
||||
}
|
||||
|
||||
char *SkipPath (char *pathname)
|
||||
{
|
||||
char *last;
|
||||
|
||||
last = pathname;
|
||||
while (*pathname)
|
||||
{
|
||||
if (*pathname=='/' || *pathname=='\\')
|
||||
last = pathname+1;
|
||||
pathname++;
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
int CSimpleLeafBuffer__SetTexType(TextureMap3 *tm)
|
||||
{
|
||||
if (tm->type == TEXMAP_CUBIC)
|
||||
return eTT_Cubemap;
|
||||
else
|
||||
if (tm->type == TEXMAP_AUTOCUBIC)
|
||||
return eTT_AutoCubemap;
|
||||
return eTT_Base;
|
||||
}
|
||||
|
||||
bool CSimpleLeafBuffer::Serialize(int & nPos, uchar * pSerBuf, bool bSave, const char * szFolderName)
|
||||
{
|
||||
assert(bSave);
|
||||
|
||||
SaveBuffer("LeafBuffer", 11, pSerBuf, nPos);
|
||||
|
||||
SaveBuffer(&m_SecVertCount, sizeof(m_SecVertCount), pSerBuf, nPos);
|
||||
|
||||
SaveBuffer( m_arrVertStripMap, m_SecVertCount*sizeof(m_arrVertStripMap[0]), pSerBuf, nPos);
|
||||
GetIndices().SaveToBuffer(pSerBuf, nPos);
|
||||
m_pIndicesPreStrip->SaveToBuffer(pSerBuf, nPos);
|
||||
SaveBuffer(&m_nPrimetiveType, sizeof(m_nPrimetiveType), pSerBuf, nPos);
|
||||
// assert(m_pBasises==0); // not needed
|
||||
SaveBuffer( m_pLoadedColors, m_SecVertCount*sizeof(m_pLoadedColors[0]), pSerBuf, nPos);
|
||||
m_pMats->SaveToBuffer(pSerBuf, nPos); // need to restore
|
||||
|
||||
// save shader info
|
||||
for (int i=0; i<m_pMats->Count(); i++)
|
||||
{
|
||||
MAT_ENTITY * pMatEnt = m_pMats->Get(i)->pMatEnt;
|
||||
SaveBuffer(pMatEnt, sizeof(*pMatEnt), pSerBuf, nPos);
|
||||
|
||||
if(m_pMats->GetAt(i).pRE)
|
||||
{
|
||||
assert(((CSimpleREOcLeaf*)m_pMats->GetAt(i).pRE)->m_pChunk->nNumIndices);
|
||||
assert(((CSimpleREOcLeaf*)m_pMats->GetAt(i).pRE)->m_pChunk == m_pMats->Get(i));
|
||||
}
|
||||
|
||||
// save primitive groups
|
||||
if(m_pMats->GetAt(i).m_dwNumSections)
|
||||
SaveBuffer((void*)m_pMats->GetAt(i).m_pPrimitiveGroups,
|
||||
sizeof(SPrimitiveGroup)*m_pMats->GetAt(i).m_dwNumSections,
|
||||
pSerBuf, nPos);
|
||||
}
|
||||
|
||||
SaveBuffer( m_pSecVertBuffer, sizeof(*m_pSecVertBuffer), pSerBuf, nPos); // need to restore
|
||||
SaveBuffer( m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData, m_SecVertCount*m_VertexSize[m_pSecVertBuffer->m_vertexformat], pSerBuf, nPos);
|
||||
SaveBuffer( m_pSecVertBuffer->m_VS[VSF_TANGENTS].m_VData, m_SecVertCount*sizeof(SPipTangents), pSerBuf, nPos);
|
||||
|
||||
assert(!m_pVertexBuffer); // not needed
|
||||
SaveBuffer(&m_vBoxMax, sizeof(m_vBoxMax), pSerBuf, nPos);
|
||||
SaveBuffer(&m_vBoxMin, sizeof(m_vBoxMin), pSerBuf, nPos);
|
||||
|
||||
// [Anton] m_arrVtxMap serialization
|
||||
int bHasVtxMap;
|
||||
if (m_arrVtxMap)
|
||||
{
|
||||
SaveBuffer(&(bHasVtxMap=1),sizeof(bHasVtxMap), pSerBuf,nPos);
|
||||
SaveBuffer(m_arrVtxMap,sizeof(uint)*m_SecVertCount, pSerBuf,nPos);
|
||||
}
|
||||
else
|
||||
SaveBuffer(&(bHasVtxMap=0),sizeof(bHasVtxMap), pSerBuf,nPos);
|
||||
|
||||
return 0;
|
||||
}
|
||||
100
ResourceCompilerPC/StatCGFCompiler/StatCGFShadVol.cpp
Normal file
100
ResourceCompilerPC/StatCGFCompiler/StatCGFShadVol.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
#include "StdAfx.h"
|
||||
#include "statcgfshadvol.h"
|
||||
|
||||
#include "meshidx.h"
|
||||
#include "IEdgeConnectivityBuilder.h"
|
||||
#include "..\StencilShadowConnectivity.h"
|
||||
#include "..\StencilShadowConnectivityBuilder.h"
|
||||
|
||||
CStatCGFShadVol::CStatCGFShadVol(ILog * pLog, CIndexedMesh * pIndexedMesh)
|
||||
{
|
||||
m_pShadowVolObject = new CShadowVolObject( pLog );
|
||||
|
||||
for (int i=0; i<pIndexedMesh->m_nFaceCount; i++)
|
||||
{
|
||||
CObjFace *cf=&pIndexedMesh->m_pFaces[i];
|
||||
|
||||
for (int v=0; v<3; v++)
|
||||
{
|
||||
cf->m_Vecs[v].x=pIndexedMesh->m_pVerts[pIndexedMesh->m_pFaces[i].v[v]].x;
|
||||
cf->m_Vecs[v].y=pIndexedMesh->m_pVerts[pIndexedMesh->m_pFaces[i].v[v]].y;
|
||||
cf->m_Vecs[v].z=pIndexedMesh->m_pVerts[pIndexedMesh->m_pFaces[i].v[v]].z;
|
||||
} //v
|
||||
|
||||
//calc plane equation
|
||||
cf->m_Plane.CalcPlane(cf->m_Vecs[2],cf->m_Vecs[1],cf->m_Vecs[0]);
|
||||
} //i
|
||||
|
||||
//precalc edges
|
||||
m_pShadowVolObject->CreateConnectivityInfo(pIndexedMesh, pLog);
|
||||
}
|
||||
|
||||
CStatCGFShadVol::~CStatCGFShadVol()
|
||||
{
|
||||
delete m_pShadowVolObject;
|
||||
}
|
||||
|
||||
#define FLAG_SKIP_SHADOWVOLUME 1 // todo: share this flag
|
||||
|
||||
void CShadowVolObject::CreateConnectivityInfo( CIndexedMesh * pIndexedMesh, ILog * pLog )
|
||||
{
|
||||
//list of faces is shared from statobj
|
||||
m_pFaceList = pIndexedMesh->m_pFaces;
|
||||
m_nNumFaces = pIndexedMesh->m_nFaceCount;
|
||||
Vec3d *pVert = pIndexedMesh->m_pVerts;
|
||||
|
||||
IEdgeConnectivityBuilder * iBuilder = new CStencilShadowStaticConnectivityBuilder();
|
||||
iBuilder->Reinit();
|
||||
|
||||
assert(iBuilder);
|
||||
|
||||
iBuilder->ReserveForTriangles(m_nNumFaces,pIndexedMesh->m_nVertCount);
|
||||
|
||||
for(int i=0;i<m_nNumFaces;i++)
|
||||
{
|
||||
CObjFace *cf = &m_pFaceList[i];
|
||||
|
||||
if(cf->m_dwFlags & FLAG_SKIP_SHADOWVOLUME)
|
||||
continue;
|
||||
|
||||
// with welding
|
||||
unsigned short a=cf->v[0],b=cf->v[1],c=cf->v[2];
|
||||
iBuilder->AddTriangleWelded(a,b,c,pVert[a],pVert[b],pVert[c]);
|
||||
}
|
||||
|
||||
m_pEdgeConnectivity = iBuilder->ConstructConnectivity();
|
||||
|
||||
#ifdef _DEBUG
|
||||
if(m_pEdgeConnectivity)
|
||||
{
|
||||
DWORD dwVertCount,dwTriCount;
|
||||
|
||||
m_pEdgeConnectivity->GetStats(dwVertCount,dwTriCount);
|
||||
|
||||
pLog->Log(" StencilEdgeConnectivity Stats:");
|
||||
pLog->Log(" %d/%d Vertices %d/%d Faces",dwVertCount,pIndexedMesh->m_nVertCount,dwTriCount,m_nNumFaces);
|
||||
}
|
||||
#endif
|
||||
|
||||
delete iBuilder;
|
||||
}
|
||||
|
||||
CShadowVolObject::~CShadowVolObject()
|
||||
{
|
||||
if(m_pEdgeConnectivity)
|
||||
{
|
||||
m_pEdgeConnectivity->Release();
|
||||
m_pEdgeConnectivity=0;
|
||||
}
|
||||
}
|
||||
|
||||
void CStatCGFShadVol::Serialize(int & nPos, void * pStream, bool bSave)
|
||||
{
|
||||
byte* pTarget = pStream ? (byte*)pStream+nPos : NULL;
|
||||
IStencilShadowConnectivity* pConnectivity = m_pShadowVolObject->GetEdgeConnectivity();
|
||||
// NOTE: passing a big number is not a good practice here, because in debug mode
|
||||
// it validates the buffers size and can detect buffer overruns early and painlessly.
|
||||
// a good practice is passing the actual number of bytes available in ths target buffer
|
||||
|
||||
nPos += pConnectivity->Serialize(bSave, pTarget, 100000000);
|
||||
}
|
||||
81
ResourceCompilerPC/StatCGFCompiler/StatCGFShadVol.h
Normal file
81
ResourceCompilerPC/StatCGFCompiler/StatCGFShadVol.h
Normal file
@@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
|
||||
class CShadowVolObject //: public CVolume
|
||||
{
|
||||
public:
|
||||
|
||||
// constructor
|
||||
CShadowVolObject(ILog * pSystem)
|
||||
{
|
||||
m_pFaceList=NULL;
|
||||
m_pReMeshShadow=NULL;
|
||||
m_pSystemVertexBuffer=NULL;
|
||||
m_pEdgeConnectivity=0;
|
||||
m_nNumVertices=0;
|
||||
m_nNumFaces=0;
|
||||
m_pSystem = pSystem;
|
||||
};
|
||||
|
||||
ILog * m_pSystem;
|
||||
|
||||
//! destructor
|
||||
~CShadowVolObject();
|
||||
|
||||
//!
|
||||
bool CheckInside(const Vec3d &pos,bool bWorldSpace=true)
|
||||
{
|
||||
//temporary return false...will be a cool AI game play feature to know
|
||||
//if we are in shadows
|
||||
return (false);
|
||||
}
|
||||
|
||||
//! precalculate the connectivity infos to build the object silouhette
|
||||
void CreateConnectivityInfo( CIndexedMesh * pIndexedMesh, ILog * pLog );
|
||||
|
||||
//! create/update a vertex buffer containing the shadow volume (for static lights)
|
||||
void RebuildDynamicShadowVolumeBuffer( const CDLight &lSource, struct IVisArea * pVisArea );// lSource has to be object relative
|
||||
|
||||
Vec3d * GetSysVertBufer() { return m_pSystemVertexBuffer; }
|
||||
|
||||
int GetNumVertices() { return(m_nNumVertices); }
|
||||
int GetNumFaces() { return(m_nNumFaces); }
|
||||
|
||||
// Shader RenderElements for stencil
|
||||
CRETriMeshShadow * m_pReMeshShadow; //!<
|
||||
|
||||
void CheckUnload();
|
||||
|
||||
class IStencilShadowConnectivity * GetEdgeConnectivity() { return m_pEdgeConnectivity; }
|
||||
|
||||
protected:
|
||||
|
||||
//! free the shadow volume buffers
|
||||
void FreeVertexBuffers();
|
||||
|
||||
//list of faces from source objects, its always shared from the stat obj
|
||||
int m_nNumFaces; //
|
||||
CObjFace *m_pFaceList; // pointer to MeshIdx faces [0..m_nNumFaces-1]
|
||||
|
||||
//list of edges...can be shared from another shadow vol object
|
||||
IStencilShadowConnectivity *m_pEdgeConnectivity; //!< stored edge connectivity for fast shadow edge extraction, could be 0, call ->Release() to free it
|
||||
|
||||
TFixedArray<unsigned short> m_arrIndices; //!<
|
||||
unsigned m_nNumVertices; //!< number of vertices in SystemBuffer
|
||||
|
||||
//!
|
||||
//! /param nNumIndices
|
||||
//! /param nNumVertices
|
||||
void PrepareShadowVolumeVertexBuffer( unsigned nNumIndices, unsigned nNumVertices );
|
||||
|
||||
//shadow volume renderer vertex buffer
|
||||
Vec3d * m_pSystemVertexBuffer;
|
||||
};
|
||||
|
||||
class CStatCGFShadVol
|
||||
{
|
||||
public:
|
||||
CStatCGFShadVol(ILog * pSystem, CIndexedMesh * pMesh);
|
||||
~CStatCGFShadVol(void);
|
||||
CShadowVolObject * m_pShadowVolObject;
|
||||
void Serialize(int & nPos, void * pStream, bool bSave);
|
||||
};
|
||||
8
ResourceCompilerPC/StatCGFCompiler/StatCGFShadowVolume.h
Normal file
8
ResourceCompilerPC/StatCGFCompiler/StatCGFShadowVolume.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
class StatCGFShadowVolume
|
||||
{
|
||||
public:
|
||||
StatCGFShadowVolume(void);
|
||||
~StatCGFShadowVolume(void);
|
||||
};
|
||||
245
ResourceCompilerPC/StatCGFCompiler/StatObj.h
Normal file
245
ResourceCompilerPC/StatCGFCompiler/StatObj.h
Normal file
@@ -0,0 +1,245 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobj.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STAT_OBJ_H
|
||||
#define STAT_OBJ_H
|
||||
|
||||
const int FAR_TEX_COUNT = 24; // number of sprites per object
|
||||
const int FAR_TEX_ANGLE = (360/FAR_TEX_COUNT);
|
||||
const int FAR_TEX_SIZE = 64;
|
||||
|
||||
const int SHADOW_TEX_SIZE = 256;
|
||||
|
||||
class CIndexedMesh;
|
||||
class CCObject;
|
||||
|
||||
#include "../Cry3DEngine/Cry3DEngineBase.h"
|
||||
#include "list2.h"
|
||||
|
||||
struct CStatObjSV;
|
||||
struct ItShadowVolume;
|
||||
|
||||
#include "istatobj.h"
|
||||
|
||||
#define STATOBJ_EFT_PLANT (EFT_USER_FIRST+1)
|
||||
#define STATOBJ_EFT_PLANT_IN_SHADOW (EFT_USER_FIRST+2)
|
||||
|
||||
struct CStatObj : public Cry3DEngineBase, IStatObj
|
||||
{
|
||||
CStatObj(ISystem * pSystem);
|
||||
~CStatObj();
|
||||
|
||||
CIndexedMesh * m_pTriData;
|
||||
CIndexedMesh * GetTriData() { return m_pTriData; }
|
||||
|
||||
int m_nLoadedTrisCount;
|
||||
float GetCenterZ() { return m_vBoxMax.z*0.5f; }
|
||||
const Vec3d GetCenter() { return (m_vBoxMax+m_vBoxMin)*0.5f; }
|
||||
inline float GetRadius() { return m_fObjectRadius; }
|
||||
|
||||
char m_szFolderName[256];
|
||||
char m_szFileName [256];
|
||||
char m_szGeomName [256];
|
||||
|
||||
bool m_bDefaultObject;
|
||||
|
||||
TArray<int> m_lstShaderTemplates;
|
||||
TArray <SShaderParam> m_ShaderParams;
|
||||
|
||||
uint m_arrSpriteTexID[FAR_TEX_COUNT];
|
||||
|
||||
float m_fObjectRadius;
|
||||
|
||||
void InitParams(float sizeZ);
|
||||
|
||||
public:
|
||||
|
||||
// Loader
|
||||
bool LoadObject(const char * szFileName, const char * szGeomName, int Stripify, bool bLoadAdditinalInfo, bool bKeepInLocalSpace, bool bLoadLater = false);
|
||||
|
||||
//! Returns script material name
|
||||
virtual const char * GetScriptMaterialName(int Id=-1);
|
||||
|
||||
virtual void Render(const SRendParams & rParams, int nLodLevel=0);
|
||||
|
||||
//virtual void RenderModel(const RenderParams *pParams);
|
||||
virtual void RenderShadowVolumes(const SRendParams *pParams);
|
||||
|
||||
//! Refresh object ( reload shaders or/and object geometry )
|
||||
virtual void Refresh(int nFlags);
|
||||
|
||||
virtual bool SetShaderTemplate(int nTemplate, const char *TemplName, const char *ShaderName, bool bOnlyRegister=false);
|
||||
virtual void SetShaderFloat(const char *Name, float Val);
|
||||
//virtual void SetRefractFactor(float fRefr) { m_fRefractFactor = fRefr; }
|
||||
|
||||
//! set shadow volume
|
||||
ItShadowVolume *GetShadowVolume() { return (m_pSvObj);}
|
||||
|
||||
//! get shadow volume
|
||||
void SetShadowVolume(ItShadowVolume *pSvObj) { m_pSvObj=pSvObj;}
|
||||
|
||||
//Marco's NOTE: NEVER OVERRIDE THESE FLAGS!
|
||||
//! get flags
|
||||
int GetFlags() { return (m_dwFlags); }
|
||||
|
||||
//! set flags
|
||||
void SetFlags(int dwFlags) { m_dwFlags=dwFlags; }
|
||||
|
||||
//Marco's NOTE: NEVER OVERRIDE THESE FLAGS!
|
||||
//! get flags
|
||||
int GetFlags2() { return (m_dwFlags); }
|
||||
|
||||
//! set flags
|
||||
void SetFlags2(int dwFlags) { m_dwFlags2=dwFlags; }
|
||||
|
||||
|
||||
protected:
|
||||
void Physicalize();
|
||||
|
||||
void CreateModelFarImages(int nTexRes);
|
||||
|
||||
CLeafBuffer * m_pLeafBuffer;
|
||||
ItShadowVolume *m_pSvObj;
|
||||
int m_dwFlags,m_dwFlags2;
|
||||
|
||||
public:
|
||||
|
||||
CLeafBuffer * GetLeafBuffer() { return m_pLeafBuffer; };
|
||||
void SetLeafBuffer( CLeafBuffer *buf ) { m_pLeafBuffer = buf; };
|
||||
|
||||
Vec3d m_vBoxMin, m_vBoxMax, m_vBoxCenter;//, m_vGeometryAngles;
|
||||
phys_geometry * m_arrPhysGeomInfo[2];
|
||||
phys_geometry * GetPhysGeom(int n = 0) { return m_arrPhysGeomInfo[n]; }
|
||||
|
||||
const char *GetFolderName() { return (m_szFolderName); }
|
||||
const char *GetFileName() { return (m_szFileName); }
|
||||
const char *GetGeoName() { return (m_szGeomName); }
|
||||
bool IsSameObject(const char * szFileName, const char * szGeomName);
|
||||
|
||||
//set object's min/max bbox
|
||||
void SetBBoxMin(const Vec3d &vBBoxMin) { m_vBoxMin=vBBoxMin; }
|
||||
void SetBBoxMax(const Vec3d &vBBoxMax) { m_vBoxMax=vBBoxMax; }
|
||||
Vec3d & GetBoxMin() { return m_vBoxMin; }
|
||||
Vec3d & GetBoxMax() { return m_vBoxMax; }
|
||||
|
||||
int m_nUsers; // reference counter
|
||||
|
||||
ShadowMapLightSource * m_pSMLSource;
|
||||
|
||||
void MakeShadowMaps(const Vec3d vSunPos);
|
||||
|
||||
protected:
|
||||
void MakeBuffers(bool make_tree, int Stripify, char * szCompiledFileName);
|
||||
void MakeLeafBuffer( CIndexedMesh *mesh,bool bStripify=false );
|
||||
|
||||
void PrepareShadowMaps(const Vec3d & obj_pos, ShadowMapLightSource * pLSource);
|
||||
|
||||
public:
|
||||
// void DrawShadowMapOnTerrain(const Vec3d & pos, const float fScale, float fAlpha, struct IndexedVertexBuffer ** ppShadowGridBuffer, CTerrain * pTerrain, bool bLMapsGeneration);
|
||||
|
||||
int GetAllocatedBytes();
|
||||
// IndexedVertexBuffer * MakeShadowGridBuffer(const Vec3d & pos, const float fScale, ShadowMapFrustum*lf, bool translate_projection, CTerrain * pTerrain);
|
||||
void AddShadowPoint(int x, int y, list2<struct_VERTEX_FORMAT_P3F> * pList, CTerrain * pTerrain);
|
||||
|
||||
void SetCurDynMask(int nCurDynMask);
|
||||
|
||||
int FindInPosBuffer(const Vec3d & opt, Vec3d * _vbuff, int _vcount, list2<int> * pHash);
|
||||
void CompactPosBuffer(Vec3d * _vbuff, int * _vcount, list2<int> * pindices);
|
||||
|
||||
virtual Vec3d GetHelperPos(const char * szHelperName);
|
||||
virtual const char *GetHelperById(int nId, Vec3d & vPos, Matrix * pMat, int * pnType);
|
||||
virtual const Matrix * GetHelperMatrixByName(const char * szHelperName);
|
||||
|
||||
virtual void UpdateCustomLightingSpritesAndShadowMaps(float fStatObjAmbientLevel, int nTexRes);
|
||||
|
||||
//float m_fRefractFactor;
|
||||
float m_fRadiusHors;
|
||||
float m_fRadiusVert;
|
||||
// float m_fBending;
|
||||
// int m_nHideability;
|
||||
|
||||
float & GetRadiusVert() { return m_fRadiusVert; }
|
||||
float & GetRadiusHors() { return m_fRadiusHors; }
|
||||
|
||||
virtual void RegisterUser();
|
||||
virtual void UnregisterUser();
|
||||
|
||||
virtual bool IsDefaultObject() { return (m_bDefaultObject); }
|
||||
virtual bool MakeObjectPicture(UCHAR * pRGBAData, int nWidth);
|
||||
|
||||
#define MAX_STATOBJ_LODS_NUM 3
|
||||
CStatObj * m_arrpLowLODs[MAX_STATOBJ_LODS_NUM];
|
||||
void LoadLowLODs(int nStripify,bool bLoadAdditinalInfo,bool bKeepInLocalSpace);
|
||||
int m_nLoadedLodsNum;
|
||||
|
||||
// virtual int GetHideability() { return m_nHideability; }
|
||||
// virtual void SetHideability(int hideability);
|
||||
bool IsSpritesCreated() { return m_arrSpriteTexID[0]>0; }
|
||||
float GetDistFromPoint(const Vec3d & vPoint);
|
||||
int GetLoadedTrisCount() { return m_nLoadedTrisCount; }
|
||||
|
||||
list2<Vec3d> m_lstOcclVolVerts;
|
||||
list2<int> m_lstOcclVolInds;
|
||||
|
||||
virtual bool GetOcclusionVolume(list2<Vec3d> * & plstOcclVolVerts, list2<int> * & plstOcclVolInds)
|
||||
{
|
||||
plstOcclVolVerts = &m_lstOcclVolVerts;
|
||||
plstOcclVolInds = &m_lstOcclVolInds;
|
||||
|
||||
return m_lstOcclVolInds.Count() >= 3;
|
||||
}
|
||||
list2<struct HelperInfo> m_lstHelpers;
|
||||
list2<CDLight> m_lstLSources;
|
||||
bool Serialize(int & nPos, uchar * pSerBuf, bool bSave, char * szFolderName);
|
||||
|
||||
virtual void FreeTriData();
|
||||
// virtual void SetBending(float fBending);
|
||||
virtual const CDLight * GetLightSources(int nId);
|
||||
void RenderDebugInfo(const SRendParams & rParams, const class CCObject * pObj);
|
||||
void DrawMatrix(const Matrix & pMat);
|
||||
|
||||
//! Release method.
|
||||
void Release() { delete this; }
|
||||
void GetMemoryUsage(class ICrySizer* pSizer);
|
||||
int GetMemoryUsage();
|
||||
void SpawnParticles( ParticleParams & SpawnParticleParams, const Matrix & matWorldSpace, bool bOnlyUpLookingFaces );
|
||||
|
||||
// connectivity object that gets pre-computed for each model once and then
|
||||
// used to extract edge topology by the stencil shadowing module
|
||||
class IStencilShadowConnectivity* m_pStencilShadowConnectivity;
|
||||
// returns the cached connectivity object for stencil shadows
|
||||
class IStencilShadowConnectivity* getStencilShadowConnectivity( );
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// builds the connectivity object for stencil shadows
|
||||
// PARAMETERS:
|
||||
// iEdgeBuilder - the builder to use to create the connectivity info
|
||||
// pbCastShadow - the array of flags, 1 flag per 1 material, if the flag is true, then this material casts shadow, otherwise not
|
||||
// numMaterials - number of items in the pbCastShadow array
|
||||
void buildStencilShadowConnectivity (class IEdgeConnectivityBuilder *inpEdgeCon, const bool* pbCastShadow, unsigned numMaterials);
|
||||
void RenderShadowVolumes (const SRendParams *rParams, int nLimitLOD);
|
||||
void ShutDown();
|
||||
void Init();
|
||||
|
||||
// loading state
|
||||
int m_nStripify;
|
||||
bool m_bLoadAdditinalInfo;
|
||||
bool m_bKeepInLocalSpace;
|
||||
int m_nLastRendFrameId;
|
||||
bool m_bStreamable;
|
||||
static float m_fStreamingTimePerFrame;
|
||||
int m_nSpriteTexRes;
|
||||
};
|
||||
|
||||
#endif // STAT_OBJ_H
|
||||
768
ResourceCompilerPC/StatCGFCompiler/StatObjConstr.cpp
Normal file
768
ResourceCompilerPC/StatCGFCompiler/StatObjConstr.cpp
Normal file
@@ -0,0 +1,768 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjconstr.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: loading
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "StatObj.h"
|
||||
#include "MeshIdx.h"
|
||||
#include "../RenderDll/Common/shadow_renderer.h"
|
||||
#include <irenderer.h>
|
||||
#include <I3dIndoorEngine.h>
|
||||
#include <CrySizer.h>
|
||||
|
||||
//#define USE_CCGF
|
||||
|
||||
float CStatObj::m_fStreamingTimePerFrame=0;
|
||||
|
||||
void CStatObj::Refresh(int nFlags)
|
||||
{
|
||||
if(nFlags & FRO_GEOMETRY)
|
||||
{
|
||||
bool bSpritesWasCreated = IsSpritesCreated();
|
||||
ShutDown();
|
||||
Init();
|
||||
bool bRes = LoadObject(m_szFileName, m_szGeomName[0] ? m_szGeomName : 0, m_nStripify, m_bLoadAdditinalInfo, m_bKeepInLocalSpace);
|
||||
if(bRes && bSpritesWasCreated)
|
||||
{
|
||||
Vec3d vColor = Get3DEngine()->GetAmbientColorFromPosition(Vec3d(-1000,-1000,-1000));
|
||||
UpdateCustomLightingSpritesAndShadowMaps(vColor.x, m_nSpriteTexRes);
|
||||
}
|
||||
|
||||
if(!bRes)
|
||||
{ // load default in case of error
|
||||
ShutDown();
|
||||
Init();
|
||||
LoadObject("Objects\\default.cgf", 0, m_nStripify, m_bLoadAdditinalInfo, m_bKeepInLocalSpace);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (nFlags & (FRO_TEXTURES | FRO_SHADERS))
|
||||
{
|
||||
CLeafBuffer *lb = m_pLeafBuffer;
|
||||
|
||||
for (int i=0; i<lb->m_pMats->Count(); i++)
|
||||
{
|
||||
IShader *e = (*lb->m_pMats)[i].shaderItem.m_pShader;
|
||||
if (e && (*lb->m_pMats)[i].pRE && (*lb->m_pMats)[i].nNumIndices)
|
||||
e->Reload(nFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CStatObj::LoadObject(const char * szFileName,
|
||||
const char*szGeomName,
|
||||
int nStripify,
|
||||
bool bLoadAdditinalInfo,
|
||||
bool bKeepInLocalSpace,
|
||||
bool bLoadLater)
|
||||
{
|
||||
if(!szFileName[0])
|
||||
{
|
||||
GetLog()->Log("Error: CStatObj::LoadObject: szFileName not specified");
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_nStripify = nStripify;
|
||||
m_bLoadAdditinalInfo = bLoadAdditinalInfo;
|
||||
m_bKeepInLocalSpace = bKeepInLocalSpace;
|
||||
m_bStreamable = bLoadLater;
|
||||
|
||||
if(bLoadLater)
|
||||
{ // define fake bbox
|
||||
Init();
|
||||
|
||||
m_vBoxMin = Vec3d(-1.f,-1.f,-1.f);
|
||||
m_vBoxMax = Vec3d( 1.f, 1.f, 1.f);
|
||||
m_vBoxCenter = Vec3d(0,0,0);
|
||||
m_fRadiusHors = m_fRadiusVert = 1.f;
|
||||
|
||||
// remember names
|
||||
strcpy(m_szFileName,szFileName);
|
||||
|
||||
if(szGeomName)
|
||||
strcpy(m_szGeomName,szGeomName);
|
||||
else
|
||||
m_szGeomName[0]=0;
|
||||
|
||||
strcpy(m_szFolderName,szFileName);
|
||||
while(m_szFolderName[0])
|
||||
{ // make folder name
|
||||
if(m_szFolderName[strlen(m_szFolderName)-1] == '\\' || m_szFolderName[strlen(m_szFolderName)-1] == '/')
|
||||
{ m_szFolderName[strlen(m_szFolderName)-1]=0; break; }
|
||||
m_szFolderName[strlen(m_szFolderName)-1]=0;
|
||||
}
|
||||
|
||||
m_nLoadedTrisCount = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FILE * f = 0;
|
||||
|
||||
#ifdef USE_CCGF
|
||||
|
||||
char szCompiledFileNameFull[512];
|
||||
{
|
||||
char szCompiledFileName[512]="";
|
||||
strcpy(szCompiledFileName,szFileName);
|
||||
|
||||
while(strstr(szCompiledFileName,"\\") || strstr(szCompiledFileName,"/"))
|
||||
strcpy(szCompiledFileName,szCompiledFileName+1);
|
||||
|
||||
while(strstr(szCompiledFileName,"."))
|
||||
szCompiledFileName[strlen(szCompiledFileName)-1]=0;
|
||||
|
||||
strcat( szCompiledFileName, "_" );
|
||||
strcat( szCompiledFileName, szGeomName ? szGeomName : "NoGeom" );
|
||||
strcat( szCompiledFileName, ".ccgf" );
|
||||
|
||||
snprintf(szCompiledFileNameFull, "CCGF\\%s", szCompiledFileName);
|
||||
}
|
||||
|
||||
f = fopen(szCompiledFileNameFull, "rb");
|
||||
|
||||
#endif // USE_CCGF
|
||||
|
||||
if(!f || szGeomName)
|
||||
{ // compile object and save to disk
|
||||
strcpy(m_szFileName,szFileName);
|
||||
|
||||
if(szGeomName)
|
||||
strcpy(m_szGeomName,szGeomName);
|
||||
else
|
||||
m_szGeomName[0]=0;
|
||||
|
||||
strcpy(m_szFolderName,szFileName);
|
||||
while(m_szFolderName[0])
|
||||
{ // make folder name
|
||||
if(m_szFolderName[strlen(m_szFolderName)-1] == '\\' || m_szFolderName[strlen(m_szFolderName)-1] == '/')
|
||||
{ m_szFolderName[strlen(m_szFolderName)-1]=0; break; }
|
||||
m_szFolderName[strlen(m_szFolderName)-1]=0;
|
||||
}
|
||||
|
||||
m_nLoadedTrisCount = 0;
|
||||
m_pTriData = new CIndexedMesh( m_pSystem, szFileName, szGeomName, &m_nLoadedTrisCount, bLoadAdditinalInfo, bKeepInLocalSpace );
|
||||
if(!m_nLoadedTrisCount)
|
||||
{
|
||||
if(!szGeomName)
|
||||
return false;
|
||||
|
||||
int i;
|
||||
for(i=0; i<m_pTriData->m_lstGeomNames.Count(); i++)
|
||||
if(strcmp(m_pTriData->m_lstGeomNames[i],szGeomName)==0)
|
||||
break;
|
||||
|
||||
if(i>=m_pTriData->m_lstGeomNames.Count())
|
||||
return false;
|
||||
}
|
||||
|
||||
m_vBoxMin = m_pTriData->m_vBoxMin;
|
||||
m_vBoxMax = m_pTriData->m_vBoxMax;
|
||||
m_vBoxCenter = (m_vBoxMax+m_vBoxMin)/2;
|
||||
|
||||
// copy helpers
|
||||
m_lstHelpers.AddList(*m_pTriData->GetHelpers());
|
||||
|
||||
// copy lsources
|
||||
for(int i=0; i<m_pTriData->GetLightSourcesList()->Count(); i++)
|
||||
m_lstLSources.Add(*m_pTriData->GetLightSourcesList()->GetAt(i));
|
||||
|
||||
InitParams(m_pTriData->m_vBoxMax.z - m_pTriData->m_vBoxMin.z);
|
||||
|
||||
Physicalize(); // can change some indices/faces
|
||||
|
||||
// create vert buffers
|
||||
if(m_nLoadedTrisCount>30000)
|
||||
GetLog()->UpdateLoadingScreen(" Indexing huge vertex buffer ...");
|
||||
|
||||
MakeBuffers(szGeomName!=0, nStripify, 0);
|
||||
|
||||
for (int i=0; m_pLeafBuffer && m_pLeafBuffer->m_pMats && i<m_pLeafBuffer->m_pMats->Count(); i++)
|
||||
m_lstShaderTemplates.Add(-1);
|
||||
|
||||
if(m_nLoadedTrisCount>30000)
|
||||
GetLog()->UpdateLoadingScreen(" Indexed OK");
|
||||
|
||||
#ifdef USE_CCGF
|
||||
|
||||
delete m_pTriData;
|
||||
m_pTriData=0;
|
||||
|
||||
CreateDirectory("CCGF", 0);
|
||||
|
||||
// Save to file
|
||||
int nPos = 0;
|
||||
Serialize(nPos, 0, true, m_szFolderName);
|
||||
|
||||
uchar * pData = new uchar[nPos];
|
||||
nPos=0;
|
||||
Serialize(nPos, pData, true, m_szFolderName);
|
||||
|
||||
f = fopen(szCompiledFileNameFull,"wb");
|
||||
if(f)
|
||||
fwrite(pData,1,nPos,f);
|
||||
delete pData;
|
||||
|
||||
}
|
||||
else
|
||||
{ // load ready object from disk
|
||||
GetLog()->UpdateLoadingScreen("Loading compiled object: %s", szCompiledFileNameFull);
|
||||
|
||||
fseek(f,0,SEEK_END);
|
||||
int nSize = ftell(f);
|
||||
fseek(f,0,SEEK_SET);
|
||||
|
||||
uchar * pData = new uchar[nSize];
|
||||
int nReadedBytes = fread(pData,1,nSize,f);
|
||||
if(nReadedBytes != nSize)
|
||||
GetConsole()->Exit("Error: CStatObj::LoadObject: Error reading ccfg: %s", szCompiledFileNameFull);
|
||||
|
||||
nSize=0;
|
||||
Serialize(nSize, pData, false, m_szFolderName);
|
||||
assert(nReadedBytes == nSize);
|
||||
|
||||
delete pData;
|
||||
|
||||
#endif // USE_CCGF
|
||||
}
|
||||
|
||||
if(f)
|
||||
fclose(f);
|
||||
|
||||
// if(!szGeomName) // m_pTriData is needed only for indoors
|
||||
// FreeTriData();
|
||||
|
||||
// buildStencilShadowConnectivity (Get3DEngine()->GetNewStaticConnectivityBuilder(), 0, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CStatObj::FreeTriData()
|
||||
{
|
||||
delete m_pTriData;
|
||||
m_pTriData=0;
|
||||
}
|
||||
|
||||
const char * CStatObj::GetScriptMaterialName(int Id)
|
||||
{
|
||||
CLeafBuffer *lb = m_pLeafBuffer;
|
||||
if (Id < 0)
|
||||
{
|
||||
for (int i=0; i<lb->m_pMats->Count(); i++)
|
||||
{
|
||||
if ((*lb->m_pMats)[i].sScriptMaterial[0])
|
||||
return (*lb->m_pMats)[i].sScriptMaterial;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
if (Id < lb->m_pMats->Count() && (*lb->m_pMats)[Id].sScriptMaterial[0])
|
||||
return (*lb->m_pMats)[Id].sScriptMaterial;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CStatObj::InitParams(float sizeZ)
|
||||
{
|
||||
m_fObjectRadius = GetDistance(m_vBoxMin, m_vBoxMax)/2;
|
||||
|
||||
// calc vert/horis radiuses
|
||||
/* float dxh = GetBoxMax().x - GetBoxMin().x;
|
||||
float dyh = GetBoxMax().y - GetBoxMin().y;
|
||||
m_fRadiusHors = sqrtf(dxh*dxh+dyh*dyh)/2;
|
||||
m_fRadiusVert = GetBoxMax().z/2;*/
|
||||
|
||||
float dxh = (float)max( fabs(GetBoxMax().x), fabs(GetBoxMin().x));
|
||||
float dyh = (float)max( fabs(GetBoxMax().y), fabs(GetBoxMin().y));
|
||||
m_fRadiusHors = (float)sqrt(dxh*dxh+dyh*dyh);
|
||||
m_fRadiusVert = 0.01f + (GetBoxMax().z - GetBoxMin().z)*0.5f;
|
||||
}
|
||||
|
||||
CStatObj::CStatObj(ISystem * pSystem)
|
||||
{
|
||||
m_pSystem = pSystem;
|
||||
m_nUsers = 0; // referense counter
|
||||
|
||||
m_nStripify=0;
|
||||
m_bLoadAdditinalInfo=false;
|
||||
m_bKeepInLocalSpace=false;
|
||||
m_bStreamable=false;
|
||||
m_nSpriteTexRes=0;
|
||||
|
||||
ZeroStruct( m_szFolderName );
|
||||
ZeroStruct( m_szFileName );
|
||||
ZeroStruct( m_szGeomName );
|
||||
|
||||
m_pStencilShadowConnectivity=0;
|
||||
|
||||
m_nLastRendFrameId = 0;
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
void CStatObj::Init()
|
||||
{
|
||||
m_pTriData = 0;
|
||||
m_nLoadedTrisCount = 0;
|
||||
m_fObjectRadius = 0;
|
||||
m_pSvObj=NULL;
|
||||
m_dwFlags=m_dwFlags2=0;
|
||||
|
||||
ZeroStruct( m_arrSpriteTexID );
|
||||
|
||||
m_vBoxMin.Set(0,0,0);
|
||||
m_vBoxMax.Set(0,0,0);
|
||||
m_vBoxCenter.Set(0,0,0);
|
||||
memset(m_arrPhysGeomInfo, 0, sizeof(m_arrPhysGeomInfo));
|
||||
|
||||
m_pSMLSource = 0;
|
||||
|
||||
m_pLeafBuffer = 0;//GetRenderer()->CreateLe afBuffer("StatObj");
|
||||
|
||||
m_bDefaultObject=false;
|
||||
|
||||
memset(m_arrpLowLODs,0,sizeof(m_arrpLowLODs));
|
||||
|
||||
m_nLoadedLodsNum=1;
|
||||
}
|
||||
|
||||
CStatObj::~CStatObj()
|
||||
{
|
||||
ShutDown();
|
||||
}
|
||||
|
||||
void CStatObj::ShutDown()
|
||||
{
|
||||
if(!m_pSystem)
|
||||
return;
|
||||
|
||||
if(m_pTriData)
|
||||
m_pTriData->FreeLMInfo();
|
||||
delete m_pTriData;
|
||||
m_pTriData = 0;
|
||||
|
||||
for(int n=0; n<2; n++)
|
||||
if(m_arrPhysGeomInfo[n])
|
||||
GetPhysicalWorld()->GetGeomManager()->UnregisterGeometry(m_arrPhysGeomInfo[n]);
|
||||
|
||||
if(m_pSMLSource && m_pSMLSource->m_LightFrustums.Count() && m_pSMLSource->m_LightFrustums[0].pModelsList)
|
||||
delete m_pSMLSource->m_LightFrustums[0].pModelsList;
|
||||
delete m_pSMLSource;
|
||||
|
||||
if(m_pLeafBuffer && !m_pLeafBuffer->m_bMaterialsWasCreatedInRenderer)
|
||||
{
|
||||
for (int i=0; i<(*m_pLeafBuffer->m_pMats).Count(); i++)
|
||||
{
|
||||
if((*m_pLeafBuffer->m_pMats)[i].pRE)
|
||||
(*m_pLeafBuffer->m_pMats)[i].pRE->Release();
|
||||
}
|
||||
delete m_pLeafBuffer->m_pMats;
|
||||
m_pLeafBuffer->m_pMats=0;
|
||||
}
|
||||
|
||||
GetRenderer()->DeleteLeafBuffer(m_pLeafBuffer);
|
||||
m_pLeafBuffer=0;
|
||||
|
||||
for(int i=0; i<FAR_TEX_COUNT; i++)
|
||||
if(m_arrSpriteTexID[i])
|
||||
GetRenderer()->RemoveTexture(m_arrSpriteTexID[i]);
|
||||
|
||||
if (m_pSvObj)
|
||||
{
|
||||
m_pSvObj->Release();
|
||||
m_pSvObj=NULL;
|
||||
}
|
||||
|
||||
for(int i=0; i<MAX_STATOBJ_LODS_NUM; i++)
|
||||
delete m_arrpLowLODs[i];
|
||||
|
||||
m_ShaderParams.Free();
|
||||
}
|
||||
|
||||
/*
|
||||
void CStatObj::BuildOcTree()
|
||||
{
|
||||
if(!m_pTriData->m_nFaceCount || m_pTriData->m_nFaceCount<=2)
|
||||
return;
|
||||
|
||||
CBox parent_box( m_pTriData->m_vBoxMin, m_pTriData->m_vBoxMax );
|
||||
parent_box.max += 0.01f;
|
||||
parent_box.min +=-0.01f;
|
||||
|
||||
CObjFace ** allFaces = new CObjFace *[m_pTriData->m_nFaceCount];
|
||||
|
||||
for(int f=0; f<m_pTriData->m_nFaceCount; f++)
|
||||
{
|
||||
m_pTriData->m_pFaces[f].m_vCenter =
|
||||
(Vec3d(&m_pTriData->m_pVerts[m_pTriData->m_pFaces[f].v[0]].x) +
|
||||
Vec3d(&m_pTriData->m_pVerts[m_pTriData->m_pFaces[f].v[1]].x) +
|
||||
Vec3d(&m_pTriData->m_pVerts[m_pTriData->m_pFaces[f].v[2]].x))/3.f;
|
||||
|
||||
allFaces[f] = &m_pTriData->m_pFaces[f];
|
||||
}
|
||||
|
||||
const int max_tris_in_leaf = 2000;
|
||||
const float leaf_min_size = stricmp(m_szGeomName,"sector_0") ? 16.f : 32.f;
|
||||
|
||||
text_to_log(" Generating octree ... ");
|
||||
m_pOcTree = new octree_node( &parent_box, allFaces, triData->m_nFaceCount, triData, leaf_min_size, max_tris_in_leaf, 2);
|
||||
text_to_log_plus("%d leafs created", octree_node::static_current_leaf_id);
|
||||
m_pOcTree->update_bbox(triData);
|
||||
|
||||
delete [] allFaces;
|
||||
}*/
|
||||
|
||||
//float MakeBuffersTime = 0;
|
||||
|
||||
void CStatObj::MakeBuffers(bool make_tree, int nStripify, char * szCompiledFileName)
|
||||
{
|
||||
// float fTimeStart = GetTimer()->GetAsyncCurTime();
|
||||
/*
|
||||
FILE * f = fopen(szCompiledFileName,"rb");
|
||||
|
||||
if(f)
|
||||
{
|
||||
fseek(f,0,SEEK_END);
|
||||
int nSize = ftell(f);
|
||||
fseek(f,0,SEEK_SET);
|
||||
|
||||
uchar * pData = new uchar[nSize];
|
||||
int nReadedBytes = fread(pData,1,nSize,f);
|
||||
m_pLeafBuffer->Serialize(nSize, pData, false, m_szFolderName, m_nEFT_Flags);
|
||||
|
||||
delete pData;
|
||||
}
|
||||
else*/
|
||||
{
|
||||
assert(!m_pLeafBuffer);
|
||||
m_pLeafBuffer = GetRenderer()->CreateLeafBuffer(eBT_Static,"StatObj");
|
||||
|
||||
m_pLeafBuffer->m_pMats = new list2<CMatInfo>;
|
||||
m_pLeafBuffer->m_pMats->AddList(m_pTriData->m_lstMatTable);
|
||||
|
||||
if(m_pTriData->m_nFaceCount)
|
||||
{
|
||||
// m_pLeafBuffer->CreateBuffer(m_pTriData, nStripify, true);
|
||||
m_pLeafBuffer->CreateBuffer(m_pTriData, STRIPTYPE_NONE, false ); // no sorting for lightmaps
|
||||
}
|
||||
|
||||
/*
|
||||
int nSize = 0;
|
||||
m_pLeafBuffer->Serialize(nSize, 0, true, m_szFolderName, m_nEFT_Flags);
|
||||
|
||||
uchar * pData = new uchar[nSize];
|
||||
m_pLeafBuffer->Serialize(nSize, pData, true, m_szFolderName, m_nEFT_Flags);
|
||||
|
||||
f = fopen(szCompiledFileName,"wb");
|
||||
fwrite(pData,1,nSize,f);
|
||||
delete pData;*/
|
||||
}
|
||||
|
||||
//fclose(f);
|
||||
|
||||
// MakeBuffersTime += (GetTimer()->GetAsyncCurTime() - fTimeStart);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CStatObj::MakeLeafBuffer( CIndexedMesh *mesh,bool bStripify )
|
||||
{
|
||||
m_pTriData = mesh;
|
||||
if (m_pLeafBuffer)
|
||||
{
|
||||
// Delete old leaf buffer.
|
||||
GetRenderer()->DeleteLeafBuffer(m_pLeafBuffer);
|
||||
}
|
||||
m_pLeafBuffer = GetRenderer()->CreateLeafBuffer(eBT_Static,"StatObj");
|
||||
|
||||
m_pLeafBuffer->m_pMats = new list2<CMatInfo>;
|
||||
m_pLeafBuffer->m_pMats->AddList(m_pTriData->m_lstMatTable);
|
||||
|
||||
if(m_pTriData->m_nFaceCount)
|
||||
{
|
||||
// m_pLeafBuffer->CreateBuffer(m_pTriData, (bStripify)?1:0, true );
|
||||
m_pLeafBuffer->CreateBuffer(m_pTriData, STRIPTYPE_NONE, false ); // no sorting for lightmaps
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CStatObj::GetAllocatedBytes()
|
||||
{
|
||||
int size = sizeof(*this) + m_pTriData ? m_pTriData->GetAllocatedBytes() : 0;
|
||||
|
||||
// for(int i=0; i<MAX_TREE_LEAFS_NUM; i++)
|
||||
{
|
||||
size += m_pLeafBuffer->GetAllocatedBytes(false);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
Vec3d CStatObj::GetHelperPos(const char * szHelperName)
|
||||
{
|
||||
for(int i=0; i<m_lstHelpers.Count(); i++)
|
||||
if(!strcmp(m_lstHelpers[i].sName,szHelperName))
|
||||
return m_lstHelpers[i].tMat.GetTranslation();
|
||||
|
||||
return Vec3d(0,0,0);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
const Matrix * CStatObj::GetHelperMatrixByName(const char * szHelperName)
|
||||
{
|
||||
for(int i=0; i<m_lstHelpers.Count(); i++)
|
||||
if(!strcmp(m_lstHelpers[i].sName,szHelperName))
|
||||
return &(m_lstHelpers[i].tMat);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
const char *CStatObj::GetHelperById(int nId, Vec3d & vPos, Matrix * pMat, int * pnType)
|
||||
{
|
||||
if ( nId >= m_lstHelpers.Count() || nId<0 )
|
||||
return (NULL);
|
||||
|
||||
vPos = m_lstHelpers[nId].tMat.GetTranslation();
|
||||
|
||||
if(pnType)
|
||||
*pnType = m_lstHelpers[nId].nType;
|
||||
|
||||
if(pMat)
|
||||
*pMat = m_lstHelpers[nId].tMat;
|
||||
|
||||
return (m_lstHelpers[nId].sName);
|
||||
}
|
||||
|
||||
/*
|
||||
bool CStatObj::GetHelper(int id, char * szHelperName, int nMaxHelperNameSize, Vec3d * pPos, Vec3d * pRot)
|
||||
{
|
||||
if(id<0 || id>=triData->m_Helpers.Count())
|
||||
return false;
|
||||
|
||||
strncpy(szHelperName, triData->m_Helpers[id].name, nMaxHelperNameSize);
|
||||
*pPos = triData->m_Helpers[id].pos;
|
||||
*pRot = triData->m_Helpers[id].rot;
|
||||
return true;
|
||||
} */
|
||||
|
||||
void CStatObj::UpdateCustomLightingSpritesAndShadowMaps(float fStatObjAmbientLevel, int nTexRes)
|
||||
{
|
||||
m_nSpriteTexRes = nTexRes;
|
||||
Vec3d vLight = m_pSystem->GetI3DEngine()->GetSunPosition();
|
||||
vLight.Normalize();
|
||||
// Vec3d vColor = m_pSystem->GetI3DEngine()->GetWorldColor();
|
||||
float fSize = m_vBoxMax.z - m_vBoxMin.z;
|
||||
|
||||
// update lighting for full lod and lower lods
|
||||
m_pLeafBuffer->UpdateCustomLighting( vLight, fSize, fStatObjAmbientLevel );
|
||||
int nLowestLod=0;
|
||||
for(int nLodLevel=1; nLodLevel<MAX_STATOBJ_LODS_NUM; nLodLevel++)
|
||||
if(m_arrpLowLODs[nLodLevel])
|
||||
{
|
||||
m_arrpLowLODs[nLodLevel]->GetLeafBuffer()->UpdateCustomLighting( vLight, fSize, fStatObjAmbientLevel );
|
||||
nLowestLod = nLodLevel;
|
||||
}
|
||||
|
||||
// make sprites
|
||||
if(nLowestLod)
|
||||
{
|
||||
// clear sprites in full lod
|
||||
for(int i=0; i<FAR_TEX_COUNT; i++)
|
||||
if(m_arrSpriteTexID[i])
|
||||
{
|
||||
GetRenderer()->RemoveTexture(m_arrSpriteTexID[i]);
|
||||
m_arrSpriteTexID[i]=0;
|
||||
}
|
||||
|
||||
// make new sprites in low lod
|
||||
m_arrpLowLODs[nLowestLod]->CreateModelFarImages(nTexRes); // use lowest lod if present
|
||||
|
||||
// move sprite id from low inro into full lod
|
||||
memcpy(m_arrSpriteTexID, m_arrpLowLODs[nLowestLod]->m_arrSpriteTexID, sizeof(m_arrSpriteTexID));
|
||||
memset(m_arrpLowLODs[nLowestLod]->m_arrSpriteTexID, 0, sizeof(m_arrpLowLODs[nLowestLod]->m_arrSpriteTexID));
|
||||
}
|
||||
else
|
||||
CreateModelFarImages(nTexRes);
|
||||
|
||||
MakeShadowMaps(vLight);
|
||||
|
||||
// if(m_pTriData && !m_pTriData->m_lstLSources.Count())
|
||||
// FreeTriData();
|
||||
}
|
||||
|
||||
/*
|
||||
const char * CStatObj::GetPhysMaterialName(int nMatID)
|
||||
{
|
||||
if(m_pLeafBuffer && m_pLeafBuffer->m_pMats && nMatID < m_pLeafBuffer->m_pMats->Count())
|
||||
return m_pLeafBuffer->m_pMats->Get(nMatID)->szPhysMat;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CStatObj::SetPhysMaterialName(int nMatID, const char * szPhysMatName)
|
||||
{
|
||||
if(m_pLeafBuffer && m_pLeafBuffer->m_pMats && nMatID < m_pLeafBuffer->m_pMats->Count())
|
||||
{
|
||||
strncpy(m_pLeafBuffer->m_pMats->Get(nMatID)->szPhysMat, szPhysMatName, sizeof(m_pLeafBuffer->m_pMats->Get(nMatID)->szPhysMat));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
void CStatObj::RegisterUser()
|
||||
{
|
||||
m_nUsers++;
|
||||
}
|
||||
|
||||
void CStatObj::UnregisterUser()
|
||||
{
|
||||
m_nUsers--;
|
||||
}
|
||||
|
||||
void CStatObj::LoadLowLODs(int nStripify,bool bLoadAdditinalInfo,bool bKeepInLocalSpace)
|
||||
{
|
||||
if(m_szGeomName[0])
|
||||
return;
|
||||
|
||||
m_nLoadedLodsNum = 1;
|
||||
|
||||
for(int nLodLevel=1; nLodLevel<MAX_STATOBJ_LODS_NUM; nLodLevel++)
|
||||
{
|
||||
// make lod file name
|
||||
char sLodFileName[512];
|
||||
strncpy(sLodFileName, m_szFileName, sizeof(m_szFileName));
|
||||
sLodFileName[strlen(sLodFileName)-4]=0;
|
||||
strcat(sLodFileName,"_lod");
|
||||
char sLodNum[8];
|
||||
ltoa(nLodLevel,sLodNum,10);
|
||||
strcat(sLodFileName,sLodNum);
|
||||
strcat(sLodFileName,".cgf");
|
||||
|
||||
// try to load
|
||||
m_arrpLowLODs[nLodLevel] = new CStatObj(m_pSystem);
|
||||
bool bRes = fxopen(sLodFileName,"r") &&
|
||||
m_arrpLowLODs[nLodLevel]->LoadObject(sLodFileName, 0, nStripify, bLoadAdditinalInfo, bKeepInLocalSpace);
|
||||
|
||||
if(!bRes || m_arrpLowLODs[nLodLevel]->m_nLoadedTrisCount > m_nLoadedTrisCount / 1.8f)
|
||||
{
|
||||
if(bRes)
|
||||
GetLog()->Log("Error: CStatObj::LoadLowLODs: Low lod model contains too many polygons (more than half of original model, loading skipped): %s", sLodFileName);
|
||||
|
||||
delete m_arrpLowLODs[nLodLevel];
|
||||
m_arrpLowLODs[nLodLevel]=0;
|
||||
break;
|
||||
}
|
||||
m_nLoadedLodsNum++;
|
||||
}
|
||||
}
|
||||
|
||||
float CStatObj::GetDistFromPoint(const Vec3d & vPoint)
|
||||
{
|
||||
float fMinDist = 4096;
|
||||
for(int v=0; v<m_pTriData->m_nVertCount; v++)
|
||||
{
|
||||
float fDist = GetDistance(m_pTriData->m_pVerts[v],vPoint);
|
||||
if(fDist < fMinDist)
|
||||
fMinDist = fDist;
|
||||
}
|
||||
|
||||
return fMinDist;
|
||||
}
|
||||
|
||||
bool CStatObj::IsSameObject(const char * szFileName, const char * szGeomName)
|
||||
{
|
||||
// cmp object names
|
||||
if (szGeomName)
|
||||
{
|
||||
if(stricmp(szGeomName,m_szGeomName)!=0)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Normilize file name
|
||||
char szFileNameNorm[MAX_PATH_LENGTH]="";
|
||||
char *pszDest = szFileNameNorm;
|
||||
const char *pszSource = szFileName;
|
||||
while (*pszSource)
|
||||
{
|
||||
if (*pszSource=='/')
|
||||
*pszDest++='\\';
|
||||
else
|
||||
*pszDest++=*pszSource;
|
||||
pszSource++;
|
||||
}
|
||||
*pszDest=0;
|
||||
|
||||
// cmp file names
|
||||
if(stricmp(szFileNameNorm,m_szFileName)!=0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
// SetHideability and SetBending will be removed from here
|
||||
#include "objman.h"
|
||||
#include "3dengine.h"
|
||||
|
||||
void CStatObj::SetHideability(int nHideability)
|
||||
{
|
||||
m_nHideability = nHideability;
|
||||
|
||||
list2<StatInstGroup> & TypeList = ((C3DEngine*)Get3DEngine())->GetObjManager()->m_lstStaticTypes;
|
||||
for(int i=0; i<TypeList.Count(); i++)
|
||||
if(TypeList[i].pStatObj == this)
|
||||
TypeList[i].bHideability = (nHideability!=0);
|
||||
}
|
||||
|
||||
void CStatObj::SetBending(float fBending)
|
||||
{
|
||||
m_fBending = fBending;
|
||||
|
||||
list2<StatInstGroup> & TypeList = ((C3DEngine*)Get3DEngine())->GetObjManager()->m_lstStaticTypes;
|
||||
for(int i=0; i<TypeList.Count(); i++)
|
||||
if(TypeList[i].pStatObj == this)
|
||||
TypeList[i].fBending = fBending;
|
||||
}
|
||||
*/
|
||||
|
||||
void CStatObj::GetMemoryUsage(ICrySizer* pSizer)
|
||||
{
|
||||
pSizer->AddObject(this,GetMemoryUsage());
|
||||
}
|
||||
|
||||
int CStatObj::GetMemoryUsage()
|
||||
{
|
||||
int nSize=0;
|
||||
|
||||
for(int i=0; i<MAX_STATOBJ_LODS_NUM; i++)
|
||||
if(m_arrpLowLODs[i])
|
||||
nSize += m_arrpLowLODs[i]->GetMemoryUsage();
|
||||
|
||||
nSize += m_lstHelpers.GetMemoryUsage();
|
||||
nSize += m_lstLSources.GetMemoryUsage();
|
||||
nSize += m_lstOcclVolInds.GetMemoryUsage();
|
||||
nSize += m_lstOcclVolVerts.GetMemoryUsage();
|
||||
nSize += m_lstShaderTemplates.GetMemoryUsage();
|
||||
nSize += m_pSMLSource ? sizeof(*m_pSMLSource) : 0;
|
||||
nSize += m_pSvObj ? m_pSvObj->GetMemoryUsage() : 0;
|
||||
nSize += m_pTriData ? m_pTriData->GetMemoryUsage() : 0;
|
||||
nSize += m_ShaderParams.GetMemoryUsage() + m_ShaderParams.Num()*sizeof(SShaderParam);
|
||||
|
||||
return nSize;
|
||||
}
|
||||
265
ResourceCompilerPC/StatCGFCompiler/StatObjPhys.cpp
Normal file
265
ResourceCompilerPC/StatCGFCompiler/StatObjPhys.cpp
Normal file
@@ -0,0 +1,265 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjphys.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: make physical representation
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "StatObj.h"
|
||||
#include "MeshIdx.h"
|
||||
#include "3dengine.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Buffer optimizer
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int CStatObj::FindInPosBuffer(const Vec3d & opt, Vec3d * _vbuff, int _vcount, list2<int> * pHash)
|
||||
{
|
||||
for(int i=0; i<pHash->Count(); i++)
|
||||
{
|
||||
if(
|
||||
IsEquivalent(*((Vec3d*)(&_vbuff[(*pHash)[i]].x)), *((Vec3d*)(&opt.x)), VEC_EPSILON)
|
||||
)
|
||||
return (*pHash)[i];
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CStatObj::CompactPosBuffer(Vec3d * _vbuff, int * _vcount, list2<int> * pindices)
|
||||
{
|
||||
int before = *_vcount; assert(before);
|
||||
if(!before)
|
||||
GetConsole()->Exit("Error: CStatObj::CompactPosBuffer: Input vertex count is zero");
|
||||
|
||||
Vec3d * tmp_buff = new Vec3d[*_vcount];
|
||||
int tmp_count = 0;
|
||||
|
||||
pindices->Clear();
|
||||
|
||||
list2<int> pos_hash_table[256];//[256];
|
||||
|
||||
for(uint v=0; v<(uint)(*_vcount); v++)
|
||||
{
|
||||
list2<int> * pHash = &pos_hash_table[(unsigned char)(_vbuff[v].x*100)];//[(unsigned char)(_vbuff[v].y*100)];
|
||||
int find = FindInPosBuffer( _vbuff[v], tmp_buff, tmp_count, pHash);
|
||||
if(find<0)
|
||||
{
|
||||
tmp_buff[tmp_count] = _vbuff[v];
|
||||
pindices->Add(tmp_count);
|
||||
|
||||
pos_hash_table[(unsigned char)(_vbuff[v].x*100)]/*[(unsigned char)(_vbuff[v].y*100)]*/.Add(tmp_count);
|
||||
|
||||
tmp_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int u = (uint)find;
|
||||
pindices->Add(u);
|
||||
}
|
||||
}
|
||||
|
||||
* _vcount = tmp_count;
|
||||
memcpy( _vbuff, tmp_buff, tmp_count*sizeof(Vec3d));
|
||||
|
||||
delete [] tmp_buff;
|
||||
}
|
||||
|
||||
// This function prepares 3 additional meshes:
|
||||
// usual physical representation(mat_phys or bounce koeff),
|
||||
// obstruct physical representation(mat_obstruct)
|
||||
// and occlusion volume(mat_occl).
|
||||
// Register physical stuff in physics engine.
|
||||
void CStatObj::Physicalize()
|
||||
{
|
||||
bool bShowINfo = (m_pTriData->m_nFaceCount>10000);
|
||||
|
||||
if(bShowINfo)
|
||||
GetLog()->UpdateLoadingScreen(" Creating buffer for physics ...");
|
||||
|
||||
// get phys material id's from game code
|
||||
IPhysMaterialEnumerator * pPhysMaterialEnumerator = ((C3DEngine*)Get3DEngine())->m_pPhysMaterialEnumerator;
|
||||
int i=0;
|
||||
for(i=0; pPhysMaterialEnumerator && i<m_pTriData->m_lstMatTable.Count(); i++)
|
||||
m_pTriData->m_lstMatTable[i].nGamePhysMatId = pPhysMaterialEnumerator->EnumPhysMaterial(m_pTriData->m_lstMatTable[i].sScriptMaterial);
|
||||
|
||||
// find mat id's
|
||||
int nPhysMatID = -1;
|
||||
int nObstrMatID = -1;
|
||||
int nOcclMatID = -1;
|
||||
|
||||
{
|
||||
// find phys material id
|
||||
for(int m=0; m<m_pTriData->m_lstMatTable.Count(); m++)
|
||||
if(strstr(m_pTriData->m_lstMatTable[m].sScriptMaterial,"mat_phys"))
|
||||
{
|
||||
nPhysMatID = m;
|
||||
break;
|
||||
}
|
||||
|
||||
// find obstruct material id
|
||||
for(int m=0; m<m_pTriData->m_lstMatTable.Count(); m++)
|
||||
if(strstr(m_pTriData->m_lstMatTable[m].sScriptMaterial,"mat_obstruct"))
|
||||
{
|
||||
nObstrMatID = m;
|
||||
break;
|
||||
}
|
||||
|
||||
// find occlusion material id
|
||||
for(int m=0; m<m_pTriData->m_lstMatTable.Count(); m++)
|
||||
if(strstr(m_pTriData->m_lstMatTable[m].sScriptMaterial,"mat_occl"))
|
||||
{
|
||||
nOcclMatID = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define MESH_PHYSIC 0
|
||||
#define MESH_OBSTRUCT 1
|
||||
#define MESH_OCCLUSION 2
|
||||
|
||||
for(int nMesh = 0; nMesh<=2; nMesh++)
|
||||
{ // fill physics indices
|
||||
list2<int> lstPhysIndices;
|
||||
list2<unsigned char> lstFaceMaterials;
|
||||
|
||||
if(nMesh == MESH_PHYSIC)
|
||||
{ // find all physicalized faces
|
||||
for(i=0; i<m_pTriData->m_nFaceCount; i++)
|
||||
{
|
||||
if( ((m_pTriData->m_lstMatTable[m_pTriData->m_pFaces[i].shader_id].m_Flags & MIF_PHYSIC) && nPhysMatID<0) ||
|
||||
m_pTriData->m_pFaces[i].shader_id == nPhysMatID )
|
||||
{
|
||||
for(int v=0; v<3; v++)
|
||||
lstPhysIndices.Add(m_pTriData->m_pFaces[i].v[v]);
|
||||
|
||||
lstFaceMaterials.Add(m_pTriData->m_lstMatTable[m_pTriData->m_pFaces[i].shader_id].nGamePhysMatId);
|
||||
|
||||
if(m_pTriData->m_pFaces[i].shader_id == nPhysMatID)
|
||||
{ // remove face from list (it's not needed for rendering)
|
||||
if(m_pTriData->m_nFaceCount>1)
|
||||
m_pTriData->m_pFaces[i] = m_pTriData->m_pFaces[m_pTriData->m_nFaceCount-1];
|
||||
m_pTriData->m_nFaceCount--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(nMesh == MESH_OBSTRUCT)
|
||||
{ // find all obstruct faces
|
||||
if(nObstrMatID>=0)
|
||||
{ // find all obstruct faces
|
||||
for(i=0; i<m_pTriData->m_nFaceCount; i++)
|
||||
{
|
||||
if(m_pTriData->m_pFaces[i].shader_id == nObstrMatID)
|
||||
{
|
||||
for(int v=0; v<3; v++)
|
||||
lstPhysIndices.Add(m_pTriData->m_pFaces[i].v[v]);
|
||||
|
||||
lstFaceMaterials.Add(m_pTriData->m_lstMatTable[m_pTriData->m_pFaces[i].shader_id].nGamePhysMatId);
|
||||
|
||||
// remove face from list (it's not needed for rendering)
|
||||
if(m_pTriData->m_nFaceCount>1)
|
||||
m_pTriData->m_pFaces[i] = m_pTriData->m_pFaces[m_pTriData->m_nFaceCount-1];
|
||||
m_pTriData->m_nFaceCount--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(nMesh == MESH_OCCLUSION)
|
||||
{
|
||||
if(nOcclMatID>=0)
|
||||
{ // find all occlusion faces
|
||||
for(i=0; i<m_pTriData->m_nFaceCount; i++)
|
||||
{
|
||||
if(m_pTriData->m_pFaces[i].shader_id == nOcclMatID)
|
||||
{
|
||||
for(int v=0; v<3; v++)
|
||||
lstPhysIndices.Add(m_pTriData->m_pFaces[i].v[v]);
|
||||
|
||||
lstFaceMaterials.Add(m_pTriData->m_lstMatTable[m_pTriData->m_pFaces[i].shader_id].nGamePhysMatId);
|
||||
|
||||
// remove face from list (it's not needed for rendering)
|
||||
if(m_pTriData->m_nFaceCount>1)
|
||||
m_pTriData->m_pFaces[i] = m_pTriData->m_pFaces[m_pTriData->m_nFaceCount-1];
|
||||
m_pTriData->m_nFaceCount--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(lstPhysIndices.Count())
|
||||
{
|
||||
Vec3d * pExVerts = new Vec3d[lstPhysIndices.Count()];
|
||||
|
||||
for(i=0; i<lstPhysIndices.Count();i++)
|
||||
pExVerts[i] = m_pTriData->m_pVerts[lstPhysIndices[i]];
|
||||
|
||||
if(bShowINfo)
|
||||
GetLog()->UpdateLoadingScreen(" Compacting buffer ...");
|
||||
|
||||
int init_count = lstPhysIndices.Count();
|
||||
CompactPosBuffer(pExVerts, &init_count, &lstPhysIndices);
|
||||
|
||||
if(bShowINfo)
|
||||
GetLog()->UpdateLoadingScreen(" Creating OBB tree ...");
|
||||
|
||||
if(GetPhysicalWorld() && (nMesh==MESH_PHYSIC || nMesh==MESH_OBSTRUCT))
|
||||
{
|
||||
IGeomManager *pGeoman = GetPhysicalWorld()->GetGeomManager();
|
||||
Vec3d ptmin=pExVerts[0],ptmax=pExVerts[0],sz;
|
||||
for(int i=1;i<lstPhysIndices.Count();i++)
|
||||
{
|
||||
ptmin.x = min(ptmin.x,pExVerts[i].x);
|
||||
ptmax.x = max(ptmax.x,pExVerts[i].x);
|
||||
ptmin.y = min(ptmin.y,pExVerts[i].y);
|
||||
ptmax.y = max(ptmax.y,pExVerts[i].y);
|
||||
ptmin.z = min(ptmin.z,pExVerts[i].z);
|
||||
ptmax.z = max(ptmax.z,pExVerts[i].z);
|
||||
}
|
||||
int nMinTrisPerNode=2, nMaxTrisPerNode=4;
|
||||
sz = ptmax-ptmin;
|
||||
int flags = mesh_multicontact1 | mesh_uchar_ids;
|
||||
float tol = 0.05f;
|
||||
flags |= lstPhysIndices.Count()<=60 ? mesh_SingleBB : mesh_OBB|mesh_AABB;
|
||||
if (strstr(m_szGeomName,"wheel"))
|
||||
{
|
||||
flags |= mesh_approx_cylinder;
|
||||
tol = 1.0f;
|
||||
} //else
|
||||
//flags |= mesh_approx_box;
|
||||
if (lstPhysIndices.Count()<600 && max(max(sz.x,sz.y),sz.z)>6) // make more dense OBBs for large (wrt terrain grid) objects
|
||||
nMinTrisPerNode = nMaxTrisPerNode = 1;
|
||||
m_arrPhysGeomInfo[nMesh] = pGeoman->RegisterGeometry(pGeoman->CreateMesh((vectorf*)&pExVerts[0], &lstPhysIndices[0],
|
||||
(short*)&lstFaceMaterials[0], lstPhysIndices.Count()/3, flags, true, true, tol, nMinTrisPerNode,nMaxTrisPerNode, 2.5f));
|
||||
}
|
||||
|
||||
if(nOcclMatID>=0 && nMesh==MESH_OCCLUSION)
|
||||
{
|
||||
m_lstOcclVolVerts.AddList(pExVerts,init_count);
|
||||
m_lstOcclVolInds.AddList(lstPhysIndices);
|
||||
}
|
||||
|
||||
delete [] pExVerts;
|
||||
}
|
||||
}
|
||||
|
||||
if(bShowINfo)
|
||||
GetLog()->UpdateLoadingScreenPlus("ok");
|
||||
|
||||
#undef MESH_PHYSIC
|
||||
#undef MESH_OBSTRUCT
|
||||
#undef MESH_OCCLUSION
|
||||
}
|
||||
353
ResourceCompilerPC/StatCGFCompiler/StatObjPhysics.cpp
Normal file
353
ResourceCompilerPC/StatCGFCompiler/StatObjPhysics.cpp
Normal file
@@ -0,0 +1,353 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: StatCGFCompiler.cpp
|
||||
// Version: v1.00
|
||||
// Created: 5/11/2002 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "StatCGFCompiler.h"
|
||||
|
||||
#include "MeshIdx.h"
|
||||
|
||||
#include "SerializeBuffer.h"
|
||||
|
||||
#define MESH_PHYSIC 0
|
||||
#define MESH_OBSTRUCT 1
|
||||
#define MESH_OCCLUSION 2
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Buffer optimizer
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int CSimpleStatObj::FindInPosBuffer(const Vec3d & opt, Vec3d * _vbuff, int _vcount, list2<int> * pHash)
|
||||
{
|
||||
for(int i=0; i<pHash->Count(); i++)
|
||||
{
|
||||
if(
|
||||
IsEquivalent(*((Vec3d*)(&_vbuff[(*pHash)[i]].x)), *((Vec3d*)(&opt.x)), VEC_EPSILON)
|
||||
)
|
||||
return (*pHash)[i];
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CSimpleStatObj::CompactPosBuffer(Vec3d * _vbuff, int * _vcount, list2<int> * pindices)
|
||||
{
|
||||
int before = *_vcount; assert(before);
|
||||
if(!before)
|
||||
m_pLog->ThrowError("Error: CSimpleStatObj::CompactPosBuffer: Input vertex count is zero");
|
||||
|
||||
Vec3d * tmp_buff = new Vec3d[*_vcount];
|
||||
int tmp_count = 0;
|
||||
|
||||
pindices->Clear();
|
||||
|
||||
list2<int> pos_hash_table[256];//[256];
|
||||
|
||||
for(uint v=0; v<(uint)(*_vcount); v++)
|
||||
{
|
||||
list2<int> * pHash = &pos_hash_table[(unsigned char)(_vbuff[v].x*100)];//[(unsigned char)(_vbuff[v].y*100)];
|
||||
int find = FindInPosBuffer( _vbuff[v], tmp_buff, tmp_count, pHash);
|
||||
if(find<0)
|
||||
{
|
||||
tmp_buff[tmp_count] = _vbuff[v];
|
||||
pindices->Add(tmp_count);
|
||||
|
||||
pos_hash_table[(unsigned char)(_vbuff[v].x*100)]/*[(unsigned char)(_vbuff[v].y*100)]*/.Add(tmp_count);
|
||||
|
||||
tmp_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int u = (uint)find;
|
||||
pindices->Add(u);
|
||||
}
|
||||
}
|
||||
|
||||
* _vcount = tmp_count;
|
||||
memcpy( _vbuff, tmp_buff, tmp_count*sizeof(Vec3d));
|
||||
|
||||
delete [] tmp_buff;
|
||||
}
|
||||
|
||||
// This function prepares 3 additional meshes:
|
||||
// usual physical representation(mat_phys or bounce koeff),
|
||||
// obstruct physical representation(mat_obstruct)
|
||||
// and occlusion volume(mat_occl).
|
||||
// Register physical stuff in physics engine.
|
||||
void CSimpleStatObj::Physicalize()
|
||||
{
|
||||
bool bShowINfo = (m_pTriData->m_nFaceCount>10000);
|
||||
|
||||
if(bShowINfo)
|
||||
m_pLog->Log(" Creating buffer for physics ...");
|
||||
|
||||
// get phys material id's from game code
|
||||
/* IPhysMaterialEnumerator * pPhysMaterialEnumerator = ((C3DEngine*)Get3DEngine())->m_pPhysMaterialEnumerator;
|
||||
int i=0;
|
||||
for(i=0; pPhysMaterialEnumerator && i<m_pTriData->m_lstMatTable.Count(); i++)
|
||||
m_pTriData->m_lstMatTable[i].nGamePhysMatId = pPhysMaterialEnumerator->EnumPhysMaterial(m_pTriData->m_lstMatTable[i].sScriptMaterial);
|
||||
*/
|
||||
// find mat id's
|
||||
int nPhysMatID = -1;
|
||||
int nObstrMatID = -1;
|
||||
int nOcclMatID = -1;
|
||||
int nLeavesMatID= -1;
|
||||
|
||||
{
|
||||
// find phys material id
|
||||
for(int m=0; m<m_pTriData->m_lstMatTable.Count(); m++)
|
||||
if(strstr(m_pTriData->m_lstMatTable[m].sScriptMaterial,"mat_phys"))
|
||||
{
|
||||
nPhysMatID = m;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// find obstruct material id
|
||||
for(int m=0; m<m_pTriData->m_lstMatTable.Count(); m++)
|
||||
if(strstr(m_pTriData->m_lstMatTable[m].sScriptMaterial,"mat_obstruct"))
|
||||
{
|
||||
nObstrMatID = m;
|
||||
break;
|
||||
}
|
||||
|
||||
// find leaves material id
|
||||
for(int m=0; m<m_pTriData->m_lstMatTable.Count(); m++)
|
||||
if(strstr(m_pTriData->m_lstMatTable[m].sScriptMaterial,"mat_leaves"))
|
||||
{
|
||||
nLeavesMatID = m;
|
||||
break;
|
||||
}
|
||||
|
||||
// find occlusion material id
|
||||
for(int m=0; m<m_pTriData->m_lstMatTable.Count(); m++)
|
||||
if(strstr(m_pTriData->m_lstMatTable[m].sScriptMaterial,"mat_occl"))
|
||||
{
|
||||
nOcclMatID = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(int nMesh = 0; nMesh<=2; nMesh++)
|
||||
{ // fill physics indices
|
||||
list2<int> lstPhysIndices;
|
||||
list2<unsigned char> lstFaceMaterials;
|
||||
|
||||
if(nMesh == MESH_PHYSIC)
|
||||
{ // find all physicalized faces
|
||||
for(int i=0; i<m_pTriData->m_nFaceCount; i++)
|
||||
{
|
||||
if( ((m_pTriData->m_lstMatTable[m_pTriData->m_pFaces[i].shader_id].m_Flags & MIF_PHYSIC) && nPhysMatID<0) ||
|
||||
m_pTriData->m_pFaces[i].shader_id == nPhysMatID )
|
||||
{
|
||||
for(int v=0; v<3; v++)
|
||||
lstPhysIndices.Add(m_pTriData->m_pFaces[i].v[v]);
|
||||
|
||||
lstFaceMaterials.Add((unsigned char)m_pTriData->m_pFaces[i].shader_id);
|
||||
|
||||
if(m_pTriData->m_pFaces[i].shader_id == nPhysMatID)
|
||||
{ // remove face from list (it's not needed for rendering)
|
||||
if(m_pTriData->m_nFaceCount>1)
|
||||
m_pTriData->m_pFaces[i] = m_pTriData->m_pFaces[m_pTriData->m_nFaceCount-1];
|
||||
m_pTriData->m_nFaceCount--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(nMesh == MESH_OBSTRUCT)
|
||||
{ // find all obstruct faces
|
||||
if(nObstrMatID>=0 || nLeavesMatID>=0)
|
||||
{ // find all obstruct faces
|
||||
for(int i=0; i<m_pTriData->m_nFaceCount; i++)
|
||||
{
|
||||
if( m_pTriData->m_pFaces[i].shader_id == nObstrMatID ||
|
||||
m_pTriData->m_pFaces[i].shader_id == nLeavesMatID )
|
||||
{
|
||||
for(int v=0; v<3; v++)
|
||||
lstPhysIndices.Add(m_pTriData->m_pFaces[i].v[v]);
|
||||
|
||||
lstFaceMaterials.Add((unsigned char)m_pTriData->m_pFaces[i].shader_id);
|
||||
|
||||
if(m_pTriData->m_pFaces[i].shader_id == nObstrMatID)
|
||||
{ // remove face from list (it's not needed for rendering)
|
||||
if(m_pTriData->m_nFaceCount>1)
|
||||
m_pTriData->m_pFaces[i] = m_pTriData->m_pFaces[m_pTriData->m_nFaceCount-1];
|
||||
m_pTriData->m_nFaceCount--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(nMesh == MESH_OCCLUSION)
|
||||
{
|
||||
if(nOcclMatID>=0)
|
||||
{ // find all occlusion faces
|
||||
for(int i=0; i<m_pTriData->m_nFaceCount; i++)
|
||||
{
|
||||
if(m_pTriData->m_pFaces[i].shader_id == nOcclMatID)
|
||||
{
|
||||
for(int v=0; v<3; v++)
|
||||
lstPhysIndices.Add(m_pTriData->m_pFaces[i].v[v]);
|
||||
|
||||
lstFaceMaterials.Add((unsigned char)m_pTriData->m_pFaces[i].shader_id);
|
||||
|
||||
// remove face from list (it's not needed for rendering)
|
||||
if(m_pTriData->m_nFaceCount>1)
|
||||
m_pTriData->m_pFaces[i] = m_pTriData->m_pFaces[m_pTriData->m_nFaceCount-1];
|
||||
m_pTriData->m_nFaceCount--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(lstPhysIndices.Count())// && lstPhysIndices.Count()<600) // 200 tris limit for physics set by Cevat
|
||||
{
|
||||
Vec3d * pExVerts;
|
||||
int init_count;
|
||||
|
||||
if (m_pTriData->m_lstGeomNames.Count()>0 && strstr(m_pTriData->m_lstGeomNames[0],"cloth")!=0)
|
||||
{
|
||||
pExVerts = m_pTriData->m_pVerts;
|
||||
init_count = m_pTriData->m_nVertCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
pExVerts = new Vec3d[lstPhysIndices.Count()];
|
||||
|
||||
for(int i=0; i<lstPhysIndices.Count();i++)
|
||||
pExVerts[i] = m_pTriData->m_pVerts[lstPhysIndices[i]];
|
||||
|
||||
if(bShowINfo)
|
||||
m_pLog->Log(" Compacting buffer ...");
|
||||
|
||||
init_count = lstPhysIndices.Count();
|
||||
CompactPosBuffer(pExVerts, &init_count, &lstPhysIndices);
|
||||
}
|
||||
|
||||
if(bShowINfo)
|
||||
m_pLog->Log(" Creating OBB tree ...");
|
||||
|
||||
if(/*GetPhysicalWorld() && */(nMesh==MESH_PHYSIC || nMesh==MESH_OBSTRUCT))
|
||||
{
|
||||
// IGeomManager *pGeoman = GetPhysicalWorld()->GetGeomManager();
|
||||
Vec3d ptmin=pExVerts[0],ptmax=pExVerts[0],sz;
|
||||
for(int i=1;i<init_count;i++)
|
||||
{
|
||||
ptmin.x = min(ptmin.x,pExVerts[i].x);
|
||||
ptmax.x = max(ptmax.x,pExVerts[i].x);
|
||||
ptmin.y = min(ptmin.y,pExVerts[i].y);
|
||||
ptmax.y = max(ptmax.y,pExVerts[i].y);
|
||||
ptmin.z = min(ptmin.z,pExVerts[i].z);
|
||||
ptmax.z = max(ptmax.z,pExVerts[i].z);
|
||||
}
|
||||
int nMinTrisPerNode=2, nMaxTrisPerNode=4;
|
||||
sz = ptmax-ptmin;
|
||||
int flags = mesh_multicontact1 | mesh_uchar_ids;
|
||||
float tol = 0.05f;
|
||||
flags |= lstPhysIndices.Count()<=60 ? mesh_SingleBB : mesh_OBB|mesh_AABB;
|
||||
if (strstr(m_pGeomName,"wheel"))
|
||||
{
|
||||
flags |= mesh_approx_cylinder;
|
||||
tol = 1.0f;
|
||||
} else
|
||||
flags |= mesh_approx_box | mesh_approx_sphere;
|
||||
if (lstPhysIndices.Count()<600 && max(max(sz.x,sz.y),sz.z)>6) // make more dense OBBs for large (wrt terrain grid) objects
|
||||
nMinTrisPerNode = nMaxTrisPerNode = 1;
|
||||
|
||||
// assert(0);
|
||||
// serialize data here
|
||||
|
||||
///// m_arrPhysGeomInfo[nMesh] = pGeoman->RegisterGeometry(pGeoman->CreateMesh((vectorf*)
|
||||
// &pExVerts[0], &lstPhysIndices[0],
|
||||
///// (short*)&lstFaceMaterials[0],
|
||||
// lstPhysIndices.Count()/3,
|
||||
// flags,
|
||||
// true,
|
||||
// true,
|
||||
// tol,
|
||||
// nMinTrisPerNode,
|
||||
// nMaxTrisPerNode,
|
||||
///// 2.5f));
|
||||
|
||||
m_lstProxyVerts[nMesh].AddList(pExVerts,init_count);
|
||||
m_lstProxyInds[nMesh].AddList(lstPhysIndices);
|
||||
m_vProxyBoxMin[nMesh] = ptmin;
|
||||
m_vProxyBoxMax[nMesh] = ptmax;
|
||||
m_lstProxyFaceMaterials[nMesh].AddList(lstFaceMaterials);
|
||||
}
|
||||
|
||||
if(nOcclMatID>=0 && nMesh==MESH_OCCLUSION)
|
||||
{
|
||||
m_lstProxyVerts[MESH_OCCLUSION].AddList(pExVerts,init_count);
|
||||
m_lstProxyInds[MESH_OCCLUSION].AddList(lstPhysIndices);
|
||||
}
|
||||
|
||||
if (pExVerts!=m_pTriData->m_pVerts)
|
||||
delete [] pExVerts;
|
||||
}
|
||||
else if(lstPhysIndices.Count())
|
||||
{
|
||||
m_pLog->Log("Error: CSimpleStatObj::Physicalize: proxy geometry contains more than 200 polygons - skipped");
|
||||
}
|
||||
}
|
||||
|
||||
if(bShowINfo)
|
||||
m_pLog->LogPlus("ok");
|
||||
}
|
||||
|
||||
void CSimpleStatObj::InitGeometry()
|
||||
{
|
||||
// copy helpers
|
||||
m_lstHelpers.AddList(*m_pTriData->GetHelpers());
|
||||
|
||||
// copy lsources
|
||||
for(int i=0; i<m_pTriData->GetLightSourcesList()->Count(); i++)
|
||||
m_lstLSources.Add(*m_pTriData->GetLightSourcesList()->GetAt(i));
|
||||
|
||||
m_vBoxMin = m_pTriData->m_vBoxMin;
|
||||
m_vBoxMax = m_pTriData->m_vBoxMax;
|
||||
}
|
||||
|
||||
void CSimpleStatObj::Serialize(int & nPos, uchar * pSerBuf, bool bSave)
|
||||
{
|
||||
assert(bSave);
|
||||
|
||||
SaveBuffer("StatObj", 8, pSerBuf, nPos);
|
||||
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
m_lstProxyVerts[i].SaveToBuffer(pSerBuf,nPos);
|
||||
m_lstProxyInds[i].SaveToBuffer(pSerBuf,nPos);
|
||||
SaveBuffer(m_vProxyBoxMin[i], sizeof(m_vProxyBoxMin[i]), pSerBuf, nPos);
|
||||
SaveBuffer(m_vProxyBoxMax[i], sizeof(m_vProxyBoxMax[i]), pSerBuf, nPos);
|
||||
m_lstProxyFaceMaterials[i].SaveToBuffer(pSerBuf,nPos);
|
||||
}
|
||||
|
||||
SaveBuffer(&m_vBoxMin, sizeof(m_vBoxMin), pSerBuf, nPos);
|
||||
SaveBuffer(&m_vBoxMax, sizeof(m_vBoxMax), pSerBuf, nPos);
|
||||
|
||||
m_lstHelpers.SaveToBuffer(pSerBuf,nPos);
|
||||
m_lstLSources.SaveToBuffer(pSerBuf,nPos);
|
||||
}
|
||||
|
||||
bool CSimpleStatObj::IsPhysicsExist()
|
||||
{
|
||||
return (m_lstProxyInds[MESH_PHYSIC].Count() || m_lstProxyInds[MESH_OBSTRUCT].Count());
|
||||
}
|
||||
|
||||
//"Objects\Natural\Bushes\beach_bush_yellow.cgf" /GeomName= /Stripify=1 /LoadAdditinalInfo=0 /KeepInLocalSpace=0 /StaticCGF=1 /refresh
|
||||
680
ResourceCompilerPC/StatCGFCompiler/tang_basis.cpp
Normal file
680
ResourceCompilerPC/StatCGFCompiler/tang_basis.cpp
Normal file
@@ -0,0 +1,680 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// bm
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "StatCGFCompiler.h"
|
||||
|
||||
#define EPS 0.00001f
|
||||
|
||||
// from nvidia kitchen
|
||||
bool CSimpleLeafBuffer::compute_tangent( const float * v0, const float * v1, const float * v2,
|
||||
const float * t0, const float * t1, const float * t2,
|
||||
Vec3d & tangent, Vec3d & binormal, Vec3d & tnormal, Vec3d & face_normal)
|
||||
{
|
||||
Vec3d cp;
|
||||
Vec3d e0;
|
||||
Vec3d e1;
|
||||
|
||||
tangent = Vec3d(0,0,1);
|
||||
binormal = Vec3d(0,1,0);
|
||||
tnormal = Vec3d(1,0,0);
|
||||
|
||||
// x
|
||||
e0[0] = v1[0] - v0[0];
|
||||
e0[1] = t1[0] - t0[0];
|
||||
e0[2] = t1[1] - t0[1];
|
||||
|
||||
e1[0] = v2[0] - v0[0];
|
||||
e1[1] = t2[0] - t0[0];
|
||||
e1[2] = t2[1] - t0[1];
|
||||
|
||||
|
||||
cp = e0.Cross(e1);
|
||||
|
||||
if ( fabs(cp[0]) > EPS )
|
||||
{
|
||||
tangent[0] = -cp[1] / cp[0];
|
||||
binormal[0] = -cp[2] / cp[0];
|
||||
}
|
||||
|
||||
// y
|
||||
e0[0] = v1[1] - v0[1];
|
||||
e0[1] = t1[0] - t0[0];
|
||||
e0[2] = t1[1] - t0[1];
|
||||
|
||||
e1[0] = v2[1] - v0[1];
|
||||
e1[1] = t2[0] - t0[0];
|
||||
e1[2] = t2[1] - t0[1];
|
||||
|
||||
cp = e0.Cross(e1);
|
||||
|
||||
if ( fabs(cp[0]) > EPS )
|
||||
{
|
||||
tangent[1] = -cp[1] / cp[0];
|
||||
binormal[1] = -cp[2] / cp[0];
|
||||
}
|
||||
|
||||
// z
|
||||
e0[0] = v1[2] - v0[2];
|
||||
e0[1] = t1[0] - t0[0];
|
||||
e0[2] = t1[1] - t0[1];
|
||||
|
||||
e1[0] = v2[2] - v0[2];
|
||||
e1[1] = t2[0] - t0[0];
|
||||
e1[2] = t2[1] - t0[1];
|
||||
|
||||
cp = e0.Cross(e1);
|
||||
|
||||
if ( fabs(cp[0]) > EPS )
|
||||
{
|
||||
tangent[2] = -cp[1] / cp[0];
|
||||
binormal[2] = -cp[2] / cp[0];
|
||||
}
|
||||
|
||||
tangent.Normalize();
|
||||
binormal.Normalize();
|
||||
|
||||
tnormal = tangent.Cross(binormal);
|
||||
tnormal.Normalize();
|
||||
|
||||
// Gram-Schmidt orthogonalization process for B
|
||||
// compute the cross product B=NxT to obtain
|
||||
// an orthogonal basis
|
||||
//binormal = tnormal.Cross(tangent);
|
||||
|
||||
if (tnormal.Dot(face_normal) < 0)
|
||||
tnormal = -tnormal;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#include "NvTriStrip/NVTriStrip.h"
|
||||
|
||||
static _inline int sGetHash(float *v, float *n)
|
||||
{
|
||||
return (int)(v[0]*64.0f+v[1]*64.0f+v[2]*64.0f+n[0]*2.0f+n[1]*2.0f+n[2]*2.0f) & 511;
|
||||
}
|
||||
|
||||
static _inline void sAddToHash(TArray<unsigned short>& hash, unsigned short ind)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<hash.Num(); i++)
|
||||
{
|
||||
if (hash[i] == ind)
|
||||
return;
|
||||
}
|
||||
hash.AddElem(ind);
|
||||
}
|
||||
|
||||
static void sGetObjectSpaceVectors( Vec3d &outvA, Vec3d &outvB, Vec3d &outvC )
|
||||
{
|
||||
outvA = Vec3d(1,0,0);
|
||||
outvB = Vec3d(0,1,0);
|
||||
outvC = Vec3d(0,0,1);
|
||||
}
|
||||
/*
|
||||
float sCalcAngle( Vec3d &invA, Vec3d &invB )
|
||||
{
|
||||
float LengthQ = invA.Length() * invB.Length();
|
||||
|
||||
if(LengthQ < 0.01f)
|
||||
LengthQ = 0.01f;
|
||||
|
||||
return acosf(invA.Dot(invB) / LengthQ);
|
||||
}
|
||||
*/
|
||||
|
||||
// orthogonalize the base vectors
|
||||
//! /param v0 input [0..2] position vertex 1
|
||||
//! /param v1 input [0..2] position vertex 2
|
||||
//! /param v2 input [0..2] position vertex 3
|
||||
//! /param t0 input [0..1] texture coordinate vertex 1
|
||||
//! /param t1 input [0..1] texture coordinate vertex 2
|
||||
//! /param t2 input [0..1] texture coordinate vertex 3
|
||||
//! /param tangent output vector 1
|
||||
//! /param binormal output vector 2
|
||||
//! /param tnormal output vector 3
|
||||
/*void CSimpleLeafBuffer::compute_tangent_base_CS( const float *v0, const float *v1, const float *v2,
|
||||
const float *t0, const float *t1, const float *t2,
|
||||
Vec3d &tangent, Vec3d &binormal, Vec3d &tnormal )
|
||||
{
|
||||
float fA[2]={ t1[0]-t0[0], t1[1]-t0[1] }, fB[2]={ t2[0]-t0[0], t2[1]-t0[1] };
|
||||
|
||||
float fOrientation = fA[0]*fB[1]-fA[1]*fB[0];
|
||||
|
||||
Vec3d vfNormal = Vec3d(0,0,1);
|
||||
compute_tangent_CS(v0,v1,v2,t0,t1,t2,tangent,binormal,tnormal,vfNormal);
|
||||
|
||||
// make sure they are orthogonal
|
||||
tnormal = tangent.Cross(binormal);
|
||||
tnormal.Normalize();
|
||||
binormal = tnormal.Cross(tangent);
|
||||
binormal.Normalize();
|
||||
if(fOrientation < 0)
|
||||
tnormal = -tnormal;
|
||||
} */
|
||||
|
||||
#define TV_EPS 0.001f
|
||||
#define TN_EPS 0.0001f
|
||||
|
||||
bool CSimpleLeafBuffer::PrepareTexSpaceBasis()
|
||||
{
|
||||
int hash;
|
||||
int i, j;
|
||||
|
||||
// allocate if not ready
|
||||
// process faces
|
||||
byte *pD = (byte *)m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData;
|
||||
SBufInfoTable *pOffs = &gBufInfoTable[m_pSecVertBuffer->m_vertexformat];
|
||||
int Stride = m_VertexSize[m_pSecVertBuffer->m_vertexformat]; // position stride
|
||||
|
||||
// Get pointers to positions, TexCoords and Normals
|
||||
byte *verts = pD;
|
||||
int StrN; // Normals Stride
|
||||
byte *norms;
|
||||
int StrTC; // Tex coords stride
|
||||
byte *tc0;
|
||||
if (pOffs->OffsNormal)
|
||||
{
|
||||
norms = &pD[pOffs->OffsNormal];
|
||||
StrN = Stride;
|
||||
}
|
||||
else
|
||||
{
|
||||
norms = (byte *)this->m_TempNormals;
|
||||
StrN = sizeof(Vec3d);
|
||||
}
|
||||
|
||||
if (pOffs->OffsTC)
|
||||
{
|
||||
tc0 = &pD[pOffs->OffsTC];
|
||||
StrTC = Stride;
|
||||
}
|
||||
else
|
||||
{
|
||||
tc0 = (byte *)this->m_TempTexCoords;
|
||||
StrTC = sizeof(SMRendTexVert);
|
||||
}
|
||||
// If there is no tex coords or normals ignore this mesh
|
||||
if (!tc0 || !norms)
|
||||
return false;
|
||||
|
||||
if(!m_pBasises)
|
||||
m_pBasises = new CBasis[m_SecVertCount];
|
||||
memset(m_pBasises, 0, sizeof(CBasis)*m_SecVertCount);
|
||||
|
||||
// Indices hash table for smoothing of vectors between different materials
|
||||
TArray<unsigned short> hash_table[2][512]; // 0. for TS; 1. for CS
|
||||
|
||||
// array for avoid smooothing multiple times
|
||||
TArray<bool> bUsed;
|
||||
bUsed.Create(m_SecVertCount);
|
||||
|
||||
// Clone space map
|
||||
/* CPBCloneMapDest *pCM = NULL;
|
||||
bool bCM = false;*/
|
||||
bool bSpace[2];
|
||||
|
||||
// Init hash tables
|
||||
for (i=0; i<2; i++)
|
||||
{
|
||||
bSpace[i] = false;
|
||||
for (j=0; j<512; j++)
|
||||
{
|
||||
hash_table[i][j].Free();
|
||||
}
|
||||
}
|
||||
|
||||
// Non-optimized geometry case (usually in Debug mode)
|
||||
if (m_nPrimetiveType != R_PRIMV_MULTI_GROUPS)
|
||||
{
|
||||
// All materials
|
||||
for (int nm=0; nm<m_pMats->Count(); nm++)
|
||||
{
|
||||
CMatInfo *mi = m_pMats->Get(nm);
|
||||
/* if (pCM)
|
||||
{
|
||||
delete pCM;
|
||||
pCM = NULL;
|
||||
}
|
||||
*/ /*
|
||||
if (mi->shaderItem.m_pShaderResources)
|
||||
{
|
||||
STexPic *pBumpTex = mi->shaderItem.m_pShaderResources->m_Textures[EFTT_BUMP].m_TU.m_TexPic;
|
||||
|
||||
// If clone space texture is present
|
||||
if (pBumpTex && (pBumpTex->m_Flags2 & FT2_CLONESPACE))
|
||||
{
|
||||
char name[128];
|
||||
strcpy(name, pBumpTex->m_SourceName.c_str());
|
||||
StripExtension(name, name);
|
||||
AddExtension(name, ".cln");
|
||||
FILE *fp = iSystem->GetIPak()->FOpen (name, "rb");
|
||||
if (fp)
|
||||
{
|
||||
iSystem->GetIPak()->FClose(fp);
|
||||
pCM = new CPBCloneMapDest;
|
||||
pCM->LoadCloneMap(name);
|
||||
bCM = true;
|
||||
}
|
||||
}
|
||||
else // otherwise if it's object-space polybump ignore this material
|
||||
if (pBumpTex && (pBumpTex->m_Flags2 & FT2_POLYBUMP))
|
||||
continue;
|
||||
}*/
|
||||
// For clone-space - another hash index for smoothing
|
||||
int nIndHash = 0;//(pCM != 0) ? 1 : 0;
|
||||
if (mi->nNumIndices)
|
||||
bSpace[nIndHash] = true;
|
||||
|
||||
for(i=0; i<mi->nNumIndices-2; i+=3)
|
||||
{
|
||||
unsigned short * face = &GetIndices()[i+mi->nFirstIndexId];
|
||||
|
||||
float *n[3] =
|
||||
{
|
||||
(float *)&norms[face[0]*StrN],
|
||||
(float *)&norms[face[1]*StrN],
|
||||
(float *)&norms[face[2]*StrN],
|
||||
};
|
||||
|
||||
float *v[3] =
|
||||
{
|
||||
(float *)&verts[face[0]*Stride],
|
||||
(float *)&verts[face[1]*Stride],
|
||||
(float *)&verts[face[2]*Stride],
|
||||
};
|
||||
|
||||
float *tc[3] =
|
||||
{
|
||||
(float *)&tc0[face[0]*StrTC],
|
||||
(float *)&tc0[face[1]*StrTC],
|
||||
(float *)&tc0[face[2]*StrTC],
|
||||
};
|
||||
// Place indices to hash (for future smoothing)
|
||||
hash = sGetHash(v[0], n[0]);
|
||||
sAddToHash(hash_table[nIndHash][hash], face[0]);
|
||||
hash = sGetHash(v[1], n[1]);
|
||||
sAddToHash(hash_table[nIndHash][hash], face[1]);
|
||||
hash = sGetHash(v[2], n[2]);
|
||||
sAddToHash(hash_table[nIndHash][hash], face[2]);
|
||||
|
||||
// Compute the face normal based on vertex normals
|
||||
Vec3d face_normal;
|
||||
face_normal.x = n[0][0] + n[1][0] + n[2][0];
|
||||
face_normal.y = n[0][1] + n[1][1] + n[2][1];
|
||||
face_normal.z = n[0][2] + n[1][2] + n[2][2];
|
||||
|
||||
face_normal.Normalize();
|
||||
|
||||
// If we have clone-space
|
||||
{
|
||||
Vec3d tangents[3];
|
||||
Vec3d binormals[3];
|
||||
Vec3d tnormals[3];
|
||||
|
||||
// compute tangent vectors
|
||||
compute_tangent(v[0], v[1], v[2], tc[0], tc[1], tc[2], tangents[0], binormals[0], tnormals[0], face_normal);
|
||||
compute_tangent(v[1], v[2], v[0], tc[1], tc[2], tc[0], tangents[1], binormals[1], tnormals[1], face_normal);
|
||||
compute_tangent(v[2], v[0], v[1], tc[2], tc[0], tc[1], tangents[2], binormals[2], tnormals[2], face_normal);
|
||||
|
||||
// accumulate
|
||||
for(j=0; j<3; j++)
|
||||
{
|
||||
m_pBasises[face[j]].tangent += tangents [j];
|
||||
m_pBasises[face[j]].binormal += binormals[j];
|
||||
m_pBasises[face[j]].tnormal += tnormals[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// smooth tangent vectors between different materials with the same positions and normals
|
||||
if (1)//CRenderer::CV_r_smoothtangents)
|
||||
{
|
||||
// Shared indices array for smoothing
|
||||
TArray<int> Inds;
|
||||
Inds.Create(32);
|
||||
// Smooth separatelly for tangent-space and clone-space
|
||||
for (int nn=0; nn<2; nn++)
|
||||
{
|
||||
// If this space wasn't used ignore it
|
||||
if (!bSpace[nn])
|
||||
continue;
|
||||
for (i=0; i<m_SecVertCount; i++)
|
||||
{
|
||||
// if this vertex was already used ignore it
|
||||
if (bUsed[i])
|
||||
continue;
|
||||
bUsed[i] = true;
|
||||
Inds.SetUse(0);
|
||||
Inds.AddElem(i);
|
||||
// Get position and normal for the current index i
|
||||
float *v = (float *)&verts[i*Stride];
|
||||
float *n = (float *)&norms[i*StrN];
|
||||
hash = sGetHash(v, n);
|
||||
for (j=0; j<hash_table[nn][hash].Num(); j++)
|
||||
{
|
||||
int m = hash_table[nn][hash][j];
|
||||
if (m == i)
|
||||
continue;
|
||||
// Get position and normal for the new index m
|
||||
float *v1 = (float *)&verts[m*Stride];
|
||||
float *n1 = (float *)&norms[m*StrN];
|
||||
// If position and normal are the same take this index int account
|
||||
if (fabs(v1[0]-v[0])<TV_EPS && fabs(v1[1]-v[1])<TV_EPS && fabs(v1[2]-v[2])<TV_EPS && fabs(n1[0]-n[0])<TN_EPS && fabs(n1[1]-n[1])<TN_EPS && fabs(n1[2]-n[2])<TN_EPS)
|
||||
{
|
||||
// Check angle between tangent vectors to avoid degenerated tangent vectors
|
||||
Vec3d tang, tang1;
|
||||
tang = m_pBasises[m].binormal;
|
||||
tang.NormalizeFast();
|
||||
tang1 = m_pBasises[i].binormal;
|
||||
tang1.NormalizeFast();
|
||||
float dot = tang.Dot(tang1);
|
||||
if (dot > 0.5f)
|
||||
{
|
||||
tang = m_pBasises[m].tangent;
|
||||
tang.NormalizeFast();
|
||||
tang1 = m_pBasises[i].tangent;
|
||||
tang1.NormalizeFast();
|
||||
dot = tang.Dot(tang1);
|
||||
if (dot > 0.5f)
|
||||
{
|
||||
tang = m_pBasises[m].tnormal;
|
||||
tang.NormalizeFast();
|
||||
tang1 = m_pBasises[i].tnormal;
|
||||
tang1.NormalizeFast();
|
||||
float dot = tang.Dot(tang1);
|
||||
if (dot > 0.5f)
|
||||
Inds.AddElem(m); // Add the new index to the shared indices list
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If we have more then one shared index smooth vectors between them
|
||||
if (Inds.Num() > 1)
|
||||
{
|
||||
Vec3d tang = m_pBasises[Inds[0]].tangent;
|
||||
Vec3d binorm = m_pBasises[Inds[0]].binormal;
|
||||
Vec3d tnorm = m_pBasises[Inds[0]].tnormal;
|
||||
for (j=1; j<Inds.Num(); j++)
|
||||
{
|
||||
int m = Inds[j];
|
||||
bUsed[m] = true;
|
||||
tang += m_pBasises[m].tangent;
|
||||
binorm += m_pBasises[m].binormal;
|
||||
tnorm += m_pBasises[m].tnormal;
|
||||
}
|
||||
for (j=0; j<Inds.Num(); j++)
|
||||
{
|
||||
int m = Inds[j];
|
||||
m_pBasises[m].tangent = tang;
|
||||
m_pBasises[m].binormal = binorm;
|
||||
m_pBasises[m].tnormal = tnorm;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Optimized geometry (Stripified)
|
||||
{
|
||||
unsigned int n;
|
||||
for (int nm=0; nm<m_pMats->Count(); nm++)
|
||||
{
|
||||
CMatInfo *mi = m_pMats->Get(nm);
|
||||
/* if (pCM)
|
||||
{
|
||||
delete pCM;
|
||||
pCM = NULL;
|
||||
}*//*
|
||||
if (mi->shaderItem.m_pShaderResources)
|
||||
{
|
||||
STexPic *pBumpTex = mi->shaderItem.m_pShaderResources->m_Textures[EFTT_BUMP].m_TU.m_TexPic;
|
||||
|
||||
// If we have clone-space texture
|
||||
if (pBumpTex && (pBumpTex->m_Flags2 & FT2_CLONESPACE))
|
||||
{
|
||||
char name[128];
|
||||
strcpy(name, pBumpTex->m_SourceName.c_str());
|
||||
StripExtension(name, name);
|
||||
AddExtension(name, ".cln");
|
||||
FILE *fp = iSystem->GetIPak()->FOpen (name, "rb");
|
||||
if (fp)
|
||||
{
|
||||
iSystem->GetIPak()->FClose(fp);
|
||||
pCM = new CPBCloneMapDest;
|
||||
pCM->LoadCloneMap(name);
|
||||
bCM = true;
|
||||
}
|
||||
}
|
||||
else // if it's object-space bump ignore this material
|
||||
if (pBumpTex && (pBumpTex->m_Flags2 & FT2_POLYBUMP))
|
||||
continue;
|
||||
} */
|
||||
// For clone-space - another hash index for smoothing
|
||||
int nIndHash = 0;//(pCM != 0) ? 1 : 0;
|
||||
if (mi->nNumIndices)
|
||||
bSpace[nIndHash] = true;
|
||||
|
||||
int nOffs = mi->nFirstIndexId;
|
||||
for (j=0; j<mi->m_dwNumSections; j++)
|
||||
{
|
||||
SPrimitiveGroup *g = &mi->m_pPrimitiveGroups[j];
|
||||
int incr;
|
||||
switch (g->type)
|
||||
{
|
||||
case PT_LIST:
|
||||
incr = 3;
|
||||
break;
|
||||
case PT_STRIP:
|
||||
case PT_FAN:
|
||||
incr = 1;
|
||||
break;
|
||||
}
|
||||
int offs = g->offsIndex + nOffs;
|
||||
for (n=0; n<g->numIndices-2; n+=incr)
|
||||
{
|
||||
int i0, i1, i2;
|
||||
switch (g->type)
|
||||
{
|
||||
case PT_LIST:
|
||||
i0 = GetIndices()[offs+n];
|
||||
i1 = GetIndices()[offs+n+1];
|
||||
i2 = GetIndices()[offs+n+2];
|
||||
break;
|
||||
case PT_STRIP:
|
||||
i0 = GetIndices()[offs+n];
|
||||
i1 = GetIndices()[offs+n+1];
|
||||
i2 = GetIndices()[offs+n+2];
|
||||
break;
|
||||
case PT_FAN:
|
||||
i0 = GetIndices()[offs+0];
|
||||
i1 = GetIndices()[offs+n+1];
|
||||
i2 = GetIndices()[offs+n+2];
|
||||
break;
|
||||
}
|
||||
// ignore degenerate triangle
|
||||
if (i0==i1 || i0==i2 || i1==i2)
|
||||
continue;
|
||||
|
||||
float *n[3] =
|
||||
{
|
||||
(float *)&norms[i0*StrN],
|
||||
(float *)&norms[i1*StrN],
|
||||
(float *)&norms[i2*StrN],
|
||||
};
|
||||
|
||||
float *v[3] =
|
||||
{
|
||||
(float *)&verts[i0*Stride],
|
||||
(float *)&verts[i1*Stride],
|
||||
(float *)&verts[i2*Stride],
|
||||
};
|
||||
|
||||
float *tc[3] =
|
||||
{
|
||||
(float *)&tc0[i0*StrTC],
|
||||
(float *)&tc0[i1*StrTC],
|
||||
(float *)&tc0[i2*StrTC],
|
||||
};
|
||||
|
||||
// Place indices to hash (for future smoothing)
|
||||
hash = sGetHash(v[0], n[0]);
|
||||
sAddToHash(hash_table[nIndHash][hash], i0);
|
||||
hash = sGetHash(v[1], n[1]);
|
||||
sAddToHash(hash_table[nIndHash][hash], i1);
|
||||
hash = sGetHash(v[2], n[2]);
|
||||
sAddToHash(hash_table[nIndHash][hash], i2);
|
||||
|
||||
// Compute the face normal based on vertex normals
|
||||
Vec3d face_normal;
|
||||
face_normal.x = n[0][0] + n[1][0] + n[2][0];
|
||||
face_normal.y = n[0][1] + n[1][1] + n[2][1];
|
||||
face_normal.z = n[0][2] + n[1][2] + n[2][2];
|
||||
|
||||
//Vec3d::Normalize(face_normal);
|
||||
face_normal.Normalize();
|
||||
|
||||
{
|
||||
Vec3d tangents[3];
|
||||
Vec3d binormals[3];
|
||||
Vec3d tnormals[3];
|
||||
|
||||
compute_tangent(v[0], v[1], v[2], tc[0], tc[1], tc[2], tangents[0], binormals[0], tnormals[0], face_normal);
|
||||
compute_tangent(v[1], v[2], v[0], tc[1], tc[2], tc[0], tangents[1], binormals[1], tnormals[1], face_normal);
|
||||
compute_tangent(v[2], v[0], v[1], tc[2], tc[0], tc[1], tangents[2], binormals[2], tnormals[2], face_normal);
|
||||
|
||||
// accumulate
|
||||
m_pBasises[i0].tangent += tangents [0];
|
||||
m_pBasises[i0].binormal += binormals[0];
|
||||
m_pBasises[i0].tnormal += tnormals[0];
|
||||
m_pBasises[i1].tangent += tangents [1];
|
||||
m_pBasises[i1].binormal += binormals[1];
|
||||
m_pBasises[i1].tnormal += tnormals[1];
|
||||
m_pBasises[i2].tangent += tangents [2];
|
||||
m_pBasises[i2].binormal += binormals[2];
|
||||
m_pBasises[i2].tnormal += tnormals[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// smooth tangent vectors between different materials with the same positions and normals
|
||||
if (1)//CRenderer::CV_r_smoothtangents)
|
||||
{
|
||||
// Shared indices array for smoothing
|
||||
TArray<int> Inds;
|
||||
Inds.Create(32);
|
||||
// Smooth separatelly for tangent-space and clone-space
|
||||
for (int nn=0; nn<2; nn++)
|
||||
{
|
||||
// If this space wasn't used ignore it
|
||||
if (!bSpace[nn])
|
||||
continue;
|
||||
for (i=0; i<m_SecVertCount; i++)
|
||||
{
|
||||
// if this vertex was already used ignore it
|
||||
if (bUsed[i])
|
||||
continue;
|
||||
bUsed[i] = true;
|
||||
Inds.SetUse(0);
|
||||
Inds.AddElem(i);
|
||||
// Get position and normal for the current index i
|
||||
float *v = (float *)&verts[i*Stride];
|
||||
float *n = (float *)&norms[i*StrN];
|
||||
hash = sGetHash(v, n);
|
||||
for (j=0; j<hash_table[nn][hash].Num(); j++)
|
||||
{
|
||||
int m = hash_table[nn][hash][j];
|
||||
// If it's the same index ignore it
|
||||
if (m == i)
|
||||
continue;
|
||||
// Get position and normal for the tested index m
|
||||
float *v1 = (float *)&verts[m*Stride];
|
||||
float *n1 = (float *)&norms[m*StrN];
|
||||
// If position and normal are the same take this index int account
|
||||
if (fabs(v1[0]-v[0])<TV_EPS && fabs(v1[1]-v[1])<TV_EPS && fabs(v1[2]-v[2])<TV_EPS && fabs(n1[0]-n[0])<TN_EPS && fabs(n1[1]-n[1])<TN_EPS && fabs(n1[2]-n[2])<TN_EPS)
|
||||
{
|
||||
// Check angle between tangent vectors to avoid degenerated tangent vectors
|
||||
Vec3d tang, tang1;
|
||||
tang = m_pBasises[m].binormal;
|
||||
tang.NormalizeFast();
|
||||
tang1 = m_pBasises[i].binormal;
|
||||
tang1.NormalizeFast();
|
||||
if (tang.Dot(tang1) > 0.5f)
|
||||
{
|
||||
tang = m_pBasises[m].tangent;
|
||||
tang.NormalizeFast();
|
||||
tang1 = m_pBasises[i].tangent;
|
||||
tang1.NormalizeFast();
|
||||
if (tang.Dot(tang1) > 0.5f)
|
||||
{
|
||||
tang = m_pBasises[m].tnormal;
|
||||
tang.NormalizeFast();
|
||||
tang1 = m_pBasises[i].tnormal;
|
||||
tang1.NormalizeFast();
|
||||
if (tang.Dot(tang1) > 0.5f)
|
||||
Inds.AddElem(m); // Add the new index to the shared indices list
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If we have more then one shared index smooth vectors between them
|
||||
if (Inds.Num() > 1)
|
||||
{
|
||||
Vec3d tang = m_pBasises[Inds[0]].tangent;
|
||||
Vec3d binorm = m_pBasises[Inds[0]].binormal;
|
||||
Vec3d tnorm = m_pBasises[Inds[0]].tnormal;
|
||||
for (j=1; j<Inds.Num(); j++)
|
||||
{
|
||||
int m = Inds[j];
|
||||
bUsed[m] = true;
|
||||
tang += m_pBasises[m].tangent;
|
||||
binorm += m_pBasises[m].binormal;
|
||||
tnorm += m_pBasises[m].tnormal;
|
||||
}
|
||||
for (j=0; j<Inds.Num(); j++)
|
||||
{
|
||||
int m = Inds[j];
|
||||
m_pBasises[m].tangent = tang;
|
||||
m_pBasises[m].binormal = binorm;
|
||||
m_pBasises[m].tnormal = tnorm;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// normalize
|
||||
for(int v=0; v<m_SecVertCount; v++)
|
||||
{
|
||||
m_pBasises[v].tangent.Normalize();
|
||||
m_pBasises[v].binormal.Normalize();
|
||||
m_pBasises[v].tnormal.Normalize();
|
||||
// if we have CV_r_unifytangentnormals (set by default) use Normals from vertex normal as Tangent normal
|
||||
// and orthonormalize tangent vectors
|
||||
if (1)//CRenderer::CV_r_unifytangentnormals && !bCM)
|
||||
{
|
||||
Vec3d *n = (Vec3d *)&norms[v*StrN];
|
||||
m_pBasises[v].tnormal = *n;
|
||||
Vec3d bin = m_pBasises[v].binormal;
|
||||
Vec3d tan = m_pBasises[v].tangent;
|
||||
m_pBasises[v].tangent = m_pBasises[v].tnormal.Cross(m_pBasises[v].binormal);
|
||||
if (m_pBasises[v].tangent.Dot(tan) < 0.0f)
|
||||
m_pBasises[v].tangent = -m_pBasises[v].tangent;
|
||||
m_pBasises[v].binormal = m_pBasises[v].tnormal.Cross(m_pBasises[v].tangent);
|
||||
if (m_pBasises[v].binormal.Dot(bin) < 0.0f)
|
||||
m_pBasises[v].binormal = -m_pBasises[v].binormal;
|
||||
m_pBasises[v].tangent.Normalize();
|
||||
m_pBasises[v].binormal.Normalize();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user