diff --git a/src/libs/Common/include/model.h b/src/libs/Common/include/model.h index de21b7c13..b16aa91e6 100644 --- a/src/libs/Common/include/model.h +++ b/src/libs/Common/include/model.h @@ -4,7 +4,6 @@ #include "Matrix.h" #include "geos.h" #include "object.h" -#include "vmodule_api.h" class NODER; @@ -53,6 +52,8 @@ class NODE const CMatrix &globm, NODER *par, const char *lmPath) = 0; virtual float Trace(const CVECTOR &src, const CVECTOR &dst) = 0; + + virtual void SubstituteGeometry(const std::string& new_model) = 0; }; class VDX9RENDER; diff --git a/src/libs/model/src/model.cpp b/src/libs/model/src/model.cpp index 7c6aa86c8..a0795f83c 100644 --- a/src/libs/model/src/model.cpp +++ b/src/libs/model/src/model.cpp @@ -393,6 +393,19 @@ uint64_t MODELR::ProcessMessage(MESSAGE &message) if (root) root->SetMaxViewDist(message.Float()); break; + case MSG_MODEL_SUBSTITUTE_GEOMETRY_NODE: { + auto &&geometry_node = message.String(); + auto &&new_model_name = message.String(); + + if (auto *node = FindNode(geometry_node.c_str())) + { + node->SubstituteGeometry(new_model_name); + } + else + { + spdlog::trace("MODELR: Cannot substitute geometry node {}", geometry_node); + } + } } return 1; } diff --git a/src/libs/model/src/modelr.h b/src/libs/model/src/modelr.h index 22b14e56b..575ff5bb5 100644 --- a/src/libs/model/src/modelr.h +++ b/src/libs/model/src/modelr.h @@ -1,16 +1,19 @@ #pragma once +#include + #include "dx9render.h" #include "geometry.h" #include "model.h" class NODER : public NODE { - char *sys_modelName; - char *sys_LightPath; - char *sys_TexPath; - char *sys_lmPath; - bool isReleaed; + std::string sys_modelName_base; + std::string sys_modelName_full; + std::string sys_LightPath; + std::string sys_TexPath; + std::string sys_lmPath; + bool isReleased; static long depth, node; uintptr_t idGeoGroup; // id of "geometry" string @@ -54,11 +57,15 @@ class NODER : public NODE void SetTechnique(const char *name) override; const char *GetTechnique() override; + + // replace only this node model without touching anything else + void SubstituteGeometry(const std::string &new_model) override; void ReleaseGeometry(); void RestoreGeometry(); void SetMaxViewDist(float fDist); + }; #define MODEL_ANI_MAXBUFFERS 16 diff --git a/src/libs/model/src/node.cpp b/src/libs/model/src/node.cpp index 24af08315..bb08490b1 100644 --- a/src/libs/model/src/node.cpp +++ b/src/libs/model/src/node.cpp @@ -6,7 +6,6 @@ VGEOMETRY *NODER::gs = nullptr; VDX9RENDER *NODER::rs = nullptr; -static long nlab = 0; long NODER::depth = -1; long NODER::node; extern long clip_nps; @@ -15,7 +14,6 @@ extern const CVECTOR *clip_c; extern float clip_r; extern GEOS::ADD_POLYGON_FUNC clip_geosap; extern ADD_POLYGON_FUNC clip_ap; -char nm[256]; GEOS::PLANE clip_gp[256]; NODE *bestTraceNode = nullptr; GEOS *clipGeo; @@ -43,7 +41,7 @@ bool AddPolygon(const GEOS::VERTEX *vr, long nv) //------------------------------------------------------------------- bool NODER::Clip() { - if (isReleaed) + if (isReleased) return false; // check for bounding spheres intersection @@ -122,7 +120,7 @@ float NODER::Update(CMatrix &mtx, CVECTOR &cnt) //---------------------------------------------------------- float NODER::Trace(const CVECTOR &src, const CVECTOR &dst) { - if (isReleaed) + if (isReleased) return 2.0f; // check for bounding spheres intersection const auto lmn = dst - src; @@ -174,10 +172,6 @@ NODER::NODER() nnext = 0; next = nullptr; parent = nullptr; - sys_modelName = nullptr; - sys_TexPath = nullptr; - sys_LightPath = nullptr; - sys_lmPath = nullptr; max_view_dist = 0.f; } @@ -185,6 +179,7 @@ NODER::NODER() bool NODER::Init(const char *lightPath, const char *pname, const char *oname, const CMatrix &m, const CMatrix &globm, NODER *par, const char *lmPath) { + isReleased = false; name[0] = 0; technique[0] = 0; geoMaterialFunc = nullptr; @@ -193,44 +188,28 @@ bool NODER::Init(const char *lightPath, const char *pname, const char *oname, co loc_mtx = m; glob_mtx.EqMultiply(loc_mtx, globm); - nlab++; - if (oname[0] == 0) - sprintf_s(nm, "%s", pname); - else - sprintf_s(nm, "%s_%s", pname, oname); - - char lp[256]; - // sprintf_s(lp, "%s\\%s", lightPath, nm); - sprintf_s(lp, "%s", lightPath); - - auto len = strlen(nm) + 1; - sys_modelName = new char[len]; - memcpy(sys_modelName, nm, len); - - len = strlen(lp) + 1; - sys_LightPath = new char[len]; - memcpy(sys_LightPath, lp, len); + if (pname == nullptr) + { + throw std::runtime_error(fmt::format("NODER::Init: got nullptr model name")); + } + sys_modelName_base = pname; - len = strlen(lmPath) + 1; - sys_lmPath = new char[len]; - memcpy(sys_lmPath, lmPath, len); + if (oname && oname[0]) + sys_modelName_full = fmt::format("{}_{}", sys_modelName_base, oname); + else + sys_modelName_full = sys_modelName_base; + + if (lightPath) + sys_LightPath = lightPath; - const auto *const tPath = gs->GetTexturePath(); - len = strlen(tPath) + 1; - sys_TexPath = new char[len]; - memcpy(sys_TexPath, tPath, len); + if (lmPath) + sys_lmPath = lmPath; - isReleaed = false; + sys_TexPath = gs->GetTexturePath(); - geo = gs->CreateGeometry(nm, lp, 0, lmPath); + geo = gs->CreateGeometry(sys_modelName_full.c_str(), sys_LightPath.c_str(), 0, lmPath); if (!geo) { - delete sys_modelName; - sys_modelName = nullptr; - delete sys_LightPath; - sys_LightPath = nullptr; - delete sys_lmPath; - sys_lmPath = nullptr; return false; } @@ -305,19 +284,15 @@ NODER::~NODER() delete next[l]; if (nnext > 0) free(next); - delete sys_modelName; - delete sys_LightPath; - delete sys_lmPath; - delete sys_TexPath; } void NODER::ReleaseGeometry() { - if (isReleaed) + if (isReleased) return; delete geo; geo = nullptr; - isReleaed = true; + isReleased = true; for (long i = 0; i < nnext; i++) { if (!next[i]) @@ -328,21 +303,21 @@ void NODER::ReleaseGeometry() void NODER::RestoreGeometry() { - if (!isReleaed) + if (!isReleased) return; const auto *const tPath = gs->GetTexturePath(); const auto len = strlen(tPath) + 1; auto *const ttPath = new char[len]; memcpy(ttPath, tPath, len); - gs->SetTexturePath(sys_TexPath); - geo = gs->CreateGeometry(sys_modelName, sys_LightPath, 0, sys_lmPath); + gs->SetTexturePath(sys_TexPath.c_str()); + geo = gs->CreateGeometry(sys_modelName_full.c_str(), sys_LightPath.c_str(), 0, sys_lmPath.c_str()); gs->SetTexturePath(ttPath); delete[] ttPath; if (!geo) - throw std::runtime_error("No geometry"); + throw std::runtime_error(fmt::format("Cannot restore geometry {}", sys_modelName_full)); - isReleaed = false; + isReleased = false; for (long i = 0; i < nnext; i++) { if (!next[i]) @@ -359,7 +334,7 @@ GEOS::PLANE TViewPlane[4]; void NODER::Draw() { - if (isReleaed) + if (isReleased) return; const auto cnt = glob_mtx * center; @@ -617,3 +592,10 @@ void NODER::SetMaxViewDist(float fDist) if (next[n]) static_cast(next[n])->SetMaxViewDist(fDist); } + +void NODER::SubstituteGeometry(const std::string &new_model) +{ + sys_modelName_full = fmt::format("{}_{}", sys_modelName_base, new_model); + ReleaseGeometry(); + RestoreGeometry(); +} diff --git a/src/libs/rigging/src/Flag.cpp b/src/libs/rigging/src/Flag.cpp index ac7e1856e..5ce39e805 100644 --- a/src/libs/rigging/src/Flag.cpp +++ b/src/libs/rigging/src/Flag.cpp @@ -151,27 +151,22 @@ uint64_t FLAG::ProcessMessage(MESSAGE &message) const auto eidModel = message.EntityID(); const auto nNation = message.Long(); - MODEL *host_mdl; - host_mdl = static_cast(EntityManager::GetEntityPointer(eidModel)); + MODEL *host_mdl = static_cast(EntityManager::GetEntityPointer(eidModel)); if (host_mdl == nullptr) { core.Trace("Missing INIT message to FLAG: bad MODEL"); + return 0; } if (groupQuantity == 0) { gdata = new GROUPDATA[1]; - if (gdata == nullptr) - throw std::runtime_error("Not memory allocation"); - groupQuantity = 1; } else { auto *const oldgdata = gdata; gdata = new GROUPDATA[groupQuantity + 1]; - if (gdata == nullptr) - throw std::runtime_error("Not memory allocation"); memcpy(gdata, oldgdata, sizeof(GROUPDATA) * groupQuantity); delete oldgdata; groupQuantity++; diff --git a/src/libs/shared_headers/include/shared/messages.h b/src/libs/shared_headers/include/shared/messages.h index 8977be358..d344ee6c6 100644 --- a/src/libs/shared_headers/include/shared/messages.h +++ b/src/libs/shared_headers/include/shared/messages.h @@ -22,6 +22,8 @@ #define MSG_MODEL_SET_FOG 20511 #define MSG_MODEL_SET_MAX_VIEW_DIST 20512 +#define MSG_MODEL_SUBSTITUTE_GEOMETRY_NODE 20600 // "ss", geometry, new model name + //============================================================================================ // blade messages //============================================================================================ diff --git a/src/libs/ship/src/ship.cpp b/src/libs/ship/src/ship.cpp index cc01657b6..43b2a6dab 100644 --- a/src/libs/ship/src/ship.cpp +++ b/src/libs/ship/src/ship.cpp @@ -1301,8 +1301,15 @@ uint64_t SHIP::ProcessMessage(MESSAGE &message) core.Send_Message(GetModelEID(), "ls", MSG_MODEL_SET_TECHNIQUE, sTech.c_str()); // MODEL * pModel = GetModel(); // NODE* pNode = pModel->GetNode(0); + break; + } + case MSG_MODEL_SUBSTITUTE_GEOMETRY_NODE: { + auto &&geometry_node = message.String(); + auto &&new_model_name = message.String(); + core.Send_Message(GetModelEID(), "lss", MSG_MODEL_SUBSTITUTE_GEOMETRY_NODE, geometry_node.c_str(), + new_model_name.c_str()); + break; } - break; } return 0; }