📄 bspconv.cpp
字号:
#include "portal.h"
#include "buildbsp.h"
#include "bspbrush.h"
#include "bsp.h"
bool _CBSPTree::BuildBSP(CMapLoader* map) {
if(!map)
return R_FAIL;
CBSPBuilder BSPBuilder;
CPortalBuilder PortalBuilder;
CBSPReachableExtractor ReachableExtractor;
CBSPFilter Filter;
srcMap = map;
if(!BSPBuilder.BuildTree(this)) {
g_CLog.Log(LOG_SYSTEM, "Compilation failed...");
return R_FAIL;
}
PortalBuilder.BuildPortals(this);
Filter.FilterBrushesAndMarkOpaqueNodes(this);
PortalBuilder.MarkNodeReachability();
if(!Filter.FilterFacesAndMarkLeaves(this, true)) {
g_CLog.Log(LOG_SYSTEM, "Map has no reachable surfaces...");
return R_FAIL;
}
if(PortalBuilder.IsMapClosed()) {
g_CLog.Log(LOG_SYSTEM, "Rebuilding optimized tree...");
BSPBuilder.RebuildTree();
PortalBuilder.RebuildPortals();
Filter.FilterBrushesAndMarkOpaqueNodes(this);
PortalBuilder.MarkNodeReachability();
Filter.FilterFacesAndMarkLeaves(this, false);
} else {
g_CLog.Log(LOG_SYSTEM, "Map is not closed...");
}
PortalBuilder.CalcBounds();
CString prtFile = *srcMap->GetFilename();
prtFile.RemoveExtension();
prtFile.Append(".prt");
PortalBuilder.SaveToFile(prtFile.GetData());
return R_OK;
#if 0 /// old non-OOP code
if(!ExtractMapData()) {
return;
}
g_CLog.Log(LOG_SYSTEM, "Building initial tree...", nLeafs);
BuildTree();
BuildPortals();
SplitBrushesAndMarkOpaqueNodes();
MarkNodeReachability();
if(!FilterMapBrushesAndClipSides()) {
ClearUp();
return;
}
if(IsMapClosed()) {
g_CLog.Log(LOG_SYSTEM, "Rebuilding optimized tree...");
BuildTree();
BuildPortals();
SplitBrushesAndMarkOpaqueNodes();
MarkNodeReachability();
AddFaceRefencesToNodes();
} else {
g_CLog.Log(LOG_SYSTEM, "Map is not closed!");
SplitBrushesAndMarkOpaqueNodes();
}
g_CLog.Log(LOG_SYSTEM, "%4d surfaces in final map.", faces.GetNum());
CalcBounds(1);
#endif // Which one looks better?
}
_CBSPTree::~_CBSPTree() {
CBSPTreeDeallocator td;
td.Deallocate(this);
for(int i=0; i<brushes.GetNum(); i++)
delete brushes[i];
}
int CBSPEmitter::AllocLeafSurface(_CBSPFace *face) {
int index = faceIndices[face];
if(index == -1) {
index = face->Emit(bsp);
faceIndices[face] = index;
}
return bsp->leafSurfIndex.Append(index);
}
int CBSPEmitter::AllocLeafBrush(_CBSPBrush *brush) {
int index = brushIndices[brush];
if(index == -1) {
index = brush->Emit(bsp);
brushIndices[brush] = index;
}
return bsp->leafBrushIndex.Append(index);
}
void CBSPEmitter::VisitLeaf(_CBSPLeafNode *l) {
int li = bsp->leafs.TailAlloc(1);
sBSPLeaf* leaf = &bsp->leafs[li];
bsp->nodes[parent].children[child] = ~li;
if(l->flags & NODE_OPAQUE) {
leaf->cluster = -1;
leaf->area = -1;
} else {
leaf->cluster = l->cluster;
leaf->area = 0;
}
leaf->mins = l->min;
leaf->maxs = l->max;
leaf->firstLeafSurface = bsp->leafSurfIndex.GetNum();
leaf->numLeafSurfaces = l->faces.GetNum();
leaf->firstLeafBrush = bsp->leafBrushIndex.GetNum();
leaf->numLeafBrushes = l->brushes.GetNum();
for(int i=0; i<l->faces.GetNum(); i++) {
AllocLeafSurface(l->faces[i]);
}
for(int i=0; i<l->brushes.GetNum(); i++) {
if(l->brushes[i]->IsValid()) {
AllocLeafBrush(l->brushes[i]);
} else {
leaf->numLeafBrushes--;
}
}
}
void CBSPEmitter::VisitNodeBegin(_CBSPSplitNode *n) {
int ni = bsp->nodes.TailAlloc(1);
sBSPNode* node = &bsp->nodes[ni];
if(parent != -1)
bsp->nodes[parent].children[child] = ni;
node->planeNum = bsp->planesHash.AddElem(*tree->srcMap->GetPlane(n->plane));
node->mins = n->min;
node->maxs = n->max;
for(int i=0; i<2; i++) {
child = i;
parent = ni;
n->children[i]->Visit(this);
}
}
void CBSPEmitter::EmitWorldEntity(CBSP* b, _CBSPTree* t) {
bsp = b;
tree = t;
parent = -1;
// Emit Geometry
tree->tree->Visit(this);
// Emit Entities
CVector<CMapEntity> *me = tree->srcMap->GetEntities();
CMapEntity* entity = &me->GetElemNoBCheck(0);
entity->EmitKVPairs(&bsp->entities);
// Emit World Model
sBSPModel *model = &bsp->models.TailAlloc();
model->min = tree->min;
model->max = tree->max;
model->firstSurface = 0;
model->numSurfaces = bsp->surfaces.GetNum();
model->firstBrush = 0;
model->numBrushes = bsp->brushes.GetNum();
}
void CBSPEmitter::Finish() {
// Emit Planes
bsp->planes.Swap(*bsp->planesHash.GetData());
bsp->planesHash.Clear();
// Emit Shaders
CString textures("textures\\", 9, false);
bsp->shaders.TailAlloc(bsp->shadersHash.GetNum());
for(int i=0; i<bsp->shadersHash.GetNum(); i++) {
sBSPShader *shader = &bsp->shaders[i];
CMapShader *mapShader = bsp->shadersHash.GetElem(i);
mapShader->name.FixPath();
mapShader->name.Prepend(textures);
strncpy(shader->shader, mapShader->name.GetData(), BSP_FILENAME_LEN - 1);
shader->shader[BSP_FILENAME_LEN-1] = 0;
shader->contentFlags = mapShader->contentFlags;
shader->surfaceFlags = mapShader->surfaceFlags;
}
bsp->shadersHash.Clear();
// Fix Normals
for(int i=0; i<bsp->planes.GetNum(); i++) {
bsp->planes[i].w = -bsp->planes[i].w;
}
}
void CBSPEmitter::EmitEntity(_CBSPLeafNode* leaf) {
sBSPModel *model = &bsp->models.TailAlloc();
model->min = leaf->min;
model->max = leaf->max;
model->firstSurface = bsp->surfaces.GetNum();
model->numSurfaces = leaf->faces.GetNum();
model->firstBrush = bsp->brushes.GetNum();
model->numBrushes = leaf->brushes.GetNum();
for(int i=0; i<leaf->faces.GetNum(); i++) {
leaf->faces[i]->Emit(bsp);
}
for(int i=0; i<leaf->brushes.GetNum(); i++) {
leaf->brushes[i]->Emit(bsp);
}
}
bool CompileMap(CBSP *bsp, CMapLoader *map) {
_CBSPTree tree;
CBSPEmitter emitter;
int models = 1;
g_CLog.Log(LOG_SYSTEM, "Compiling BSP tree...");
if(!tree.BuildBSP(map))
return R_FAIL;
emitter.EmitWorldEntity(bsp, &tree);
g_CLog.Log(LOG_SYSTEM, "Compiling submodels...");
for(int i=1; i<map->GetEntities()->GetNum(); i++) {
CMapEntity* entity = &map->GetEntities()->GetElemNoBCheck(i);
_CBSPLeafNode* leaf = CreateSubmodel(entity);
if(leaf) {
CString model("model", 5, false);
char cname[] = {'*', models+'0', 0};
CString name(cname, 2, false);
entity->keyValPairs.Add(model, name);
emitter.EmitEntity(leaf);
for(int i=0; i<leaf->brushes.GetNum(); i++) {
delete leaf->brushes[i];
}
delete leaf;
models++;
}
entity->EmitKVPairs(&bsp->entities);
}
emitter.Finish();
return R_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -