diff --git a/src/libs/geometry/include/geometry.h b/src/libs/geometry/include/geometry.h index 80d835118..c73ec8e55 100644 --- a/src/libs/geometry/include/geometry.h +++ b/src/libs/geometry/include/geometry.h @@ -4,6 +4,9 @@ #include "service.h" #include "vma.hpp" + +constexpr size_t TECHNIQUES_COUNT = 10; + class ANIMATION { public: @@ -31,7 +34,8 @@ class VGEOMETRY : public SERVICE const char *lmPath = nullptr) = 0; virtual void DeleteGeometry(GEOS *) = 0; virtual ANIMATION *LoadAnimation(const char *anim) = 0; - virtual void SetTechnique(const char *name) = 0; + virtual void SetTechnique(const char *name, size_t index) = 0; + virtual void SetTechniques(char aTechniques[TECHNIQUES_COUNT][256]) = 0; virtual void SetVBConvertFunc(VERTEX_TRANSFORM _transform_func) = 0; virtual ANIMATION_VB GetAnimationVBDesc(int32_t avb) = 0; diff --git a/src/libs/geometry/include/geos.h b/src/libs/geometry/include/geos.h index 068bf0d94..8a1ba4fff 100644 --- a/src/libs/geometry/include/geos.h +++ b/src/libs/geometry/include/geos.h @@ -13,6 +13,9 @@ Import library main header #include #include + +typedef size_t NameToTechniqueFunc(const char *name); + class GEOS { public: @@ -177,12 +180,14 @@ class GEOS ID vertex_buff; int32_t start_vertex, num_vertices; int32_t bones[4]; + int32_t technology_index; }; virtual int32_t FindObjN(int32_t start_index, int32_t name_id) = 0; virtual int32_t FindObjG(int32_t start_index, int32_t group_name_id) = 0; virtual void GetObj(int32_t o, OBJECT &ob) const = 0; virtual void SetObj(int32_t o, const OBJECT &ob) = 0; + virtual void SetTechniques(NameToTechniqueFunc) = 0; //----------------------------------------- // light sources @@ -302,7 +307,8 @@ class GEOM_SERVICE virtual void SetIndexBuffer(GEOS::ID ibuff) = 0; virtual void SetVertexBuffer(int32_t vsize, GEOS::ID vbuff) = 0; - virtual void DrawIndexedPrimitive(int32_t minv, int32_t numv, int32_t vrtsize, int32_t startidx, int32_t numtrg) = 0; + virtual void DrawIndexedPrimitive(int32_t minv, int32_t numv, int32_t vrtsize, int32_t startidx, int32_t numtrg, + size_t iTechIndex) = 0; virtual GEOS::ID CreateLight(GEOS::LIGHT) = 0; virtual void ActivateLight(GEOS::ID n) = 0; diff --git a/src/libs/geometry/src/geom.h b/src/libs/geometry/src/geom.h index 74a750e30..4bbe291d6 100644 --- a/src/libs/geometry/src/geom.h +++ b/src/libs/geometry/src/geom.h @@ -75,6 +75,7 @@ class GEOM : public GEOS virtual int32_t FindObjG(int32_t start_index, int32_t group_name_id); virtual void GetObj(int32_t o, OBJECT &ob) const; virtual void SetObj(int32_t o, const OBJECT &ob); + virtual void SetTechniques(NameToTechniqueFunc); virtual int32_t FindMaterialN(int32_t start_index, int32_t name_id); virtual int32_t FindMaterialG(int32_t start_index, int32_t group_name_id); diff --git a/src/libs/geometry/src/geom_static.cpp b/src/libs/geometry/src/geom_static.cpp index 78df7b6d5..a231a3372 100644 --- a/src/libs/geometry/src/geom_static.cpp +++ b/src/libs/geometry/src/geom_static.cpp @@ -142,6 +142,7 @@ GEOM::GEOM(const char *fname, const char *lightname, GEOM_SERVICE &_srv, int32_t object[o].vertex_buff = obj[o].vertex_buff; object[o].start_vertex = obj[o].svertex; object[o].num_vertices = obj[o].nvertices; + object[o].technology_index = 0; atriangles[o] = obj[o].atriangles; } srv.free(obj); @@ -292,8 +293,11 @@ void GEOM::Draw(const PLANE *pl, int32_t np, MATERIAL_FUNC mtf) const srv.SetMaterial(material[object[o].material]); if (mtf != nullptr) mtf(material[object[o].material]); + + size_t iTechIndex = object[o].technology_index; + srv.DrawIndexedPrimitive(object[o].start_vertex, object[o].num_vertices, vb->stride, object[o].striangle * 3, - object[o].ntriangles); + object[o].ntriangles, iTechIndex); } } @@ -387,6 +391,15 @@ void GEOM::GetObj(int32_t o, OBJECT &ob) const ob.vertex_buff = vbuff[object[o].vertex_buff].dev_buff; } +void GEOM::SetTechniques(NameToTechniqueFunc ntt) +{ + for (int32_t o = 0; o < rhead.nobjects; o++) + { + object[o].technology_index = ntt(object[o].name); + } +} + + void GEOM::GetInfo(INFO &i) const { i.ntextures = rhead.ntextures; diff --git a/src/libs/geometry/src/geometry.cpp b/src/libs/geometry/src/geometry.cpp index d2ef36f50..b0ba36062 100644 --- a/src/libs/geometry/src/geometry.cpp +++ b/src/libs/geometry/src/geometry.cpp @@ -7,7 +7,8 @@ CREATE_SERVICE(GEOMETRY) IDirect3DVertexDeclaration9 *GEOM_SERVICE_R::vertexDecl_ = nullptr; -char technique[256] = ""; +char techniques[TECHNIQUES_COUNT][256] = {0}; + char RenderServiceName[] = "dx9render"; GEOM_SERVICE_R GSR; char texturePath[256]; @@ -34,9 +35,16 @@ void GEOMETRY::SetTexturePath(const char *path) //================================================================================================= // Block 1 //================================================================================================= -void GEOMETRY::SetTechnique(const char *name) +void GEOMETRY::SetTechnique(const char *name, size_t index) +{ + if (index >= TECHNIQUES_COUNT) + return; + strcpy_s(techniques[index], name); +} + +void GEOMETRY::SetTechniques(char aTechniques[TECHNIQUES_COUNT][256]) { - strcpy_s(technique, name); + memcpy(techniques, aTechniques, sizeof(techniques)); } GEOMETRY::ANIMATION_VB GEOMETRY::GetAnimationVBDesc(int32_t vb) @@ -86,6 +94,10 @@ int vrtSize; GEOS *GEOMETRY::CreateGeometry(const char *file_name, const char *light_file_name, int32_t flags, const char *lmPath) { + if (!strcmp(file_name, "characters\\Blad_0")) + { + file_name = file_name; + } char fnt[256], lfn[256]; if (light_file_name != nullptr) { @@ -425,7 +437,8 @@ void GEOM_SERVICE_R::SetVertexBuffer(int32_t vsize, GEOS::ID vbuff) CurentVertexBufferSize = vsize; } -void GEOM_SERVICE_R::DrawIndexedPrimitive(int32_t minv, int32_t numv, int32_t vrtsize, int32_t startidx, int32_t numtrg) +void GEOM_SERVICE_R::DrawIndexedPrimitive(int32_t minv, int32_t numv, int32_t vrtsize, int32_t startidx, int32_t numtrg, + size_t iTechIndex) { if (!RenderService) return; @@ -456,7 +469,10 @@ void GEOM_SERVICE_R::DrawIndexedPrimitive(int32_t minv, int32_t numv, int32_t vr // float SSBias = -0.6f; // RenderService->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(int*)&SSBias); } - + if (iTechIndex >= TECHNIQUES_COUNT || !techniques[iTechIndex][0]) + { + iTechIndex = 0; + } // draw animation if (transform_func != nullptr) { @@ -468,8 +484,8 @@ void GEOM_SERVICE_R::DrawIndexedPrimitive(int32_t minv, int32_t numv, int32_t vr { RenderService->SetStreamSource(0, transformed_vb, cavb->stride); RenderService->SetFVF(cavb->fvf); - - RenderService->DrawBuffer(-1, cavb->stride, CurentIndexBuffer, minv, numv, startidx, numtrg, technique); + RenderService->DrawBuffer(-1, cavb->stride, CurentIndexBuffer, minv, numv, startidx, numtrg, + techniques[iTechIndex]); } else { @@ -483,7 +499,7 @@ void GEOM_SERVICE_R::DrawIndexedPrimitive(int32_t minv, int32_t numv, int32_t vr { if (!bCaustic) RenderService->DrawBuffer(CurentVertexBuffer, vrtsize, CurentIndexBuffer, minv, numv, startidx, numtrg, - technique); + techniques[iTechIndex]); else RenderService->DrawIndexedPrimitiveNoVShader(D3DPT_TRIANGLELIST, CurentVertexBuffer, vrtsize, CurentIndexBuffer, minv, numv, startidx, numtrg, "caustic"); diff --git a/src/libs/geometry/src/geometry_r.h b/src/libs/geometry/src/geometry_r.h index c1020b74a..b7c257077 100644 --- a/src/libs/geometry/src/geometry_r.h +++ b/src/libs/geometry/src/geometry_r.h @@ -18,7 +18,8 @@ class GEOMETRY final : public VGEOMETRY GEOS *CreateGeometry(const char *file_name, const char *light_file_name, int32_t flags, const char *lmPath); void DeleteGeometry(GEOS *); ANIMATION *LoadAnimation(const char *anim); - void SetTechnique(const char *name); + void SetTechnique(const char *name, size_t index); + void SetTechniques(char aTechniques[TECHNIQUES_COUNT][256]); void SetVBConvertFunc(VERTEX_TRANSFORM _transform_func); ANIMATION_VB GetAnimationVBDesc(int32_t avb); @@ -64,7 +65,8 @@ class GEOM_SERVICE_R final : public GEOM_SERVICE void SetIndexBuffer(GEOS::ID ibuff); void SetVertexBuffer(int32_t vsize, GEOS::ID vbuff); - void DrawIndexedPrimitive(int32_t minv, int32_t numv, int32_t vrtsize, int32_t startidx, int32_t numtrg); + void DrawIndexedPrimitive(int32_t minv, int32_t numv, int32_t vrtsize, int32_t startidx, + int32_t numtrg, size_t iTechIndex); GEOS::ID CreateLight(const GEOS::LIGHT); void ActivateLight(GEOS::ID n); diff --git a/src/libs/location/src/character.cpp b/src/libs/location/src/character.cpp index 06dbfd43e..28c91fc13 100644 --- a/src/libs/location/src/character.cpp +++ b/src/libs/location/src/character.cpp @@ -330,6 +330,7 @@ void Character::RTuner::Set(MODEL *model, VDX9RENDER *rs) if (a >= 1.0f) { n->SetTechnique("Animation"); + n->SetTechnique("EnvAmmoShader", 1); } else { @@ -3147,6 +3148,21 @@ void Character::ReleaseSound(int32_t id) // Encapsulation // ============================================================================================ + +static size_t characterNameToTechIndex(const char *name) +{ + if (!name) + return 0; + + const char *metalPrefix = "metal_"; + if (!strncmp(metalPrefix, name, strlen(metalPrefix))) + { + return 1; + } + + return 0; +} + bool Character::zLoadModel(MESSAGE &message) { char mpath[300]; @@ -3178,6 +3194,15 @@ bool Character::zLoadModel(MESSAGE &message) } if (gs) gs->SetTexturePath(""); + + + auto model = Model(); + auto node = model->GetNode(0); + if (node) + { + node->SetTechniqueIndexes(characterNameToTechIndex); + } + if (!core.Send_Message(mdl, "ls", MSG_MODEL_LOAD_ANI, ani.c_str()) != 0) { core.Trace("Character animation '%s' not loaded", ani.c_str()); diff --git a/src/libs/location/src/location.cpp b/src/libs/location/src/location.cpp index a5648e26d..f3527618f 100644 --- a/src/libs/location/src/location.cpp +++ b/src/libs/location/src/location.cpp @@ -477,6 +477,20 @@ bool Location::CheckIfLocatorExists(const char *lName) return false; } +static size_t locationNameToTechIndex(const char *name) +{ + if (!name) + return 0; + + const char *metalPrefix = "metal_"; + if (!strncmp(metalPrefix, name, strlen(metalPrefix))) + { + return 1; + } + + return 0; +} + int32_t Location::LoadStaticModel(const char *modelName, const char *tech, int32_t level, bool useDynamicLights) { lights = static_cast(core.GetEntityPointer(lightsid)); @@ -496,6 +510,9 @@ int32_t Location::LoadStaticModel(const char *modelName, const char *tech, int32 model.DeleteModel(im); return -1; } + + node->SetTechniqueIndexesRec(locationNameToTechIndex); + node->SetTechniqueRec("EnvAmmoShader", 1); // for metal auto *const g = node->geo; if (!g) { diff --git a/src/libs/locator/src/blast.cpp b/src/libs/locator/src/blast.cpp index 2cbe02ebc..cc3a0fdfd 100644 --- a/src/libs/locator/src/blast.cpp +++ b/src/libs/locator/src/blast.cpp @@ -214,7 +214,7 @@ void BLAST::Realize(uint32_t Delta_Time) ProcessTime(Delta_Time); - gs->SetTechnique(""); + gs->SetTechnique("", 0); for (n = 0; n < ItemsNum; n++) { if (Item[n].geo) diff --git a/src/libs/model/include/model.h b/src/libs/model/include/model.h index 75e55dd1c..897227160 100644 --- a/src/libs/model/include/model.h +++ b/src/libs/model/include/model.h @@ -45,14 +45,31 @@ class NODE // link model to node virtual void Link(entid_t model, bool transform = true) = 0; - virtual void SetTechnique(const char *name) = 0; - virtual const char *GetTechnique() = 0; + virtual void SetTechnique(const char *name, size_t index = 0) = 0; + virtual void SetTechniqueRec(const char *name, size_t index = 0) = 0; + virtual const char *GetTechnique(size_t index = 0) = 0; virtual bool Init(const char *lightPath, const char *pname, const char *oname, const CMatrix &m, 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; + + void SetTechniqueIndexes(NameToTechniqueFunc ntt) + { + if (geo) + geo->SetTechniques(ntt); + } + + void SetTechniqueIndexesRec(NameToTechniqueFunc ntt) + { + SetTechniqueIndexes(ntt); + for (auto& cur : next) + { + if (cur) + cur->SetTechniqueIndexesRec(ntt); + } + } }; class VDX9RENDER; diff --git a/src/libs/model/src/modelr.h b/src/libs/model/src/modelr.h index 75bf485fe..75feb6309 100644 --- a/src/libs/model/src/modelr.h +++ b/src/libs/model/src/modelr.h @@ -18,7 +18,7 @@ class NODER : public NODE static int32_t depth, node; uintptr_t idGeoGroup; // id of "geometry" string - char technique[256], name[256]; + char techniques[TECHNIQUES_COUNT][256], name[256]; // local radius and center of geometry float geo_radius; @@ -56,8 +56,9 @@ class NODER : public NODE // link model to node void Link(entid_t model, bool transform = true) override; - void SetTechnique(const char *name) override; - const char *GetTechnique() override; + void SetTechnique(const char *name, size_t index = 0) override; + void SetTechniqueRec(const char *name, size_t index = 0) override; + const char *GetTechnique(size_t index = 0) override; // replace only this node model without touching anything else void SubstituteGeometry(const std::string &new_model) override; diff --git a/src/libs/model/src/node.cpp b/src/libs/model/src/node.cpp index c8b8d7d38..fc5ffb2a3 100644 --- a/src/libs/model/src/node.cpp +++ b/src/libs/model/src/node.cpp @@ -180,7 +180,7 @@ bool NODER::Init(const char *lightPath, const char *pname, const char *oname, co { isReleased = false; name[0] = 0; - technique[0] = 0; + memset(techniques, 0, sizeof(techniques)); geoMaterialFunc = nullptr; flags = VISIBLE | VISIBLE_TREE | CLIP_ENABLE | CLIP_ENABLE_TREE | TRACE_ENABLE | TRACE_ENABLE_TREE; @@ -394,10 +394,10 @@ void NODER::Draw() if (p == 4) { rs->SetTransform(D3DTS_WORLD, (D3DMATRIX *)&glob_mtx); - gs->SetTechnique(&technique[0]); + gs->SetTechniques(techniques); if (max_view_dist > 0.f && distance_blend > 0.f) { - gs->SetTechnique("geomdistanceblend"); + gs->SetTechnique("geomdistanceblend", 0); uint32_t dwTFColor; dwTFColor = (static_cast(255.f - 255.f * distance_blend) << 24) | 0xFFFFFF; rs->SetRenderState(D3DRS_TEXTUREFACTOR, dwTFColor); @@ -563,17 +563,30 @@ void NODER::Link(entid_t id, bool transform) //------------------------------------------------------------------- // //------------------------------------------------------------------- -void NODER::SetTechnique(const char *name) +void NODER::SetTechnique(const char *name, size_t index) { - strcpy_s(technique, name); + if (index >= TECHNIQUES_COUNT) + return; + strcpy_s(techniques[index], name); +} + +void NODER::SetTechniqueRec(const char *name, size_t index) +{ + if (index >= TECHNIQUES_COUNT) + return; + SetTechnique(name, index); + for (auto &n : next) + n->SetTechniqueRec(name, index); } //------------------------------------------------------------------- // //------------------------------------------------------------------- -const char *NODER::GetTechnique() +const char *NODER::GetTechnique(size_t index) { - return &technique[0]; + if (index >= TECHNIQUES_COUNT) + index = 0; + return &techniques[index][0]; } void NODER::SetMaxViewDist(float fDist) diff --git a/src/libs/ship/src/ship.cpp b/src/libs/ship/src/ship.cpp index d2edaed7d..d5c40dae5 100644 --- a/src/libs/ship/src/ship.cpp +++ b/src/libs/ship/src/ship.cpp @@ -1424,6 +1424,20 @@ void SHIP::LoadPositionFromAttributes() RecalculateWorldOffset(); } +static size_t shipNameToTechIndex(const char *name) +{ + if (!name) + return 0; + + const char *metalPrefix = "metal_"; + if (!strncmp(metalPrefix, name, strlen(metalPrefix))) + { + return 1; + } + + return 0; +} + bool SHIP::Mount(ATTRIBUTES *_pAShip) { Assert(_pAShip); @@ -1530,6 +1544,8 @@ bool SHIP::Mount(ATTRIBUTES *_pAShip) Assert(pModel); NODE *pNode = pModel->GetNode(0); Assert(pNode); + pNode->SetTechniqueIndexesRec(shipNameToTechIndex); + pNode->SetTechniqueRec("EnvAmmoShader", 1); pNode->geo->GetInfo(ginfo); CalcRealBoxsize(); diff --git a/src/libs/worldmap/src/wdm_render_model.cpp b/src/libs/worldmap/src/wdm_render_model.cpp index 9ad5de519..6f925cd50 100644 --- a/src/libs/worldmap/src/wdm_render_model.cpp +++ b/src/libs/worldmap/src/wdm_render_model.cpp @@ -124,11 +124,11 @@ void WdmRenderModel::Render(VDX9RENDER *rs) const if (a >= 255.0f) { a = 255.0f; - wdmObjects->gs->SetTechnique(tech); + wdmObjects->gs->SetTechnique(tech, 0); } else { - wdmObjects->gs->SetTechnique(techa); + wdmObjects->gs->SetTechnique(techa, 0); rs->SetRenderState(D3DRS_TEXTUREFACTOR, (static_cast(a) << 24) | 0xffffff); } // Check for visibility @@ -144,5 +144,5 @@ void WdmRenderModel::Render(VDX9RENDER *rs) const return; } geo->Draw(nullptr, 0, nullptr); - wdmObjects->gs->SetTechnique(""); + wdmObjects->gs->SetTechnique("", 0); }