mirror of
https://github.com/nzp-team/fteqw.git
synced 2025-02-01 05:00:46 +00:00
More preliminary support for patches. Loading+Saving+Display of control points will now work. No QC interactions yet.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5297 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
ffd726eb50
commit
3fb88f2ec2
3 changed files with 289 additions and 158 deletions
|
@ -517,7 +517,7 @@ typedef struct
|
||||||
//q2origin,q3origin 0x01000000 //could define, but normally removed by compiler, so why?
|
//q2origin,q3origin 0x01000000 //could define, but normally removed by compiler, so why?
|
||||||
#define FTECONTENTS_BODY 0x02000000
|
#define FTECONTENTS_BODY 0x02000000
|
||||||
#define FTECONTENTS_CORPSE 0x04000000
|
#define FTECONTENTS_CORPSE 0x04000000
|
||||||
//q2detail,q3detail 0x08000000 //not very useful to us
|
#define FTECONTENTS_DETAIL 0x08000000 //not very useful to us, but used by .map support
|
||||||
//q2translucent,q3structual 0x10000000
|
//q2translucent,q3structual 0x10000000
|
||||||
//q2ladder,q3translucent 0x20000000
|
//q2ladder,q3translucent 0x20000000
|
||||||
//q3trigger 0x40000000
|
//q3trigger 0x40000000
|
||||||
|
|
|
@ -5760,7 +5760,7 @@ void Terr_Brush_Draw(heightmap_t *hm, batch_t **batches, entity_t *e)
|
||||||
const miptex_t *tx = NULL;
|
const miptex_t *tx = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!Q_strcasecmp(bt->shadername, "clip"))
|
if (!Q_strcasecmp(bt->shadername, "clip") || !Q_strcasecmp(bt->shadername, "hint") || !Q_strcasecmp(bt->shadername, "skip"))
|
||||||
bt->shader = R_RegisterShader(bt->shadername, SUF_LIGHTMAP, "{\nsurfaceparm nodraw\n}");
|
bt->shader = R_RegisterShader(bt->shadername, SUF_LIGHTMAP, "{\nsurfaceparm nodraw\n}");
|
||||||
else
|
else
|
||||||
bt->shader = R_RegisterCustom (bt->shadername, SUF_LIGHTMAP, Shader_DefaultBSPQ1, NULL);
|
bt->shader = R_RegisterCustom (bt->shadername, SUF_LIGHTMAP, Shader_DefaultBSPQ1, NULL);
|
||||||
|
@ -6015,6 +6015,11 @@ static brushes_t *Terr_Brush_Insert(model_t *model, heightmap_t *hm, brushes_t *
|
||||||
out->axialplanes = 0;
|
out->axialplanes = 0;
|
||||||
out->patch = NULL;
|
out->patch = NULL;
|
||||||
|
|
||||||
|
out->planes = NULL;
|
||||||
|
out->faces = NULL;
|
||||||
|
out->numplanes = 0;
|
||||||
|
if (brush->numplanes)
|
||||||
|
{
|
||||||
out->planes = BZ_Malloc((sizeof(*out->planes)+sizeof(*out->faces)) * brush->numplanes);
|
out->planes = BZ_Malloc((sizeof(*out->planes)+sizeof(*out->faces)) * brush->numplanes);
|
||||||
out->faces = (void*)(out->planes+brush->numplanes);
|
out->faces = (void*)(out->planes+brush->numplanes);
|
||||||
ClearBounds(out->mins, out->maxs);
|
ClearBounds(out->mins, out->maxs);
|
||||||
|
@ -6122,18 +6127,35 @@ static brushes_t *Terr_Brush_Insert(model_t *model, heightmap_t *hm, brushes_t *
|
||||||
// Con_Printf("lm extents: %u %u (%i points)\n", out->faces[oface].lmextents[0], out->faces[oface].lmextents[1], numpoints);
|
// Con_Printf("lm extents: %u %u (%i points)\n", out->faces[oface].lmextents[0], out->faces[oface].lmextents[1], numpoints);
|
||||||
oface++;
|
oface++;
|
||||||
}
|
}
|
||||||
if (oface < 4)
|
out->numplanes = oface;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (brush->patch)
|
||||||
|
{
|
||||||
|
out->patch = BZ_Malloc(sizeof(*out->patch)-sizeof(out->patch->verts) + sizeof(*out->patch->verts)*brush->patch->xpoints*brush->patch->ypoints);
|
||||||
|
memcpy(out->patch, brush->patch, sizeof(*out->patch)-sizeof(out->patch->verts) + sizeof(*out->patch->verts)*brush->patch->xpoints*brush->patch->ypoints);
|
||||||
|
|
||||||
|
numpoints = out->patch->xpoints*out->patch->ypoints;
|
||||||
|
//FIXME: lightmap...
|
||||||
|
for (j = 0; j < numpoints; j++)
|
||||||
|
AddPointToBounds(out->patch->verts[j].v, out->mins, out->maxs);
|
||||||
|
|
||||||
|
out->patch->tex->rebuild = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((out->numplanes < 4 && out->numplanes) || (out->numplanes && out->patch) || (!out->numplanes && !out->patch))
|
||||||
{ //a brush with less than 4 planes cannot be a valid convex area (but can happen when certain redundant planes are chopped out). don't accept creation
|
{ //a brush with less than 4 planes cannot be a valid convex area (but can happen when certain redundant planes are chopped out). don't accept creation
|
||||||
//(we often get 2-plane brushes if the sides are sucked in)
|
//(we often get 2-plane brushes if the sides are sucked in)
|
||||||
for (j = 0; j < oface; j++)
|
for (j = 0; j < out->numplanes; j++)
|
||||||
{
|
{
|
||||||
BZ_Free(out->faces[j].lightdata);
|
BZ_Free(out->faces[j].lightdata);
|
||||||
BZ_Free(out->faces[j].points);
|
BZ_Free(out->faces[j].points);
|
||||||
}
|
}
|
||||||
BZ_Free(out->planes);
|
BZ_Free(out->planes);
|
||||||
|
BZ_Free(out->patch);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
out->numplanes = oface;
|
|
||||||
if (brush->id)
|
if (brush->id)
|
||||||
out->id = brush->id;
|
out->id = brush->id;
|
||||||
else
|
else
|
||||||
|
@ -6169,6 +6191,42 @@ static brushes_t *Terr_Brush_Insert(model_t *model, heightmap_t *hm, brushes_t *
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static brushes_t *Terr_Patch_Insert(model_t *model, heightmap_t *hm, brushtex_t *patch_tex, int patch_w, int patch_h, vec5_t *patch_v, int stride)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
brushes_t brush;
|
||||||
|
//finish the brush
|
||||||
|
brush.contents = 0;
|
||||||
|
brush.numplanes = 0;
|
||||||
|
brush.planes = NULL;
|
||||||
|
brush.faces = NULL;
|
||||||
|
brush.id = 0;
|
||||||
|
brush.patch = alloca(sizeof(*brush.patch)-sizeof(brush.patch->verts) + sizeof(*brush.patch->verts)*patch_w*patch_h);
|
||||||
|
|
||||||
|
brush.patch->tex = patch_tex;
|
||||||
|
brush.patch->xpoints = patch_w;
|
||||||
|
brush.patch->ypoints = patch_h;
|
||||||
|
|
||||||
|
for (y = 0; y < patch_h; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < patch_w; x++)
|
||||||
|
{
|
||||||
|
brush.patch->verts[x + y*patch_w].v[0] = patch_v[x][0];
|
||||||
|
brush.patch->verts[x + y*patch_w].v[1] = patch_v[x][1];
|
||||||
|
brush.patch->verts[x + y*patch_w].v[2] = patch_v[x][2];
|
||||||
|
brush.patch->verts[x + y*patch_w].tc[0] = patch_v[x][3];
|
||||||
|
brush.patch->verts[x + y*patch_w].tc[1] = patch_v[x][4];
|
||||||
|
//brush.patch->verts[x + y*patch_w].norm
|
||||||
|
//brush.patch->verts[x + y*patch_w].sdir
|
||||||
|
//brush.patch->verts[x + y*patch_w].tdir
|
||||||
|
}
|
||||||
|
patch_v += stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Terr_Brush_Insert(model, hm, &brush);
|
||||||
|
}
|
||||||
|
|
||||||
static void Terr_Brush_DeleteIdx(heightmap_t *hm, size_t idx)
|
static void Terr_Brush_DeleteIdx(heightmap_t *hm, size_t idx)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -6997,17 +7055,14 @@ void QCBUILTIN PF_brush_findinvolume(pubprogfuncs_t *prinst, struct globalvars_s
|
||||||
|
|
||||||
void Terr_WriteBrushInfo(vfsfile_t *file, brushes_t *br)
|
void Terr_WriteBrushInfo(vfsfile_t *file, brushes_t *br)
|
||||||
{
|
{
|
||||||
//valve 220 format:
|
|
||||||
//{
|
|
||||||
//( -0 -0 16 ) ( -0 -0 32 ) ( 64 -0 16 ) texname [x y z d] [x y z d] rotation sscale tscale
|
|
||||||
//}
|
|
||||||
float *point[3];
|
float *point[3];
|
||||||
int i, x, y;
|
int i, x, y;
|
||||||
|
qboolean valve220 = true;
|
||||||
|
|
||||||
VFS_PRINTF(file, "\n{");
|
VFS_PRINTF(file, "\n{");
|
||||||
if (br->patch)
|
if (br->patch)
|
||||||
{
|
{
|
||||||
VFS_PRINTF(file, "\n\tpatchDef2\n\t{\n\t\"%s\"\n\t( %.9g %.9g %.9g %.9g %.9g )\n\t(\t\n",
|
VFS_PRINTF(file, "\n\tpatchDef2\n\t{\n\t\t\"%s\"\n\t\t( %.9g %.9g %.9g %.9g %.9g )\n\t\t(\n",
|
||||||
br->patch->tex?br->patch->tex->shadername:"",
|
br->patch->tex?br->patch->tex->shadername:"",
|
||||||
0.0/*xoffset*/,
|
0.0/*xoffset*/,
|
||||||
0.0/*yoffset*/,
|
0.0/*yoffset*/,
|
||||||
|
@ -7016,37 +7071,74 @@ void Terr_WriteBrushInfo(vfsfile_t *file, brushes_t *br)
|
||||||
1.0/*yscale*/);
|
1.0/*yscale*/);
|
||||||
for (y = 0; y < br->patch->ypoints; y++)
|
for (y = 0; y < br->patch->ypoints; y++)
|
||||||
{
|
{
|
||||||
VFS_PRINTF(file, "\t\t( ");
|
VFS_PRINTF(file, "\t\t\t(\n");
|
||||||
for (x = 0; x < br->patch->xpoints; x++)
|
for (x = 0; x < br->patch->xpoints; x++)
|
||||||
{
|
{
|
||||||
VFS_PRINTF(file, "( %.9g %.9g %.9g %.9g %.9g )", br->patch->verts[x + y*br->patch->xpoints].v[0],
|
VFS_PRINTF(file, "\t\t\t\t( %.9g %.9g %.9g %.9g %.9g )\n", br->patch->verts[x + y*br->patch->xpoints].v[0],
|
||||||
br->patch->verts[x + y*br->patch->xpoints].v[1],
|
br->patch->verts[x + y*br->patch->xpoints].v[1],
|
||||||
br->patch->verts[x + y*br->patch->xpoints].v[2],
|
br->patch->verts[x + y*br->patch->xpoints].v[2],
|
||||||
br->patch->verts[x + y*br->patch->xpoints].tc[0],
|
br->patch->verts[x + y*br->patch->xpoints].tc[0],
|
||||||
br->patch->verts[x + y*br->patch->xpoints].tc[1]);
|
br->patch->verts[x + y*br->patch->xpoints].tc[1]);
|
||||||
}
|
}
|
||||||
VFS_PRINTF(file, " )");
|
VFS_PRINTF(file, "\t\t\t)\n");
|
||||||
}
|
}
|
||||||
VFS_PRINTF(file, " )\n\t}\n");
|
VFS_PRINTF(file, "\t\t)\n\t}\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (i = 0; i < br->numplanes; i++)
|
for (i = 0; i < br->numplanes; i++)
|
||||||
{
|
{
|
||||||
|
const char *texname, *s;
|
||||||
point[0] = br->faces[i].points[0];
|
point[0] = br->faces[i].points[0];
|
||||||
point[1] = br->faces[i].points[1];
|
point[1] = br->faces[i].points[1];
|
||||||
point[2] = br->faces[i].points[2];
|
point[2] = br->faces[i].points[2];
|
||||||
|
|
||||||
|
//valve 220 format:
|
||||||
|
//(-0 -0 16) (-0 -0 32) (64 -0 16) texname [x y z d] [x y z d] rotation sscale tscale
|
||||||
|
//don't treat whitespace as optional, even if it works with qbsp it'll screw up third party editors.
|
||||||
|
|
||||||
//%.9g is 'meant' to be lossless for a standard ieee single-precision float. (%.17g for a double)
|
//%.9g is 'meant' to be lossless for a standard ieee single-precision float. (%.17g for a double)
|
||||||
VFS_PRINTF(file, "\n( %.9g %.9g %.9g ) ( %.9g %.9g %.9g ) ( %.9g %.9g %.9g ) \"%s\" [ %.9g %.9g %.9g %.9g ] [ %.9g %.9g %.9g %.9g ] 0 1 1",
|
|
||||||
|
//write the 3 points-on-plane. I really hope its not degenerate
|
||||||
|
VFS_PRINTF(file, "\n( %.9g %.9g %.9g ) ( %.9g %.9g %.9g ) ( %.9g %.9g %.9g )",
|
||||||
point[0][0], point[0][1], point[0][2],
|
point[0][0], point[0][1], point[0][2],
|
||||||
point[1][0], point[1][1], point[1][2],
|
point[1][0], point[1][1], point[1][2],
|
||||||
point[2][0], point[2][1], point[2][2],
|
point[2][0], point[2][1], point[2][2]
|
||||||
br->faces[i].tex?br->faces[i].tex->shadername:"",
|
);
|
||||||
|
|
||||||
|
//write the name - if it contains markup or control chars, or other weird glyphs then be sure to quote it.
|
||||||
|
//we could always quote it, but that can and will screw up some editor somewhere...
|
||||||
|
for (s = texname = br->faces[i].tex?br->faces[i].tex->shadername:""; *s; s++)
|
||||||
|
{
|
||||||
|
if (*s <= 32 || *s >= 127 || *s == '\\' || *s == '(' || *s == '[' || *s == '{' || *s == ')' || *s == ']' || *s == '}')
|
||||||
|
break; //
|
||||||
|
}
|
||||||
|
VFS_PRINTF(file, (!*texname || *s)?" \"%s\"":" %s", texname);
|
||||||
|
|
||||||
|
if (valve220)
|
||||||
|
{
|
||||||
|
VFS_PRINTF(file, " [ %.9g %.9g %.9g %.9g ] [ %.9g %.9g %.9g %.9g ] 0 1 1",
|
||||||
br->faces[i].stdir[0][0], br->faces[i].stdir[0][1], br->faces[i].stdir[0][2], br->faces[i].stdir[0][3],
|
br->faces[i].stdir[0][0], br->faces[i].stdir[0][1], br->faces[i].stdir[0][2], br->faces[i].stdir[0][3],
|
||||||
br->faces[i].stdir[1][0], br->faces[i].stdir[1][1], br->faces[i].stdir[1][2], br->faces[i].stdir[1][3]
|
br->faces[i].stdir[1][0], br->faces[i].stdir[1][1], br->faces[i].stdir[1][2], br->faces[i].stdir[1][3]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float soffset, toffset, rotation, sscale, tscale;
|
||||||
|
//FIXME: project onto the axial plane, then figure out new values.
|
||||||
|
soffset = toffset = 0;
|
||||||
|
rotation = 0;
|
||||||
|
sscale = tscale = 1;
|
||||||
|
VFS_PRINTF(file, " %.9g %.9g %.9g %.9g %.9g", soffset, toffset, rotation, sscale, tscale);
|
||||||
|
}
|
||||||
|
|
||||||
|
//historical note: Q2 used contents|surfaceflags|value.
|
||||||
|
// however, Q3 uses the contents value exclusively for a detail flag. everything else comes from shaders.
|
||||||
|
if (br->contents != FTECONTENTS_SOLID || br->faces[i].surfaceflags || br->faces[i].surfacevalue)
|
||||||
|
VFS_PRINTF(file, " %i %i %i", br->contents, br->faces[i].surfaceflags, br->faces[i].surfacevalue);
|
||||||
|
// else if (hexen2)
|
||||||
|
// VFS_PRINTF(file, " -1"); //Light
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VFS_PRINTF(file, "\n}");
|
VFS_PRINTF(file, "\n}");
|
||||||
|
@ -7201,17 +7293,23 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
|
||||||
char *out, *outstart, *start;
|
char *out, *outstart, *start;
|
||||||
int i;
|
int i;
|
||||||
int submodelnum = 0;
|
int submodelnum = 0;
|
||||||
qboolean isdetail = false;
|
|
||||||
qboolean foundsubmodel = false;
|
qboolean foundsubmodel = false;
|
||||||
qboolean inbrush = false;
|
qboolean inbrush = false;
|
||||||
int numplanes = 0;
|
|
||||||
vec4_t planes[64];
|
|
||||||
struct brushface_s faces[64];
|
|
||||||
int brushcontents = FTECONTENTS_SOLID;
|
int brushcontents = FTECONTENTS_SOLID;
|
||||||
heightmap_t *subhm = NULL;
|
heightmap_t *subhm = NULL;
|
||||||
model_t *submod = NULL;
|
model_t *submod = NULL;
|
||||||
const char *brushpunct = "(){}[]"; //use an empty string for better compat with vanilla qbsp...
|
const char *brushpunct = "(){}[]"; //use an empty string for better compat with vanilla qbsp...
|
||||||
|
|
||||||
|
//brush planes
|
||||||
|
int numplanes = 0;
|
||||||
|
vec4_t planes[256];
|
||||||
|
struct brushface_s faces[countof(planes)];
|
||||||
|
|
||||||
|
//patch info
|
||||||
|
brushtex_t *patch_tex;
|
||||||
|
int patch_w, patch_h;
|
||||||
|
vec5_t patch_v[64][64];
|
||||||
|
|
||||||
#ifdef RUNTIMELIGHTING
|
#ifdef RUNTIMELIGHTING
|
||||||
hm->entsdirty = true;
|
hm->entsdirty = true;
|
||||||
hm->relightcontext = LightStartup(NULL, mod, false, false);
|
hm->relightcontext = LightStartup(NULL, mod, false, false);
|
||||||
|
@ -7230,6 +7328,11 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
|
||||||
{
|
{
|
||||||
nest--;
|
nest--;
|
||||||
if (inbrush)
|
if (inbrush)
|
||||||
|
{
|
||||||
|
if (subhm)
|
||||||
|
{
|
||||||
|
qboolean oe = subhm->brushesedited;
|
||||||
|
if (numplanes)
|
||||||
{
|
{
|
||||||
brushes_t brush;
|
brushes_t brush;
|
||||||
//finish the brush
|
//finish the brush
|
||||||
|
@ -7238,14 +7341,17 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
|
||||||
brush.planes = planes;
|
brush.planes = planes;
|
||||||
brush.faces = faces;
|
brush.faces = faces;
|
||||||
brush.id = 0;
|
brush.id = 0;
|
||||||
if (numplanes && subhm)
|
brush.patch = NULL;
|
||||||
{
|
|
||||||
qboolean oe = subhm->brushesedited;
|
|
||||||
Terr_Brush_Insert(submod, subhm, &brush);
|
Terr_Brush_Insert(submod, subhm, &brush);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Terr_Patch_Insert(submod, subhm, patch_tex, patch_w, patch_h, patch_v[0], countof(patch_v[0]));
|
||||||
subhm->brushesedited = oe;
|
subhm->brushesedited = oe;
|
||||||
}
|
}
|
||||||
numplanes = 0;
|
numplanes = 0;
|
||||||
inbrush = false;
|
inbrush = false;
|
||||||
|
patch_tex = NULL;
|
||||||
|
brushcontents = FTECONTENTS_SOLID;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7255,16 +7361,10 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
|
||||||
if (nest == 1)
|
if (nest == 1)
|
||||||
{ //entering a new entity
|
{ //entering a new entity
|
||||||
foundsubmodel = false;
|
foundsubmodel = false;
|
||||||
isdetail = false;
|
|
||||||
}
|
}
|
||||||
if (nest == 2)
|
if (nest == 2)
|
||||||
{
|
{
|
||||||
if (isdetail) //func_detail injects its brushes into the world model for some reason.
|
if (!foundsubmodel)
|
||||||
{
|
|
||||||
submod = mod;
|
|
||||||
subhm = hm;
|
|
||||||
}
|
|
||||||
else if (!foundsubmodel)
|
|
||||||
{
|
{
|
||||||
foundsubmodel = true;
|
foundsubmodel = true;
|
||||||
if (submodelnum)
|
if (submodelnum)
|
||||||
|
@ -7332,12 +7432,18 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
|
||||||
}
|
}
|
||||||
else if (inbrush && !strcmp(token, "patchDef2"))
|
else if (inbrush && !strcmp(token, "patchDef2"))
|
||||||
{
|
{
|
||||||
vec5_t pvert[64][64];
|
|
||||||
int x, y;
|
int x, y;
|
||||||
|
if (numplanes || patch_tex)
|
||||||
|
{
|
||||||
|
Con_Printf(CON_ERROR "%s: mixed patch+planes\n", mod->name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memset(patch_v, 0, sizeof(patch_v));
|
||||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||||
if (strcmp(token, "{")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
|
if (strcmp(token, "{")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
|
||||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||||
/*parse texture name*/
|
/*parse texture name*/
|
||||||
|
patch_tex = Terr_Brush_FindTexture(subhm, token);
|
||||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||||
if (strcmp(token, "(")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
|
if (strcmp(token, "(")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
|
||||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||||
|
@ -7356,6 +7462,7 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
|
||||||
if (strcmp(token, "(")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
|
if (strcmp(token, "(")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
|
||||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||||
y = 0;
|
y = 0;
|
||||||
|
patch_w = patch_h = 0;
|
||||||
while (!strcmp(token, "("))
|
while (!strcmp(token, "("))
|
||||||
{
|
{
|
||||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||||
|
@ -7363,31 +7470,35 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
|
||||||
while (!strcmp(token, "("))
|
while (!strcmp(token, "("))
|
||||||
{
|
{
|
||||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||||
pvert[y][x][0] = atof(token);
|
patch_v[y][x][0] = atof(token);
|
||||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||||
pvert[y][x][1] = atof(token);
|
patch_v[y][x][1] = atof(token);
|
||||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||||
pvert[y][x][2] = atof(token);
|
patch_v[y][x][2] = atof(token);
|
||||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||||
pvert[y][x][3] = atof(token);
|
patch_v[y][x][3] = atof(token);
|
||||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||||
pvert[y][x][4] = atof(token);
|
patch_v[y][x][4] = atof(token);
|
||||||
|
|
||||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||||
if (strcmp(token, ")")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
|
if (strcmp(token, ")")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
|
||||||
|
|
||||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||||
if (x < countof(pvert[y])-1)
|
if (x < countof(patch_v[y])-1)
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
|
if (patch_w < x)
|
||||||
|
patch_w = x;
|
||||||
if (strcmp(token, ")")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
|
if (strcmp(token, ")")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
|
||||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||||
if (y < countof(pvert)-1)
|
if (y < countof(patch_v)-1)
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
|
patch_h = y;
|
||||||
if (strcmp(token, ")")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
|
if (strcmp(token, ")")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
|
||||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||||
if (strcmp(token, "}")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
|
if (strcmp(token, "}")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else if (inbrush)
|
else if (inbrush)
|
||||||
{
|
{
|
||||||
|
@ -7406,6 +7517,11 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
|
||||||
int p;
|
int p;
|
||||||
qboolean hlstyle = false;
|
qboolean hlstyle = false;
|
||||||
memset(points, 0, sizeof(points));
|
memset(points, 0, sizeof(points));
|
||||||
|
if (patch_tex)
|
||||||
|
{
|
||||||
|
Con_Printf(CON_ERROR "%s: mixed patch+planes\n", mod->name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
for (p = 0; p < 3; p++)
|
for (p = 0; p < 3; p++)
|
||||||
{
|
{
|
||||||
if (token[0] != '(' || token[1] != 0)
|
if (token[0] != '(' || token[1] != 0)
|
||||||
|
@ -7454,10 +7570,14 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
|
||||||
brushcontents = FTECONTENTS_SKY;
|
brushcontents = FTECONTENTS_SKY;
|
||||||
else if (!Q_strcasecmp(token, "clip"))
|
else if (!Q_strcasecmp(token, "clip"))
|
||||||
brushcontents = FTECONTENTS_PLAYERCLIP|FTECONTENTS_MONSTERCLIP;
|
brushcontents = FTECONTENTS_PLAYERCLIP|FTECONTENTS_MONSTERCLIP;
|
||||||
|
else if (!Q_strcasecmp(token, "hint"))
|
||||||
|
brushcontents = 0;
|
||||||
|
else if (!Q_strcasecmp(token, "skip"))
|
||||||
|
;//brushcontents = 0;
|
||||||
else
|
else
|
||||||
brushcontents = FTECONTENTS_SOLID;
|
brushcontents = FTECONTENTS_SOLID;
|
||||||
|
|
||||||
//FIXME: halflife format has the entire [x y z dist] plane specified.
|
//halflife/valve220 format has the entire [x y z dist] plane specified.
|
||||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||||
if (*token == '[')
|
if (*token == '[')
|
||||||
{
|
{
|
||||||
|
@ -7490,7 +7610,7 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
|
||||||
//]
|
//]
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{ //vanilla quake
|
||||||
VectorClear(texplane[0]);
|
VectorClear(texplane[0]);
|
||||||
VectorClear(texplane[1]);
|
VectorClear(texplane[1]);
|
||||||
texplane[0][3] = atof(token);
|
texplane[0][3] = atof(token);
|
||||||
|
@ -7506,30 +7626,44 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
|
||||||
scale[1] = atof(token);
|
scale[1] = atof(token);
|
||||||
|
|
||||||
//hexen2 has some extra junk that is useless - some 'light' value, but its never used and should normally be -1.
|
//hexen2 has some extra junk that is useless - some 'light' value, but its never used and should normally be -1.
|
||||||
//quake3 on the other hand has 3 different args. Contents Unused Unused. The contents conveys only CONTENTS_DETAIL. which is awkward as it varies by game.
|
//quake2/3 on the other hand has 3 different args. Contents SurfaceFlags SurfaceValue.
|
||||||
|
//the SurfaceFlags and SurfaceVales are no longer used in q3 (shaders do it all), but contents is still partially used.
|
||||||
|
//The contents conveys only CONTENTS_DETAIL. which is awkward as it varies somewhat by game, but we assume q2/q3.
|
||||||
|
faces[numplanes].surfaceflags = 0;
|
||||||
|
faces[numplanes].surfacevalue = 0;
|
||||||
while (*entities == ' ' || *entities == '\t')
|
while (*entities == ' ' || *entities == '\t')
|
||||||
entities++;
|
entities++;
|
||||||
if (*entities == '-' || (*entities >= '0' && *entities <= '9'))
|
if (*entities == '-' || (*entities >= '0' && *entities <= '9'))
|
||||||
{
|
{
|
||||||
int ex1;
|
int ex1, ex2 = 0, ex3 = 0;
|
||||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||||
ex1 = atoi(token);
|
ex1 = atoi(token);
|
||||||
|
|
||||||
while (*entities == ' ' || *entities == '\t')
|
while (*entities == ' ' || *entities == '\t')
|
||||||
entities++;
|
entities++;
|
||||||
if (*entities == '-' || (*entities >= '0' && *entities <= '9'))
|
if (*entities == '-' || (*entities >= '0' && *entities <= '9'))
|
||||||
|
{
|
||||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||||
|
ex2 = atoi(token);
|
||||||
|
}
|
||||||
|
|
||||||
while (*entities == ' ' || *entities == '\t')
|
while (*entities == ' ' || *entities == '\t')
|
||||||
entities++;
|
entities++;
|
||||||
if (*entities == '-' || (*entities >= '0' && *entities <= '9'))
|
if (*entities == '-' || (*entities >= '0' && *entities <= '9'))
|
||||||
{
|
{
|
||||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||||
|
ex3 = atoi(token);
|
||||||
//if we got this far, then its q3 format.
|
//if we got this far, then its q3 format.
|
||||||
//q3 is weird. the first extra arg is contents. but only the detail contents is used.
|
//q3 is weird. the first extra arg is contents. but only the detail contents is used.
|
||||||
if (ex1 & Q3CONTENTS_DETAIL)
|
if (ex1 & Q3CONTENTS_DETAIL)
|
||||||
|
{
|
||||||
brushcontents |= Q3CONTENTS_DETAIL;
|
brushcontents |= Q3CONTENTS_DETAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//propagate these, in case someone tries editing a q2bsp.
|
||||||
|
faces[numplanes].surfaceflags = ex2;
|
||||||
|
faces[numplanes].surfacevalue = ex3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//okay, that's all the actual parsing, now try to make sense of this plane.
|
//okay, that's all the actual parsing, now try to make sense of this plane.
|
||||||
|
@ -7592,12 +7726,7 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!strcmp(token, "classname"))
|
if (!strcmp(token, "classname"))
|
||||||
{
|
|
||||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||||
|
|
||||||
if (!strcmp(token, "func_detail"))
|
|
||||||
isdetail = true;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -281,7 +281,7 @@ typedef struct
|
||||||
vec3_t sdir;
|
vec3_t sdir;
|
||||||
vec3_t tdir;
|
vec3_t tdir;
|
||||||
} verts[1]; //x+(y*xpoints)
|
} verts[1]; //x+(y*xpoints)
|
||||||
} *patch;
|
} *patch; //if this is NULL, then its a regular brush. otherwise its a patch.
|
||||||
struct brushface_s
|
struct brushface_s
|
||||||
{
|
{
|
||||||
brushtex_t *tex;
|
brushtex_t *tex;
|
||||||
|
@ -295,6 +295,8 @@ typedef struct
|
||||||
unsigned short relit:1;
|
unsigned short relit:1;
|
||||||
int lmbias[2];
|
int lmbias[2];
|
||||||
unsigned short lmextents[2];
|
unsigned short lmextents[2];
|
||||||
|
unsigned int surfaceflags; //used by q2
|
||||||
|
unsigned int surfacevalue; //used by q2 (generally light levels)
|
||||||
qbyte *lightdata;
|
qbyte *lightdata;
|
||||||
} *faces;
|
} *faces;
|
||||||
} brushes_t;
|
} brushes_t;
|
||||||
|
|
Loading…
Reference in a new issue