Some strange shit happens

This commit is contained in:
Vladislav Khorev 2026-04-22 22:38:20 +03:00
parent 4d9a5b0a6e
commit c655678486
10 changed files with 148 additions and 36 deletions

View File

@ -3,9 +3,19 @@
{
"id": "npc_01_default",
"name": "NPC Default Guard",
"texturePath": "resources/w/default_skin001.png",
"animationIdlePath": "resources/w/default_idle002.anim",
"animationWalkPath": "resources/w/default_walk001.anim",
"animationIdlePath": "resources/w/new_anims/gg_stand_idle003.anim",
"animationWalkPath": "resources/w/new_anims/gg_run003.anim",
"meshTextures": {
"Body": "resources/w/new_anims/male_packed0_diffuse.png",
"Bottoms": "resources/w/new_anims/male_packed1_diffuse.png",
"Eyelashes": "resources/w/new_anims/male_packed0_diffuse.png",
"Eyes": "resources/w/new_anims/male_packed0_diffuse.png",
"Eyewear": "resources/w/new_anims/male_packed0_diffuse.png",
"Gloves": "resources/w/new_anims/male_packed1_diffuse.png",
"Hair": "resources/w/new_anims/male_packed0_diffuse.png",
"Shoes": "resources/w/new_anims/male_packed1_diffuse.png",
"Tops": "resources/w/new_anims/male_packed2_diffuse.png"
},
"positionX": 0.0,
"positionY": 0.0,
"positionZ": -10.0,

BIN
resources/w/new_anims/male_packed0_diffuse.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resources/w/new_anims/male_packed1_diffuse.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resources/w/new_anims/male_packed2_diffuse.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -74,6 +74,27 @@ void Character::setPathPlanner(PathPlanner planner) {
pathPlanner = std::move(planner);
}
void Character::setTexture(std::shared_ptr<ZL::Texture> texture)
{
for (auto& animEntry : animations) {
for (const auto& name : animEntry.second.model.meshNamesOrdered) {
meshTextures[name] = texture;
}
}
}
void Character::setTexture(const std::string& meshName, std::shared_ptr<Texture> tex) {
meshTextures[meshName] = std::move(tex);
}
/*
void Character::setTexture(std::shared_ptr<Texture> tex) {
for (auto& animEntry : animations) {
for (const auto& name : animEntry.second.model.meshNamesOrdered) {
meshTextures[name] = tex;
}
}
}
*/
AnimationState Character::resolveActiveState() const {
if (animations.count(currentState)) return currentState;
@ -299,7 +320,7 @@ void Character::draw(Renderer& renderer) {
AnimationState drawState = resolveActiveState();
auto it = animations.find(drawState);
if (it == animations.end() || !texture) return;
if (it == animations.end()) return;
renderer.shaderManager.PushShader(defaultShaderName);
renderer.RenderUniform1i(textureUniformName, 0);
@ -315,10 +336,12 @@ void Character::draw(Renderer& renderer) {
renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix());
auto& anim = it->second;
glBindTexture(GL_TEXTURE_2D, texture->getTexID());
for (const auto& name : anim.model.meshNamesOrdered) {
auto mit = anim.model.meshes.find(name);
if (mit == anim.model.meshes.end()) continue;
auto tit = meshTextures.find(name);
if (tit == meshTextures.end() || !tit->second) continue;
glBindTexture(GL_TEXTURE_2D, tit->second->getTexID());
modelMutable.AssignFrom(mit->second.mesh);
modelMutable.RefreshVBO();
renderer.DrawVertexRenderStruct(modelMutable);
@ -335,7 +358,7 @@ void Character::draw(Renderer& renderer) {
void Character::drawGpuSkinning(Renderer& renderer) {
AnimationState drawState = resolveActiveState();
auto it = animations.find(drawState);
if (it == animations.end() || !texture)
if (it == animations.end())
{
return;
}
@ -372,9 +395,14 @@ void Character::drawGpuSkinning(Renderer& renderer) {
static_cast<int>(anim.gpuSkinningShaderData.skinningMatrices.size()), false,
anim.gpuSkinningShaderData.skinningMatrices[0].data());
glBindTexture(GL_TEXTURE_2D, texture->getTexID());
anim.gpuSkinningShaderData.RenderVBO(renderer, anim.model.meshNamesOrdered);
for (const auto& name : anim.model.meshNamesOrdered) {
auto pit = anim.gpuSkinningShaderData.perMesh.find(name);
if (pit == anim.gpuSkinningShaderData.perMesh.end()) continue;
auto tit = meshTextures.find(name);
if (tit == meshTextures.end() || !tit->second) continue;
glBindTexture(GL_TEXTURE_2D, tit->second->getTexID());
pit->second.RenderVBO(renderer);
}
renderer.PopMatrix();
@ -474,6 +502,8 @@ void Character::drawShadowDepthCpu(Renderer& renderer) {
for (const auto& name : anim.model.meshNamesOrdered) {
auto mit = anim.model.meshes.find(name);
if (mit == anim.model.meshes.end()) continue;
auto tit = meshTextures.find(name);
if (tit == meshTextures.end() || !tit->second) continue;
modelMutable.AssignFrom(mit->second.mesh);
modelMutable.RefreshVBO();
renderer.DrawVertexRenderStruct(modelMutable);
@ -514,7 +544,13 @@ void Character::drawShadowDepthGpuSkinning(Renderer& renderer) {
it->second.gpuSkinningShaderData.skinningMatrices[0].data());
CheckGlError(__FILE__, __LINE__);
it->second.gpuSkinningShaderData.RenderVBO(renderer, it->second.model.meshNamesOrdered);
for (const auto& name : it->second.model.meshNamesOrdered) {
auto pit = it->second.gpuSkinningShaderData.perMesh.find(name);
if (pit == it->second.gpuSkinningShaderData.perMesh.end()) continue;
auto tit = meshTextures.find(name);
if (tit == meshTextures.end() || !tit->second) continue;
pit->second.RenderVBO(renderer);
}
CheckGlError(__FILE__, __LINE__);
renderer.PopMatrix();
@ -538,7 +574,7 @@ void Character::drawWithShadow(Renderer& renderer, const Eigen::Matrix4f& lightF
void Character::drawCpuWithShadow(Renderer& renderer, const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const Eigen::Vector3f& lightDirCamera) {
AnimationState drawState = resolveActiveState();
auto it = animations.find(drawState);
if (it == animations.end() || !texture) return;
if (it == animations.end()) return;
static const std::string shadowShader = "default_shadow";
@ -563,10 +599,12 @@ void Character::drawCpuWithShadow(Renderer& renderer, const Eigen::Matrix4f& lig
renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix());
auto& anim = it->second;
glBindTexture(GL_TEXTURE_2D, texture->getTexID());
for (const auto& name : anim.model.meshNamesOrdered) {
auto mit = anim.model.meshes.find(name);
if (mit == anim.model.meshes.end()) continue;
auto tit = meshTextures.find(name);
if (tit == meshTextures.end() || !tit->second) continue;
glBindTexture(GL_TEXTURE_2D, tit->second->getTexID());
modelMutable.AssignFrom(mit->second.mesh);
modelMutable.RefreshVBO();
renderer.DrawVertexRenderStruct(modelMutable);
@ -586,7 +624,7 @@ void Character::drawCpuWithShadow(Renderer& renderer, const Eigen::Matrix4f& lig
void Character::drawGpuSkinningWithShadow(Renderer& renderer, const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const Eigen::Vector3f& lightDirCamera) {
AnimationState drawState = resolveActiveState();
auto it = animations.find(drawState);
if (it == animations.end() || !texture) return;
if (it == animations.end()) return;
CheckGlError(__FILE__, __LINE__);
@ -627,10 +665,15 @@ void Character::drawGpuSkinningWithShadow(Renderer& renderer, const Eigen::Matri
it->second.gpuSkinningShaderData.skinningMatrices[0].data());
CheckGlError(__FILE__, __LINE__);
glBindTexture(GL_TEXTURE_2D, texture->getTexID());
CheckGlError(__FILE__, __LINE__);
it->second.gpuSkinningShaderData.RenderVBO(renderer, it->second.model.meshNamesOrdered);
for (const auto& name : it->second.model.meshNamesOrdered) {
auto pit = it->second.gpuSkinningShaderData.perMesh.find(name);
if (pit == it->second.gpuSkinningShaderData.perMesh.end()) continue;
auto tit = meshTextures.find(name);
if (tit == meshTextures.end() || !tit->second) continue;
glBindTexture(GL_TEXTURE_2D, tit->second->getTexID());
pit->second.RenderVBO(renderer);
}
renderer.PopMatrix();

View File

@ -9,6 +9,7 @@
#include <string>
#include <cstdint>
#include <vector>
#include <unordered_map>
namespace ZL {
@ -30,9 +31,11 @@ public:
void loadAnimation(AnimationState state, const std::string& filename, const std::string& zipFile = "");
void loadBinaryAnimation(AnimationState state, const std::string& filename, const std::string& zipFile = "");
void setTexture(std::shared_ptr<Texture> texture) {
this->texture = texture;
}
// Assigns the given texture to a specific mesh (by name, as defined in the animation file).
void setTexture(const std::string& meshName, std::shared_ptr<Texture> texture);
// Assigns the given texture to every mesh in every loaded animation.
// Call AFTER loading animations so the mesh names are known.
void setTexture(std::shared_ptr<ZL::Texture> texture);
void update(int64_t deltaMs);
// onArrived is called once when the character reaches this target.
// From Python you can chain further commands (walk, wait, trigger others).
@ -87,7 +90,7 @@ private:
std::map<AnimationState, BoneAnimationDataNew> animations;
VertexRenderStruct modelMutable;
std::shared_ptr<Texture> texture;
std::unordered_map<std::string, std::shared_ptr<Texture>> meshTextures;
Eigen::Vector3f walkTarget = Eigen::Vector3f(0.f, 0.f, 0.f);
Eigen::Vector3f requestedWalkTarget = Eigen::Vector3f(0.f, 0.f, 0.f);

View File

@ -24,6 +24,17 @@
namespace ZL
{
void set_Texture(Character& npc, TextureDataStruct& texture)
{
auto tt = std::make_shared<Texture>(texture);
npc.setTexture(tt);
}
void set_Texture(Character& npc, const std::string& meshName, TextureDataStruct& texture)
{
auto tt = std::make_shared<Texture>(texture);
npc.setTexture(meshName, tt);
}
#ifdef EMSCRIPTEN
const char* CONST_ZIP_FILE = "resources.zip";
#else

View File

@ -11,7 +11,7 @@
#include <memory>
#include <cfloat>
#include "GameConstants.h"
#include "Character.h"
namespace ZL
@ -91,7 +91,7 @@ namespace ZL
std::cout << "Load resurces step 9" << std::endl;
// Load NPCs from JSON
npcs = GameObjectLoader::loadAndCreateNpcs("resources/config2/npcs.json", CONST_ZIP_FILE);
npcs = GameObjectLoader::loadAndCreate_Npcs("resources/config2/npcs.json", CONST_ZIP_FILE);
auto ghostTexture = std::make_shared<Texture>(CreateTextureDataFromPng("resources/w/ghost_skin001.png", CONST_ZIP_FILE));

View File

@ -6,15 +6,18 @@
#include "render/TextureManager.h"
#include "utils/Utils.h"
#include <Eigen/Geometry>
#include "../Character.h"
namespace ZL {
void set_Texture(Character& npc, TextureDataStruct& texture);
void set_Texture(Character& npc, const std::string& meshName, TextureDataStruct& texture);
using json = nlohmann::json;
std::vector<GameObjectData> GameObjectLoader::loadFromJson(const std::string& jsonPath, const std::string& zipPath)
{
std::vector<GameObjectData> objects;
std::string content;
try {
if (zipPath.empty()) {
@ -34,6 +37,7 @@ namespace ZL {
throw std::runtime_error("Failed to load UI file: " + jsonPath);
}
json j;
try {
j = json::parse(content);
@ -340,6 +344,13 @@ namespace ZL {
data.id = item.value("id", "npc_unknown");
data.name = item.value("name", "Unknown NPC");
data.texturePath = item.value("texturePath", "");
if (item.contains("meshTextures") && item["meshTextures"].is_object()) {
for (auto it = item["meshTextures"].begin(); it != item["meshTextures"].end(); ++it) {
if (it.value().is_string()) {
data.meshTextures[it.key()] = it.value().get<std::string>();
}
}
}
data.interactionRadius = item.value("interactionRadius", 0.0f);
data.animationIdlePath = item.value("animationIdlePath", "");
data.animationWalkPath = item.value("animationWalkPath", "");
@ -378,7 +389,7 @@ namespace ZL {
return npcs;
}
std::vector<std::unique_ptr<Character>> GameObjectLoader::loadAndCreateNpcs(
std::vector<std::unique_ptr<Character>> GameObjectLoader::loadAndCreate_Npcs(
const std::string& jsonPath,
const std::string& zipPath)
{
@ -424,11 +435,31 @@ namespace ZL {
continue;
}
// Load texture
// Load textures: per-mesh map takes precedence; fall back to single texturePath.
try {
auto texture = std::make_shared<Texture>(CreateTextureDataFromPng(npcData.texturePath, zipPath.c_str()));
npc->setTexture(texture);
std::cout << " Loaded texture: " << npcData.texturePath << std::endl;
if (!npcData.meshTextures.empty()) {
std::unordered_map<std::string, std::shared_ptr<Texture>> cache;
for (const auto& entry : npcData.meshTextures) {
const std::string& meshName = entry.first;
const std::string& path = entry.second;
/*auto cit = cache.find(path);
if (cit == cache.end()) {
auto tex = std::make_shared<Texture>(CreateTextureDataFromPng(path, zipPath.c_str()));
cit = cache.emplace(path, std::move(tex)).first;
std::cout << " Loaded texture: " << path << std::endl;
}*/
//npc->setTexture(meshName, std::make_shared<Texture>(CreateTextureDataFromPng(path, zipPath.c_str())));
set_Texture(*npc, meshName, CreateTextureDataFromPng(path, zipPath.c_str()));
//std::cout << xxa(*npc, CreateTextureDataFromPng(path, zipPath.c_str())) << std::endl;
std::cout << " -> mesh '" << meshName << "'" << std::endl;
}
}
else {
//auto texture = std::make_shared<Texture>(CreateTextureDataFromPng(npcData.texturePath, zipPath.c_str()));
set_Texture(*npc, CreateTextureDataFromPng(npcData.texturePath, zipPath.c_str()));
//std::cout << xxa(*npc, CreateTextureDataFromPng(npcData.texturePath, zipPath.c_str())) << std::endl;
std::cout << " Loaded texture: " << npcData.texturePath << std::endl;
}
}
catch (const std::exception& e) {
std::cerr << "GameObjectLoader: Failed to load texture for '" << npcData.name << "': " << e.what() << std::endl;

View File

@ -3,15 +3,18 @@
#include <vector>
#include <memory>
#include <unordered_map>
#include <map>
#include "external/nlohmann/json.hpp"
#include "TextModel.h"
#include "InteractiveObject.h"
#include "Character.h"
namespace ZL {
//#include "Character.h"
//#include "render/TextureManager.h"
struct Texture;
struct VertexRenderStruct;
class Renderer;
namespace ZL {
//struct Texture;
//struct VertexRenderStruct;
//class Renderer;
class Character;
struct GameObjectData {
@ -45,6 +48,7 @@ namespace ZL {
std::string id;
std::string name;
std::string texturePath;
std::map<std::string, std::string> meshTextures;
std::string animationIdlePath;
std::string animationWalkPath;
float positionX = 0.0f;
@ -82,7 +86,7 @@ namespace ZL {
const std::string& zipPath = ""
);
static std::vector<std::unique_ptr<Character>> loadAndCreateNpcs(
static std::vector<std::unique_ptr<ZL::Character>> loadAndCreate_Npcs(
const std::string& jsonPath,
const std::string& zipPath = ""
);
@ -90,4 +94,5 @@ namespace ZL {
static std::vector<NpcData> loadNpcsFromJson(const std::string& jsonPath, const std::string& zipPath = "");
};
} // namespace ZL
} // namespace ZL