diff --git a/src/bsp/Bsp.cpp b/src/bsp/Bsp.cpp index b1e449a3..88e955bb 100644 --- a/src/bsp/Bsp.cpp +++ b/src/bsp/Bsp.cpp @@ -5602,7 +5602,7 @@ BSPMIPTEX* Bsp::find_embedded_texture(const char* name, int& texid) if (oldOffset >= 0) { BSPMIPTEX* oldTex = (BSPMIPTEX*)(textures + oldOffset); - if (oldTex->szName[0] != '\0' && strcasecmp(name, oldTex->szName) == 0 && oldTex->nOffsets[0] > 0) + if (oldTex->szName[0] != '\0' && oldTex->nOffsets[0] > 0 && strcasecmp(name, oldTex->szName) == 0) { texid = i; return oldTex; @@ -9438,20 +9438,37 @@ void Bsp::ExportToObjWIP(const std::string& path, int iscale, bool lightmapmode, scale = std::abs(scale); - FILE* f = NULL; print_log(get_localized_string(LANG_0194), bsp_name + ".obj", path); print_log(get_localized_string(LANG_0195), iscale == 1 ? "scale" : iscale < 0 ? "downscale" : "upscale", abs(iscale)); - fopen_s(&f, (path + bsp_name + ".obj").c_str(), "wb"); - if (f) + + + std::ofstream obj_file(path + bsp_name + ".obj", std::ios::binary); + if (obj_file) { - fprintf(f, "# Exported using bspguy!\n"); + obj_file << "# Exported using bspguy!\n"; - fprintf(f, "mtllib %s.mtl\n", bsp_name.c_str()); + obj_file << "mtllib " << bsp_name << ".mtl\n"; std::string groupname = std::string(); BspRenderer* bsprend = renderer; + remove_faces_by_content(CONTENTS_SKY); + remove_faces_by_content(CONTENTS_SOLID); + + remove_unused_model_structures(); + + int merged = merge_all_verts(0.1f); + print_log(PRINT_RED, " Merged {} verts \n", merged); + remove_unused_model_structures(CLEAN_EDGES_FORCE | CLEAN_TEXINFOS_FORCE); + + save_undo_lightmaps(); + resize_all_lightmaps(); + bsprend->reuploadTextures(); + bsprend->loadLightmaps(); + bsprend->calcFaceMaths(); + + //g_app->reloading = true; //bsprend->reload(); //g_app->reloading = false; @@ -9461,6 +9478,7 @@ void Bsp::ExportToObjWIP(const std::string& path, int iscale, bool lightmapmode, std::vector matnames; int vertoffset = 1; + int normoffset = 0; std::string materialid = std::string(); std::string lastmaterialid = std::string(); @@ -9594,15 +9612,19 @@ void Bsp::ExportToObjWIP(const std::string& path, int iscale, bool lightmapmode, toLowerCase(tex.szName) == "skip" ) { - materials.push_back("illum 4"); materials.push_back("map_Kd " + std::string("textures/") + tex.szName + std::string(".bmp")); materials.push_back("map_d " + std::string("textures/") + tex.szName + std::string(".bmp")); + materials.push_back("Ni 1.000"); + materials.push_back("d 1.000"); + materials.push_back("illum 4"); } else { materials.push_back("map_Kd " + std::string("textures/") + tex.szName + std::string(".bmp")); + materials.push_back("Ni 1.000"); + materials.push_back("d 1.000"); + materials.push_back("illum 0"); } - materials.push_back(""); matnames.push_back(tex.szName); } @@ -9685,14 +9707,6 @@ void Bsp::ExportToObjWIP(const std::string& path, int iscale, bool lightmapmode, vec3 origin_offset = ent->origin.flip(); - if ("Model_" + std::to_string(mdlid) + "_ent_" + std::to_string(tmpentid) != groupname) - { - groupname = "Model_" + std::to_string(mdlid) + "_ent_" + std::to_string(tmpentid); - fprintf(f, "o %s\n", groupname.c_str()); - - print_log(PRINT_RED, "Entity {} angles {}\n", tmpentid, rendEnt->angles.toKeyvalueString()); - //fprintf(f, "\ng %s\n\n", groupname.c_str()); - } /*else { fprintf(f, "\n\n"); @@ -9711,7 +9725,7 @@ void Bsp::ExportToObjWIP(const std::string& path, int iscale, bool lightmapmode, renderer->setRenderAngles(ent->classname, angle_mat, angles); } - for (int n = 0; n < rface->vertCount; n++) + for (int n = rface->vertCount - 1; n >= 0; n--) { lightmapVert& vert = ((lightmapVert*)rgroup->buffer->get_data())[rface->vertOffset + n]; @@ -9724,23 +9738,27 @@ void Bsp::ExportToObjWIP(const std::string& path, int iscale, bool lightmapmode, org_pos += origin_offset; - fprintf(f, "v %f %f %f\n", org_pos.x * scale, org_pos.y * scale, org_pos.z * scale); + org_pos *= scale; + + obj_file << "v " << org_pos.toKeyvalueString() << "\n"; } BSPPLANE tmpPlane = getPlaneFromFace(&face); + vec3 org_norm = tmpPlane.vNormal; - for (int n = 0; n < rface->vertCount; n++) + if (rendEnt->needAngles) { - vec3 org_norm = tmpPlane.vNormal; + org_norm = (angle_mat * vec4(org_norm, 1.0)).xyz(); + } - if (rendEnt->needAngles) - { - org_norm = (angle_mat * vec4(org_norm, 1.0)).xyz(); - } + org_norm = org_norm.flip(); - fprintf(f, "vn %f %f %f\n", org_norm.x, org_norm.z, -org_norm.y); - } - for (int n = 0; n < rface->vertCount; n++) + obj_file << "vn " << org_norm.toKeyvalueString() << "\n"; + + normoffset++; + + + for (int n = rface->vertCount - 1; n >= 0; n--) { lightmapVert& vert = ((lightmapVert*)rgroup->buffer->get_data())[rface->vertOffset + n]; @@ -9755,47 +9773,53 @@ void Bsp::ExportToObjWIP(const std::string& path, int iscale, bool lightmapmode, float fU = dotProduct(texinfo.vS, org_pos) + texinfo.shiftS; float fV = dotProduct(texinfo.vT, org_pos) + texinfo.shiftT; + fU /= (float)tex.nWidth; fV /= -(float)tex.nHeight; - fprintf(f, "vt %f %f\n", fU, fV); + + obj_file << "vt " << flt_to_str(fU) << " " << flt_to_str(fV) << "\n"; } - fprintf(f, "%s", "s off\n"); + if ("Model_" + std::to_string(mdlid) + "_ent_" + std::to_string(tmpentid) != groupname) + { + groupname = "Model_" + std::to_string(mdlid) + "_ent_" + std::to_string(tmpentid); + obj_file << "o " << groupname << "\n"; + + print_log(PRINT_RED, "Entity {} angles {}\n", tmpentid, rendEnt->angles.toKeyvalueString()); + //fprintf(f, "\ng %s\n\n", groupname.c_str()); + } if (lastmaterialid != materialid) { - fprintf(f, "usemtl %s\n", materialid.c_str()); + obj_file << "usemtl " << materialid << "\n"; } lastmaterialid = materialid; - fprintf(f, "%s", "f"); - for (int n = rface->vertCount - 1; n >= 0; n--) + obj_file << "f"; + + for (int n = 0; n < rface->vertCount; n++) { int id = vertoffset + n; - fprintf(f, " %i/%i/%i", id, id, id); + obj_file << " " << id << "/" << id << "/" << normoffset; } + obj_file << "\n"; vertoffset += rface->vertCount; - fprintf(f, "%s", "\n"); - } } - FILE* fmat = NULL; - fopen_s(&fmat, (path + bsp_name + ".mtl").c_str(), "wt"); + + std::ofstream fmat(path + bsp_name + ".mtl", std::ios::binary); if (fmat) { for (auto const& s : materials) { - fprintf(fmat, "%s\n", s.c_str()); + fmat << s << '\n'; } - fclose(fmat); } - fclose(f); - renderer->undo(); @@ -11501,18 +11525,6 @@ int Bsp::import_mdl_to_bspmodel(size_t ent, bool generateClipnodes) auto mdl_input = renderer->renderEnts[ent].mdl; if (mdl_input->mdl_mesh_groups.size()) { - std::vector all_verts; - std::vector merged_meshes; - for (size_t group = 0; group < mdl_input->mdl_mesh_groups.size(); group++) - { - for (size_t meshid = 0; meshid < mdl_input->mdl_mesh_groups[group].size(); meshid++) - { - merged_meshes.push_back(mdl_input->mdl_mesh_groups[group][meshid]); - - for (auto v : mdl_input->mdl_mesh_groups[group][meshid].verts) - all_verts.push_back(v.pos.flipUV()); - } - } bool is_valid_nodes = false; mat4x4 angle_mat; @@ -11530,6 +11542,21 @@ int Bsp::import_mdl_to_bspmodel(size_t ent, bool generateClipnodes) //print_log(PRINT_RED, "CONVERT ANGLES : {} for {} ent\n", angles.toKeyvalueString(), ents[ent]->classname); } + std::vector all_verts; + std::vector merged_meshes; + for (size_t group = 0; group < mdl_input->mdl_mesh_groups.size(); group++) + { + for (size_t meshid = 0; meshid < mdl_input->mdl_mesh_groups[group].size(); meshid++) + { + merged_meshes.push_back(mdl_input->mdl_mesh_groups[group][meshid]); + if (generateClipnodes) + { + for (auto v : mdl_input->mdl_mesh_groups[group][meshid].verts) + all_verts.push_back((angle_mat * vec4(v.pos.flipUV(), 1.0f)).xyz()); + } + } + } + int newModelIdx = import_mdl_to_bspmodel(merged_meshes, angle_mat, is_valid_nodes); if (ents[ent]->hasKey("angles")) @@ -11726,7 +11753,7 @@ int Bsp::import_mdl_to_bspmodel(size_t ent, bool generateClipnodes) }*/ - models[newModelIdx].iHeadnodes[0] = models[models_to_merge_pass3[0]].iHeadnodes[0]; + //models[newModelIdx].iHeadnodes[0] = models[models_to_merge_pass3[0]].iHeadnodes[0]; models[newModelIdx].iHeadnodes[1] = models[models_to_merge_pass3[0]].iHeadnodes[1]; models[newModelIdx].iHeadnodes[2] = models[models_to_merge_pass3[0]].iHeadnodes[2]; models[newModelIdx].iHeadnodes[3] = models[models_to_merge_pass3[0]].iHeadnodes[3]; @@ -11794,9 +11821,6 @@ int Bsp::import_mdl_to_bspmodel(std::vector& meshes, mat4x4 angles, for (v = (int)startVertCount; v < newVertCount; v++) { newverts[v] = (angles * vec4(mesh_verts[v - startVertCount].pos.unflip(), 1.0f)).xyz(); - - - newuv[v] = { mesh_verts[v - startVertCount].u, mesh_verts[v - startVertCount].v }; newVertIndexes.push_back(v); expandBoundingBox(newverts[v], mins, maxs); @@ -11938,8 +11962,13 @@ int Bsp::import_mdl_to_bspmodel(std::vector& meshes, mat4x4 angles, trueTexName.erase(trueTexName.begin()); } - miptex = add_texture(trueTexName.c_str(), (unsigned char*)tmpData, newWidth, - newHeight); + auto tmpTex = find_embedded_texture(trueTexName.c_str(), miptex); + + if (miptex < 0 || !tmpTex || tmpTex->nWidth != newWidth || tmpTex->nHeight != newHeight) + { + miptex = add_texture(trueTexName.c_str(), (unsigned char*)tmpData, newWidth, + newHeight); + } delete[] tmpData; } @@ -12017,6 +12046,7 @@ int Bsp::import_mdl_to_bspmodel(std::vector& meshes, mat4x4 angles, { BSPTEXTUREINFO& texInfo = newtexinfos[newfaces[f].iTextureInfo]; texInfo.nFlags = TEX_SPECIAL; + print_log(PRINT_BLUE, "Found bad face {} extents, set to SPECIAL\n", f); } } } @@ -12031,15 +12061,18 @@ int Bsp::import_mdl_to_bspmodel(std::vector& meshes, mat4x4 angles, models[newModelIdx].nVisLeafs = 1; int empty_leaf = create_leaf(CONTENTS_EMPTY); - leaves[leafCount - 1].nMins = mins + 1.0f; - leaves[leafCount - 1].nMaxs = maxs - 1.0f; - leaves[leafCount - 1].nVisOffset = -1; + leaves[empty_leaf].nMins = mins + 1.0f; + leaves[empty_leaf].nMaxs = maxs - 1.0f; + leaves[empty_leaf].nVisOffset = -1; + + update_lump_pointers(); for (int i = modelFirstFace; i < modelFirstFace + modelFaces; i++) { - leaf_add_face(i, leafCount - 1); + leaf_add_face(i, empty_leaf); } + /*unsigned int startNode = nodeCount; { int newnodecount = nodeCount + modelFaces + 2; @@ -12446,29 +12479,40 @@ bool Bsp::CalcFaceExtents(lightinfo_t* l) bool Bsp::GetFaceExtents(int facenum, int mins_out[2], int maxs_out[2]) { - bool findpos = CanFindFacePosition(this, facenum, mins_out, maxs_out); - bool retval = true; + bool retval = CanFindFacePosition(this, facenum, mins_out, maxs_out); BSPFACE32& face = faces[facenum]; BSPTEXTUREINFO tex = texinfos[face.iTextureInfo]; + if (tex.nFlags & TEX_SPECIAL) + { + retval = true; + } + for (int i = 0; i < 2; i++) { int tmpTextureStep = CalcFaceTextureStep(facenum); if (!(tex.nFlags & TEX_SPECIAL) && (maxs_out[i] - mins_out[i]) * tmpTextureStep > (MAX_SURFACE_EXTENT * MAX_SURFACE_EXTENT)) { + if (retval) + { + print_log(get_localized_string("BAD_SURFACE_EXT"), facenum, (int)((maxs_out[i] - mins_out[i]) * tmpTextureStep), (MAX_SURFACE_EXTENT * MAX_SURFACE_EXTENT)); + print_log("TRACE: Mins {} maxs {}\n", mins_out[i], maxs_out[i]); + } retval = false; - print_log(get_localized_string("BAD_SURFACE_EXT"), facenum, (int)((maxs_out[i] - mins_out[i]) * tmpTextureStep), (MAX_SURFACE_EXTENT * MAX_SURFACE_EXTENT)); - print_log("TRACE: Mins {} maxs {}\n", mins_out[i], maxs_out[i]); mins_out[i] = 1; maxs_out[i] = 1; } if (maxs_out[i] - mins_out[i] < 0) { + if (retval) + { + print_log(PRINT_RED, "Face {} extents are bad. Map can crash.\n", facenum); + print_log("TRACE: Mins {} maxs {}\n", mins_out[i], maxs_out[i]); + } retval = false; - print_log(PRINT_RED, "Face {} extents are bad. Map can crash.\n", facenum); mins_out[i] = 1; maxs_out[i] = 1; } @@ -12486,19 +12530,19 @@ int Bsp::GetFaceSingleLightmapSizeBytes(int facenum) return size[0] * size[1] * sizeof(COLOR3); } -void Bsp::GetFaceLightmapSize(int facenum, int size[2]) +bool Bsp::GetFaceLightmapSize(int facenum, int size[2]) { int mins[2]; int maxs[2]; - GetFaceExtents(facenum, mins, maxs); + bool foundExtents = GetFaceExtents(facenum, mins, maxs); size[0] = (maxs[0] - mins[0]); size[1] = (maxs[1] - mins[1]); size[0] += 1; size[1] += 1; - //return !badSurfaceExtents; + return foundExtents; } int Bsp::GetFaceLightmapSizeBytes(int facenum) diff --git a/src/bsp/Bsp.h b/src/bsp/Bsp.h index 40e57b44..4467e3b9 100644 --- a/src/bsp/Bsp.h +++ b/src/bsp/Bsp.h @@ -375,7 +375,7 @@ class Bsp void mark_clipnode_structures(int iNode, STRUCTUSAGE* usage); const BSPPLANE getPlaneFromFace(const BSPFACE32* const face); - void GetFaceLightmapSize(int facenum, int size[2]); + bool GetFaceLightmapSize(int facenum, int size[2]); int GetFaceLightmapSizeBytes(int facenum); int GetFaceSingleLightmapSizeBytes(int facenum); bool GetFaceExtents(int facenum, int mins_out[2], int maxs_out[2]); diff --git a/src/qtools/rad.cpp b/src/qtools/rad.cpp index 4a9069bb..db17cb97 100644 --- a/src/qtools/rad.cpp +++ b/src/qtools/rad.cpp @@ -10,105 +10,43 @@ // ApplyMatrix: (x y z 1)T -> matrix * (x y z 1)T -void ApplyMatrix(const matrix_t& m, const vec3 in, vec3& out) +void ApplyMatrix(const mat4x4& m, const vec3 in, vec3& out) { - int i; - - VectorCopy(m.v[3], out); - for (i = 0; i < 3; i++) - { - VectorMA(out, in[i], m.v[i], out); - } + out = (m * vec4(in, 1.0f)).xyz(); } -bool InvertMatrix(const matrix_t& m, matrix_t& m_inverse) +bool InvertMatrix(mat4x4 m, mat4x4& m_inverse) { - float texplanes[2][4]{}; - float faceplane[4]{}; - int i; - float texaxis[2][3]{}; - float normalaxis[3]{}; - float det, sqrlen1, sqrlen2, sqrlen3; - float texorg[3]{}; - - for (i = 0; i < 4; i++) - { - texplanes[0][i] = m.v[i][0]; - texplanes[1][i] = m.v[i][1]; - faceplane[i] = m.v[i][2]; - } - - sqrlen1 = DotProduct(texplanes[0], texplanes[0]); - sqrlen2 = DotProduct(texplanes[1], texplanes[1]); - sqrlen3 = DotProduct(faceplane, faceplane); - if (sqrlen1 <= EPSILON * EPSILON || sqrlen2 <= EPSILON * EPSILON || sqrlen3 <= EPSILON * EPSILON) - // s gradient, t gradient or face normal is too close to 0 - { - return false; - } - - CrossProduct(texplanes[0], texplanes[1], normalaxis); - det = DotProduct(normalaxis, faceplane); - if (det * det <= sqrlen1 * sqrlen2 * sqrlen3 * EPSILON * EPSILON) - // s gradient, t gradient and face normal are coplanar - { - return false; - } - VectorScale(normalaxis, 1 / det, normalaxis); - - CrossProduct(texplanes[1], faceplane, texaxis[0]); - VectorScale(texaxis[0], 1 / det, texaxis[0]); - - CrossProduct(faceplane, texplanes[0], texaxis[1]); - VectorScale(texaxis[1], 1 / det, texaxis[1]); - - VectorScale(normalaxis, -faceplane[3], texorg); - VectorMA(texorg, -texplanes[0][3], texaxis[0], texorg); - VectorMA(texorg, -texplanes[1][3], texaxis[1], texorg); - - VectorCopy(texaxis[0], m_inverse.v[0]); - VectorCopy(texaxis[1], m_inverse.v[1]); - VectorCopy(normalaxis, m_inverse.v[2]); - VectorCopy(texorg, m_inverse.v[3]); + m_inverse = m.invert(); return true; } -void TranslateWorldToTex(Bsp* bsp, int facenum, matrix_t& m) -// without g_face_offset +void TranslateWorldToTex(Bsp* bsp, int facenum, mat4x4& m) { - BSPFACE32* f; - BSPTEXTUREINFO* ti; - - int i; - - f = &bsp->faces[facenum]; + BSPFACE32* f = &bsp->faces[facenum]; const BSPPLANE fp = bsp->getPlaneFromFace(f); - ti = &bsp->texinfos[f->iTextureInfo]; - for (i = 0; i < 3; i++) + BSPTEXTUREINFO* ti = &bsp->texinfos[f->iTextureInfo]; + + for (int i = 0; i < 3; i++) { - m.v[i][0] = ((float*)&ti->vS)[i]; - m.v[i][1] = ((float*)&ti->vT)[i]; + m.m[i * 4 + 0] = ((float*)&ti->vS)[i]; + m.m[i * 4 + 1] = ((float*)&ti->vT)[i]; + m.m[i * 4 + 2] = ((float*)&fp.vNormal)[i]; } - m.v[0][2] = fp.vNormal.x; - m.v[1][2] = fp.vNormal.y; - m.v[2][2] = fp.vNormal.z; - m.v[3][0] = ti->shiftS; - m.v[3][1] = ti->shiftT; - m.v[3][2] = -fp.fDist; + m.m[3 * 4 + 0] = ti->shiftS; + m.m[3 * 4 + 1] = ti->shiftT; + m.m[3 * 4 + 2] = -fp.fDist; } bool CanFindFacePosition(Bsp* bsp, int facenum, int imins[2], int imaxs[2]) { float texmins[2] = { 0.0f,0.0f }; - float texmaxs[2] = { 0.0f,0.0f }; - matrix_t worldtotex; - memset(worldtotex.v, 0, sizeof(worldtotex.v)); - matrix_t textoworld; - memset(worldtotex.v, 0, sizeof(worldtotex.v)); + mat4x4 worldtotex; + worldtotex.loadIdentity(); BSPFACE32* f = &bsp->faces[facenum]; if (f->iTextureInfo < 0 || bsp->texinfos[f->iTextureInfo].nFlags & TEX_SPECIAL) @@ -120,9 +58,13 @@ bool CanFindFacePosition(Bsp* bsp, int facenum, int imins[2], int imaxs[2]) BSPTEXTUREINFO& tex = bsp->texinfos[f->iTextureInfo]; TranslateWorldToTex(bsp, facenum, worldtotex); - if (!InvertMatrix(worldtotex, textoworld)) + + bool canInvert = true; + worldtotex.invert(&canInvert); + + if (!canInvert) { - print_log(PRINT_RED, "CanFindFacePosition error InvertMatrix!\n"); + print_log(PRINT_RED, "CanFindFacePosition error InvertMatrix face {}!\n", facenum); imins[0] = imins[1] = imaxs[0] = imaxs[1] = 1; return false; } diff --git a/src/qtools/rad.h b/src/qtools/rad.h index d561f803..da8224f9 100644 --- a/src/qtools/rad.h +++ b/src/qtools/rad.h @@ -46,12 +46,6 @@ #define VectorCopy(a,b) { (b)[0]=(a)[0]; (b)[1]=(a)[1]; (b)[2]=(a)[2]; } #define VectorMA(a, scale, b, dest) { (dest)[0] = (a)[0] + (scale) * (b)[0]; (dest)[1] = (a)[1] + (scale) * (b)[1]; (dest)[2] = (a)[2] + (scale) * (b)[2]; } -typedef struct -{ - float v[4][3]; -} -matrix_t; - struct BSPEDGE32; struct BSPTEXTUREINFO; struct BSPPLANE; diff --git a/src/util/mat4x4.cpp b/src/util/mat4x4.cpp index f600ff8d..3ecfed0b 100644 --- a/src/util/mat4x4.cpp +++ b/src/util/mat4x4.cpp @@ -17,13 +17,13 @@ void mat4x4::loadIdentity() memcpy(m, m_identity, sizeof(m_identity)); } -void loadEmptyMat4x4(float * m) +void loadEmptyMat4x4(float* m) { memcpy(m, m_zero, sizeof(m_zero)); } void glhFrustumf2(float* matrix, float left, float right, float bottom, float top, - float znear, float zfar) + float znear, float zfar) { float temp, temp2, temp3, temp4; temp = 2.0f * znear; @@ -150,16 +150,16 @@ void mat4x4::rotate(float pitch, float yaw, float roll) sr = sin(angle); cr = cos(angle); - float mat[16] = {0.0f}; - mat[0* 4 + 0] = cp * cy; - mat[1* 4 + 0] = cp * sy; - mat[2* 4 + 0] = -sp; - mat[0* 4 + 1] = sr * sp * cy + cr * -sy; - mat[1* 4 + 1] = sr * sp * sy + cr * cy; - mat[2* 4 + 1] = sr * cp; - mat[0* 4 + 2] = (cr * sp * cy + -sr * -sy); - mat[1* 4 + 2] = (cr * sp * sy + -sr * cy); - mat[2* 4 + 2] = cr * cp; + float mat[16] = { 0.0f }; + mat[0 * 4 + 0] = cp * cy; + mat[1 * 4 + 0] = cp * sy; + mat[2 * 4 + 0] = -sp; + mat[0 * 4 + 1] = sr * sp * cy + cr * -sy; + mat[1 * 4 + 1] = sr * sp * sy + cr * cy; + mat[2 * 4 + 1] = sr * cp; + mat[0 * 4 + 2] = (cr * sp * cy + -sr * -sy); + mat[1 * 4 + 2] = (cr * sp * sy + -sr * cy); + mat[2 * 4 + 2] = cr * cp; mat[0 * 4 + 3] = 0.0f; mat[1 * 4 + 3] = 0.0f; @@ -279,7 +279,7 @@ mat4x4 mat4x4::transpose() } // http://stackoverflow.com/questions/1148309/inverting-a-4x4-matrix -mat4x4 mat4x4::invert() +mat4x4 mat4x4::invert(bool* result) { mat4x4 out; loadEmptyMat4x4(out.m); @@ -402,6 +402,8 @@ mat4x4 mat4x4::invert() if (std::abs(det) < EPSILON) { + if (result) + *result = false; print_log(PRINT_RED | PRINT_INTENSITY, get_localized_string(LANG_1010)); return out; } @@ -431,7 +433,7 @@ mat4x4 mat4x4::invert() void mat4x4::mult(float mat[16]) { - mat4x4 & _other = *((mat4x4*)mat); + mat4x4& _other = *((mat4x4*)mat); *this = *this * _other; } diff --git a/src/util/mat4x4.h b/src/util/mat4x4.h index 7e0f96df..c1c43f31 100644 --- a/src/util/mat4x4.h +++ b/src/util/mat4x4.h @@ -29,7 +29,7 @@ struct mat4x4 // converts row-major matrix to column-major (for OpenGL) mat4x4 transpose(); - mat4x4 invert(); + mat4x4 invert(bool * result = NULL); float& operator ()(size_t idx) { diff --git a/src/util/util.cpp b/src/util/util.cpp index 97fcc8a6..65495d6d 100644 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -2830,4 +2830,19 @@ int str_to_int(const std::string& s) } return 0; +} + +std::string flt_to_str(float f) +{ + std::string retstr = std::to_string(f); + auto it = retstr.find('.'); + if (it != std::string::npos) + { + retstr.erase(retstr.find_last_not_of('0') + 1, std::string::npos); + if (retstr[retstr.size() - 1] == '.') + { + retstr = retstr.substr(0, retstr.size() - 1); + } + } + return retstr; } \ No newline at end of file diff --git a/src/util/util.h b/src/util/util.h index 12354121..9daf4ef7 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -429,4 +429,6 @@ class JackReader { }; int str_to_int(const std::string& s); -float str_to_float(const std::string& s); \ No newline at end of file +float str_to_float(const std::string& s); + +std::string flt_to_str(float f); \ No newline at end of file