Merge branch 'brushbsp' of https://github.com/ericwa/ericw-tools into brushbsp

# Conflicts:
#	common/bspfile.cc
This commit is contained in:
Jonathan 2023-05-08 17:47:12 -04:00
commit 0ab3aae111
28 changed files with 474 additions and 185 deletions

View File

@ -4,10 +4,10 @@ Language: Cpp
AccessModifierOffset: -4
AlignAfterOpenBracket: false
#AlignArrayOfStructures: Right
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveBitFields: false
AlignConsecutiveDeclarations: false
AlignConsecutiveMacros: None
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: None
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments: false
@ -92,7 +92,7 @@ PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: true
SortIncludes: false
SortIncludes: Never
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
@ -111,7 +111,7 @@ SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
Standard: c++17
Standard: c++20
TabWidth: 4
UseCRLF: false
UseTab: Never

15
.readthedocs.yaml Normal file
View File

@ -0,0 +1,15 @@
version: 2
build:
os: "ubuntu-22.04"
tools:
python: "3.11"
# Build from the docs/ directory with Sphinx
sphinx:
configuration: docs/conf.py
# Explicitly set the version of Python and its requirements
python:
install:
- requirements: docs/requirements.txt

View File

@ -41,7 +41,7 @@ static void PrintBSPTextureUsage(const mbsp_t &bsp)
continue;
}
auto points = GLM_FacePoints(&bsp, &face);
auto points = Face_Points(&bsp, &face);
polylib::winding_t w(points.begin(), points.end());
vec_t area = w.area();

View File

@ -1803,7 +1803,8 @@ static auto as_tuple(const surfflags_t &flags)
{
return std::tie(flags.native, flags.is_nodraw, flags.is_hintskip, flags.is_hint, flags.no_dirt, flags.no_shadow,
flags.no_bounce, flags.no_minlight, flags.no_expand, flags.no_phong, flags.light_ignore,
flags.surflight_rescale, flags.surflight_style, flags.surflight_targetname, flags.surflight_color, flags.surflight_minlight_scale, flags.phong_angle, flags.phong_angle_concave, flags.phong_group, flags.minlight,
flags.surflight_rescale, flags.surflight_style, flags.surflight_color, flags.surflight_minlight_scale,
flags.surflight_targetname, flags.phong_angle, flags.phong_angle_concave, flags.phong_group, flags.minlight,
flags.minlight_color, flags.light_alpha, flags.maxlight, flags.lightcolorscale, flags.surflight_group,
flags.world_units_per_luxel, flags.object_channel_mask);
}

View File

@ -512,8 +512,7 @@ std::vector<const dbrush_t *> Leaf_Brushes(const mbsp_t *bsp, const mleaf_t *lea
return result;
}
// glm stuff
std::vector<qvec3f> GLM_FacePoints(const mbsp_t *bsp, const mface_t *face)
std::vector<qvec3f> Face_Points(const mbsp_t *bsp, const mface_t *face)
{
std::vector<qvec3f> points;
@ -539,7 +538,7 @@ polylib::winding_t Face_Winding(const mbsp_t *bsp, const mface_t *face)
qvec3f Face_Centroid(const mbsp_t *bsp, const mface_t *face)
{
auto points = GLM_FacePoints(bsp, face);
auto points = Face_Points(bsp, face);
return qv::PolyCentroid(points.begin(), points.end());
}

View File

@ -282,7 +282,7 @@ private:
if (!winding) {
return;
}
inwardFacingEdgePlanes = GLM_MakeInwardFacingEdgePlanes(winding->glm_winding_points());
inwardFacingEdgePlanes = MakeInwardFacingEdgePlanes(winding->glm_winding_points());
}
public:
@ -493,8 +493,7 @@ struct decomp_brush_t
for (auto &point : face.winding.value()) {
// check against all planes
for (auto &otherSide : sides) {
float distance =
GLM_DistAbovePlane(qvec4f(otherSide.plane.normal, otherSide.plane.dist), point);
float distance = DistAbovePlane(qvec4f(otherSide.plane.normal, otherSide.plane.dist), point);
if (distance > 0.1) {
return false;
}

View File

@ -172,7 +172,7 @@ float Lanczos2D(float x, float y, float a)
using namespace std;
qvec3f GLM_FaceNormal(std::vector<qvec3f> points)
qvec3f FaceNormal(std::vector<qvec3f> points)
{
const int N = static_cast<int>(points.size());
float maxArea = -FLT_MAX;
@ -200,14 +200,14 @@ qvec3f GLM_FaceNormal(std::vector<qvec3f> points)
return normal;
}
qvec4f GLM_PolyPlane(const std::vector<qvec3f> &points)
qvec4f PolyPlane(const std::vector<qvec3f> &points)
{
const qvec3f normal = GLM_FaceNormal(points);
const qvec3f normal = FaceNormal(points);
const float dist = qv::dot(points.at(0), normal);
return qvec4f(normal[0], normal[1], normal[2], dist);
}
std::pair<bool, qvec4f> GLM_MakeInwardFacingEdgePlane(const qvec3f &v0, const qvec3f &v1, const qvec3f &faceNormal)
std::pair<bool, qvec4f> MakeInwardFacingEdgePlane(const qvec3f &v0, const qvec3f &v1, const qvec3f &faceNormal)
{
const float v0v1len = qv::length(v1 - v0);
if (v0v1len < POINT_EQUAL_EPSILON)
@ -220,7 +220,7 @@ std::pair<bool, qvec4f> GLM_MakeInwardFacingEdgePlane(const qvec3f &v0, const qv
return make_pair(true, qvec4f(edgeplane_normal[0], edgeplane_normal[1], edgeplane_normal[2], edgeplane_dist));
}
vector<qvec4f> GLM_MakeInwardFacingEdgePlanes(const std::vector<qvec3f> &points)
vector<qvec4f> MakeInwardFacingEdgePlanes(const std::vector<qvec3f> &points)
{
const size_t N = points.size();
if (N < 3)
@ -229,7 +229,7 @@ vector<qvec4f> GLM_MakeInwardFacingEdgePlanes(const std::vector<qvec3f> &points)
vector<qvec4f> result;
result.reserve(points.size());
const qvec3f faceNormal = GLM_FaceNormal(points);
const qvec3f faceNormal = FaceNormal(points);
if (qv::emptyExact(faceNormal))
return {};
@ -238,7 +238,7 @@ vector<qvec4f> GLM_MakeInwardFacingEdgePlanes(const std::vector<qvec3f> &points)
const qvec3f &v0 = points[i];
const qvec3f &v1 = points[(i + 1) % N];
const auto edgeplane = GLM_MakeInwardFacingEdgePlane(v0, v1, faceNormal);
const auto edgeplane = MakeInwardFacingEdgePlane(v0, v1, faceNormal);
if (!edgeplane.first)
continue;
@ -248,12 +248,12 @@ vector<qvec4f> GLM_MakeInwardFacingEdgePlanes(const std::vector<qvec3f> &points)
return result;
}
float GLM_EdgePlanes_PointInsideDist(const std::vector<qvec4f> &edgeplanes, const qvec3f &point)
float EdgePlanes_PointInsideDist(const std::vector<qvec4f> &edgeplanes, const qvec3f &point)
{
float min = FLT_MAX;
for (int i = 0; i < edgeplanes.size(); i++) {
const float planedist = GLM_DistAbovePlane(edgeplanes[i], point);
const float planedist = DistAbovePlane(edgeplanes[i], point);
if (planedist < min)
min = planedist;
}
@ -261,33 +261,33 @@ float GLM_EdgePlanes_PointInsideDist(const std::vector<qvec4f> &edgeplanes, cons
return min; // "outermost" point
}
bool GLM_EdgePlanes_PointInside(const vector<qvec4f> &edgeplanes, const qvec3f &point)
bool EdgePlanes_PointInside(const vector<qvec4f> &edgeplanes, const qvec3f &point)
{
if (edgeplanes.empty())
return false;
const float minDist = GLM_EdgePlanes_PointInsideDist(edgeplanes, point);
const float minDist = EdgePlanes_PointInsideDist(edgeplanes, point);
return minDist >= -POINT_EQUAL_EPSILON;
}
qvec4f GLM_MakePlane(const qvec3f &normal, const qvec3f &point)
qvec4f MakePlane(const qvec3f &normal, const qvec3f &point)
{
return qvec4f(normal[0], normal[1], normal[2], qv::dot(point, normal));
}
float GLM_DistAbovePlane(const qvec4f &plane, const qvec3f &point)
float DistAbovePlane(const qvec4f &plane, const qvec3f &point)
{
return qv::dot(qvec3f(plane), point) - plane[3];
}
qvec3f GLM_ProjectPointOntoPlane(const qvec4f &plane, const qvec3f &point)
qvec3f ProjectPointOntoPlane(const qvec4f &plane, const qvec3f &point)
{
float dist = GLM_DistAbovePlane(plane, point);
float dist = DistAbovePlane(plane, point);
qvec3f move = qvec3f(plane) * -dist;
return point + move;
}
poly_random_point_state_t GLM_PolyRandomPoint_Setup(const std::vector<qvec3f> &points)
poly_random_point_state_t PolyRandomPoint_Setup(const std::vector<qvec3f> &points)
{
Q_assert(points.size() >= 3);
@ -314,7 +314,7 @@ poly_random_point_state_t GLM_PolyRandomPoint_Setup(const std::vector<qvec3f> &p
}
// r1, r2, r3 must be in [0, 1]
qvec3f GLM_PolyRandomPoint(const poly_random_point_state_t &state, float r1, float r2, float r3)
qvec3f PolyRandomPoint(const poly_random_point_state_t &state, float r1, float r2, float r3)
{
// Pick a random triangle, with probability proportional to triangle area
const float uniformRandom = r1;
@ -330,7 +330,7 @@ qvec3f GLM_PolyRandomPoint(const poly_random_point_state_t &state, float r1, flo
return point;
}
std::pair<int, qvec3f> GLM_ClosestPointOnPolyBoundary(const std::vector<qvec3f> &poly, const qvec3f &point)
std::pair<int, qvec3f> ClosestPointOnPolyBoundary(const std::vector<qvec3f> &poly, const qvec3f &point)
{
const int N = static_cast<int>(poly.size());
@ -357,7 +357,7 @@ std::pair<int, qvec3f> GLM_ClosestPointOnPolyBoundary(const std::vector<qvec3f>
return make_pair(bestI, bestPointOnPoly);
}
std::pair<bool, qvec3f> GLM_InterpolateNormal(
std::pair<bool, qvec3f> InterpolateNormal(
const std::vector<qvec3f> &points, const std::vector<face_normal_t> &normals, const qvec3f &point)
{
std::vector<qvec3f> normalvecs;
@ -365,10 +365,10 @@ std::pair<bool, qvec3f> GLM_InterpolateNormal(
normalvecs.push_back(normal.normal);
}
return GLM_InterpolateNormal(points, normalvecs, point);
return InterpolateNormal(points, normalvecs, point);
}
std::pair<bool, qvec3f> GLM_InterpolateNormal(
std::pair<bool, qvec3f> InterpolateNormal(
const std::vector<qvec3f> &points, const std::vector<qvec3f> &normals, const qvec3f &point)
{
Q_assert(points.size() == normals.size());
@ -388,11 +388,11 @@ std::pair<bool, qvec3f> GLM_InterpolateNormal(
const qvec3f &p2 = points.at(i);
const qvec3f &n2 = normals.at(i);
const auto edgeplanes = GLM_MakeInwardFacingEdgePlanes({p0, p1, p2});
const auto edgeplanes = MakeInwardFacingEdgePlanes({p0, p1, p2});
if (edgeplanes.size() != 3)
continue;
if (GLM_EdgePlanes_PointInside(edgeplanes, point)) {
if (EdgePlanes_PointInside(edgeplanes, point)) {
// Found the correct triangle
const qvec3f bary = qv::Barycentric_FromPoint(point, p0, p1, p2);
@ -409,7 +409,7 @@ std::pair<bool, qvec3f> GLM_InterpolateNormal(
}
/// Returns (front part, back part)
std::pair<std::vector<qvec3f>, std::vector<qvec3f>> GLM_ClipPoly(const std::vector<qvec3f> &poly, const qvec4f &plane)
std::pair<std::vector<qvec3f>, std::vector<qvec3f>> ClipPoly(const std::vector<qvec3f> &poly, const qvec4f &plane)
{
if (poly.empty())
return make_pair(vector<qvec3f>(), vector<qvec3f>());
@ -428,15 +428,15 @@ std::pair<std::vector<qvec3f>, std::vector<qvec3f>> GLM_ClipPoly(const std::vect
return result;
}
std::vector<qvec3f> GLM_ShrinkPoly(const std::vector<qvec3f> &poly, const float amount)
std::vector<qvec3f> ShrinkPoly(const std::vector<qvec3f> &poly, const float amount)
{
const vector<qvec4f> edgeplanes = GLM_MakeInwardFacingEdgePlanes(poly);
const vector<qvec4f> edgeplanes = MakeInwardFacingEdgePlanes(poly);
vector<qvec3f> clipped = poly;
for (const qvec4f &edge : edgeplanes) {
const qvec4f shrunkEdgePlane(edge[0], edge[1], edge[2], edge[3] + amount);
clipped = GLM_ClipPoly(clipped, shrunkEdgePlane).first;
clipped = ClipPoly(clipped, shrunkEdgePlane).first;
}
return clipped;

View File

@ -42,9 +42,9 @@ exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
html_theme = 'furo'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_static_path = ['_static']

2
docs/requirements.in Normal file
View File

@ -0,0 +1,2 @@
sphinx==6.2.1
furo==2023.3.27

View File

@ -1,2 +1,63 @@
sphinx==5.1.1
sphinx_rtd_theme==1.0.0
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
# pip-compile requirements.in
#
alabaster==0.7.13
# via sphinx
babel==2.12.1
# via sphinx
beautifulsoup4==4.12.2
# via furo
certifi==2022.12.7
# via requests
charset-normalizer==3.1.0
# via requests
colorama==0.4.6
# via sphinx
docutils==0.19
# via sphinx
furo==2023.3.27
# via -r requirements.in
idna==3.4
# via requests
imagesize==1.4.1
# via sphinx
jinja2==3.1.2
# via sphinx
markupsafe==2.1.2
# via jinja2
packaging==23.1
# via sphinx
pygments==2.15.1
# via
# furo
# sphinx
requests==2.30.0
# via sphinx
snowballstemmer==2.2.0
# via sphinx
soupsieve==2.4.1
# via beautifulsoup4
sphinx==6.2.1
# via
# -r requirements.in
# furo
# sphinx-basic-ng
sphinx-basic-ng==1.0.0b1
# via furo
sphinxcontrib-applehelp==1.0.4
# via sphinx
sphinxcontrib-devhelp==1.0.2
# via sphinx
sphinxcontrib-htmlhelp==2.0.1
# via sphinx
sphinxcontrib-jsmath==1.0.1
# via sphinx
sphinxcontrib-qthelp==1.0.3
# via sphinx
sphinxcontrib-serializinghtml==1.1.5
# via sphinx
urllib3==2.0.2
# via requests

View File

@ -176,7 +176,8 @@ struct surfflags_t
// light doesn't bounce off this face
bool no_bounce;
// opt out of minlight on this face
// opt out of minlight on this face (including opting out of local minlight, so
// not the same as just setting minlight to 0).
bool no_minlight;
// don't expand this face for larger clip hulls
@ -213,8 +214,8 @@ struct surfflags_t
// _phong_group key, equivalent q2 map format's use of the "value" field
int phong_group;
// minlight value for this face
vec_t minlight;
// minlight value for this face. empty = inherit from worldspawn.
std::optional<vec_t> minlight;
// red minlight colors for this face
qvec3b minlight_color;

View File

@ -102,7 +102,7 @@ std::vector<const mface_t *> Leaf_Markfaces(const mbsp_t *bsp, const mleaf_t *le
std::vector<const dbrush_t *> Leaf_Brushes(const mbsp_t *bsp, const mleaf_t *leaf);
const qvec3f &Vertex_GetPos(const mbsp_t *bsp, int num);
qvec3d Face_Normal(const mbsp_t *bsp, const mface_t *f);
std::vector<qvec3f> GLM_FacePoints(const mbsp_t *bsp, const mface_t *face);
std::vector<qvec3f> Face_Points(const mbsp_t *bsp, const mface_t *face);
polylib::winding_t Face_Winding(const mbsp_t *bsp, const mface_t *face);
qvec3f Face_Centroid(const mbsp_t *bsp, const mface_t *face);
void Face_DebugPrint(const mbsp_t *bsp, const mface_t *face);

View File

@ -110,14 +110,8 @@ constexpr struct
const char *suffix;
ext id;
decltype(load_wal) *loader;
} extension_list[] = {
{".png", ext::STB, load_stb},
{".jpg", ext::STB, load_stb},
{".tga", ext::TGA, load_tga},
{".wal", ext::WAL, load_wal},
{".mip", ext::MIP, load_mip},
{"", ext::MIP, load_mip}
};
} extension_list[] = {{".png", ext::STB, load_stb}, {".jpg", ext::STB, load_stb}, {".tga", ext::TGA, load_tga},
{".wal", ext::WAL, load_wal}, {".mip", ext::MIP, load_mip}, {"", ext::MIP, load_mip}};
// Attempt to load a texture from the specified name.
std::tuple<std::optional<texture>, fs::resolve_result, fs::data> load_texture(
@ -142,9 +136,7 @@ constexpr struct
meta_ext id;
decltype(load_wal_meta) *loader;
} meta_extension_list[] = {
{".wal_json", meta_ext::WAL_JSON, load_wal_json_meta},
{".wal", meta_ext::WAL, load_wal_meta}
};
{".wal_json", meta_ext::WAL_JSON, load_wal_json_meta}, {".wal", meta_ext::WAL, load_wal_meta}};
// Attempt to load a texture meta from the specified name.
std::tuple<std::optional<texture_meta>, fs::resolve_result, fs::data> load_texture_meta(

View File

@ -1047,25 +1047,25 @@ qmat3x3d RotateAboutZ(double radians);
qmat3x3f RotateFromUpToSurfaceNormal(const qvec3f &surfaceNormal);
// Returns (0 0 0) if we couldn't determine the normal
qvec3f GLM_FaceNormal(std::vector<qvec3f> points);
std::pair<bool, qvec4f> GLM_MakeInwardFacingEdgePlane(const qvec3f &v0, const qvec3f &v1, const qvec3f &faceNormal);
std::vector<qvec4f> GLM_MakeInwardFacingEdgePlanes(const std::vector<qvec3f> &points);
bool GLM_EdgePlanes_PointInside(const std::vector<qvec4f> &edgeplanes, const qvec3f &point);
float GLM_EdgePlanes_PointInsideDist(const std::vector<qvec4f> &edgeplanes, const qvec3f &point);
qvec4f GLM_MakePlane(const qvec3f &normal, const qvec3f &point);
float GLM_DistAbovePlane(const qvec4f &plane, const qvec3f &point);
qvec3f GLM_ProjectPointOntoPlane(const qvec4f &plane, const qvec3f &point);
qvec4f GLM_PolyPlane(const std::vector<qvec3f> &points);
qvec3f FaceNormal(std::vector<qvec3f> points);
std::pair<bool, qvec4f> MakeInwardFacingEdgePlane(const qvec3f &v0, const qvec3f &v1, const qvec3f &faceNormal);
std::vector<qvec4f> MakeInwardFacingEdgePlanes(const std::vector<qvec3f> &points);
bool EdgePlanes_PointInside(const std::vector<qvec4f> &edgeplanes, const qvec3f &point);
float EdgePlanes_PointInsideDist(const std::vector<qvec4f> &edgeplanes, const qvec3f &point);
qvec4f MakePlane(const qvec3f &normal, const qvec3f &point);
float DistAbovePlane(const qvec4f &plane, const qvec3f &point);
qvec3f ProjectPointOntoPlane(const qvec4f &plane, const qvec3f &point);
qvec4f PolyPlane(const std::vector<qvec3f> &points);
/// Returns the index of the polygon edge, and the closest point on that edge, to the given point
std::pair<int, qvec3f> GLM_ClosestPointOnPolyBoundary(const std::vector<qvec3f> &poly, const qvec3f &point);
std::pair<int, qvec3f> ClosestPointOnPolyBoundary(const std::vector<qvec3f> &poly, const qvec3f &point);
/// Returns `true` and the interpolated normal if `point` is in the polygon, otherwise returns false.
std::pair<bool, qvec3f> GLM_InterpolateNormal(
std::pair<bool, qvec3f> InterpolateNormal(
const std::vector<qvec3f> &points, const std::vector<face_normal_t> &normals, const qvec3f &point);
std::pair<bool, qvec3f> GLM_InterpolateNormal(
std::pair<bool, qvec3f> InterpolateNormal(
const std::vector<qvec3f> &points, const std::vector<qvec3f> &normals, const qvec3f &point);
std::vector<qvec3f> GLM_ShrinkPoly(const std::vector<qvec3f> &poly, const float amount);
std::vector<qvec3f> ShrinkPoly(const std::vector<qvec3f> &poly, const float amount);
/// Returns (front part, back part)
std::pair<std::vector<qvec3f>, std::vector<qvec3f>> GLM_ClipPoly(const std::vector<qvec3f> &poly, const qvec4f &plane);
std::pair<std::vector<qvec3f>, std::vector<qvec3f>> ClipPoly(const std::vector<qvec3f> &poly, const qvec4f &plane);
class poly_random_point_state_t
{
@ -1075,8 +1075,8 @@ public:
std::vector<float> triareas_cdf;
};
poly_random_point_state_t GLM_PolyRandomPoint_Setup(const std::vector<qvec3f> &points);
qvec3f GLM_PolyRandomPoint(const poly_random_point_state_t &state, float r1, float r2, float r3);
poly_random_point_state_t PolyRandomPoint_Setup(const std::vector<qvec3f> &points);
qvec3f PolyRandomPoint(const poly_random_point_state_t &state, float r1, float r2, float r3);
/// projects p onto the vw line.
/// returns 0 for p==v, 1 for p==w

View File

@ -291,8 +291,8 @@ struct texture_def_issues_t : logging::stat_tracker_t
false, true);
stat &num_repaired = register_stat(
"faces have invalid texture projections and were repaired. Use -verbose to display affected faces."
, false, true);
"faces have invalid texture projections and were repaired. Use -verbose to display affected faces.", false,
true);
};
bool ParseEntity(parser_t &parser, mapentity_t &entity, texture_def_issues_t &issues_stats);

View File

@ -209,6 +209,7 @@ public:
setting_bool forceprt1;
setting_tjunc tjunc;
setting_bool objexport;
setting_bool noextendedsurfflags;
setting_bool wrbrushes;
setting_redirect wrbrushesonly;
setting_bool bmodelcontents;

View File

@ -463,7 +463,7 @@ void LightGrid(bspdata_t *bspdata)
logging::print(" {} grid_mins\n", data.grid_mins);
logging::print(" {} grid_maxs\n", grid_maxs);
logging::print(" {} num_styles\n", data.num_styles);
// octree lump
if (light_options.lightgrid_format.value() == lightgrid_format_t::OCTREE) {
bspdata->bspx.transfer("LIGHTGRID_OCTREE", MakeOctreeLump(bsp, data));

View File

@ -133,10 +133,10 @@ position_t CalcPointNormal(const mbsp_t *bsp, const mface_t *face, const qvec3f
return position_t(origPoint);
// project `point` onto the surface plane, then lift it off again
const qvec3f point = GLM_ProjectPointOntoPlane(surfplane, origPoint) + (qvec3f(surfplane) * sampleOffPlaneDist);
const qvec3f point = ProjectPointOntoPlane(surfplane, origPoint) + (qvec3f(surfplane) * sampleOffPlaneDist);
// check if in face..
if (GLM_EdgePlanes_PointInside(edgeplanes, point)) {
if (EdgePlanes_PointInside(edgeplanes, point)) {
return PositionSamplePointOnFace(bsp, face, phongShaded, point, modelOffset);
}
@ -161,21 +161,21 @@ position_t CalcPointNormal(const mbsp_t *bsp, const mface_t *face, const qvec3f
const qvec3f in1_normal = qv::cross(qv::normalize(n.p0 - centroid), facecache.normal());
const qvec3f in2_normal = qv::cross(facecache.normal(), qv::normalize(n.p1 - centroid));
const qvec4f in1 = GLM_MakePlane(in1_normal, n.p0);
const qvec4f in2 = GLM_MakePlane(in2_normal, n.p1);
const qvec4f in1 = MakePlane(in1_normal, n.p0);
const qvec4f in2 = MakePlane(in2_normal, n.p1);
const float in1_dist = GLM_DistAbovePlane(in1, point);
const float in2_dist = GLM_DistAbovePlane(in2, point);
const float in1_dist = DistAbovePlane(in1, point);
const float in2_dist = DistAbovePlane(in2, point);
if (in1_dist >= 0 && in2_dist >= 0) {
const auto &n_facecache = FaceCacheForFNum(Face_GetNum(bsp, n.face));
const qvec4f &n_surfplane = n_facecache.plane();
const auto &n_edgeplanes = n_facecache.edgePlanes();
// project `point` onto the surface plane, then lift it off again
const qvec3f n_point = GLM_ProjectPointOntoPlane(n_surfplane, origPoint) + (qvec3f(n_surfplane) * sampleOffPlaneDist);
const qvec3f n_point = ProjectPointOntoPlane(n_surfplane, origPoint) + (qvec3f(n_surfplane) * sampleOffPlaneDist);
// check if in face..
if (GLM_EdgePlanes_PointInside(n_edgeplanes, n_point)) {
if (EdgePlanes_PointInside(n_edgeplanes, n_point)) {
return PositionSamplePointOnFace(bsp, n.face, phongShaded, n_point, modelOffset);
}
}
@ -192,11 +192,11 @@ position_t CalcPointNormal(const mbsp_t *bsp, const mface_t *face, const qvec3f
const qvec3f &v0 = points.at(i);
const qvec3f &v1 = points.at((i + 1) % points.size());
const auto edgeplane = GLM_MakeInwardFacingEdgePlane(v0, v1, surfplane);
const auto edgeplane = MakeInwardFacingEdgePlane(v0, v1, surfplane);
if (!edgeplane.first)
continue; // degenerate edge
const float planedist = GLM_DistAbovePlane(edgeplane.second, point);
const float planedist = DistAbovePlane(edgeplane.second, point);
if (planedist < POINT_EQUAL_EPSILON) {
// behind this plane. check whether we're between the endpoints.
@ -236,7 +236,7 @@ position_t CalcPointNormal(const mbsp_t *bsp, const mface_t *face, const qvec3f
// 2. Try snapping to poly
const pair<int, qvec3f> closest = GLM_ClosestPointOnPolyBoundary(points, point);
const pair<int, qvec3f> closest = ClosestPointOnPolyBoundary(points, point);
float luxelSpaceDist;
{
auto desired_point_in_lmspace = faceextents.worldToLMCoord(point);
@ -332,13 +332,13 @@ static position_t PositionSamplePointOnFace(
return position_t(point);
}
const float planedist = GLM_DistAbovePlane(plane, point);
const float planedist = DistAbovePlane(plane, point);
if (!(fabs(planedist - sampleOffPlaneDist) <= 0.1)) {
// something is wrong?
return position_t(point);
}
const float insideDist = GLM_EdgePlanes_PointInsideDist(edgeplanes, point);
const float insideDist = EdgePlanes_PointInsideDist(edgeplanes, point);
if (insideDist < -POINT_EQUAL_EPSILON) {
// Non-convex polygon
return position_t(point);
@ -353,7 +353,7 @@ static position_t PositionSamplePointOnFace(
// Get the point normal
qvec3f pointNormal;
if (phongShaded) {
const auto interpNormal = GLM_InterpolateNormal(points, normals, point);
const auto interpNormal = InterpolateNormal(points, normals, point);
// We already know the point is in the face, so this should always succeed
if (!interpNormal.first)
return position_t(point);
@ -383,12 +383,12 @@ static position_t PositionSamplePointOnFace(
// this has issues with narrow sliver-shaped faces moving the sample points a lot into vastly different lighting
// Check distance to border
const float distanceInside = GLM_EdgePlanes_PointInsideDist(edgeplanes, point);
const float distanceInside = EdgePlanes_PointInsideDist(edgeplanes, point);
if (distanceInside < 1.0f) {
// Point is too close to the border. Try nudging it inside.
const auto &shrunk = facecache.pointsShrunkBy1Unit();
if (!shrunk.empty()) {
const pair<int, qvec3f> closest = GLM_ClosestPointOnPolyBoundary(shrunk, point);
const pair<int, qvec3f> closest = ClosestPointOnPolyBoundary(shrunk, point);
const qvec3f newPoint = closest.second + (qvec3f(plane) * sampleOffPlaneDist);
if (!Light_PointInAnySolid(bsp, mi->model, newPoint + modelOffset))
return position_t(face, newPoint, pointNormal);
@ -427,8 +427,8 @@ static void CalcPoints(
surf->occluded.resize(num_points);
surf->realfacenums.resize(num_points);
const auto points = GLM_FacePoints(bsp, face);
const auto edgeplanes = GLM_MakeInwardFacingEdgePlanes(points);
const auto points = Face_Points(bsp, face);
const auto edgeplanes = MakeInwardFacingEdgePlanes(points);
for (int t = 0; t < surf->height; t++) {
for (int s = 0; s < surf->width; s++) {
@ -615,8 +615,10 @@ static std::unique_ptr<lightsurf_t> Lightsurf_Init(const modelinfo_t *modelinfo,
// minlight
if (modelinfo->minlight.is_changed()) {
lightsurf->minlight = modelinfo->minlight.value();
} else if (extended_flags.minlight) {
lightsurf->minlight = *extended_flags.minlight;
} else {
lightsurf->minlight = extended_flags.minlight;
lightsurf->minlight = light_options.minlight.value();
}
// minlightMottle
@ -660,13 +662,10 @@ static std::unique_ptr<lightsurf_t> Lightsurf_Init(const modelinfo_t *modelinfo,
// minlight_color
if (modelinfo->minlight_color.is_changed()) {
lightsurf->minlight_color = modelinfo->minlight_color.value();
} else if (!qv::emptyExact(extended_flags.minlight_color)) {
lightsurf->minlight_color = extended_flags.minlight_color;
} else {
// if modelinfo mincolor not set, use the one from the .texinfo file
if (lightsurf->minlight > 0 && qv::emptyExact(extended_flags.minlight_color)) {
lightsurf->minlight_color = {255.0};
} else {
lightsurf->minlight_color = extended_flags.minlight_color;
}
lightsurf->minlight_color = light_options.minlight_color.value();
}
/* never receive dirtmapping on lit liquids */

View File

@ -41,11 +41,11 @@ using namespace std;
face_cache_t::face_cache_t(){};
face_cache_t::face_cache_t(const mbsp_t *bsp, const mface_t *face, const std::vector<face_normal_t> &normals)
: m_points(GLM_FacePoints(bsp, face)),
: m_points(Face_Points(bsp, face)),
m_normals(normals),
m_plane(Face_Plane(bsp, face).vec4()),
m_edgePlanes(GLM_MakeInwardFacingEdgePlanes(m_points)),
m_pointsShrunkBy1Unit(GLM_ShrinkPoly(m_points, 1.0f)),
m_edgePlanes(MakeInwardFacingEdgePlanes(m_points)),
m_pointsShrunkBy1Unit(ShrinkPoly(m_points, 1.0f)),
m_neighbours(NeighbouringFaces_new(bsp, face))
{
}
@ -464,7 +464,7 @@ void CalculateVertexNormals(const mbsp_t *bsp)
// Q1 phong angle stuff
auto *f_texinfo = Face_Texinfo(bsp, &f);
const auto f_points = GLM_FacePoints(bsp, &f);
const auto f_points = Face_Points(bsp, &f);
const qvec3d f_norm = Face_Normal(bsp, &f);
const qplane3d f_plane = Face_Plane(bsp, &f);
@ -520,7 +520,7 @@ void CalculateVertexNormals(const mbsp_t *bsp)
}
}
const auto f2_points = GLM_FacePoints(bsp, f2);
const auto f2_points = Face_Points(bsp, f2);
const qvec3f f2_centroid = qv::PolyCentroid(f2_points.begin(), f2_points.end());
const qvec3d f2_norm = Face_Normal(bsp, f2);
@ -580,7 +580,7 @@ void CalculateVertexNormals(const mbsp_t *bsp)
// walk fPlusNeighbours
for (auto f2 : fPlusNeighbours) {
const auto f2_poly = GLM_FacePoints(bsp, f2);
const auto f2_poly = Face_Points(bsp, f2);
const float f2_area = qv::PolyArea(f2_poly.begin(), f2_poly.end());
const qvec3f f2_norm = Face_Normal(bsp, f2);

View File

@ -65,7 +65,7 @@ static void MakeSurfaceLight(const mbsp_t *bsp, const settings::worldspawn_keys
std::optional<qvec3f> texture_color, bool is_directional, bool is_sky, int32_t style, int32_t light_value)
{
// Create face points...
auto poly = GLM_FacePoints(bsp, face);
auto poly = Face_Points(bsp, face);
const float facearea = qv::PolyArea(poly.begin(), poly.end());
const surfflags_t &extended_flags = extended_texinfo_flags[face->texinfo];
@ -107,7 +107,7 @@ static void MakeSurfaceLight(const mbsp_t *bsp, const settings::worldspawn_keys
} else {
// Handle arghrad sky light settings http://www.bspquakeeditor.com/arghrad/sunlight.html#sky
if (!texture_color.has_value()) {
if (cfg.sky_surface.is_changed() && is_sky) {
if (cfg.sky_surface.is_changed() && is_sky) {
// FIXME: this only handles the "_sky_surface" "red green blue" format.
// There are other more complex variants we could handle documented in the link above.
// FIXME: we require value to be nonzero, see the check above - not sure if this matches arghrad

View File

@ -715,18 +715,18 @@ static void Brush_LoadEntity(mapentity_t &dst, mapentity_t &src, hull_index_t hu
if (map.is_world_entity(src) || IsWorldBrushEntity(src) || IsNonRemoveWorldBrushEntity(src)) {
if (map.region) {
if (map.region->bounds.disjoint(mapbrush.bounds)) {
//stats.regioned_brushes++;
//it = entity.mapbrushes.erase(it);
//logging::print("removed broosh\n");
// stats.regioned_brushes++;
// it = entity.mapbrushes.erase(it);
// logging::print("removed broosh\n");
continue;
}
}
for (auto &region : map.antiregions) {
if (!region.bounds.disjoint(mapbrush.bounds)) {
//stats.regioned_brushes++;
//it = entity.mapbrushes.erase(it);
//logging::print("removed broosh\n");
// stats.regioned_brushes++;
// it = entity.mapbrushes.erase(it);
// logging::print("removed broosh\n");
continue;
}
}

View File

@ -669,9 +669,10 @@ static surfflags_t SurfFlagsForEntity(
// FIXME: get_color, to match settings
if (entity.epairs.has("_surflight_color") && entity.epairs.get_vector("_surflight_color", color) == 3) {
if (color[0] <= 1 && color[1] <= 1 && color[2] <= 1) {
flags.surflight_color = qvec3b{ (uint8_t) (color[0] * 255), (uint8_t) (color[1] * 255), (uint8_t) (color[2] * 255) };
flags.surflight_color =
qvec3b{(uint8_t)(color[0] * 255), (uint8_t)(color[1] * 255), (uint8_t)(color[2] * 255)};
} else {
flags.surflight_color = qvec3b{ (uint8_t) (color[0]), (uint8_t) (color[1]), (uint8_t) (color[2]) };
flags.surflight_color = qvec3b{(uint8_t)(color[0]), (uint8_t)(color[1]), (uint8_t)(color[2])};
}
}
}
@ -683,7 +684,8 @@ static surfflags_t SurfFlagsForEntity(
if (entity.epairs.has("_surflight_minlight_scale"))
flags.surflight_minlight_scale = entity.epairs.get_float("_surflight_minlight_scale");
// Paril: inherit _surflight_minlight_scale from worldspawn if unset
else if (!entity.epairs.has("_surflight_minlight_scale") && map.world_entity().epairs.has("_surflight_minlight_scale"))
else if (!entity.epairs.has("_surflight_minlight_scale") &&
map.world_entity().epairs.has("_surflight_minlight_scale"))
flags.surflight_minlight_scale = map.world_entity().epairs.get_float("_surflight_minlight_scale");
// "_minlight_exclude", "_minlight_exclude2", "_minlight_exclude3"...
@ -742,11 +744,10 @@ static surfflags_t SurfFlagsForEntity(
flags.phong_group = entity.epairs.get_int("_phong_group");
// handle "_minlight"
const vec_t minlight = entity.epairs.get_float("_minlight");
if (minlight > 0) {
// CHECK: allow > 510 now that we're float? or is it not worth it since it will
// be beyond max?
flags.minlight = clamp(minlight, 0.0, 510.0);
if (entity.epairs.has("_minlight")) {
const vec_t minlight = entity.epairs.get_float("_minlight");
// handle -1 as an alias for 0 (same with other negative values).
flags.minlight = max(0., minlight);
}
// handle "_maxlight"
@ -2564,7 +2565,7 @@ static mapbrush_t ParseBrush(parser_t &parser, mapentity_t &entity, texture_def_
new_brush.contents = brush.contents;
new_brush.line = brush.line;
for (auto &side : brush.faces) {
// if it's the side we're extruding, increase its dist
@ -2575,10 +2576,11 @@ static mapbrush_t ParseBrush(parser_t &parser, mapentity_t &entity, texture_def_
new_side.raw_info = side.raw_info;
new_side.texname = side.texname;
new_side.planenum = side.planenum;
new_side.planenum = map.add_or_find_plane({ new_side.get_plane().get_normal(), new_side.get_plane().get_dist() + 16.f });
new_side.planenum = map.add_or_find_plane(
{new_side.get_plane().get_normal(), new_side.get_plane().get_dist() + 16.f});
new_brush.faces.emplace_back(std::move(new_side));
// the inverted side is special
// the inverted side is special
} else if (side.get_plane().get_normal() == -new_brush_side.get_plane().get_normal()) {
// add the other side
@ -2587,7 +2589,8 @@ static mapbrush_t ParseBrush(parser_t &parser, mapentity_t &entity, texture_def_
flipped_side.contents = side.contents;
flipped_side.raw_info = side.raw_info;
flipped_side.texname = side.texname;
flipped_side.planenum = map.add_or_find_plane({ -new_brush_side.get_plane().get_normal(), -new_brush_side.get_plane().get_dist() });
flipped_side.planenum = map.add_or_find_plane(
{-new_brush_side.get_plane().get_normal(), -new_brush_side.get_plane().get_dist()});
new_brush.faces.emplace_back(std::move(flipped_side));
} else {
@ -3245,7 +3248,7 @@ void ProcessMapBrushes()
// remove ents in region
if (map.region || map.antiregions.size()) {
for (auto it = map.entities.begin(); it != map.entities.end(); ) {
for (auto it = map.entities.begin(); it != map.entities.end();) {
auto &entity = *it;
bool removed = false;

View File

@ -532,6 +532,7 @@ qbsp_settings::qbsp_settings()
&debugging_group, "T-junction fix level"},
objexport{
this, "objexport", false, &debugging_group, "export the map file as .OBJ models during various CSG phases"},
noextendedsurfflags{this, "noextendedsurfflags", false, &debugging_group, "suppress writing a .texinfo file"},
wrbrushes{this, {"wrbrushes", "bspx"}, false, &common_format_group,
"includes a list of brushes for brush-based collision"},
wrbrushesonly{this, {"wrbrushesonly", "bspxonly"}, {&wrbrushes, &noclip}, &common_format_group,

View File

@ -338,7 +338,7 @@ static void WriteExtendedTexinfoFlags(void)
}
}
if (!needwrite)
if (!needwrite || qbsp_options.noextendedsurfflags.value())
return;
// sort by output texinfo number
@ -406,7 +406,7 @@ static void WriteExtendedTexinfoFlags(void)
t["phong_group"] = tx.flags.phong_group;
}
if (tx.flags.minlight) {
t["minlight"] = tx.flags.minlight;
t["minlight"] = *tx.flags.minlight;
}
if (tx.flags.maxlight) {
t["maxlight"] = tx.flags.maxlight;

View File

@ -145,6 +145,7 @@
{
"classname" "func_wall"
"_object_channel_mask" "2"
"_minlight" "0"
// brush 0
{
( 656 1280 944 ) ( 656 1281 944 ) ( 656 1280 945 ) e1u1/twall2_1 -32 0 0 1 1
@ -177,6 +178,7 @@
{
"classname" "func_wall"
"_object_channel_mask" "4"
"_minlight" "0"
// brush 0
{
( 880 1248 944 ) ( 880 1249 944 ) ( 880 1248 945 ) e1u1/twall2_1 0 0 0 1 1
@ -208,6 +210,7 @@
"classname" "func_wall"
"_object_channel_mask" "8"
"_shadow" "1"
"_minlight" "0"
// brush 0
{
( 1264 1248 944 ) ( 1264 1249 944 ) ( 1264 1248 945 ) e1u1/twall2_1 0 0 0 1 1
@ -230,6 +233,7 @@
{
"classname" "func_group"
"_object_channel_mask" "8"
"_minlight" "0"
// brush 0
{
( 1456 1248 944 ) ( 1456 1249 944 ) ( 1456 1248 945 ) e1u1/twall2_1 0 0 0 1 1

View File

@ -0,0 +1,153 @@
// Game: Quake 2
// Format: Quake2
// entity 0
{
"classname" "worldspawn"
"_tb_textures" "textures/e1u1"
"_bounce" "0"
"_minlight" "0.5"
"_minlight_mottle" "0"
"_minlight_color" "1 0 0"
// brush 0
{
( -480 -176 -16 ) ( -480 -175 -16 ) ( -480 -176 -15 ) e1u1/twall2_1 -16 112 0 1 1
( -256 -640 -16 ) ( -256 -640 -15 ) ( -255 -640 -16 ) e1u1/twall2_1 64 112 0 1 1
( -256 -176 -16 ) ( -255 -176 -16 ) ( -256 -175 -16 ) e1u1/twall2_1 64 16 0 1 1
( -16 208 0 ) ( -16 209 0 ) ( -15 208 0 ) e1u1/twall2_1 64 16 0 1 1
( -16 224 0 ) ( -15 224 0 ) ( -16 224 1 ) e1u1/twall2_1 64 112 0 1 1
( 480 208 0 ) ( 480 208 1 ) ( 480 209 0 ) e1u1/twall2_1 -16 112 0 1 1
}
// brush 1
{
( -480 -176 304 ) ( -480 -175 304 ) ( -480 -176 305 ) e1u1/twall2_1 64 16 0 1 1
( -256 -640 304 ) ( -256 -640 305 ) ( -255 -640 304 ) e1u1/twall2_1 64 16 0 1 1
( -256 -176 304 ) ( -255 -176 304 ) ( -256 -175 304 ) e1u1/twall2_1 64 16 0 1 1
( -16 208 320 ) ( -16 209 320 ) ( -15 208 320 ) e1u1/twall2_1 64 16 0 1 1
( -16 224 320 ) ( -15 224 320 ) ( -16 224 321 ) e1u1/twall2_1 64 16 0 1 1
( 480 208 320 ) ( 480 208 321 ) ( 480 209 320 ) e1u1/twall2_1 64 16 0 1 1
}
// brush 2
{
( -480 -656 -16 ) ( -480 -655 -16 ) ( -480 -656 -15 ) e1u1/twall2_1 16 16 0 1 1
( -256 -656 -16 ) ( -256 -656 -15 ) ( -255 -656 -16 ) e1u1/twall2_1 64 16 0 1 1
( -256 -656 -16 ) ( -255 -656 -16 ) ( -256 -655 -16 ) e1u1/twall2_1 64 -64 0 1 1
( -16 -272 304 ) ( -16 -271 304 ) ( -15 -272 304 ) e1u1/twall2_1 64 -64 0 1 1
( -16 -640 0 ) ( -15 -640 0 ) ( -16 -640 1 ) e1u1/twall2_1 64 16 0 1 1
( 496 -272 0 ) ( 496 -272 1 ) ( 496 -271 0 ) e1u1/twall2_1 16 16 0 1 1
}
// brush 3
{
( -480 128 -16 ) ( -480 129 -16 ) ( -480 128 -15 ) e1u1/twall2_1 64 16 0 1 1
( -128 224 -16 ) ( -128 224 -15 ) ( -127 224 -16 ) e1u1/twall2_1 64 16 0 1 1
( -128 128 -16 ) ( -127 128 -16 ) ( -128 129 -16 ) e1u1/twall2_1 64 16 0 1 1
( 112 512 304 ) ( 112 513 304 ) ( 113 512 304 ) e1u1/twall2_1 64 16 0 1 1
( 112 240 0 ) ( 113 240 0 ) ( 112 240 1 ) e1u1/twall2_1 64 16 0 1 1
( 480 128 -16 ) ( 480 128 -15 ) ( 480 129 -16 ) e1u1/twall2_1 64 16 0 1 1
}
// brush 4
{
( 480 -176 112 ) ( 480 -175 112 ) ( 480 -176 113 ) e1u1/twall2_1 64 16 0 1 1
( 160 -640 112 ) ( 160 -640 113 ) ( 161 -640 112 ) e1u1/twall2_1 64 16 0 1 1
( 160 -176 -16 ) ( 161 -176 -16 ) ( 160 -175 -16 ) e1u1/twall2_1 64 16 0 1 1
( 400 208 304 ) ( 400 209 304 ) ( 401 208 304 ) e1u1/twall2_1 64 16 0 1 1
( 400 224 128 ) ( 401 224 128 ) ( 400 224 129 ) e1u1/twall2_1 64 16 0 1 1
( 496 208 128 ) ( 496 208 129 ) ( 496 209 128 ) e1u1/twall2_1 64 16 0 1 1
}
// brush 5
{
( -496 -176 112 ) ( -496 -175 112 ) ( -496 -176 113 ) e1u1/twall2_1 64 16 0 1 1
( -816 -640 112 ) ( -816 -640 113 ) ( -815 -640 112 ) e1u1/twall2_1 64 16 0 1 1
( -816 -176 -16 ) ( -815 -176 -16 ) ( -816 -175 -16 ) e1u1/twall2_1 64 16 0 1 1
( -576 208 304 ) ( -576 209 304 ) ( -575 208 304 ) e1u1/twall2_1 64 16 0 1 1
( -576 224 128 ) ( -575 224 128 ) ( -576 224 129 ) e1u1/twall2_1 64 16 0 1 1
( -480 208 128 ) ( -480 208 129 ) ( -480 209 128 ) e1u1/twall2_1 64 16 0 1 1
}
}
// entity 1
{
"classname" "info_player_start"
"origin" "272 -104 72"
"angle" "90"
}
// entity 2
{
"classname" "func_group"
// brush 0
{
( 288 0 0 ) ( 288 1 0 ) ( 288 0 1 ) e1u1/twall2_1 -16 16 0 1 1
( 176 0 0 ) ( 176 0 1 ) ( 177 0 0 ) e1u1/twall2_1 0 16 0 1 1
( 176 0 0 ) ( 177 0 0 ) ( 176 1 0 ) e1u1/twall2_1 0 -32 0 1 1
( 416 144 16 ) ( 416 145 16 ) ( 417 144 16 ) e1u1/twall2_1 0 -32 0 1 1
( 416 144 16 ) ( 417 144 16 ) ( 416 144 17 ) e1u1/twall2_1 0 16 0 1 1
( 416 144 16 ) ( 416 144 17 ) ( 416 145 16 ) e1u1/twall2_1 -16 16 0 1 1
}
}
// entity 3
{
"classname" "func_wall"
// brush 0
{
( 144 0 0 ) ( 144 1 0 ) ( 144 0 1 ) e1u1/twall2_1 -16 16 0 1 1
( 32 0 0 ) ( 32 0 1 ) ( 33 0 0 ) e1u1/twall2_1 16 16 0 1 1
( 32 0 0 ) ( 33 0 0 ) ( 32 1 0 ) e1u1/twall2_1 16 -32 0 1 1
( 272 144 16 ) ( 272 145 16 ) ( 273 144 16 ) e1u1/twall2_1 16 -32 0 1 1
( 272 144 16 ) ( 273 144 16 ) ( 272 144 17 ) e1u1/twall2_1 16 16 0 1 1
( 272 144 16 ) ( 272 144 17 ) ( 272 145 16 ) e1u1/twall2_1 -16 16 0 1 1
}
}
// entity 4
{
"classname" "func_wall"
"_minlight" "1"
// brush 0
{
( 144 -160 0 ) ( 144 -159 0 ) ( 144 -160 1 ) e1u1/twall2_1 16 16 0 1 1
( 32 -160 0 ) ( 32 -160 1 ) ( 33 -160 0 ) e1u1/twall2_1 16 16 0 1 1
( 32 -160 0 ) ( 33 -160 0 ) ( 32 -159 0 ) e1u1/twall2_1 16 -64 0 1 1
( 272 -16 16 ) ( 272 -15 16 ) ( 273 -16 16 ) e1u1/twall2_1 16 -64 0 1 1
( 272 -16 16 ) ( 273 -16 16 ) ( 272 -16 17 ) e1u1/twall2_1 16 16 0 1 1
( 272 -16 16 ) ( 272 -16 17 ) ( 272 -15 16 ) e1u1/twall2_1 16 16 0 1 1
}
}
// entity 5
{
"classname" "func_group"
"_minlight" "1"
// brush 0
{
( 288 -160 0 ) ( 288 -159 0 ) ( 288 -160 1 ) e1u1/twall2_1 16 16 0 1 1
( 176 -160 0 ) ( 176 -160 1 ) ( 177 -160 0 ) e1u1/twall2_1 0 16 0 1 1
( 176 -160 0 ) ( 177 -160 0 ) ( 176 -159 0 ) e1u1/twall2_1 0 -64 0 1 1
( 416 -16 16 ) ( 416 -15 16 ) ( 417 -16 16 ) e1u1/twall2_1 0 -64 0 1 1
( 416 -16 16 ) ( 417 -16 16 ) ( 416 -16 17 ) e1u1/twall2_1 0 16 0 1 1
( 416 -16 16 ) ( 416 -16 17 ) ( 416 -15 16 ) e1u1/twall2_1 16 16 0 1 1
}
}
// entity 6
{
"classname" "func_group"
"_minlight_color" "0 1 0"
// brush 0
{
( 288 -320 0 ) ( 288 -319 0 ) ( 288 -320 1 ) e1u1/twall2_1 48 16 0 1 1
( 176 -320 0 ) ( 176 -320 1 ) ( 177 -320 0 ) e1u1/twall2_1 0 16 0 1 1
( 176 -320 0 ) ( 177 -320 0 ) ( 176 -319 0 ) e1u1/twall2_1 0 -96 0 1 1
( 416 -176 16 ) ( 416 -175 16 ) ( 417 -176 16 ) e1u1/twall2_1 0 -96 0 1 1
( 416 -176 16 ) ( 417 -176 16 ) ( 416 -176 17 ) e1u1/twall2_1 0 16 0 1 1
( 416 -176 16 ) ( 416 -176 17 ) ( 416 -175 16 ) e1u1/twall2_1 48 16 0 1 1
}
}
// entity 7
{
"classname" "func_wall"
"_minlight_color" "0 1 0"
// brush 0
{
( 144 -320 0 ) ( 144 -319 0 ) ( 144 -320 1 ) e1u1/twall2_1 48 16 0 1 1
( 32 -320 0 ) ( 32 -320 1 ) ( 33 -320 0 ) e1u1/twall2_1 16 16 0 1 1
( 32 -320 0 ) ( 33 -320 0 ) ( 32 -319 0 ) e1u1/twall2_1 16 -96 0 1 1
( 272 -176 16 ) ( 272 -175 16 ) ( 273 -176 16 ) e1u1/twall2_1 16 -96 0 1 1
( 272 -176 16 ) ( 273 -176 16 ) ( 272 -176 17 ) e1u1/twall2_1 16 16 0 1 1
( 272 -176 16 ) ( 272 -176 17 ) ( 272 -175 16 ) e1u1/twall2_1 48 16 0 1 1
}
}

View File

@ -38,15 +38,15 @@ TEST_SUITE("mathlib")
static void checkBox(const vector<qvec4f> &edges, const vector<qvec3f> &poly)
{
CHECK(GLM_EdgePlanes_PointInside(edges, qvec3f(0, 0, 0)));
CHECK(GLM_EdgePlanes_PointInside(edges, qvec3f(64, 0, 0)));
CHECK(GLM_EdgePlanes_PointInside(edges, qvec3f(32, 32, 0)));
CHECK(GLM_EdgePlanes_PointInside(edges, qvec3f(32, 32, 32))); // off plane
CHECK(EdgePlanes_PointInside(edges, qvec3f(0, 0, 0)));
CHECK(EdgePlanes_PointInside(edges, qvec3f(64, 0, 0)));
CHECK(EdgePlanes_PointInside(edges, qvec3f(32, 32, 0)));
CHECK(EdgePlanes_PointInside(edges, qvec3f(32, 32, 32))); // off plane
CHECK_FALSE(GLM_EdgePlanes_PointInside(edges, qvec3f(-0.1, 0, 0)));
CHECK_FALSE(GLM_EdgePlanes_PointInside(edges, qvec3f(64.1, 0, 0)));
CHECK_FALSE(GLM_EdgePlanes_PointInside(edges, qvec3f(0, -0.1, 0)));
CHECK_FALSE(GLM_EdgePlanes_PointInside(edges, qvec3f(0, 64.1, 0)));
CHECK_FALSE(EdgePlanes_PointInside(edges, qvec3f(-0.1, 0, 0)));
CHECK_FALSE(EdgePlanes_PointInside(edges, qvec3f(64.1, 0, 0)));
CHECK_FALSE(EdgePlanes_PointInside(edges, qvec3f(0, -0.1, 0)));
CHECK_FALSE(EdgePlanes_PointInside(edges, qvec3f(0, 64.1, 0)));
}
TEST_CASE("EdgePlanesOfNonConvexPoly")
@ -54,7 +54,7 @@ TEST_SUITE("mathlib")
// hourglass, non-convex
const vector<qvec3f> poly{{0, 0, 0}, {64, 64, 0}, {0, 64, 0}, {64, 0, 0}};
const auto edges = GLM_MakeInwardFacingEdgePlanes(poly);
const auto edges = MakeInwardFacingEdgePlanes(poly);
// CHECK(vector<qvec4f>() == edges);
}
@ -65,9 +65,9 @@ TEST_SUITE("mathlib")
qvec3f(248, -1893.21741, 1810.43481), qvec3f(248, -1921.59998, 1812.80005), qvec3f(248, -1924, 1813),
qvec3f(80, -1924, 1631), qvec3f(80, -1744, 1616)};
const auto edges = GLM_MakeInwardFacingEdgePlanes(poly);
const auto edges = MakeInwardFacingEdgePlanes(poly);
REQUIRE_FALSE(edges.empty());
CHECK(GLM_EdgePlanes_PointInside(edges, qvec3f(152.636963, -1814, 1702)));
CHECK(EdgePlanes_PointInside(edges, qvec3f(152.636963, -1814, 1702)));
}
TEST_CASE("PointInPolygon")
@ -75,7 +75,7 @@ TEST_SUITE("mathlib")
// clockwise
const vector<qvec3f> poly{{0, 0, 0}, {0, 64, 0}, {64, 64, 0}, {64, 0, 0}};
const auto edges = GLM_MakeInwardFacingEdgePlanes(poly);
const auto edges = MakeInwardFacingEdgePlanes(poly);
checkBox(edges, poly);
}
@ -85,7 +85,7 @@ TEST_SUITE("mathlib")
const vector<qvec3f> poly{{0, 0, 0}, {0, 64, 0}, {0, 64, 0}, // repeat of last point
{64, 64, 0}, {64, 0, 0}};
const auto edges = GLM_MakeInwardFacingEdgePlanes(poly);
const auto edges = MakeInwardFacingEdgePlanes(poly);
checkBox(edges, poly);
}
@ -93,9 +93,9 @@ TEST_SUITE("mathlib")
{
const vector<qvec3f> poly{};
const auto edges = GLM_MakeInwardFacingEdgePlanes(poly);
CHECK_FALSE(GLM_EdgePlanes_PointInside(edges, qvec3f(0, 0, 0)));
CHECK_FALSE(GLM_EdgePlanes_PointInside(edges, qvec3f(10, 10, 10)));
const auto edges = MakeInwardFacingEdgePlanes(poly);
CHECK_FALSE(EdgePlanes_PointInside(edges, qvec3f(0, 0, 0)));
CHECK_FALSE(EdgePlanes_PointInside(edges, qvec3f(10, 10, 10)));
}
TEST_CASE("PointInPolygon_DegenerateFaceHandling2")
@ -106,10 +106,10 @@ TEST_SUITE("mathlib")
{0, 0, 0},
};
const auto edges = GLM_MakeInwardFacingEdgePlanes(poly);
CHECK_FALSE(GLM_EdgePlanes_PointInside(edges, qvec3f(0, 0, 0)));
CHECK_FALSE(GLM_EdgePlanes_PointInside(edges, qvec3f(10, 10, 10)));
CHECK_FALSE(GLM_EdgePlanes_PointInside(edges, qvec3f(-10, -10, -10)));
const auto edges = MakeInwardFacingEdgePlanes(poly);
CHECK_FALSE(EdgePlanes_PointInside(edges, qvec3f(0, 0, 0)));
CHECK_FALSE(EdgePlanes_PointInside(edges, qvec3f(10, 10, 10)));
CHECK_FALSE(EdgePlanes_PointInside(edges, qvec3f(-10, -10, -10)));
}
TEST_CASE("PointInPolygon_DegenerateFaceHandling3")
@ -120,10 +120,10 @@ TEST_SUITE("mathlib")
{20, 20, 20},
};
const auto edges = GLM_MakeInwardFacingEdgePlanes(poly);
CHECK_FALSE(GLM_EdgePlanes_PointInside(edges, qvec3f(0, 0, 0)));
CHECK_FALSE(GLM_EdgePlanes_PointInside(edges, qvec3f(10, 10, 10)));
CHECK_FALSE(GLM_EdgePlanes_PointInside(edges, qvec3f(-10, -10, -10)));
const auto edges = MakeInwardFacingEdgePlanes(poly);
CHECK_FALSE(EdgePlanes_PointInside(edges, qvec3f(0, 0, 0)));
CHECK_FALSE(EdgePlanes_PointInside(edges, qvec3f(10, 10, 10)));
CHECK_FALSE(EdgePlanes_PointInside(edges, qvec3f(-10, -10, -10)));
}
TEST_CASE("PointInPolygon_ColinearPointHandling")
@ -132,7 +132,7 @@ TEST_SUITE("mathlib")
const vector<qvec3f> poly{{0, 0, 0}, {0, 32, 0}, // colinear
{0, 64, 0}, {64, 64, 0}, {64, 0, 0}};
const auto edges = GLM_MakeInwardFacingEdgePlanes(poly);
const auto edges = MakeInwardFacingEdgePlanes(poly);
checkBox(edges, poly);
}
@ -152,13 +152,13 @@ TEST_SUITE("mathlib")
{64, 0, 0} // edge 3 start, edge 2 end
};
CHECK(make_pair(0, qvec3f(0, 0, 0)) == GLM_ClosestPointOnPolyBoundary(poly, qvec3f(0, 0, 0)));
CHECK(make_pair(0, qvec3f(0, 0, 0)) == ClosestPointOnPolyBoundary(poly, qvec3f(0, 0, 0)));
// Either edge 1 or 2 contain the point qvec3f(64,64,0), but we expect the first edge to be returned
CHECK(make_pair(1, qvec3f(64, 64, 0)) == GLM_ClosestPointOnPolyBoundary(poly, qvec3f(100, 100, 100)));
CHECK(make_pair(2, qvec3f(64, 32, 0)) == GLM_ClosestPointOnPolyBoundary(poly, qvec3f(100, 32, 0)));
CHECK(make_pair(1, qvec3f(64, 64, 0)) == ClosestPointOnPolyBoundary(poly, qvec3f(100, 100, 100)));
CHECK(make_pair(2, qvec3f(64, 32, 0)) == ClosestPointOnPolyBoundary(poly, qvec3f(100, 32, 0)));
CHECK(make_pair(0, qvec3f(0, 0, 0)) == GLM_ClosestPointOnPolyBoundary(poly, qvec3f(-1, -1, 0)));
CHECK(make_pair(0, qvec3f(0, 0, 0)) == ClosestPointOnPolyBoundary(poly, qvec3f(-1, -1, 0)));
}
TEST_CASE("PolygonCentroid_empty")
@ -240,8 +240,8 @@ TEST_SUITE("mathlib")
const std::array<qvec3f, 3> tri{qvec3f{0, 0, 0}, {0, 64, 0}, {64, 0, 0}};
const auto triAsVec = vector<qvec3f>{tri.begin(), tri.end()};
const auto edges = GLM_MakeInwardFacingEdgePlanes(triAsVec);
const auto plane = GLM_PolyPlane(triAsVec);
const auto edges = MakeInwardFacingEdgePlanes(triAsVec);
const auto plane = PolyPlane(triAsVec);
for (int i = 0; i < 100; i++) {
const float r0 = Random();
@ -256,9 +256,9 @@ TEST_SUITE("mathlib")
CHECK(doctest::Approx(1.0f) == bary[0] + bary[1] + bary[2]);
const qvec3f point = qv::Barycentric_ToPoint(bary, tri[0], tri[1], tri[2]);
CHECK(GLM_EdgePlanes_PointInside(edges, point));
CHECK(EdgePlanes_PointInside(edges, point));
CHECK(doctest::Approx(0.0f) == GLM_DistAbovePlane(plane, point));
CHECK(doctest::Approx(0.0f) == DistAbovePlane(plane, point));
}
}
@ -278,29 +278,29 @@ TEST_SUITE("mathlib")
TEST_CASE("MakePlane")
{
CHECK(qvec4f(0, 0, 1, 10) == GLM_MakePlane(qvec3f(0, 0, 1), qvec3f(0, 0, 10)));
CHECK(qvec4f(0, 0, 1, 10) == GLM_MakePlane(qvec3f(0, 0, 1), qvec3f(100, 100, 10)));
CHECK(qvec4f(0, 0, 1, 10) == MakePlane(qvec3f(0, 0, 1), qvec3f(0, 0, 10)));
CHECK(qvec4f(0, 0, 1, 10) == MakePlane(qvec3f(0, 0, 1), qvec3f(100, 100, 10)));
}
TEST_CASE("DistAbovePlane")
{
qvec4f plane(0, 0, 1, 10);
qvec3f point(100, 100, 100);
CHECK(doctest::Approx(90) == GLM_DistAbovePlane(plane, point));
CHECK(doctest::Approx(90) == DistAbovePlane(plane, point));
}
TEST_CASE("InterpolateNormalsDegenerate")
{
CHECK_FALSE(GLM_InterpolateNormal({}, std::vector<qvec3f>{}, qvec3f(0, 0, 0)).first);
CHECK_FALSE(GLM_InterpolateNormal({qvec3f(0, 0, 0)}, {qvec3f(0, 0, 1)}, qvec3f(0, 0, 0)).first);
CHECK_FALSE(GLM_InterpolateNormal(
{qvec3f(0, 0, 0), qvec3f(10, 0, 0)}, {qvec3f(0, 0, 1), qvec3f(0, 0, 1)}, qvec3f(0, 0, 0))
.first);
CHECK_FALSE(InterpolateNormal({}, std::vector<qvec3f>{}, qvec3f(0, 0, 0)).first);
CHECK_FALSE(InterpolateNormal({qvec3f(0, 0, 0)}, {qvec3f(0, 0, 1)}, qvec3f(0, 0, 0)).first);
CHECK_FALSE(
InterpolateNormal({qvec3f(0, 0, 0), qvec3f(10, 0, 0)}, {qvec3f(0, 0, 1), qvec3f(0, 0, 1)}, qvec3f(0, 0, 0))
.first);
}
TEST_CASE("InterpolateNormals")
{
// This test relies on the way GLM_InterpolateNormal is implemented
// This test relies on the way InterpolateNormal is implemented
// o--o--o
// | / / |
@ -315,20 +315,20 @@ TEST_SUITE("mathlib")
// First try all the known points
for (int i = 0; i < poly.size(); i++) {
const auto res = GLM_InterpolateNormal(poly, normals, poly.at(i));
const auto res = InterpolateNormal(poly, normals, poly.at(i));
CHECK(true == res.first);
CHECK(qv::epsilonEqual(normals.at(i), res.second, static_cast<float>(POINT_EQUAL_EPSILON)));
}
{
const qvec3f firstTriCentroid = (poly[0] + poly[1] + poly[2]) / 3.0f;
const auto res = GLM_InterpolateNormal(poly, normals, firstTriCentroid);
const auto res = InterpolateNormal(poly, normals, firstTriCentroid);
CHECK(true == res.first);
CHECK(qv::epsilonEqual(qvec3f(1 / 3.0f), res.second, static_cast<float>(POINT_EQUAL_EPSILON)));
}
// Outside poly
CHECK_FALSE(GLM_InterpolateNormal(poly, normals, qvec3f(-0.1, 0, 0)).first);
CHECK_FALSE(InterpolateNormal(poly, normals, qvec3f(-0.1, 0, 0)).first);
}
static bool polysEqual(const vector<qvec3f> &p1, const vector<qvec3f> &p2)
@ -350,7 +350,7 @@ TEST_SUITE("mathlib")
const vector<qvec3f> backRes{{32, 64, 0}, {64, 64, 0}, {64, 0, 0}, {32, 0, 0}};
auto clipRes = GLM_ClipPoly(poly, qvec4f(-1, 0, 0, -32));
auto clipRes = ClipPoly(poly, qvec4f(-1, 0, 0, -32));
CHECK(polysEqual(frontRes, clipRes.first));
CHECK(polysEqual(backRes, clipRes.second));
@ -362,7 +362,7 @@ TEST_SUITE("mathlib")
const vector<qvec3f> shrunkPoly{{1, 1, 0}, {1, 63, 0}, {63, 63, 0}, {63, 1, 0}};
const auto actualShrunk = GLM_ShrinkPoly(poly, 1.0f);
const auto actualShrunk = ShrinkPoly(poly, 1.0f);
CHECK(polysEqual(shrunkPoly, actualShrunk));
}
@ -377,7 +377,7 @@ TEST_SUITE("mathlib")
{63, 1, 0},
};
const auto actualShrunk = GLM_ShrinkPoly(poly, 1.0f);
const auto actualShrunk = ShrinkPoly(poly, 1.0f);
CHECK(polysEqual(shrunkPoly, actualShrunk));
}
@ -542,18 +542,18 @@ TEST_CASE("RandomPointInPoly") {
{ 64,0,0 }
};
const auto edgeplanes = GLM_MakeInwardFacingEdgePlanes(poly);
const auto edgeplanes = MakeInwardFacingEdgePlanes(poly);
qvec3f min(FLT_MAX);
qvec3f max(-FLT_MAX);
qvec3f avg{};
const auto randomstate = GLM_PolyRandomPoint_Setup(poly);
const auto randomstate = PolyRandomPoint_Setup(poly);
const int N=100;
for (int i=0; i<N; i++) {
const qvec3f point = GLM_PolyRandomPoint(randomstate, Random(), Random(), Random());
REQUIRE(GLM_EdgePlanes_PointInside(edgeplanes, point));
const qvec3f point = PolyRandomPoint(randomstate, Random(), Random(), Random());
REQUIRE(EdgePlanes_PointInside(edgeplanes, point));
//std::cout << "point: " << qv::to_string(point) << std::endl;

View File

@ -681,4 +681,62 @@ TEST_CASE("q2_light_low_luxel_res2" * doctest::may_fail())
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {49, 49, 49}, {2964, 1046, -694}, {-1, 0, 0}, nullptr, &bspx);
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {25, 25, 25}, {2964, 1046, -706}, {-1, 0, 0}, nullptr, &bspx);
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {1, 1, 1}, {2964, 1046, -716}, {-1, 0, 0}, nullptr, &bspx);
}
TEST_CASE("q2_minlight_inherited")
{
auto [bsp, bspx] = QbspVisLight_Q2("q2_minlight_inherited.map", {});
{
INFO("check worldspawn minlight");
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {64, 0, 0}, {456, 196, 0}, {0, 0, 1}, nullptr, &bspx);
}
{
INFO("check that func_group inherits worldspawn minlight");
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {64, 0, 0}, {360, 72, 16}, {0, 0, 1}, nullptr, &bspx);
}
{
INFO("check that func_wall inherits worldspawn minlight");
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[1], {64, 0, 0}, {208, 72, 16}, {0, 0, 1}, nullptr, &bspx);
}
{
INFO("check that func_group can override worldspawn minlight");
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {128, 0, 0}, {360, -84, 16}, {0, 0, 1}, nullptr, &bspx);
}
{
INFO("check that func_wall can override worldspawn minlight");
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[2], {128, 0, 0}, {208, -84, 16}, {0, 0, 1}, nullptr, &bspx);
}
{
INFO("check that func_group can override worldspawn minlight color");
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {0, 64, 0}, {360, -248, 16}, {0, 0, 1}, nullptr, &bspx);
}
{
INFO("check that func_wall can override worldspawn minlight color");
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[3], {0, 64, 0}, {208, -248, 16}, {0, 0, 1}, nullptr, &bspx);
}
}
TEST_CASE("q2_minlight_inherited + -noextendedsurfflags")
{
auto [bsp, bspx] =
QbspVisLight_Common("q2_minlight_inherited.map", {"-q2bsp", "-noextendedsurfflags"}, {}, runvis_t::no);
{
INFO("check that func_wall inherits worldspawn minlight");
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[1], {64, 0, 0}, {208, 72, 16}, {0, 0, 1}, nullptr, &bspx);
}
{
INFO("check that func_wall can override worldspawn minlight");
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[2], {128, 0, 0}, {208, -84, 16}, {0, 0, 1}, nullptr, &bspx);
}
{
INFO("check that func_wall can override worldspawn minlight color");
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[3], {0, 64, 0}, {208, -248, 16}, {0, 0, 1}, nullptr, &bspx);
}
}