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

📄 pqmaploader_new.cpp

📁 一个类似QUAKE的CSG关卡编辑器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
                          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 + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -