⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pqmaploader_cuts.cpp

📁 一个类似QUAKE的CSG关卡编辑器
💻 CPP
字号:
// PqmapLoader.cpp: implementation of the PqmapLoader class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "stdio.h"
#include "..\\_include\\BspFIleStr.h"
#include "baselib.h"
#include "basecont.h"
#include "PqmapLoader.h"


//---------------------------------------------------------------------------------------
void CalcTexCoord(QPoly& qp)
{
    UV			maxuv[2];
    Box         box ;

    vvector<UV>& uvs = qp._uvs;
    FOREACH(vvector<V3>, qp._vxes, pvx)
    {
        /*
        assert(pvx->x < INFINIT);
        assert(pvx->y < INFINIT);
        assert(pvx->z < INFINIT);

        assert(pvx->x > -INFINIT);
        assert(pvx->y > -INFINIT);
        assert(pvx->z > -INFINIT);
        */

        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);
/*
				t.v*=_texcoord.scaley;
				t.u*=_texcoord.scalex;

				t.v+=_texcoord.shifty;
				t.u+=_texcoord.shiftx;
*/
                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);
/*
				t.u*=_texcoord.scalex;
				t.v*=_texcoord.scaley;

				t.u+=_texcoord.shiftx;
				t.v+=_texcoord.shifty;
*/
                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);
/*
				t.u*=_texcoord.scalex;
				t.v*=_texcoord.scaley;

				t.u+=_texcoord.shiftx;
				t.v+=_texcoord.shifty;
*/
                break;
        }
        qp._uvs << t;
    }
}

//---------------------------------------------------------------------------------------
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);
	//REAL	fA = plane.GetSide(itxA._xyz);
    
    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;
    }
}

//---------------------------------------------------------------------------------------
void FromPlane(const Plane& p, QPoly& qp, V3* center)
{
	V3		ax = GetMajorAxes((V3&)p._n);  // get to see what wax we are using for rotation cp
    ax.norm();

    // build a polygon from plane
	V3		uDr  = Vcp(ax,  p._n);		   // to corner vectors;
	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);					// switch this to be able to rotate it
	qp._vxes <<  c-(uDr+vDr);
}

//---------------------------------------------------------------------------------------
void  FromPlanes(vvector<Plane*>& planes,
                 vvector<V3*>& centers,
                 BOOL front, vvector<QPoly>& outPolys)
{
    int jidx = 0;
    FOREACH(vvector<Plane*>, planes, pplane)
    {
        QPoly qp;
        
        FromPlane(**pplane, qp, centers[jidx++]);

        // 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;
            }
        }
        //assert(qp._vxes.size() >= 3);
        if(qp._vxes.size() >= 3)
        {
            CalcTexCoord(qp);
            outPolys << (qp);
        }
    }
}

//---------------------------------------------------------------------------------------
INLN TCHAR*	StripChar(TCHAR* psz, TCHAR ch)
{
	TCHAR* ps = psz;
	TCHAR* pd = psz;
	while(*ps){
		if(*ps==ch)
		{	ps++;continue;}
		*pd++=*ps++;
	}
	*pd=0;
	return psz;
}

//---------------------------------------------------------------------------------------
struct QLevel
{

    vvector<QEntity*>   _entities;
    vvector<string>     _texNames;
}__QLevel;

