pqmaploader_new.cpp
来自「一个类似QUAKE的CSG关卡编辑器」· C++ 代码 · 共 702 行 · 第 1/2 页
CPP
702 行
p.vXes[2]._xyz.x, p.vXes[2]._xyz.z, p.vXes[2]._xyz.y,
p.vXes[1]._xyz.x, p.vXes[1]._xyz.z, p.vXes[1]._xyz.y,
texname,
p.texax[0].x, p.texax[0].y, p.texax[0].z, p.texShift.u,
p.texax[1].x, p.texax[1].y, p.texax[1].z, p.texShift.v); //texScale._u, texScale._v)
}
::fprintf(fw._pf, "}\r\n");
delete (*ppPlgBrush);
}
fragments.clear();
}
::fprintf(fw._pf, "}\r\n");
return 0;
}
//---------------------------------------------------------------------------------------
void PqmapLoader::MakeConvex(Plg_Brush& bf, vvector<Plg_Brush*> outs)
{
QBrCvx inbrush;
// use this for storage convenience.
// move them and pass the mem managemebt to stl.
for(int j=0; j < bf.nPolys;j++){
Plg_Poly& p = bf.pPolys[j];
QPoly qp;
qp._texIdx = bf.pPolys[j].texIdx[0];
qp._flags = bf.flags;
for(int v=0; v < p.nvXes;v++){
qp._vxes << p.vXes[v]._xyz;
qp._uvs << p.vXes[v]._uv[0];
}
cvxbr._flags = bf.flags;
cvxbr._polys << qp;
}
MakeConvex(inbrush, cvxbr);
}
//---------------------------------------------------------------------------------------
int PqmapLoader::IsConvex(QBrCvx& inbrush, QBrCvx& a, QBrCvx& b, QPoly* splPoly)
{
FOREACH(vvector<QPoly>, inbrush._polys, pp)
{
Plane pl(pp->_vxes[0], pp->_vxes[1], pp->_vxes[2]);
FOREACH(vvector<QPoly>, inbrush._polys, pp2)
{
if(pp2 == pp) continue;
QPoly pa;
QPoly pb;
pa._texIdx = pp2->._texIdx;
Split(pl, pp2->_vxes, pa._vxes, pb._vxes);
if(pa._vxes.size()>=3)
a._polys << pa;
if(pb._vxes.size()>=3)
b._polys << pb;
}
if(b._polys.size() && a._polys.size())
{
pp->_flags |= POLY_IS_SPLITTER;
splPoly = pp;
return HAS_BOTH;
}
}
return b._polys.size() ? HAS_BACKS : HAS_FRONTS;
}
//---------------------------------------------------------------------------------------
void PqmapLoader::MakeConvex(QBrCvx inbrush, vvector<QBrCvx>& cvx)
{
QBrCvx a;
QBrCvx b;
QPoly* pSlitter;
DWORD dwRez = IsConvex(inbrush, a, b, pSlitter);
switch(dwRez)
{
case HAS_BOTH:
MakeConvex(a, cvx);
MakeConvex(b, cvx);
break;
case HAS_BACKS:
cvx << b;
break;
case HAS_FRONTS:
//discard these
break;
}
}
//---------------------------------------------------------------------------------------
// pseudo code how to split the brush
/*
allocate out convex brushes
for each face plane
classify all brush vertexes.
if only front vertexex
is concave error
if only back vertexes
is convex store in out convex brushes and return
if back and front vertexes
split brush by this face plane
seal both fragment brush { build a bogus poly on this splitter
cut it with all faces that have been split or touched
add remainig polygon to both fragments. reverse one
face acordingly}
repeat for front and back fragments
save the out convex brushes
*/
//---------------------------------------------------------------------------------------
long PqmapLoader::GetMenuStringAndType(TCHAR* bsFileName, DWORD* type)
{
_tcscpy(bsFileName,"Quake map files,map");
*type = PLUG_IMPORTER|PLUG_EXPORTER;
return 0;
}
//---------------------------------------------------------------------------------------
long PqmapLoader::ImportFile(IGeticEditor* pe, TCHAR* bsFileName, Plg_Scene** pScene)
{
FileWrap fw;
if(!fw.Open(bsFileName, "rb"))
return -1;
Parser parser(&fw);
while(parser.Step()>=0);
fw.Close();
return PostProcess(pScene);
}
//---------------------------------------------------------------------------------------
long PqmapLoader::ReleaseScene(Plg_Scene* pScene)
{
RELEASE_SCENE(pScene);
return NO_ERROR;
}
//---------------------------------------------------------------------------------------
int Parser::Parse(vvector<string>& tokens)
{
map<string, PfHandler>::iterator fi = _classes.find(tokens[0]);
if(fi != _classes.end()){
return (this->*_classes[tokens[0]])(tokens);
}
return 1;
}
//---------------------------------------------------------------------------------------
int Parser::BaseParse(const char* pline)
{
vvector<string> tokens;
Explode(pline, tokens,' ');
if(tokens.size()){
TRACEX(pline);
TRACEX("\r\n");
return Parse(tokens);
}
return -1;
}
//---------------------------------------------------------------------------------------
void Parser::Explode(const char* pline, vvector<string>& tokens, char token)
{
char localline[256]= {0};
::strcpy(localline, pline);
char* pLocal = localline;
char pTok[2]= {token,'\0'};
char* pSubStr;
while(pSubStr = strtok(pLocal, pTok)){
pLocal = 0;
tokens << pSubStr;
}
}
//---------------------------------------------------------------------------------------
int Parser::Handle_Open(vvector<string>& tokens)
{
_pEntity = new QEntity(_pfw);
TRACEX("New Entity\r\n");
while(_pEntity->Step()>0);
return 1;
}
//---------------------------------------------------------------------------------------
int Parser::Step()
{
char line[255]={0};
char* pline = line;
char* pend; //= pline+strlen(line);
_pfw->ReadLine(line, 255);
if(feof(_pfw->_pf))
return -1;
// remove triling crlf
pend = pline+strlen(line)-1;
while(*pend=='\n'||*pend=='\r')
--pend;
*(pend+1)='\0';
// remove start spaces
while(*pline==' '||*pline=='\t')
++pline;
return BaseParse(pline);
}
//---------------------------------------------------------------------------------------
int QEntity::Handle_Open(vvector<string>& tokens)
{
if(_classname== "\"worldspawn\"")
{
TRACEX("New Brush\r\n");
QBrush* pBrush = new QBrush(_pfw, this);
while(pBrush->Step() > 0);
}
return 1;
}
//---------------------------------------------------------------------------------------
int QEntity::Handle_KeyVal(vvector<string>& tokens)
{
if(tokens.size() == 0)
return 1;
string values;
for(int i=1; i<tokens.size(); ++i){
values += tokens[i];
values += " ";
}
if(values.length())
_keyvals[tokens[0]] = values;
return 1;
}
//---------------------------------------------------------------------------------------
int QEntity::Handle_Comment(vvector<string>& tokens)
{
string values;
for(int i=1; i<tokens.size(); ++i){
values += tokens[i];
values += " ";
}
if(values.length())
_keyvals[tokens[0]] = values;
return 1;
}
//---------------------------------------------------------------------------------------
int QEntity::Handle_Close(vvector<string>& tokens)
{
if(_classname== "\"worldspawn\""){
TRACEX("Store entity brush in scene\r\n");
this->_flags = BRSH_SOLID;
__QLevel._entities << this;
}else{
TRACEX("Store entity in scene\r\n");
__QLevel._entities << this;
}
return 0;
}
//---------------------------------------------------------------------------------------
int QBrush::Handle_Line(vvector<string>& tokens)
{
QBrushFace* pLine = new QBrushFace(_pfw, this);
pLine->Handle_Line(tokens);
if(pLine->_OK)
_pbrshlines << pLine;
return 1;
}
//---------------------------------------------------------------------------------------
int QBrush::Handle_Close(vvector<string>& tokens)
{
if(this->_pbrshlines.size() &&_pParent->_classname=="\"worldspawn\""){
TRACEX("store Qbrush in entity");
_pParent->_brushes << this;
}
return 0; // end brush
}
//---------------------------------------------------------------------------------------
int QBrushFace::Handle_Line(vvector<string>& tokens)
{
float a,b,c,d,e,f,g,h,i;
float u0=0,u1=0,u2=0,u3=0,v0=0,v1=0,v2=0,v3=0;
char name[32];
char originalLine[255]={0};
if(_pParent->_pParent->_classname != "\"worldspawn\"")
return 1;
FOREACH(vvector<string>, tokens, pstring){
::strcat(originalLine, pstring->c_str());
::strcat(originalLine, " ");
}
int spacecount = tokens.size();
if(spacecount > 22){ // new file
::sscanf(originalLine, "( %f %f %f ) ( %f %f %f ) ( %f %f %f ) %s %f %f %f %f %f %f %f %f" , &a,&b,&c,&d,&e,&f,&g,&h,&i, name, &u0, &u1, &u2, &u3, &v0, &v1, &v2, &v3);
}
else{ // never tested (old file)
::sscanf(originalLine, "( %f %f %f ) ( %f %f %f ) ( %f %f %f ) %s %f %f %f" , &a,&b,&c,&d,&e,&f,&g,&h,&i, name, &u0, &u1, &u2);
}
// scale the world by 4
V3 v11(a,c,b);
V3 v22(d,f,e);
V3 v33(g,i,h);
v11*=4.0f; v22*=4.0f; v33*=4.0f;
_center = V3(0,0,0);
_center += v11;
_center += v22;
_center += v33;
_center /= 3.0f; // from wich we spawn the polygon
_plane.CalcNormal (v11,v22,v33);
// reject same planes in this brush
FOREACH(vvector<QBrushFace*>, _pParent->_pbrshlines, ppBrLine)
{
QBrushFace* pLine = *ppBrLine;
if(_plane == pLine->_plane){
return 1;
}
}
_OK = TRUE;
// save texture information
_indexTex = __QLevel.AddTex(name);
_ax[0] = V3(u0, u1, u2);
_shft.u = u3;
_ax[1] = V3(v0, v1, v2);
_shft.v = v3;
return 1;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?