mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-26 13:50:53 +00:00
Forgot to add this. its buggy as heck.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3736 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
946b5d6f52
commit
cb834a8534
1 changed files with 555 additions and 0 deletions
555
engine/client/r_d3.c
Normal file
555
engine/client/r_d3.c
Normal file
|
@ -0,0 +1,555 @@
|
|||
#include "quakedef.h"
|
||||
#ifndef SERVERONLY
|
||||
#include "shader.h"
|
||||
#endif
|
||||
|
||||
void RMod_SetParent (mnode_t *node, mnode_t *parent);
|
||||
|
||||
qboolean Mod_LoadMap_Proc(model_t *model, char *data)
|
||||
{
|
||||
char token[256];
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
if (strcmp(token, "mapProcFile003"))
|
||||
{
|
||||
Con_Printf("proc format not compatible %s\n", token);
|
||||
return false;
|
||||
}
|
||||
/*FIXME: add sanity checks*/
|
||||
|
||||
while(1)
|
||||
{
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
if (!data)
|
||||
break;
|
||||
else if (!strcmp(token, "model"))
|
||||
{
|
||||
batch_t *b;
|
||||
mesh_t *m;
|
||||
model_t *sub;
|
||||
float f;
|
||||
int numsurfs, surf;
|
||||
int numverts, v, j;
|
||||
int numindicies;
|
||||
char *vdata;
|
||||
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
if (strcmp(token, "{"))
|
||||
return false;
|
||||
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
sub = Mod_FindName(va("*%s", token));
|
||||
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
numsurfs = atoi(token);
|
||||
if (numsurfs < 0 || numsurfs > 10000)
|
||||
return false;
|
||||
b = Hunk_Alloc(sizeof(*b) * numsurfs);
|
||||
m = Hunk_Alloc(sizeof(*m) * numsurfs);
|
||||
sub->numsurfaces = numsurfs;
|
||||
|
||||
sub->batches[0] = b;
|
||||
|
||||
for (surf = 0; surf < numsurfs; surf++)
|
||||
{
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
if (strcmp(token, "{"))
|
||||
break;
|
||||
if (!data)
|
||||
return false;
|
||||
b[surf].meshes = 1;
|
||||
b[surf].mesh = (mesh_t**)&m[surf];
|
||||
b[surf].lightmap = -1;
|
||||
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
b[surf].shader = R_RegisterShader_Vertex(token);
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
numverts = atoi(token);
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
numindicies = atoi(token);
|
||||
|
||||
m[surf].numvertexes = numverts;
|
||||
m[surf].numindexes = numindicies;
|
||||
vdata = Hunk_Alloc(numverts * (sizeof(vecV_t) + sizeof(vec2_t) + sizeof(vec3_t)) + numindicies * sizeof(index_t));
|
||||
|
||||
m[surf].xyz_array = (vecV_t*)vdata;vdata += sizeof(vecV_t)*numverts;
|
||||
m[surf].st_array = (vec2_t*)vdata;vdata += sizeof(vec2_t)*numverts;
|
||||
m[surf].normals_array = (vec3_t*)vdata;vdata += sizeof(vec3_t)*numverts;
|
||||
m[surf].indexes = (index_t*)vdata;
|
||||
sub->mins[0] = 99999999;
|
||||
sub->mins[1] = 99999999;
|
||||
sub->mins[2] = 99999999;
|
||||
sub->maxs[0] = -99999999;
|
||||
sub->maxs[1] = -99999999;
|
||||
sub->maxs[2] = -99999999;
|
||||
|
||||
for (v = 0; v < numverts; v++)
|
||||
{
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
if (strcmp(token, "("))
|
||||
return false;
|
||||
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
m[surf].xyz_array[v][0] = atof(token);
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
m[surf].xyz_array[v][1] = atof(token);
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
m[surf].xyz_array[v][2] = atof(token);
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
m[surf].st_array[v][0] = atof(token);
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
m[surf].st_array[v][1] = atof(token);
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
m[surf].normals_array[v][0] = atof(token);
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
m[surf].normals_array[v][1] = atof(token);
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
m[surf].normals_array[v][2] = atof(token);
|
||||
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
f = m[surf].xyz_array[v][j];
|
||||
if (f > sub->maxs[j])
|
||||
sub->maxs[j] = f;
|
||||
else if (f < sub->mins[j])
|
||||
sub->mins[j] = f;
|
||||
}
|
||||
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
if (strcmp(token, ")"))
|
||||
return false;
|
||||
}
|
||||
for (v = 0; v < numindicies; v++)
|
||||
{
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
m[surf].indexes[v] = atoi(token);
|
||||
}
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
if (strcmp(token, "}"))
|
||||
return false;
|
||||
}
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
if (strcmp(token, "}"))
|
||||
return false;
|
||||
sub->needload = false;
|
||||
sub->fromgame = fg_doom3;
|
||||
sub->type = mod_brush;
|
||||
}
|
||||
else if (!strcmp(token, "shadowModel"))
|
||||
{
|
||||
int numverts, v;
|
||||
int numindexes, i;
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
if (strcmp(token, "{"))
|
||||
return false;
|
||||
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
//name
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
numverts = atoi(token);
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
//nocaps
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
//nofrontcaps
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
numindexes = atoi(token);
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
//planebits
|
||||
|
||||
for (v = 0; v < numverts; v++)
|
||||
{
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
if (strcmp(token, "("))
|
||||
return false;
|
||||
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
//x
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
//y
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
//z
|
||||
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
if (strcmp(token, ")"))
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < numindexes; i++)
|
||||
{
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
}
|
||||
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
if (strcmp(token, "}"))
|
||||
return false;
|
||||
}
|
||||
else if (!strcmp(token, "nodes"))
|
||||
{
|
||||
int numnodes, n;
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
if (strcmp(token, "{"))
|
||||
return false;
|
||||
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
numnodes = atoi(token);
|
||||
model->nodes = Hunk_Alloc(sizeof(*model->nodes)*numnodes);
|
||||
model->planes = Hunk_Alloc(sizeof(*model->planes)*numnodes);
|
||||
|
||||
for (n = 0; n < numnodes; n++)
|
||||
{
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
if (strcmp(token, "("))
|
||||
return false;
|
||||
|
||||
model->nodes[n].plane = &model->planes[n];
|
||||
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
model->planes[n].normal[0] = atof(token);
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
model->planes[n].normal[1] = atof(token);
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
model->planes[n].normal[2] = atof(token);
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
model->planes[n].dist = atof(token);
|
||||
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
if (strcmp(token, ")"))
|
||||
return false;
|
||||
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
model->nodes[n].childnum[0] = atoi(token);
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
model->nodes[n].childnum[1] = atoi(token);
|
||||
}
|
||||
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
if (strcmp(token, "}"))
|
||||
return false;
|
||||
|
||||
RMod_SetParent(model->nodes, NULL);
|
||||
}
|
||||
else if (!strcmp(token, "interAreaPortals"))
|
||||
{
|
||||
int numareas;
|
||||
int pno, v;
|
||||
portal_t *p;
|
||||
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
if (strcmp(token, "{"))
|
||||
return false;
|
||||
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
numareas = atoi(token);
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
model->numportals = atoi(token);
|
||||
|
||||
model->portal = p = Hunk_Alloc(sizeof(*p) * model->numportals);
|
||||
|
||||
for (pno = 0; pno < model->numportals; pno++, p++)
|
||||
{
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
p->numpoints = atoi(token);
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
p->area[0] = atoi(token);
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
p->area[1] = atoi(token);
|
||||
|
||||
p->points = Hunk_Alloc(sizeof(*p->points) * p->numpoints);
|
||||
|
||||
ClearBounds(p->min, p->max);
|
||||
for (v = 0; v < p->numpoints; v++)
|
||||
{
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
if (strcmp(token, "("))
|
||||
return false;
|
||||
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
p->points[v][0] = atof(token);
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
p->points[v][1] = atof(token);
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
p->points[v][2] = atof(token);
|
||||
p->points[v][3] = 1;
|
||||
|
||||
AddPointToBounds(p->points[v], p->min, p->max);
|
||||
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
if (strcmp(token, ")"))
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data = COM_ParseOut(data, token, sizeof(token));
|
||||
if (strcmp(token, "}"))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Printf("unexpected token %s\n", token);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//edict system as opposed to q2 game dll system.
|
||||
void D3_FindTouchedLeafs (struct model_s *model, struct pvscache_s *ent, vec3_t cullmins, vec3_t cullmaxs)
|
||||
{
|
||||
}
|
||||
qbyte *D3_LeafPVS (struct model_s *model, int num, qbyte *buffer, unsigned int buffersize)
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
int D3_LeafnumForPoint (struct model_s *model, vec3_t point)
|
||||
{
|
||||
float p;
|
||||
int c;
|
||||
mnode_t *node;
|
||||
node = model->nodes;
|
||||
while(1)
|
||||
{
|
||||
p = DotProduct(point, node->plane->normal) + node->plane->dist;
|
||||
c = node->childnum[p<0];
|
||||
if (c <= 0)
|
||||
return -1-c;
|
||||
node = model->nodes + c;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
unsigned int D3_FatPVS (struct model_s *model, vec3_t org, qbyte *pvsbuffer, unsigned int buffersize, qboolean merge)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void D3_StainNode (struct mnode_s *node, float *parms)
|
||||
{
|
||||
}
|
||||
|
||||
qboolean D3_Trace (struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, struct trace_s *trace)
|
||||
{
|
||||
trace->fraction = 0;
|
||||
VectorCopy(p1, trace->endpos);
|
||||
trace->allsolid = true;
|
||||
trace->startsolid = true;
|
||||
trace->ent = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int D3_PointContents (struct model_s *model, vec3_t axis[3], vec3_t p)
|
||||
{
|
||||
return FTECONTENTS_SOLID;
|
||||
}
|
||||
|
||||
void D3_LightPointValues (struct model_s *model, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir)
|
||||
{
|
||||
VectorClear(res_diffuse);
|
||||
VectorClear(res_ambient);
|
||||
VectorClear(res_dir);
|
||||
res_dir[2] = 1;
|
||||
}
|
||||
|
||||
|
||||
qboolean D3_EdictInFatPVS (struct model_s *model, struct pvscache_s *edict, qbyte *pvsbuffer)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < edict->num_leafs; i++)
|
||||
if (pvsbuffer[edict->leafnums[i]>>3] & (1u<<(edict->leafnums[i]&7)))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static qboolean D3_PolyBounds(vec_t result[4], int count, vec4_t *vlist)
|
||||
{
|
||||
qboolean ret = false;
|
||||
int i;
|
||||
vec4_t tempv, v;
|
||||
/*inverted*/
|
||||
result[0] = 10000;
|
||||
result[1] = -10000;
|
||||
result[2] = 10000;
|
||||
result[3] = -10000;
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
Matrix4_Transform4(r_refdef.m_view, vlist[i], tempv);
|
||||
Matrix4_Transform4(r_refdef.m_projection, tempv, v);
|
||||
|
||||
v[0] /= v[3];
|
||||
v[1] /= v[3];
|
||||
// if (v[2] < 0)
|
||||
// continue;
|
||||
|
||||
if (result[0] > v[0])
|
||||
result[0] = v[0];
|
||||
if (result[1] < v[0])
|
||||
result[1] = v[0];
|
||||
if (result[2] > v[1])
|
||||
result[2] = v[1];
|
||||
if (result[3] < v[1])
|
||||
result[3] = v[1];
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
qboolean R_CullBox (vec3_t mins, vec3_t maxs);
|
||||
|
||||
static int walkno;
|
||||
/*convert each portal to a 2d box, because its much much simpler than true poly clipping*/
|
||||
void D3_WalkPortal(model_t *mod, int start, vec_t bounds[4], unsigned char *vis)
|
||||
{
|
||||
int i;
|
||||
portal_t *p;
|
||||
int side;
|
||||
vec_t newbounds[4];
|
||||
|
||||
vis[start>>3] |= 1<<(start&7);
|
||||
|
||||
for (i = 0; i < mod->numportals; i++)
|
||||
{
|
||||
p = mod->portal+i;
|
||||
if (p->walkno == walkno)
|
||||
continue;
|
||||
if (p->area[0] == start)
|
||||
side = 0;
|
||||
else if (p->area[1] == start)
|
||||
side = 1;
|
||||
else
|
||||
continue;
|
||||
|
||||
R_CullBox(p->min, p->max);
|
||||
|
||||
if (!D3_PolyBounds(newbounds, p->numpoints, p->points))
|
||||
{
|
||||
p->walkno = walkno;
|
||||
continue;
|
||||
}
|
||||
/*new poly was to the right of it, or fully to the left*/
|
||||
if (newbounds[1] <= bounds[0] || newbounds[0] >= bounds[1])
|
||||
continue;
|
||||
if (newbounds[3] <= bounds[2] || newbounds[2] >= bounds[3])
|
||||
continue;
|
||||
|
||||
if (newbounds[0] < bounds[0])
|
||||
newbounds[0] = bounds[0];
|
||||
if (newbounds[1] > bounds[1])
|
||||
newbounds[1] = bounds[1];
|
||||
|
||||
if (newbounds[2] < bounds[2])
|
||||
newbounds[2] = bounds[2];
|
||||
if (newbounds[3] > bounds[3])
|
||||
newbounds[3] = bounds[3];
|
||||
|
||||
/*FIXME: clip the new bounds to the old bounds*/
|
||||
|
||||
p->walkno = walkno;
|
||||
D3_WalkPortal(mod, p->area[!side], newbounds, vis);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char *D3_CalcVis(model_t *mod, vec3_t org)
|
||||
{
|
||||
int start;
|
||||
static unsigned char vis[256];
|
||||
vec_t newbounds[4];
|
||||
|
||||
start = D3_LeafnumForPoint(mod, org);
|
||||
/*figure out which area we're in*/
|
||||
if (start < 0)
|
||||
{
|
||||
/*outside the world, just make it all visible, and take the fps hit*/
|
||||
memset(vis, 255, 4);
|
||||
return vis;
|
||||
}
|
||||
else if (r_novis.value)
|
||||
return vis;
|
||||
else
|
||||
{
|
||||
memset(vis, 0, 4);
|
||||
/*make a bounds the size of the view*/
|
||||
newbounds[0] = -1;
|
||||
newbounds[1] = 1;
|
||||
newbounds[2] = -1;
|
||||
newbounds[3] = 1;
|
||||
walkno++;
|
||||
D3_WalkPortal(mod, start, newbounds, vis);
|
||||
// Con_Printf("%x %x %x %x\n", vis[0], vis[1], vis[2], vis[3]);
|
||||
return vis;
|
||||
}
|
||||
}
|
||||
|
||||
/*emits static entities, one for each area, which is only visible if that area is in the vis*/
|
||||
void D3_GenerateAreas(model_t *mod)
|
||||
{
|
||||
entity_t *ent;
|
||||
|
||||
int area;
|
||||
|
||||
for (area = 0; area < 256*8; area++)
|
||||
{
|
||||
if (cl.num_statics == cl_max_static_entities)
|
||||
{
|
||||
cl_max_static_entities += 16;
|
||||
cl_static_entities = BZ_Realloc(cl_static_entities, sizeof(*cl_static_entities) * cl_max_static_entities);
|
||||
}
|
||||
|
||||
ent = &cl_static_entities[cl.num_statics].ent;
|
||||
cl_static_entities[cl.num_statics].mdlidx = 0;
|
||||
memset(ent, 0, sizeof(*ent));
|
||||
ent->model = Mod_FindName(va("*_area%i", area));
|
||||
ent->scale = 1;
|
||||
AngleVectors(ent->angles, ent->axis[0], ent->axis[1], ent->axis[2]);
|
||||
VectorInverse(ent->axis[1]);
|
||||
ent->shaderRGBAf[0] = 1;
|
||||
ent->shaderRGBAf[1] = 1;
|
||||
ent->shaderRGBAf[2] = 1;
|
||||
ent->shaderRGBAf[3] = 1;
|
||||
|
||||
/*put it in that area*/
|
||||
cl_static_entities[cl.num_statics].pvscache.num_leafs = 1;
|
||||
cl_static_entities[cl.num_statics].pvscache.leafnums[0] = area;
|
||||
|
||||
if (ent->model && !ent->model->needload)
|
||||
cl.num_statics++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
qboolean D3_LoadMap_CollisionMap(model_t *mod, char *buf)
|
||||
{
|
||||
char token[256];
|
||||
buf = COM_ParseOut(buf, token, sizeof(token));
|
||||
if (strcmp(token, "CM"))
|
||||
return false;
|
||||
|
||||
buf = COM_ParseOut(buf, token, sizeof(token));
|
||||
if (atof(token) != 1.0)
|
||||
return false;
|
||||
|
||||
/*load up the .map so we can get some entities (anyone going to bother making a qc mod compatible with this?)*/
|
||||
COM_StripExtension(mod->name, token, sizeof(token));
|
||||
mod->entities = FS_LoadMallocFile(va("%s.map", token));
|
||||
|
||||
mod->funcs.FindTouchedLeafs = D3_FindTouchedLeafs;
|
||||
mod->funcs.Trace = D3_Trace;
|
||||
mod->funcs.PointContents = D3_PointContents;
|
||||
mod->funcs.FatPVS = D3_FatPVS;
|
||||
mod->funcs.LeafnumForPoint = D3_LeafnumForPoint;
|
||||
mod->funcs.StainNode = D3_StainNode;
|
||||
mod->funcs.LightPointValues = D3_LightPointValues;
|
||||
mod->funcs.EdictInFatPVS = D3_EdictInFatPVS;
|
||||
|
||||
mod->fromgame = fg_doom3;
|
||||
|
||||
/*that's the physics sorted*/
|
||||
#ifndef SERVERONLY
|
||||
if (isDedicated)
|
||||
return true;
|
||||
COM_StripExtension(mod->name, token, sizeof(token));
|
||||
buf = FS_LoadMallocFile(va("%s.proc", token));
|
||||
Mod_LoadMap_Proc(mod, buf);
|
||||
BZ_Free(buf);
|
||||
return true;
|
||||
#endif
|
||||
}
|
Loading…
Reference in a new issue