//---------------------------------------------------------------------------------------
long PqmapLoader::PostProcess(Plg_Scene** pScene)
{
    vvector<QBrush*>    allBrushes;

    // collect all brushes
    FOREACH(vvector<QEntity*>, __QLevel._entities, ppEntity)
    {
        if((*ppEntity)->_classname== "\"worldspawn\"")
        {
            FOREACH(vvector<QBrush*>, (*ppEntity)->_brushes, ppBrush)
            {
                allBrushes << (*ppBrush);
            }
        }
    }

    // allocate space for scene and for all brushes
    *pScene = new Plg_Scene;
    (*pScene)->nBrushes = allBrushes.size();
    (*pScene)->pBrushes = new Plg_Brush[allBrushes.size()];
    (*pScene)->pTextures = 0;

    // for each q-brush
    int indexBr = 0;
    FOREACH(vvector<QBrush*>,  allBrushes, ppBrush)
    {
        vvector<Plane*>     faces;  
        vvector<V3*>        centers;  
        Plg_Brush&          plgBrush =  (*pScene)->pBrushes[indexBr];
        QBrush*             pBrush   = *ppBrush;
        
        // for each qface line collect planes 
        FOREACH(vvector<QBrushFace*>,  pBrush->_pbrshlines, ppBrLine)
        {
            QBrushFace* pLine = *ppBrLine;
            faces << &pLine->_plane;
            centers << &pLine->_center;
        }

        // all brush faces, get out brush polygons
        vvector<QPoly>          polys;
        FromPlanes(faces, centers, 0, polys);   

        // load them in the plgBrush
        // alloc poly pointer
        plgBrush.nPolys = polys.size();
        plgBrush.pPolys = new Plg_Poly[polys.size()];

        // first step allocate space for vertexes
        int indexp=0;
        FOREACH(vvector<QPoly>, polys, ppPoly)
        {

            plgBrush.pPolys[indexp].nvXes = ppPoly->_vxes.size();
            plgBrush.pPolys[indexp].vXes  = new Vtx[ppPoly->_vxes.size()];
            ++indexp;
        }

        // second one p
        indexp=0;
        _FOREACH(vvector<QPoly>, polys, ppPoly)
        {
            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::ExportFile(TCHAR* bsFileName, const Plg_Scene* pBrush)
{
    return -1;
}

//---------------------------------------------------------------------------------------
long PqmapLoader::GetMenuStringAndType(TCHAR* bsFileName, DWORD* type)
{
    //large enough
    _tcscpy(bsFileName,"map files,map");
    *type = PLUG_IMPORTER;
    return 0;
}


//---------------------------------------------------------------------------------------
long PqmapLoader::ImportFile(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)
{
   
    if(pScene)
    {
        if(pScene->pTextures)
            delete[] pScene->pTextures;

		for(int i=0; i< pScene->nBrushes;i++)
		{
            Plg_Brush& b = pScene->pBrushes[i];
			for(int j=0; j< b.nPolys;j++)
			{
                Plg_Poly& p = b.pPolys[j];
                delete[] p.vXes;
			}
			delete[]b.pPolys;
		}
        delete[] pScene->pBrushes;
        delete pScene;
    }
    return 0;
}

//---------------------------------------------------------------------------------------
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)
{
    // handle only brushes
    if(_classname== "\"worldspawn\"")
    {
        TRACEX("New Brush\r\n");
        QBrush* pBrush = new QBrush(_pfw, this);
        while(pBrush->Step()>0)
        {
            ;
        }
    }
    return -1;
}

//---------------------------------------------------------------------------------------
int    QEntity::Handle_Close(vvector<string>& tokens)
{
    if(_classname== "\"worldspawn\"")
    {
        TRACEX("Store entity in scene\r\n");
        __QLevel._entities << this;
    }
    return -1;
}

//---------------------------------------------------------------------------------------
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_Open(vvector<string>& tokens)
{
    return _pParent->Handle_Open(tokens);
}

//---------------------------------------------------------------------------------------
int QBrush::Handle_Close(vvector<string>& tokens)
{
    TRACEX("store Qbrush in entity");
    _pParent->_brushes << this;
    return 0;       // end brush
}


//---------------------------------------------------------------------------------------
int QBrushFace::Handle_Line(vvector<string>& tokens)
{
    int     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};

    FOREACH(vvector<string>, tokens, pstring)
    {
        ::strcat(originalLine, pstring->c_str());
        ::strcat(originalLine, " ");
    }

    int spacecount = tokens.size();
    if(spacecount > 22)
    {
        ::sscanf(originalLine, "( %d %d %d ) ( %d %d %d ) ( %d %d %d ) %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
    {
        ::sscanf(originalLine, "( %d %d %d ) ( %d %d %d ) ( %d %d %d ) %s %f %f %f" , &a,&b,&c,&d,&e,&f,&g,&h,&i, name, &u0, &u1, &u2);
    }

    V3  v11(a,c,b);
    V3  v22(d,f,e);
    V3  v33(g,i,h);

    v11*=6.0;
    v22*=6.0;
    v33*=6.0;

    _center = v11;
    _center += v22;
    _center += v33;
    _center /= 3.0f;

    _plane.CalcNormal (v11,v22,v33);

    FOREACH(vvector<QBrushFace*>,  _pParent->_pbrshlines, ppBrLine)
    {
        QBrushFace* pLine = *ppBrLine;
        if(_plane == pLine->_plane)
        {
            return 0;
        }
    }
    _OK = TRUE;
    ::strcpy(_texname, name);
    _u[0] = u0;
    _u[1] = u1;
    _u[2] = u2;
    _u[3] = u3;

    _v[0] = v0;
    _v[1] = v1;
    _v[2] = v2;
    _v[3] = v3;

    return 1;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -