📄 map.c
字号:
{
k = (j+1)%w->numpoints;
VectorSubtract (w->p[j], w->p[k], vec);
if (VectorNormalize (vec) < 0.5)
continue;
SnapVector (vec);
for (k=0 ; k<3 ; k++)
if ( vec[k] == -1 || vec[k] == 1)
break; // axial
if (k != 3)
continue; // only test non-axial edges
// try the six possible slanted axials from this edge
for (axis=0 ; axis <3 ; axis++)
{
for (dir=-1 ; dir <= 1 ; dir+=2)
{
// construct a plane
VectorClear (vec2);
vec2[axis] = dir;
CrossProduct (vec, vec2, normal);
if (VectorNormalize (normal) < 0.5)
continue;
dist = DotProduct (w->p[j], normal);
// if all the points on all the sides are
// behind this plane, it is a proper edge bevel
for (k=0 ; k<b->numsides ; k++)
{
// if this plane has allready been used, skip it
if (PlaneEqual (&mapplanes[b->original_sides[k].planenum]
, normal, dist) )
break;
w2 = b->original_sides[k].winding;
if (!w2)
continue;
for (l=0 ; l<w2->numpoints ; l++)
{
d = DotProduct (w2->p[l], normal) - dist;
if (d > 0.1)
break; // point in front
}
if (l != w2->numpoints)
break;
}
if (k != b->numsides)
continue; // wasn't part of the outer hull
// add this plane
if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
Error ("MAX_MAP_BRUSHSIDES");
nummapbrushsides++;
s2 = &b->original_sides[b->numsides];
s2->planenum = FindFloatPlane (normal, dist);
s2->texinfo = b->original_sides[0].texinfo;
#ifdef SIN
s2->lightinfo = b->original_sides[0].lightinfo;
#endif
s2->contents = b->original_sides[0].contents;
s2->flags |= SFL_BEVEL;
c_edgebevels++;
b->numsides++;
}
}
}
}
} //end of the function AddBrushBevels
//===========================================================================
// creates windigs for sides and mins / maxs for the brush
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean MakeBrushWindings(mapbrush_t *ob)
{
int i, j;
winding_t *w;
side_t *side;
plane_t *plane;
ClearBounds (ob->mins, ob->maxs);
for (i = 0; i < ob->numsides; i++)
{
plane = &mapplanes[ob->original_sides[i].planenum];
w = BaseWindingForPlane(plane->normal, plane->dist);
for (j = 0; j <ob->numsides && w; j++)
{
if (i == j) continue;
if (ob->original_sides[j].flags & SFL_BEVEL) continue;
plane = &mapplanes[ob->original_sides[j].planenum^1];
ChopWindingInPlace(&w, plane->normal, plane->dist, 0); //CLIP_EPSILON);
}
side = &ob->original_sides[i];
side->winding = w;
if (w)
{
side->flags |= SFL_VISIBLE;
for (j = 0; j < w->numpoints; j++)
AddPointToBounds (w->p[j], ob->mins, ob->maxs);
}
}
for (i = 0; i < 3; i++)
{
//IDBUG: all the indexes into the mins and maxs were zero (not using i)
if (ob->mins[i] < -MAX_MAP_BOUNDS || ob->maxs[i] > MAX_MAP_BOUNDS)
{
Log_Print("entity %i, brush %i: bounds out of range\n", ob->entitynum, ob->brushnum);
ob->numsides = 0; //remove the brush
break;
} //end if
if (ob->mins[i] > MAX_MAP_BOUNDS || ob->maxs[i] < -MAX_MAP_BOUNDS)
{
Log_Print("entity %i, brush %i: no visible sides on brush\n", ob->entitynum, ob->brushnum);
ob->numsides = 0; //remove the brush
break;
} //end if
} //end for
return true;
} //end of the function MakeBrushWindings
//===========================================================================
// FIXME: currently doesn't mark all bevels
// NOTE: when one brush bevel is found the remaining sides of the brush
// are bevels as well (when the brush isn't expanded for AAS :))
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void MarkBrushBevels(mapbrush_t *brush)
{
int i;
int we;
side_t *s;
//check all the sides of the brush
for (i = 0; i < brush->numsides; i++)
{
s = brush->original_sides + i;
//if the side has no winding
if (!s->winding)
{
Log_Write("MarkBrushBevels: brush %d no winding", brush->brushnum);
s->flags |= SFL_BEVEL;
} //end if
//if the winding is tiny
else if (WindingIsTiny(s->winding))
{
s->flags |= SFL_BEVEL;
Log_Write("MarkBrushBevels: brush %d tiny winding", brush->brushnum);
} //end else if
//if the winding has errors
else
{
we = WindingError(s->winding);
if (we == WE_NOTENOUGHPOINTS
|| we == WE_SMALLAREA
|| we == WE_POINTBOGUSRANGE
// || we == WE_NONCONVEX
)
{
Log_Write("MarkBrushBevels: brush %d %s", brush->brushnum, WindingErrorString());
s->flags |= SFL_BEVEL;
} //end else if
} //end else
if (s->flags & SFL_BEVEL)
{
s->flags &= ~SFL_VISIBLE;
//if the side has a valid plane
if (s->planenum > 0 && s->planenum < nummapplanes)
{
//if it is an axial plane
if (mapplanes[s->planenum].type < 3) c_boxbevels++;
else c_edgebevels++;
} //end if
} //end if
} //end for
} //end of the function MarkBrushBevels
//===========================================================================
// returns true if the map brush already exists
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BrushExists(mapbrush_t *brush)
{
int i, s1, s2;
side_t *side1, *side2;
mapbrush_t *brush1, *brush2;
for (i = 0; i < nummapbrushes; i++)
{
brush1 = brush;
brush2 = &mapbrushes[i];
//compare the brushes
if (brush1->entitynum != brush2->entitynum) continue;
//if (brush1->contents != brush2->contents) continue;
if (brush1->numsides != brush2->numsides) continue;
for (s1 = 0; s1 < brush1->numsides; s1++)
{
side1 = brush1->original_sides + s1;
//
for (s2 = 0; s2 < brush2->numsides; s2++)
{
side2 = brush2->original_sides + s2;
//
if ((side1->planenum & ~1) == (side2->planenum & ~1)
// && side1->texinfo == side2->texinfo
// && side1->contents == side2->contents
// && side1->surf == side2->surf
) break;
} //end if
if (s2 >= brush2->numsides) break;
} //end for
if (s1 >= brush1->numsides) return true;
} //end for
return false;
} //end of the function BrushExists
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean WriteMapBrush(FILE *fp, mapbrush_t *brush, vec3_t origin)
{
int sn, rotate, shift[2], sv, tv, planenum, p1, i, j;
float scale[2], originshift[2], ang1, ang2, newdist;
vec3_t vecs[2], axis[2];
map_texinfo_t *ti;
winding_t *w;
side_t *s;
plane_t *plane;
if (noliquids)
{
if (brush->contents & (CONTENTS_WATER|CONTENTS_SLIME|CONTENTS_LAVA))
{
return true;
} //end if
} //end if
//if the brush has no contents
if (!brush->contents) return true;
//print the leading {
if (fprintf(fp, " { //brush %d\n", brush->brushnum) < 0) return false;
//write brush sides
for (sn = 0; sn < brush->numsides; sn++)
{
s = brush->original_sides + sn;
//don't write out bevels
if (!(s->flags & SFL_BEVEL))
{
//if the entity has an origin set
if (origin[0] || origin[1] || origin[2])
{
newdist = mapplanes[s->planenum].dist +
DotProduct(mapplanes[s->planenum].normal, origin);
planenum = FindFloatPlane(mapplanes[s->planenum].normal, newdist);
} //end if
else
{
planenum = s->planenum;
} //end else
//always take the first plane, then flip the points if necesary
plane = &mapplanes[planenum & ~1];
w = BaseWindingForPlane(plane->normal, plane->dist);
//
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
if (fabs(w->p[i][j]) < 0.2) w->p[i][j] = 0;
else if (fabs((int)w->p[i][j] - w->p[i][j]) < 0.3) w->p[i][j] = (int) w->p[i][j];
//w->p[i][j] = (int) (w->p[i][j] + 0.2);
} //end for
} //end for
//three non-colinear points to define the plane
if (planenum & 1) p1 = 1;
else p1 = 0;
if (fprintf(fp," ( %5i %5i %5i ) ", (int)w->p[p1][0], (int)w->p[p1][1], (int)w->p[p1][2]) < 0) return false;
if (fprintf(fp,"( %5i %5i %5i ) ", (int)w->p[!p1][0], (int)w->p[!p1][1], (int)w->p[!p1][2]) < 0) return false;
if (fprintf(fp,"( %5i %5i %5i ) ", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2]) < 0) return false;
//free the winding
FreeWinding(w);
//
if (s->texinfo == TEXINFO_NODE)
{
if (brush->contents & CONTENTS_PLAYERCLIP)
{
//player clip
if (loadedmaptype == MAPTYPE_SIN)
{
if (fprintf(fp, "generic/misc/clip 0 0 0 1 1") < 0) return false;
} //end if
else if (loadedmaptype == MAPTYPE_QUAKE2)
{ //FIXME: don't always use e1u1
if (fprintf(fp, "e1u1/clip 0 0 0 1 1") < 0) return false;
} //end else
else if (loadedmaptype == MAPTYPE_QUAKE3)
{
if (fprintf(fp, "e1u1/clip 0 0 0 1 1") < 0) return false;
} //end else if
else
{
if (fprintf(fp, "clip 0 0 0 1 1") < 0) return false;
} //end else
} //end if
else if (brush->contents == CONTENTS_MONSTERCLIP)
{
//monster clip
if (loadedmaptype == MAPTYPE_SIN)
{
if (fprintf(fp, "generic/misc/monster 0 0 0 1 1") < 0) return false;
} //end if
else if (loadedmaptype == MAPTYPE_QUAKE2)
{
if (fprintf(fp, "e1u1/clip_mon 0 0 0 1 1") < 0) return false;
} //end else
else
{
if (fprintf(fp, "clip 0 0 0 1 1") < 0) return false;
} //end else
} //end else
else
{
if (fprintf(fp, "clip 0 0 0 1 1") < 0) return false;
Log_Write("brush->contents = %d\n", brush->contents);
} //end else
} //end if
else if (loadedmaptype == MAPTYPE_SIN && s->texinfo == 0)
{
if (brush->contents & CONTENTS_DUMMYFENCE)
{
if (fprintf(fp, "generic/misc/fence 0 0 0 1 1") < 0) return false;
} //end if
else if (brush->contents & CONTENTS_MIST)
{
if (fprintf(fp, "generic/misc/volumetric_base 0 0 0 1 1") < 0) return false;
} //end if
else //unknown so far
{
if (fprintf(fp, "generic/misc/red 0 0 0 1 1") < 0) return false;
} //end else
} //end if
else if (loadedmaptype == MAPTYPE_QUAKE3)
{
//always use the same texture
if (fprintf(fp, "e2u3/floor1_2 0 0 0 1 1 1 0 0") < 0) return false;
} //end else if
else
{
//*
ti = &map_texinfo[s->texinfo];
//the scaling of the texture
scale[0] = 1 / VectorNormalize2(ti->vecs[0], vecs[0]);
scale[1] = 1 / VectorNormalize2(ti->vecs[1], vecs[1]);
//
TextureAxisFromPlane(plane, axis[0], axis[1]);
//calculate texture shift done by entity origin
originshift[0] = DotProduct(origin, axis[0]);
originshift[1] = DotProduct(origin, axis[1]);
//the texture shift without origin shift
shift[0] = ti->vecs[0][3] - originshift[0];
shift[1] = ti->vecs[1][3] - originshift[1];
//
if (axis[0][0]) sv = 0;
else if (axis[0][1]) sv = 1;
else sv = 2;
if (axis[1][0]) tv = 0;
else if (axis[1][1]) tv = 1;
else tv = 2;
//calculate rotation of texture
if (vecs[0][tv] == 0) ang1 = vecs[0][sv] > 0 ? 90.0 : -90.0;
else ang1 = atan2(vecs[0][sv], vecs[0][tv]) * 180 / Q_PI;
if (ang1 < 0) ang1 += 360;
if (ang1 >= 360) ang1 -= 360;
if (axis[0][tv] == 0) ang2 = axis[0][sv] > 0 ? 90.0 : -90.0;
else ang2 = atan2(axis[0][sv], axis[0][tv]) * 180 / Q_PI;
if (ang2 < 0) ang2 += 360;
if (ang2 >= 360) ang2 -= 360;
rotate = ang2 - ang1;
if (rotate < 0) rotate += 360;
if (rotate >= 360) rotate -= 360;
//write the texture info
if (fprintf(fp, "%s %d %d %d", ti->texture, shift[0], shift[1], rotate) < 0) return false;
if (fabs(scale[0] - ((int) scale[0])) < 0.001)
{
if (fprintf(fp, " %d", (int) scale[0]) < 0) return false;
} //end if
else
{
if (fprintf(fp, " %4f", scale[0]) < 0) return false;
} //end if
if (fabs(scale[1] - ((int) scale[1])) < 0.001)
{
if (fprintf(fp, " %d", (int) scale[1]) < 0) return false;
} //end if
else
{
if (fprintf(fp, " %4f", scale[1]) < 0) return false;
} //end else
//write the extra brush side info
if (loadedmaptype == MAPTYPE_QUAKE2)
{
if (fprintf(fp, " %ld %ld %ld", s->contents, ti->flags, ti->value) < 0) return false;
} //end if
//*/
} //end else
if (fprintf(fp, "\n") < 0) return false;
} //end if
} //end if
if (fprintf(fp, " }\n") < 0) return false;
c_writtenbrushes++;
return true;
} //end of the function WriteMapBrush
//===========================================================================
//
// Parameter: -
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -