diff --git a/common/bsputils.cc b/common/bsputils.cc index 1c95709b..fee0508d 100644 --- a/common/bsputils.cc +++ b/common/bsputils.cc @@ -73,6 +73,17 @@ const bsp2_dface_t *BSP_GetFace(const mbsp_t *bsp, int fnum) return &bsp->dfaces[fnum]; } +const gtexinfo_t *BSP_GetTexinfo(const mbsp_t *bsp, int texinfo) { + if (texinfo < 0) { + return nullptr; + } + if (texinfo >= bsp->numtexinfo) { + return nullptr; + } + const gtexinfo_t *tex = &bsp->texinfo[texinfo]; + return tex; +} + bsp2_dface_t *BSP_GetFace(mbsp_t *bsp, int fnum) { Q_assert(fnum >= 0 && fnum < bsp->numfaces); diff --git a/include/common/bsputils.hh b/include/common/bsputils.hh index 18e32d69..2457bab9 100644 --- a/include/common/bsputils.hh +++ b/include/common/bsputils.hh @@ -35,6 +35,7 @@ const mleaf_t* BSP_GetLeaf(const mbsp_t *bsp, int leafnum); const mleaf_t* BSP_GetLeafFromNodeNum(const mbsp_t *bsp, int nodenum); const dplane_t *BSP_GetPlane(const mbsp_t *bsp, int planenum); const bsp2_dface_t *BSP_GetFace(const mbsp_t *bsp, int fnum); +const gtexinfo_t *BSP_GetTexinfo(const mbsp_t *bsp, int texinfo); bsp2_dface_t *BSP_GetFace(mbsp_t *bsp, int fnum); int Face_VertexAtIndex(const mbsp_t *bsp, const bsp2_dface_t *f, int v); diff --git a/light/phong.cc b/light/phong.cc index 7724fec5..c45656ef 100644 --- a/light/phong.cc +++ b/light/phong.cc @@ -398,6 +398,21 @@ static vector MakeFaceCache(const mbsp_t *bsp) return result; } +/** + * Q2: Returns nonzero if phong is requested on this face, in which case that is + * the face tag to smooth with. Otherwise returns 0. + */ +static int Q2_FacePhongValue(const mbsp_t *bsp, const bsp2_dface_t *face) { + const gtexinfo_t* texinfo = BSP_GetTexinfo(bsp, face->texinfo); + if (texinfo != nullptr) { + if (texinfo->value != 0 + && ((texinfo->flags & Q2_SURF_LIGHT) == 0)) { + return texinfo->value; + } + } + return 0; +} + void CalcualateVertexNormals(const mbsp_t *bsp) { @@ -504,6 +519,30 @@ CalcualateVertexNormals(const mbsp_t *bsp) } } + // Q2: build the "face -> faces to smooth with" map + for (int i = 0; i < bsp->numfaces; i++) { + const bsp2_dface_t *f = BSP_GetFace(const_cast(bsp), i); + const int f_phongValue = Q2_FacePhongValue(bsp, f); + if (f_phongValue == 0) + continue; + + for (int j = 0; j < f->numedges; j++) { + const int v = Face_VertexAtIndex(bsp, f, j); + // walk over all faces incident to f (we will walk over neighbours multiple times, doesn't matter) + for (const bsp2_dface_t *f2 : vertsToFaces[v]) { + if (f2 == f) + continue; + + const int f2_phongValue = Q2_FacePhongValue(bsp, f2); + if (f_phongValue != f2_phongValue) + continue; + + // we've already checked f_phongValue is nonzero, so smooth these two faces. + smoothFaces[f].insert(f2); + } + } + } + // finally do the smoothing for each face for (int i = 0; i < bsp->numfaces; i++) {