📄 pqmaploader.cpp
字号:
// **************************************************************************************
// Copyright (c) 2000-2005 Zalsoft Inc
// www.zalsoft.com
// sales@zalsoft.com
// You are licensed to use this file on a single computer only.
// **************************************************************************************
#include "stdafx.h"
#include "stdio.h"
#include "baselib.h"
#include "baseutils.h"
#include "basecont.h"
#include "PqmapLoader.h"
#include <algorithm>
//----------------------------------------------------------------------------------
bool Parser::_doubleopen = false;
//----------------------------------------------------------------------------------
const REAL __epsilon = 1e-5;
//---------------------------------------------------------------------------------------
struct QLevel
{
vvector<QEntity*> _entities;
vvector<string> _texnames;
// adds a unique tex and returns the index into this array
int AddTex(const char* n){
vvector<string>::iterator fi = find(_texnames.begin(), _texnames.end(), n);
if(fi != _texnames.end())
return fi-_texnames.begin();
_texnames<<n;
return _texnames.size()-1;
}
}__QLevel;
//---------------------------------------------------------------------------------------
// this may not be properly handeled. See UT calc tex coord how is done
void CalcTexCoord(QPoly& qp, UV* shift)
{
UV maxuv[2];
Box box ;
vvector<UV>& uvs = qp._uvs;
FOREACH(vvector<V3>, qp._vxes, pvx){
box.AddPoint(*pvx);
}
box.FlatIt(maxuv);
for(int i=0; i < qp._vxes.size() ;i++)
{
V3& v = qp._vxes[i];
UV t;
switch(box.GetMinimAx())
{
case 'x': //z,y
t.v = (v.y-maxuv[0].v) / (maxuv[1].v-maxuv[0].v);
t.u = (v.z-maxuv[0].u) / (maxuv[1].u-maxuv[0].u);
break;
case 'y': //x,z
t.u = (v.x-maxuv[0].u) / (maxuv[1].u-maxuv[0].u);
t.v = (v.z-maxuv[0].v) / (maxuv[1].v-maxuv[0].v);
break;
case 'z': //x,y
t.u = (v.x-maxuv[0].u) / (maxuv[1].u-maxuv[0].u);
t.v = (v.y-maxuv[0].v) / (maxuv[1].v-maxuv[0].v);
break;
}
t.v +=shift->u;
t.u +=shift->v;
qp._uvs << t;
}
}
//---------------------------------------------------------------------------------------
// splits by plane all 'p' and populates a and b
void Split(Plane& plane, vvector<V3>& p, vvector<V3>& a, vvector<V3>& b)
{
V3 iv;
V3 itxB = *p.begin();
V3 itxA = p.back();
REAL fB;
REAL fA = plane.DistTo(itxA);
FOREACH(vvector<V3>, p, vxI)
{
itxB = *vxI;
fB = plane.DistTo(itxB);
if(fB > 0.01)
{
if(fA < -0.01f)
{
REAL t = -fA /(fB - fA);
iv.interpolate(itxA,itxB,t);
a << iv;
b << iv;
}
a<<itxB;
}
else if(fB < -0.01f)
{
if(fA > 0.01f)
{
REAL t = -fA /(fB - fA); // t of segment
iv.interpolate(itxA,itxB,t);
a << iv;
b << iv;
}
b <<itxB;
}
else
{
a << itxB;
b << itxB;
}
itxA = itxB;
fA = fB;
}
}
//---------------------------------------------------------------------------------------
// from plane p builds a huge polygon 'qp'
void FromPlane(const Plane& p, QPoly& qp, V3* center)
{
// get to see what wax we are using for rotation cp
V3 ax = GetMinAx((V3&)p._n);
ax.norm();
// to corner vectors;
V3 uDr = Vcp(ax, p._n);
V3 vDr = Vcp(uDr, p._n);
uDr *= 36635.0;
vDr *= 36635.0;
REAL vdp = Vdp(p._n, ax);
V3& c = *center;
qp._vxes << c+(uDr-vDr);
qp._vxes << c+(uDr+vDr);
qp._vxes << c-(uDr-vDr);
qp._vxes << c-(uDr+vDr);
}
//---------------------------------------------------------------------------------------
// from all brush planes build all brush polygons
void FromPlanes(vvector<Plane*>& planes,
vvector<V3*>& centers,
vvector<UV*> shifts,
vvector<int> texIdxes,
BOOL front,
vvector<QPoly>& outPolys)
{
int jidx = 0;
FOREACH(vvector<Plane*>, planes, pplane)
{
QPoly qp;
FromPlane(*(*pplane), qp, centers[jidx]);
qp._texIdx = texIdxes[jidx];
// see if builded polygon plane faces as original
// polygon which was build from
{
Plane pOfPoly;
pOfPoly.CalcNormal(qp._vxes[0], qp._vxes[1], qp._vxes[2]);
if(IsZero(Vdp(pOfPoly._n, (*pplane)->_n)), __epsilon)// poly has to be reversed
{
qp._vxes.reverse();
}
}
// cut it with all other polygons
FOREACH(vvector<Plane*>, planes, pplane2)
{
if(pplane2 == pplane)
continue;
vvector<V3> a;
vvector<V3> b;
Split(**pplane2, qp._vxes, a, b);
qp._vxes.clear();
if(front)
{
qp._vxes = a;
}
else
{
qp._vxes = b;
}
}
if(qp._vxes.size() >= 3)
{
// calc if normals are the same
CalcTexCoord(qp, shifts[jidx]);
outPolys << qp;
}
++jidx;
}
}
//---------------------------------------------------------------------------------------
void GatherBrushes(vvector<QBrush*>& allBrushes, vvector<QEntity*>& allEntities)
{
FOREACH(vvector<QEntity*>, __QLevel._entities, ppEntity)
{
if((*ppEntity)->_classname== "\"worldspawn\"")
{
FOREACH(vvector<QBrush*>, (*ppEntity)->_brushes, ppBrush)
{
allBrushes << (*ppBrush);
}
}
if((*ppEntity)->_classname== "\"light\"")
{
allEntities << *ppEntity;
}
}
}
//---------------------------------------------------------------------------------------
long PqmapLoader::PostProcess(Plg_Scene** pScene)
{
vvector<QBrush*> allBrushes;
vvector<QEntity*> allEntities;
GatherBrushes(allBrushes, allEntities);
// allocate space for scene and for all brushes
*pScene = new Plg_Scene;
::memset(*pScene, 0, sizeof(Plg_Scene));
(*pScene)->nBrushes = allBrushes.size();
(*pScene)->pBrushes = new Plg_Brush[allBrushes.size()];
(*pScene)->nTextures = __QLevel._texnames.size();
(*pScene)->pTextures = new Plg_Texture[__QLevel._texnames.size()];
// store textures here
for(int t = 0; t < __QLevel._texnames.size(); t++)
{
(*pScene)->pTextures[t].target = 0; // GL_TEXTURE2D
::strcpy((*pScene)->pTextures[t].filename, __QLevel._texnames[t].c_str());
}
if(allEntities.size())
{
(*pScene)->nItems = allEntities.size();
(*pScene)->pItems = new Plg_Item[(*pScene)->nItems];
int index = 0;
FOREACH(vvector<QEntity*>, allEntities, ppEntity)
{
Plg_Item& itm = (*pScene)->pItems[index];
itm.classType=CLASS_IS_LIGHT;
strcpy(itm.classname, (*ppEntity)->_classname.c_str());
itm.position = (*ppEntity)->_pos;
itm._U._Light.radius = (REAL)(*ppEntity)->_intensity * 15.0;
itm._U._Light.intensity = (*ppEntity)->_intensity ;
itm._U._Light.color[0] = 255;
itm._U._Light.color[1] = 255;
itm._U._Light.color[2] = 255;
++index;
}
}
// for each q-brush
int indexBr = 0;
FOREACH(vvector<QBrush*>, allBrushes, ppBrush)
{
vvector<Plane*> planes;
vvector<QPoly> polys;
vvector<V3*> centers;
vvector<UV*> shifts;
vvector<int> texIdxes;
Plg_Brush& plgBrush = (*pScene)->pBrushes[indexBr];
QBrush* pBrush = *ppBrush;
int indexp = 0;
//
// for each qface line collect planes
//
FOREACH(vvector<QBrushFace*>, pBrush->_pbrshlines, ppBrLine)
{
QBrushFace* pLine = *ppBrLine;
planes << &pLine->_plane;
centers << &pLine->_center;
shifts << &pLine->_shft;
texIdxes << pLine->_indexTex;
}
//
// all brush faces, get out brush polygons
//
FromPlanes(planes, centers, shifts, texIdxes, 0, polys);
//
// load them in the plgBrush
//
if(polys.size() > 4)
{
plgBrush.nPolys = polys.size();
plgBrush.pPolys = new Plg_Poly[polys.size()];
// alloc vertexes space
FOREACH(vvector<QPoly>, polys, ppPoly)
{
plgBrush.pPolys[indexp].nvXes = ppPoly->_vxes.size();
plgBrush.pPolys[indexp].vXes = new Vtx[ppPoly->_vxes.size()];
++indexp;
}
//
// store info in plg brush
//
plgBrush.flags = pBrush->_pParent->_flags;
plgBrush.name[0] = '\0';
indexp = 0;
_FOREACH(vvector<QPoly>, polys, ppPoly)
{
plgBrush.pPolys[indexp].texIdx[2] = -1;
plgBrush.pPolys[indexp].texIdx[1] = -1;
plgBrush.pPolys[indexp].texIdx[0] = ppPoly->_texIdx; // index in texture previously saved
plgBrush.pPolys[indexp].texapply[0] = 0;
plgBrush.pPolys[indexp].texapply[1] = 0;
plgBrush.pPolys[indexp].texapply[2] = 0;
plgBrush.pPolys[indexp].combine = 0x1; // one texture has been set
plgBrush.pPolys[indexp].flags = 0;
int idxv = 0;
FOREACH(vvector<V3>, ppPoly->_vxes, pVx)
{
plgBrush.pPolys[indexp].vXes[idxv]._xyz = *pVx;
plgBrush.pPolys[indexp].vXes[idxv]._uv[0] = ppPoly->_uvs[idxv];
++idxv;
}
++indexp;
}
}
++indexBr;
}
return 0;
}
//---------------------------------------------------------------------------------------
long PqmapLoader::GetVersion()
{
return 1;
}
//---------------------------------------------------------------------------------------
static BOOL GetCloseUpPoly(Plg_Poly* pPolys, int count , Plg_Poly& p, V3& vx)
{
// find adiacent polygon which
return FALSE;
}
//---------------------------------------------------------------------------------------
long PqmapLoader::ExportFile(IGeticEditor* pe, char* installDir, char* bsFileName, const Plg_Scene* pScene)
{
int bn = 0;
FileWrap fw;
char texname[64];
char cd[256];
_getcwd(cd,256);
string mapname = bsFileName;
int idx = mapname.find(".");
if(idx !=-1)
{
mapname = mapname.substr(0,idx);
PathHandler ph(mapname.c_str());
_mapname = ph.JustFile();
}
mkdir(_mapname.c_str());
if(!fw.Open(bsFileName, "wb"))
return -1;
// expand textures in a readable variable
Plg_Texture* ptrTotextures = pScene->pTextures;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -