runtime: CMake-ify
This commit is contained in:
@@ -0,0 +1,762 @@
|
||||
|
||||
#include "std.hpp"
|
||||
#include "q3bsprep.hpp"
|
||||
|
||||
/* Quake3 File format types */
|
||||
|
||||
#pragma pack(push,1)
|
||||
|
||||
struct q3_plane {
|
||||
Vector normal;
|
||||
float distance;
|
||||
};
|
||||
|
||||
struct q3_tex {
|
||||
char name[64];
|
||||
int flags, contents;
|
||||
};
|
||||
|
||||
struct q3_vertex {
|
||||
Vector coords;
|
||||
float tex_coords[4];
|
||||
Vector normal;
|
||||
unsigned char color[4];
|
||||
};
|
||||
|
||||
struct q3_node {
|
||||
int plane;
|
||||
int children[2];
|
||||
int mins[3];
|
||||
int maxs[3];
|
||||
};
|
||||
|
||||
struct q3_face {
|
||||
int texture;
|
||||
int effect;
|
||||
int type;
|
||||
int vertex;
|
||||
int n_verts;
|
||||
int meshvert;
|
||||
int n_meshverts;
|
||||
int lm_index;
|
||||
int lm_start[2];
|
||||
int lm_size[2];
|
||||
float lm_origin[3];
|
||||
float lm_vecs[2][3];
|
||||
float normal[3];
|
||||
int patch_size[2];
|
||||
};
|
||||
|
||||
struct q3_leaf {
|
||||
int cluster;
|
||||
int area;
|
||||
int mins[3];
|
||||
int maxs[3];
|
||||
int leafface;
|
||||
int n_leaffaces;
|
||||
int leafbrush;
|
||||
int n_leafbrushes;
|
||||
};
|
||||
|
||||
struct q3_brush {
|
||||
int brushside;
|
||||
int n_brushsides;
|
||||
int texture;
|
||||
};
|
||||
|
||||
struct q3_brushside {
|
||||
int plane;
|
||||
int texture;
|
||||
};
|
||||
|
||||
struct q3_direntry {
|
||||
union {
|
||||
int offset;
|
||||
void *lump;
|
||||
};
|
||||
int length;
|
||||
};
|
||||
|
||||
struct q3_header {
|
||||
unsigned magic;
|
||||
int version;
|
||||
q3_direntry dir[17];
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/* Loading reps */
|
||||
struct Surf {
|
||||
Q3BSPSurf *surf;
|
||||
int texture, lm_index;
|
||||
vector<int> verts, tris;
|
||||
};
|
||||
|
||||
struct FaceCmp {
|
||||
bool operator()(const q3_face *a, const q3_face *b)const {
|
||||
if (a->texture < b->texture) return true;
|
||||
if (b->texture < a->texture) return false;
|
||||
if (a->lm_index < b->lm_index) return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
typedef map<q3_face*, Surf*, FaceCmp> FaceMap;
|
||||
|
||||
/* render reps */
|
||||
|
||||
struct Q3BSPFace;
|
||||
|
||||
struct Q3BSPSurf {
|
||||
Brush brush;
|
||||
gxMesh *mesh;
|
||||
vector<Q3BSPFace*> r_faces;
|
||||
int texture, lm_index;
|
||||
};
|
||||
|
||||
struct Q3BSPFace {
|
||||
union {
|
||||
Surf *t_surf;
|
||||
Q3BSPSurf *surf;
|
||||
};
|
||||
int vert, n_verts, tri, n_tris;
|
||||
};
|
||||
|
||||
struct Q3BSPBrush {
|
||||
vector<Plane> planes;
|
||||
};
|
||||
|
||||
struct Q3BSPLeaf {
|
||||
int cluster;
|
||||
Box box;
|
||||
vector<Q3BSPFace*> faces;
|
||||
};
|
||||
|
||||
struct Q3BSPNode {
|
||||
Box box;
|
||||
Plane plane;
|
||||
Q3BSPNode *nodes[2];
|
||||
Q3BSPLeaf *leafs[2];
|
||||
|
||||
~Q3BSPNode() { delete nodes[0]; delete nodes[1]; delete leafs[0]; delete leafs[1]; }
|
||||
};
|
||||
|
||||
static q3_header header;
|
||||
static FaceMap face_map;
|
||||
static vector<Surf*> t_surfs;
|
||||
static vector<q3_vertex> p_verts; //patch vertices
|
||||
static vector<Vector> p_coll_verts;
|
||||
static vector<MeshCollider::Triangle> coll_tris;
|
||||
|
||||
static float gamma_adj;
|
||||
|
||||
static Vector r_eye;
|
||||
static int r_cluster;
|
||||
static Frustum r_frustum;
|
||||
static Vector r_frustedges[12];
|
||||
static map<int, Q3BSPFace*> q3face_map;
|
||||
|
||||
extern gxScene *gx_scene;
|
||||
extern gxRuntime *gx_runtime;
|
||||
extern gxGraphics *gx_graphics;
|
||||
|
||||
//#define SWAPTRIS
|
||||
Vector static tf(const Vector &v) {
|
||||
return Vector(-v.y, v.z, v.x);
|
||||
}
|
||||
|
||||
#ifdef BETA
|
||||
static void debuglog(const string &t) {
|
||||
gx_runtime->debugLog(t.c_str());
|
||||
}
|
||||
#else
|
||||
static void debuglog(const string &t) {}
|
||||
#endif
|
||||
|
||||
static Surf *findSurf(q3_face *f) {
|
||||
FaceMap::const_iterator it = face_map.find(f);
|
||||
if (it != face_map.end()) return it->second;
|
||||
Surf *s = new Surf;
|
||||
s->texture = f->texture;
|
||||
s->lm_index = f->lm_index;
|
||||
face_map.insert(make_pair(f, s));
|
||||
t_surfs.push_back(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
void Q3BSPRep::createTextures() {
|
||||
int n_texs = header.dir[1].length / sizeof(q3_tex);
|
||||
q3_tex *q3tex = (q3_tex*)header.dir[1].lump;
|
||||
for (int k = 0; k < n_texs; ++k) {
|
||||
string t = string(q3tex->name);
|
||||
char fl[32], co[32];
|
||||
_itoa(q3tex->flags, fl, 16);
|
||||
_itoa(q3tex->contents, co, 16);
|
||||
debuglog(t + ", flags=0x" + fl + ", contents=0x" + co);
|
||||
Texture tex(t + ".tga", 1);
|
||||
if (!tex.getCanvas(0)) {
|
||||
tex = Texture(t + ".jpg", 1);
|
||||
if (!tex.getCanvas(0)) {
|
||||
tex = Texture(t + ".png", 1);
|
||||
if (!tex.getCanvas(0)) {
|
||||
tex = Texture(t + ".dds", 1);
|
||||
if (!tex.getCanvas(0)) debuglog("Failed!");
|
||||
}
|
||||
}
|
||||
}
|
||||
tex.setFlags(1);
|
||||
textures.push_back(tex);
|
||||
++q3tex;
|
||||
}
|
||||
}
|
||||
|
||||
void Q3BSPRep::createLightMaps() {
|
||||
int n_lmaps = header.dir[14].length / (128 * 128 * 3);
|
||||
unsigned char *rgb = (unsigned char*)header.dir[14].lump;
|
||||
unsigned char adj[256];
|
||||
int k;
|
||||
for (k = 0; k < 256; ++k) adj[k] = pow(k / 255.0f, gamma_adj)*255.0f;
|
||||
|
||||
for (k = 0; k < n_lmaps; ++k) {
|
||||
Texture tex(128, 128, 1 + 8 + 16 + 32, 1);
|
||||
tex.setBlend(gxScene::BLEND_ADD);
|
||||
gxCanvas *c = tex.getCanvas(0);
|
||||
c->lock();
|
||||
for (int y = 0; y < 128; ++y) {
|
||||
for (int x = 0; x < 128; ++x) {
|
||||
unsigned argb = 0xff000000 | (adj[rgb[0]] << 16) | (adj[rgb[1]] << 8) | adj[rgb[2]];
|
||||
c->setPixelFast(x, y, argb);
|
||||
rgb += 3;
|
||||
}
|
||||
}
|
||||
c->unlock();
|
||||
light_maps.push_back(tex);
|
||||
}
|
||||
}
|
||||
|
||||
void Q3BSPRep::createVis() {
|
||||
int *vis = (int*)header.dir[16].lump;
|
||||
int n_vecs = *vis++;
|
||||
vis_sz = *vis++;
|
||||
debuglog("vis: " + itoa(n_vecs) + "," + itoa(vis_sz));
|
||||
vis_data = new char[n_vecs*vis_sz];
|
||||
memcpy(vis_data, vis, n_vecs*vis_sz);
|
||||
}
|
||||
|
||||
void Q3BSPRep::createCollider() {
|
||||
vector<MeshCollider::Vertex> coll_verts;
|
||||
int n_verts = header.dir[10].length / sizeof(q3_vertex);
|
||||
q3_vertex *t = (q3_vertex*)header.dir[10].lump;
|
||||
MeshCollider::Vertex cv;
|
||||
int k;
|
||||
for (k = 0; k < n_verts; ++k) {
|
||||
cv.coords = tf(t->coords);
|
||||
coll_verts.push_back(cv);
|
||||
++t;
|
||||
}
|
||||
for (k = 0; k < p_coll_verts.size(); ++k) {
|
||||
cv.coords = p_coll_verts[k];
|
||||
coll_verts.push_back(cv);
|
||||
}
|
||||
#ifdef SWAPTRIS
|
||||
for (k = 0; k < coll_tris.size(); ++k) {
|
||||
std::swap(coll_tris[k].verts[1], coll_tris[k].verts[2]);
|
||||
}
|
||||
#endif
|
||||
collider = new MeshCollider(coll_verts, coll_tris);
|
||||
p_coll_verts.clear();
|
||||
coll_verts.clear();
|
||||
coll_tris.clear();
|
||||
}
|
||||
|
||||
void Q3BSPRep::createSurfs() {
|
||||
int k;
|
||||
for (k = 0; k < t_surfs.size(); ++k) {
|
||||
Surf *s = t_surfs[k];
|
||||
gxMesh *mesh = gx_graphics->createMesh(s->verts.size(), s->tris.size() / 3, 0);
|
||||
|
||||
mesh->lock(true);
|
||||
int j;
|
||||
for (j = 0; j < s->verts.size(); ++j) {
|
||||
q3_vertex *t;
|
||||
int n = s->verts[j];
|
||||
if (n >= 0) {
|
||||
t = (q3_vertex*)header.dir[10].lump + n;
|
||||
} else {
|
||||
t = &p_verts[-n - 1];
|
||||
}
|
||||
float tex_coords[2][2] = { {t->tex_coords[2],t->tex_coords[3]},{t->tex_coords[0],t->tex_coords[1]} };
|
||||
unsigned argb = 0xff000000 | (t->color[0] << 16) | (t->color[1] << 8) | t->color[2];
|
||||
mesh->setVertex(j, tf(t->coords), tf(t->normal), argb, tex_coords);
|
||||
}
|
||||
for (j = 0; j < s->tris.size(); j += 3) {
|
||||
#ifdef SWAPTRIS
|
||||
mesh->setTriangle(j / 3, s->tris[j], s->tris[j + 2], s->tris[j + 1]);
|
||||
#else
|
||||
mesh->setTriangle(j / 3, s->tris[j], s->tris[j + 1], s->tris[j + 2]);
|
||||
#endif
|
||||
}
|
||||
mesh->unlock();
|
||||
|
||||
Q3BSPSurf *surf = new Q3BSPSurf;
|
||||
surf->texture = s->texture;
|
||||
surf->lm_index = s->lm_index;
|
||||
surf->mesh = mesh;
|
||||
surfs.push_back(surf);
|
||||
s->surf = surf;
|
||||
}
|
||||
for (k = 0; k < faces.size(); ++k) {
|
||||
Q3BSPFace *f = faces[k];
|
||||
f->surf = f->t_surf->surf;
|
||||
f->tri /= 3; f->n_tris /= 3;
|
||||
}
|
||||
for (k = 0; k < t_surfs.size(); ++k) {
|
||||
delete t_surfs[k];
|
||||
}
|
||||
face_map.clear();
|
||||
t_surfs.clear();
|
||||
p_verts.clear();
|
||||
}
|
||||
|
||||
static void average(const q3_vertex &a, const q3_vertex &b, q3_vertex *c) {
|
||||
c->coords = (a.coords + b.coords)*.5f;
|
||||
c->normal = (a.normal + b.normal)*.5f;
|
||||
for (int k = 0; k < 4; ++k) {
|
||||
c->color[k] = (a.color[k] + b.color[k] + 1) / 2;
|
||||
c->tex_coords[k] = (a.tex_coords[k] + b.tex_coords[k])*.5f;
|
||||
}
|
||||
}
|
||||
|
||||
static void subdivide(vector<q3_vertex> &verts, int level, int index, int step) {
|
||||
if (!level) {
|
||||
q3_vertex t1, t2;
|
||||
average(verts[index], verts[index + step], &t1);
|
||||
average(verts[index + step], verts[index + step * 2], &t2);
|
||||
average(t1, t2, &verts[index + step]);
|
||||
return;
|
||||
}
|
||||
average(verts[index], verts[index + step], &verts[index + step / 2]);
|
||||
average(verts[index + step], verts[index + step * 2], &verts[index + step + step / 2]);
|
||||
average(verts[index + step / 2], verts[index + step + step / 2], &verts[index + step]);
|
||||
subdivide(verts, level - 1, index, step / 2);
|
||||
subdivide(verts, level - 1, index + step, step / 2);
|
||||
}
|
||||
|
||||
static void patchFace(Q3BSPFace *face, q3_face *q3face, bool draw, bool solid, int level) {
|
||||
|
||||
int k, x, y;
|
||||
vector<q3_vertex> verts;
|
||||
|
||||
if (draw) {
|
||||
int step = 1 << level;
|
||||
int size_x = (q3face->patch_size[0] - 1)*step + 1;
|
||||
int size_y = (q3face->patch_size[1] - 1)*step + 1;
|
||||
verts.resize(size_x*size_y);
|
||||
|
||||
//seed initial verts
|
||||
q3_vertex *t = (q3_vertex*)header.dir[10].lump + q3face->vertex;
|
||||
for (y = 0; y < size_y; y += step) {
|
||||
for (x = 0; x < size_x; x += step) {
|
||||
verts[y*size_x + x] = *t++;
|
||||
}
|
||||
}
|
||||
//subdivide!
|
||||
for (y = 0; y < size_y; y += step) {
|
||||
for (x = 0; x < size_x - 1; x += step * 2) {
|
||||
subdivide(verts, level, y*size_x + x, step);
|
||||
}
|
||||
}
|
||||
for (x = 0; x < size_x; ++x) {
|
||||
for (y = 0; y < size_y - 1; y += step * 2) {
|
||||
subdivide(verts, level, y*size_x + x, size_x*step);
|
||||
}
|
||||
}
|
||||
|
||||
Surf *surf = face->t_surf;
|
||||
int vert = surf->verts.size() - face->vert;
|
||||
|
||||
//generate patch verts
|
||||
for (k = 0; k < size_x*size_y; ++k) {
|
||||
p_verts.push_back(verts[k]);
|
||||
surf->verts.push_back(p_verts.size()); // Why was there a - here
|
||||
}
|
||||
face->n_verts += size_x*size_y;
|
||||
|
||||
//generate tris...
|
||||
for (y = 0; y < size_y - 1; ++y) {
|
||||
int n = y*size_x + vert;
|
||||
for (x = 0; x < size_x - 1; ++n, ++x) {
|
||||
surf->tris.push_back(n);
|
||||
surf->tris.push_back(n + size_x);
|
||||
surf->tris.push_back(n + 1);
|
||||
surf->tris.push_back(n + size_x + 1);
|
||||
surf->tris.push_back(n + 1);
|
||||
surf->tris.push_back(n + size_x);
|
||||
}
|
||||
}
|
||||
face->n_tris += (size_x - 1)*(size_y - 1) * 6;
|
||||
}
|
||||
|
||||
if (solid) {
|
||||
vector<q3_vertex> verts;
|
||||
int step = 1;
|
||||
int size_x = q3face->patch_size[0];
|
||||
int size_y = q3face->patch_size[1];
|
||||
verts.resize(size_x*size_y);
|
||||
|
||||
//seed initial verts
|
||||
q3_vertex *t = (q3_vertex*)header.dir[10].lump + q3face->vertex;
|
||||
for (k = 0; k < size_x*size_y; ++k) verts[k] = *t++;
|
||||
//subdivide!
|
||||
for (y = 0; y < size_y; y += step) {
|
||||
for (x = 0; x < size_x - 1; x += step * 2) {
|
||||
subdivide(verts, 0, y*size_x + x, step);
|
||||
}
|
||||
}
|
||||
for (x = 0; x < size_x; ++x) {
|
||||
for (y = 0; y < size_y - 1; y += step * 2) {
|
||||
subdivide(verts, 0, y*size_x + x, size_x*step);
|
||||
}
|
||||
}
|
||||
|
||||
int vert = header.dir[10].length / sizeof(q3_vertex) + p_coll_verts.size();
|
||||
|
||||
//generate patch verts
|
||||
for (k = 0; k < size_x*size_y; ++k) p_coll_verts.push_back(tf(verts[k].coords));
|
||||
|
||||
MeshCollider::Triangle ct;
|
||||
ct.surface = 0; ct.index = 0;
|
||||
//generate tris...
|
||||
for (y = 0; y < size_y - 1; ++y) {
|
||||
int n = y*size_x + vert;
|
||||
for (x = 0; x < size_x - 1; ++n, ++x) {
|
||||
ct.verts[0] = n;
|
||||
ct.verts[1] = n + size_x;
|
||||
ct.verts[2] = n + 1;
|
||||
coll_tris.push_back(ct);
|
||||
ct.verts[0] = n + size_x + 1;
|
||||
ct.verts[1] = n + 1;
|
||||
ct.verts[2] = n + size_x;
|
||||
coll_tris.push_back(ct);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void meshFace(Q3BSPFace *face, q3_face *q3face, bool draw, bool solid) {
|
||||
static map<int, int> vert_map;
|
||||
vert_map.clear();
|
||||
int *meshverts = (int*)header.dir[11].lump + q3face->meshvert;
|
||||
MeshCollider::Triangle ct;
|
||||
ct.surface = 0; ct.index = 0;
|
||||
for (int j = 0; j < q3face->n_meshverts; j += 3) {
|
||||
for (int q = 0; q < 3; ++q) {
|
||||
int n = meshverts[j + q] + q3face->vertex;
|
||||
if (draw) {
|
||||
if (!vert_map.count(n)) {
|
||||
vert_map[n] = face->t_surf->verts.size() - face->vert;
|
||||
face->t_surf->verts.push_back(n);
|
||||
++face->n_verts;
|
||||
}
|
||||
face->t_surf->tris.push_back(vert_map[n]);
|
||||
++face->n_tris;
|
||||
}
|
||||
ct.verts[q] = n;
|
||||
}
|
||||
if (solid) coll_tris.push_back(ct);
|
||||
}
|
||||
}
|
||||
|
||||
static Q3BSPBrush *createBrush(int n) {
|
||||
Q3BSPBrush *brush = new Q3BSPBrush;
|
||||
q3_brush *q3brush = (q3_brush*)header.dir[8].lump + n;
|
||||
q3_brushside *q3brushside = (q3_brushside*)header.dir[9].lump + q3brush->brushside;
|
||||
Plane p;
|
||||
for (int j = 0; j < q3brush->n_brushsides; ++j) {
|
||||
q3_plane *q3plane = (q3_plane*)header.dir[2].lump + q3brushside[j].plane;
|
||||
p.n = tf(q3plane->normal);
|
||||
p.d = -q3plane->distance;
|
||||
brush->planes.push_back(p);
|
||||
}
|
||||
return brush;
|
||||
}
|
||||
|
||||
Q3BSPLeaf *Q3BSPRep::createLeaf(int n) {
|
||||
q3_leaf *q3leaf = (q3_leaf*)header.dir[4].lump + n;
|
||||
|
||||
Q3BSPLeaf *leaf = new Q3BSPLeaf;
|
||||
|
||||
leaf->cluster = q3leaf->cluster;
|
||||
|
||||
Vector mins(q3leaf->mins[0], q3leaf->mins[1], q3leaf->mins[2]);
|
||||
Vector maxs(q3leaf->maxs[0], q3leaf->maxs[1], q3leaf->maxs[2]);
|
||||
leaf->box = Box(tf(mins));
|
||||
leaf->box.update(tf(maxs));
|
||||
int *leaffaces = (int*)header.dir[5].lump + q3leaf->leafface;
|
||||
|
||||
for (int k = 0; k < q3leaf->n_leaffaces; ++k) {
|
||||
|
||||
int face_n = leaffaces[k];
|
||||
|
||||
map<int, Q3BSPFace*>::const_iterator it = q3face_map.find(face_n);
|
||||
if (it != q3face_map.end()) {
|
||||
if (it->second) leaf->faces.push_back(it->second);
|
||||
continue;
|
||||
}
|
||||
|
||||
q3_face *q3face = (q3_face*)header.dir[13].lump + leaffaces[k];
|
||||
|
||||
if (q3face->type == 1 || q3face->type == 3) {
|
||||
if (!q3face->n_meshverts || (q3face->n_meshverts % 3)) continue;
|
||||
} else if (q3face->type != 2) continue;
|
||||
|
||||
bool draw = true, solid = true;
|
||||
|
||||
if (q3face->texture >= 0) {
|
||||
q3_tex *q3tex = (q3_tex*)header.dir[1].lump + q3face->texture;
|
||||
if (!(q3tex->contents & 1)) continue;
|
||||
if (q3tex->flags & 0x84) draw = false;
|
||||
}
|
||||
|
||||
if (!draw && !solid) continue;
|
||||
|
||||
Q3BSPFace *face = 0;
|
||||
if (draw) {
|
||||
Surf *surf = findSurf(q3face);
|
||||
face = new Q3BSPFace;
|
||||
face->t_surf = surf;
|
||||
face->vert = surf->verts.size();
|
||||
face->tri = surf->tris.size();
|
||||
face->n_verts = face->n_tris = 0;
|
||||
leaf->faces.push_back(face);
|
||||
faces.push_back(face);
|
||||
q3face_map.insert(make_pair(face_n, face));
|
||||
}
|
||||
|
||||
if (q3face->type == 2) {
|
||||
patchFace(face, q3face, draw, solid, 1);
|
||||
} else {
|
||||
meshFace(face, q3face, draw, solid);
|
||||
}
|
||||
}
|
||||
|
||||
return leaf;
|
||||
}
|
||||
|
||||
Q3BSPNode *Q3BSPRep::createNode(int n) {
|
||||
q3_node *q3node = (q3_node*)header.dir[3].lump + n;
|
||||
q3_plane *q3plane = (q3_plane*)header.dir[2].lump + q3node->plane;
|
||||
|
||||
Q3BSPNode *node = new Q3BSPNode;
|
||||
|
||||
Vector mins(q3node->mins[0], q3node->mins[1], q3node->mins[2]);
|
||||
Vector maxs(q3node->maxs[0], q3node->maxs[1], q3node->maxs[2]);
|
||||
|
||||
node->box = Box(tf(mins));
|
||||
node->box.update(tf(maxs));
|
||||
node->plane.n = tf(q3plane->normal);
|
||||
node->plane.d = -q3plane->distance;
|
||||
|
||||
for (int k = 0; k < 2; ++k) {
|
||||
if (q3node->children[k] >= 0) {
|
||||
node->nodes[k] = createNode(q3node->children[k]);
|
||||
node->leafs[k] = 0;
|
||||
} else {
|
||||
node->leafs[k] = createLeaf(-q3node->children[k] - 1);
|
||||
node->nodes[k] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
Q3BSPRep::Q3BSPRep(const string &f, float gam) :root_node(0), vis_sz(0), vis_data(0), use_lmap(true) {
|
||||
|
||||
gamma_adj = 1 - gam;
|
||||
|
||||
FILE *buf = fopen(f.c_str(), "rb"); if (!buf) return;
|
||||
|
||||
fread(&header, sizeof(header), 1, buf);
|
||||
if (header.magic != 'PSBI' || header.version != 0x2e) {
|
||||
fclose(buf); return;
|
||||
}
|
||||
|
||||
debuglog("Header OK");
|
||||
|
||||
int k;
|
||||
//load all lumps...
|
||||
for (k = 0; k < 17; ++k) {
|
||||
if (header.dir[k].offset && header.dir[k].length) {
|
||||
fseek(buf, header.dir[k].offset, SEEK_SET);
|
||||
header.dir[k].lump = new char[header.dir[k].length];
|
||||
fread(header.dir[k].lump, header.dir[k].length, 1, buf);
|
||||
} else {
|
||||
header.dir[k].lump = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//create root of BSP tree
|
||||
root_node = createNode(0);
|
||||
|
||||
createCollider();
|
||||
|
||||
createTextures();
|
||||
|
||||
createLightMaps();
|
||||
|
||||
createSurfs();
|
||||
|
||||
createVis();
|
||||
|
||||
//unload all lumps...
|
||||
for (k = 0; k < 17; ++k) {
|
||||
delete[] header.dir[k].lump;
|
||||
}
|
||||
|
||||
fclose(buf);
|
||||
|
||||
use_lmap = false;
|
||||
setLighting(true);
|
||||
|
||||
q3face_map.clear();
|
||||
}
|
||||
|
||||
Q3BSPRep::~Q3BSPRep() {
|
||||
delete root_node;
|
||||
delete[] vis_data;
|
||||
int k;
|
||||
for (k = 0; k < surfs.size(); ++k) {
|
||||
gx_graphics->freeMesh(surfs[k]->mesh);
|
||||
delete surfs[k];
|
||||
}
|
||||
for (k = 0; k < faces.size(); ++k) {
|
||||
delete faces[k];
|
||||
}
|
||||
}
|
||||
|
||||
void Q3BSPRep::vis(Q3BSPNode *n) {
|
||||
int i = n->plane.distance(r_eye) < 0;
|
||||
if (n->nodes[i]) vis(n->nodes[i]);
|
||||
else r_cluster = n->leafs[i]->cluster;
|
||||
}
|
||||
|
||||
static bool cull(const Box &b, int *clip) {
|
||||
for (int n = 0; n < 6; ++n) {
|
||||
int mask = 1 << n;
|
||||
if (!(*clip & mask)) continue;
|
||||
const Plane &p = r_frustum.getPlane(n);
|
||||
int q =
|
||||
(p.distance(b.corner(0)) >= 0) + (p.distance(b.corner(1)) >= 0) +
|
||||
(p.distance(b.corner(2)) >= 0) + (p.distance(b.corner(3)) >= 0) +
|
||||
(p.distance(b.corner(4)) >= 0) + (p.distance(b.corner(5)) >= 0) +
|
||||
(p.distance(b.corner(6)) >= 0) + (p.distance(b.corner(7)) >= 0);
|
||||
if (!q) return false;
|
||||
if (q == 8) *clip &= ~mask;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Q3BSPRep::render(Q3BSPLeaf *l, int clip) {
|
||||
int cluster = l->cluster;
|
||||
if (cluster < 0) return;
|
||||
|
||||
if (r_cluster >= 0) {
|
||||
if (!(vis_data[cluster*vis_sz + r_cluster / 8] & (1 << (r_cluster & 7)))) return;
|
||||
}
|
||||
|
||||
if (clip && !cull(l->box, &clip)) return;
|
||||
|
||||
for (int k = 0; k < l->faces.size(); ++k) {
|
||||
Q3BSPFace *f = l->faces[k];
|
||||
if (Q3BSPSurf *s = f->surf) {
|
||||
if (!s->r_faces.size()) r_surfs.push_back(s);
|
||||
s->r_faces.push_back(f);
|
||||
f->surf = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Q3BSPRep::render(Q3BSPNode *n, int clip) {
|
||||
if (clip && !cull(n->box, &clip)) return;
|
||||
|
||||
//draw front to back...
|
||||
int i = n->plane.distance(r_eye) < 0;
|
||||
if (n->nodes[i]) render(n->nodes[i], clip);
|
||||
else render(n->leafs[i], clip);
|
||||
i ^= 1;
|
||||
if (n->nodes[i]) render(n->nodes[i], clip);
|
||||
else render(n->leafs[i], clip);
|
||||
}
|
||||
|
||||
void Q3BSPRep::render(Model *model, const RenderContext &rc) {
|
||||
r_eye = -model->getRenderTform() * rc.getCameraTform().v;
|
||||
new(&r_frustum) Frustum(rc.getWorldFrustum(), -model->getRenderTform());
|
||||
|
||||
vis(root_node);
|
||||
if (r_cluster == -1) debuglog("No cluster!");
|
||||
render(root_node, 0x3f);
|
||||
|
||||
if (!r_surfs.size()) return;
|
||||
|
||||
gx_scene->setAmbient2(&ambient.x);
|
||||
gx_scene->setWorldMatrix((gxScene::Matrix*)&model->getRenderTform());
|
||||
|
||||
int k;
|
||||
for (k = 0; k < r_surfs.size(); ++k) {
|
||||
Q3BSPSurf *s = r_surfs[k];
|
||||
gx_scene->setRenderState(s->brush.getRenderState());
|
||||
int j;
|
||||
for (j = 0; j < s->r_faces.size(); ++j) {
|
||||
Q3BSPFace *f = s->r_faces[j];
|
||||
gx_scene->render(s->mesh, f->vert, f->n_verts, f->tri, f->n_tris);
|
||||
f->surf = s;
|
||||
}
|
||||
s->r_faces.clear();
|
||||
}
|
||||
r_surfs.clear();
|
||||
}
|
||||
|
||||
bool Q3BSPRep::collide(const Line &line, float radius, Collision *curr_coll, const Transform &t) {
|
||||
return collider->collide(line, radius, curr_coll, t);
|
||||
}
|
||||
|
||||
void Q3BSPRep::setAmbient(const Vector &t) {
|
||||
ambient = t;
|
||||
}
|
||||
|
||||
void Q3BSPRep::setLighting(bool lmap) {
|
||||
if (lmap == use_lmap) return;
|
||||
int fx = gxScene::FX_CONDLIGHT;
|
||||
if (use_lmap = lmap) {
|
||||
int k;
|
||||
for (k = 0; k < surfs.size(); ++k) {
|
||||
Q3BSPSurf *s = surfs[k];
|
||||
if (s->lm_index >= 0) {
|
||||
//has a lightmap...
|
||||
s->brush.setFX(fx);
|
||||
s->brush.setTexture(0, light_maps[s->lm_index], 0);
|
||||
if (s->texture >= 0) {
|
||||
s->brush.setTexture(1, textures[s->texture], 0);
|
||||
}
|
||||
} else {
|
||||
s->brush.setFX(fx | gxScene::FX_EMISSIVE);
|
||||
if (s->texture >= 0) {
|
||||
s->brush.setTexture(0, textures[s->texture], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int k;
|
||||
Texture tex;
|
||||
for (k = 0; k < surfs.size(); ++k) {
|
||||
Q3BSPSurf *s = surfs[k];
|
||||
s->brush.setFX(fx | gxScene::FX_EMISSIVE);
|
||||
if (s->texture >= 0) {
|
||||
s->brush.setTexture(0, textures[s->texture], 0);
|
||||
} else {
|
||||
s->brush.setTexture(0, tex, 0);
|
||||
}
|
||||
s->brush.setTexture(1, tex, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user