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

📄 pqmaploader.cpp

📁 一个类似QUAKE的CSG关卡编辑器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// **************************************************************************************
// 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 + -