mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-04-28 13:47:58 +03:00
Add tr_vis
This commit is contained in:
parent
546b90d75f
commit
66664b7b46
2 changed files with 397 additions and 0 deletions
361
code/renderergl2/tr_vis.cpp
Normal file
361
code/renderergl2/tr_vis.cpp
Normal file
|
@ -0,0 +1,361 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 2023-2024 the OpenMoHAA team
|
||||
|
||||
This file is part of OpenMoHAA source code.
|
||||
|
||||
OpenMoHAA source code is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
OpenMoHAA source code is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenMoHAA source code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// tr_vis.cpp: visibility culling
|
||||
|
||||
#include "tr_local.h"
|
||||
#include "tr_vis.h"
|
||||
|
||||
#define MAX_POINTS_ON_WINDING 128
|
||||
#define MAX_MAP_VISIBILITY 0x200000
|
||||
#define MAX_VPORTALS 1024
|
||||
|
||||
typedef struct {
|
||||
int numpoints;
|
||||
vec3_t p[24];
|
||||
} viswinding_t;
|
||||
|
||||
typedef struct {
|
||||
int numpoints;
|
||||
vec3_t p[4];
|
||||
} winding_t;
|
||||
|
||||
typedef struct {
|
||||
vec3_t normal;
|
||||
float dist;
|
||||
} plane_t;
|
||||
|
||||
typedef struct {
|
||||
int num;
|
||||
qboolean hint;
|
||||
plane_t plane;
|
||||
int leaf;
|
||||
vec3_t origin;
|
||||
float radius;
|
||||
viswinding_t *winding;
|
||||
} vportal_t;
|
||||
|
||||
typedef struct leaf_s {
|
||||
int numportals;
|
||||
vportal_t *portals[MAX_VPORTALS];
|
||||
} leaf_t;
|
||||
|
||||
int portalclusters;
|
||||
int numportals;
|
||||
int numfaces;
|
||||
int leafbytes;
|
||||
int leaflongs;
|
||||
int portalbytes;
|
||||
int portallongs;
|
||||
vportal_t *portals;
|
||||
leaf_t *leafs;
|
||||
int numVisBytes;
|
||||
static char mapname[256];
|
||||
static qboolean prev_showportal = qfalse;
|
||||
|
||||
winding_t *AllocWinding(int points)
|
||||
{
|
||||
winding_t *w;
|
||||
int s;
|
||||
|
||||
if (points > MAX_POINTS_ON_WINDING) {
|
||||
ri.Error(ERR_DROP, "Exceeded MAX_POINTS_ON_WINDING");
|
||||
return NULL;
|
||||
}
|
||||
s = sizeof(vec_t) * 4 * points + sizeof(int) * 4;
|
||||
|
||||
w = (winding_t *)malloc(s);
|
||||
if (!w) {
|
||||
ri.Error(ERR_DROP, "Couldn't allocate winding");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (s < 0) {
|
||||
s = sizeof(vec_t) * 4 * points + sizeof(int) * 4 + 3;
|
||||
}
|
||||
|
||||
memset(w, 0, s);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
viswinding_t *AllocVisWinding(int points)
|
||||
{
|
||||
return (viswinding_t *)AllocWinding(points);
|
||||
}
|
||||
|
||||
void PlaneFromWinding(viswinding_t *w, plane_t *plane)
|
||||
{
|
||||
vec3_t v1, v2;
|
||||
|
||||
VectorSubtract(w->p[2], w->p[1], v1);
|
||||
VectorSubtract(w->p[2], w->p[1], v1);
|
||||
CrossProduct(v2, v1, plane->normal);
|
||||
VectorNormalize(plane->normal);
|
||||
|
||||
plane->dist = DotProduct(w->p[0], plane->normal);
|
||||
}
|
||||
|
||||
void SetPortalSphere(vportal_t *p)
|
||||
{
|
||||
int i;
|
||||
vec3_t total;
|
||||
vec3_t dist;
|
||||
viswinding_t *w;
|
||||
float r;
|
||||
float bestr;
|
||||
|
||||
w = p->winding;
|
||||
VectorCopy(vec3_origin, total);
|
||||
|
||||
for (i = 0; i < w->numpoints; i++) {
|
||||
VectorAdd(total, w->p[i], total);
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
total[i] /= w->numpoints;
|
||||
}
|
||||
|
||||
bestr = 0;
|
||||
|
||||
for (i = 0; i < w->numpoints; i++) {
|
||||
VectorSubtract(w->p[i], total, dist);
|
||||
r = VectorLength(dist);
|
||||
if (bestr < r) {
|
||||
bestr = r;
|
||||
}
|
||||
}
|
||||
|
||||
VectorCopy(total, p->origin);
|
||||
p->radius = bestr;
|
||||
}
|
||||
|
||||
void LoadPortals(const char *name)
|
||||
{
|
||||
int i, j;
|
||||
vportal_t *p;
|
||||
leaf_t *l;
|
||||
const char *magic;
|
||||
int leafnums[2];
|
||||
plane_t plane;
|
||||
char *data;
|
||||
char *f;
|
||||
int numpoints;
|
||||
qboolean bHint;
|
||||
|
||||
if (ri.FS_ReadFile(name, (void **)&f) == -1) {
|
||||
ri.Error(ERR_DROP, "LoadPortals: couldn't read %s\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
data = f;
|
||||
magic = COM_Parse(&data);
|
||||
|
||||
if (strcmp(magic, "PRT1")) {
|
||||
ri.Error(1, "LoadPortals: not a portal file");
|
||||
}
|
||||
|
||||
portalclusters = atoi(COM_Parse(&data));
|
||||
numportals = atoi(COM_Parse(&data));
|
||||
numfaces = atoi(COM_Parse(&data));
|
||||
|
||||
ri.Printf(PRINT_DEVELOPER, "%6i portalclusters\n", portalclusters);
|
||||
ri.Printf(PRINT_DEVELOPER, "%6i numportals\n", numportals);
|
||||
ri.Printf(PRINT_DEVELOPER, "%6i numfaces\n", numfaces);
|
||||
|
||||
leafbytes = ((portalclusters + 63) & 0xC0) >> 3;
|
||||
leaflongs = leafbytes >> 2;
|
||||
portalbytes = ((numportals * 2 + 63) & 0xC0) >> 3;
|
||||
portallongs = portalbytes >> 2;
|
||||
|
||||
//
|
||||
// Initialize portals
|
||||
//
|
||||
portals = (vportal_t *)malloc(numportals * sizeof(vportal_t));
|
||||
if (!portals) {
|
||||
ri.Error(ERR_DROP, "LoadPortals: portals allocation failed\n");
|
||||
return;
|
||||
}
|
||||
memset(portals, 0, numportals * sizeof(vportal_t));
|
||||
|
||||
//
|
||||
// Initialize leafs
|
||||
//
|
||||
leafs = (leaf_t *)malloc(portalclusters * sizeof(leaf_t));
|
||||
if (!leafs) {
|
||||
ri.Error(ERR_DROP, "LoadPortals: leafs allocation failed\n");
|
||||
return;
|
||||
}
|
||||
memset(leafs, 0, portalclusters * sizeof(leaf_t));
|
||||
|
||||
assert(leafbytes * portalclusters + sizeof(leafnums) <= MAX_MAP_VISIBILITY);
|
||||
if (numVisBytes > MAX_MAP_VISIBILITY) {
|
||||
ri.Error(ERR_DROP, "LoadPortals: NumVisBytes %d exceeds %d\n", numVisBytes, 0x200000);
|
||||
}
|
||||
|
||||
for (i = 0; i < numportals; i++) {
|
||||
viswinding_t *w;
|
||||
|
||||
p = &portals[i];
|
||||
|
||||
numpoints = atoi(COM_Parse(&data));
|
||||
leafnums[0] = atoi(COM_Parse(&data));
|
||||
leafnums[1] = atoi(COM_Parse(&data));
|
||||
|
||||
if (numpoints > MAX_POINTS_ON_WINDING) {
|
||||
ri.Error(ERR_DROP, "LoadPortals: portal %i has too many points", i);
|
||||
return;
|
||||
}
|
||||
|
||||
if (leafnums[0] > portalclusters || leafnums[1] > portalclusters) {
|
||||
ri.Error(ERR_DROP, "LoadPortals: reading portal %i", i);
|
||||
return;
|
||||
}
|
||||
|
||||
bHint = atoi(COM_Parse(&data));
|
||||
w = AllocVisWinding(numpoints);
|
||||
w->numpoints = numpoints;
|
||||
p->winding = w;
|
||||
|
||||
for (j = 0; j < numpoints; j++) {
|
||||
magic = COM_Parse(&data);
|
||||
if (magic[0] != '(') {
|
||||
ri.Error(ERR_DROP, "LoadPortals: expecting '(' not '%s'", magic);
|
||||
return;
|
||||
}
|
||||
|
||||
if (magic[1]) {
|
||||
w->p[j][0] = atof(magic + 1);
|
||||
} else {
|
||||
w->p[j][0] = atof(COM_Parse(&data));
|
||||
}
|
||||
|
||||
w->p[j][1] = atof(COM_Parse(&data));
|
||||
w->p[j][2] = atof(COM_Parse(&data));
|
||||
|
||||
magic = COM_Parse(&data);
|
||||
if (strcmp(")", magic)) {
|
||||
ri.Error(ERR_DROP, "LoadPortals: expecting ')' not '%s'", magic);
|
||||
}
|
||||
}
|
||||
|
||||
PlaneFromWinding(w, &plane);
|
||||
|
||||
//
|
||||
// Leafs
|
||||
//
|
||||
|
||||
// First leaf
|
||||
|
||||
l = &leafs[leafnums[0]];
|
||||
|
||||
if (l->numportals == ARRAY_LEN(l->portals)) {
|
||||
ri.Error(ERR_DROP, "Leaf with too many portals");
|
||||
return;
|
||||
}
|
||||
|
||||
l->portals[l->numportals++] = p;
|
||||
p->num = i + 1;
|
||||
p->hint = bHint;
|
||||
p->winding = w;
|
||||
VectorSubtract(vec3_origin, plane.normal, p->plane.normal);
|
||||
p->plane.dist = -plane.dist;
|
||||
p->leaf = leafnums[1];
|
||||
SetPortalSphere(p);
|
||||
|
||||
// Second leaf
|
||||
|
||||
p++;
|
||||
|
||||
l = &leafs[leafnums[1]];
|
||||
if (l->numportals == ARRAY_LEN(l->portals)) {
|
||||
ri.Error(ERR_DROP, "Leaf with too many portals");
|
||||
return;
|
||||
}
|
||||
|
||||
l->portals[l->numportals++] = p;
|
||||
p->num = i + 1;
|
||||
p->hint = bHint;
|
||||
p->winding = (viswinding_t *)AllocVisWinding(w->numpoints);
|
||||
p->winding->numpoints = w->numpoints;
|
||||
|
||||
for (j = 0; j < w->numpoints; j++) {
|
||||
VectorCopy(w->p[numpoints - (j + 1)], p->winding->p[j]);
|
||||
}
|
||||
|
||||
p->plane = plane;
|
||||
p->leaf = leafnums[0];
|
||||
SetPortalSphere(p);
|
||||
}
|
||||
|
||||
ri.FS_FreeFile(f);
|
||||
}
|
||||
|
||||
void R_VisDebug()
|
||||
{
|
||||
int leafnum;
|
||||
int cluster;
|
||||
int numportals;
|
||||
leaf_t *leaf;
|
||||
vportal_t *p;
|
||||
int pnum;
|
||||
viswinding_t *w;
|
||||
int numpoints;
|
||||
int i;
|
||||
|
||||
if (!r_showportal->integer) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!prev_showportal) {
|
||||
char buffer[256];
|
||||
|
||||
prev_showportal = qtrue;
|
||||
COM_StripExtension(mapname, buffer, sizeof(buffer));
|
||||
Q_strcat(buffer, sizeof(buffer), ".prt");
|
||||
LoadPortals(buffer);
|
||||
}
|
||||
|
||||
leafnum = ri.CM_PointLeafnum(tr.refdef.vieworg);
|
||||
cluster = ri.CM_LeafCluster(leafnum);
|
||||
if (cluster < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
leaf = &leafs[cluster];
|
||||
numportals = leaf->numportals;
|
||||
for (pnum = 0; pnum < numportals; pnum++) {
|
||||
p = leaf->portals[pnum];
|
||||
w = p->winding;
|
||||
|
||||
numpoints = w->numpoints;
|
||||
for (i = 0; i < numpoints; i++) {
|
||||
R_DebugLine(w->p[i], w->p[(i + 1) % numpoints], 0.0, 1.0, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void R_VisDebugLoad(const char *szBSPName)
|
||||
{
|
||||
prev_showportal = qfalse;
|
||||
return Q_strncpyz(mapname, szBSPName, sizeof(mapname));
|
||||
}
|
36
code/renderergl2/tr_vis.h
Normal file
36
code/renderergl2/tr_vis.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 2023-2024 the OpenMoHAA team
|
||||
|
||||
This file is part of OpenMoHAA source code.
|
||||
|
||||
OpenMoHAA source code is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
OpenMoHAA source code is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenMoHAA source code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tr_local.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void R_VisDebugLoad(const char* szBSPName);
|
||||
void R_VisDebug();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue