Working on web, change python to lua

This commit is contained in:
Vladislav Khorev committed 2026-04-04 14:29:20 +03:00
1 parent 90e2a369f4
commit 178f69967b
14 files changed
+327 -162

No files matched your search

+56 -16
View File
@@ -17,6 +17,10 @@ namespace ZL
return i;
}
}
std::cout << "Bone name not found: " << name << std::endl;
throw std::runtime_error("Bone name not found: " + name);
return -1;
}
@@ -178,22 +182,34 @@ namespace ZL
}
std::cout << "bone names count : " << boneNames.size() << std::endl;
//Now process all the bones:
for (int i = 0; i < numberBones; i++)
{
std::string boneName = boneNames[i];
std::string boneParent = boneParentNames[i];
if (boneParent == "")
if (boneParent == "" || boneParent == "None")
{
bones[i].parent = -1;
}
else
{
/*std::cout << "-Processing bone: " << boneName << ", parent: " << boneParent << " " << "sizeof:" << boneParent.size() << " " << strlen("None") <<
int(boneParent[0])<<","<<
int(boneParent[1]) << ","<<
int(boneParent[2]) << ","<<
int(boneParent[3]) << ","<<
int(boneParent[4]) << "," <<
int(boneParent[5]) << ","
<< std::endl;*/
bones[i].parent = getIndexByValue(boneParent, boneNames);
}
for (int j = 0; j < boneChildren[boneName].size(); j++)
{
//std::cout << "Enumerating bones:" << j << " " << boneName << " " << boneChildren[boneName][j] << std::endl;
bones[i].children.push_back(getIndexByValue(boneChildren[boneName][j], boneNames));
}
@@ -241,7 +257,7 @@ namespace ZL
//==== process uv and normals begin
std::cout << "Hello x1" << std::endl;
//std::cout << "Hello x1" << std::endl;
std::getline(f, tempLine); //===UV Coordinates:
@@ -310,7 +326,7 @@ namespace ZL
}
std::cout << "Hello eee" << std::endl;
//std::cout << "Hello eee" << std::endl;
std::getline(f, tempLine); //===Normals:
@@ -395,10 +411,9 @@ namespace ZL
{
std::getline(f, tempLine); //Group: 'Bone', Weight: 0.9929084181785583
if (std::regex_search(tempLine, match, pattern_bone_weight)) {
// ��������� ����� (��� �������)
std::string word = match.str(1);
double weight = std::stod(match.str(2));
//std::cout << "Bone name: " << word << ", weight: " << weight << std::endl;
int boneNumber = getIndexByValue(word, boneNames);
localVerticesBoneWeight[i][j].boneIndex = boneNumber;
localVerticesBoneWeight[i][j].weight = weight;
@@ -450,10 +465,10 @@ namespace ZL
throw std::runtime_error("No number found in the input string.");
}
if (i == 0)
/*if (i == 0)
{
startingFrame == numberFrame;
}
startingFrame = numberFrame;
}*/
animations[0].keyFrames[i].frame = numberFrame;
@@ -463,6 +478,7 @@ namespace ZL
{
std::getline(f, tempLine);
std::string boneName = tempLine.substr(8);
//std::cout << "Processing keyframe " << i << ", bone: " << j << " " << boneName << std::endl;
int boneNumber = getIndexByValue(boneName, boneNames);
animations[0].keyFrames[i].bones[boneNumber] = startBones[boneNumber];
@@ -588,6 +604,7 @@ namespace ZL
if (startingFrame == -1)
{
std::cout << "Exception here: frame number is out of range of keyframes. Frame: " << frame << std::endl;
throw std::runtime_error("Exception here");
}
@@ -601,7 +618,6 @@ namespace ZL
std::vector<Bone>& nextFrameBones = animations[0].keyFrames[startingFrame+1].bones;
std::vector<Matrix4f> skinningMatrixForEachBone;
//std::vector<Matrix3f> skinningMatrixForEachBone;
skinningMatrixForEachBone.resize(currentBones.size());
@@ -645,7 +661,14 @@ namespace ZL
skinningMatrixForEachBone[i] = currentBoneMatrixWorld4 * inverstedStartBoneMatrixWorld4;
}
/*std::cout << "m=" << skinningMatrixForEachBone[5] << std::endl;
std::cout << "Start Mesh data " << std::endl;
std::cout << startMesh.PositionData[0] << std::endl;
std::cout << startMesh.PositionData[10] << std::endl;
std::cout << startMesh.PositionData[100] << std::endl;
*/
for (int i = 0; i < mesh.PositionData.size(); i++)
{
Vector4f originalPos = {
@@ -661,16 +684,36 @@ namespace ZL
{
if (verticesBoneWeight[i][j].weight != 0)
{
if (verticesBoneWeight[i][j].boneIndex == -1)
{
std::cout << "Exception here: bone index is -1 but weight is > 0" << std::endl;
throw std::runtime_error("Bones loaded incorrectly - bone index is -1 but weight is > 0");
}
vMoved = true;
//finalPos = finalPos + MultVectorMatrix(originalPos, skinningMatrixForEachBone[verticesBoneWeight[i][j].boneIndex]) * verticesBoneWeight[i][j].weight;
finalPos = finalPos + (skinningMatrixForEachBone[verticesBoneWeight[i][j].boneIndex] * originalPos) * verticesBoneWeight[i][j].weight;
/*if (i == 100)
{
std::cout << "bone index=" << verticesBoneWeight[i][j].boneIndex << std::endl;
std::cout << "weight=" << verticesBoneWeight[i][j].weight << std::endl;
std::cout << "skinning matrix=" << skinningMatrixForEachBone[verticesBoneWeight[i][j].boneIndex] << std::endl;
std::cout << "original pos=" << originalPos.transpose() << std::endl;
std::cout << "final pos=" << finalPos.transpose() << std::endl;
std::cout << "-----------------" << std::endl;
}*/
}
}
if (abs(finalPos(0) - originalPos(0)) > 1 || abs(finalPos(1) - originalPos(1)) > 1 || abs(finalPos(2) - originalPos(2)) > 1)
/*if (i == 100)
{
std::cout << originalPos << std::endl;
std::cout << finalPos << std::endl;
}*/
/*if (abs(finalPos(0) - originalPos(0)) > 1 || abs(finalPos(1) - originalPos(1)) > 1 || abs(finalPos(2) - originalPos(2)) > 1)
{
}
}*/
if (!vMoved)
{
@@ -682,9 +725,6 @@ namespace ZL
mesh.PositionData[i](2) = finalPos(2);
}
}
+4
View File
@@ -1,5 +1,6 @@
#include "Character.h"
#include <cmath>
#include <iostream>
namespace ZL {
@@ -29,6 +30,7 @@ AnimationState Character::resolveActiveState() const {
}
void Character::update(int64_t deltaMs) {
//std::cout << "update called with deltaMs: " << deltaMs << std::endl;
// Move toward walk target on the XZ plane
Eigen::Vector3f toTarget = walkTarget - position;
toTarget.y() = 0.f;
@@ -72,6 +74,7 @@ void Character::update(int64_t deltaMs) {
auto& anim = it->second;
anim.currentFrame += static_cast<float>(deltaMs) / 24.f;
//std::cout << "Current animation frame: " << anim.currentFrame << " / " << anim.totalFrames << " -- " << anim.lastFrame << std::endl;
if (static_cast<int>(anim.currentFrame) >= anim.totalFrames-1) {
anim.currentFrame = anim.model.startingFrame;
}
@@ -82,6 +85,7 @@ void Character::update(int64_t deltaMs) {
}
void Character::draw(Renderer& renderer) {
//std::cout << "draw called for Character at position: " << position.transpose() << std::endl;
AnimationState drawState = resolveActiveState();
auto it = animations.find(drawState);
if (it == animations.end() || !texture) return;
+6
View File
@@ -9,6 +9,12 @@
namespace ZL {
#ifdef EMSCRIPTEN
using std::min;
using std::max;
#endif
constexpr float DEFAULT_ZOOM = 36.f;
class Environment {
+27 -6
View File
@@ -39,6 +39,7 @@ namespace ZL
Game* Game::s_instance = nullptr;
void Game::onResourcesZipLoaded(const char* /*filename*/) {
std::cout << "Resources.zip loaded successfully" << std::endl;
if (s_instance) {
s_instance->mainThreadHandler.EnqueueMainThreadTask([&]() {
s_instance->setupPart2();
@@ -47,7 +48,7 @@ namespace ZL
}
void Game::onResourcesZipError(const char* /*filename*/) {
std::cerr << "Failed to download resources.zip" << std::endl;
std::cout << "Failed to download resources.zip" << std::endl;
}
#endif
@@ -84,7 +85,7 @@ namespace ZL
renderer.shaderManager.AddShaderFromFiles("defaultColor", "resources/shaders/defaultColor.vertex", "resources/shaders/defaultColor_desktop.fragment", CONST_ZIP_FILE);
renderer.shaderManager.AddShaderFromFiles("default", "resources/shaders/default.vertex", "resources/shaders/default_desktop.fragment", CONST_ZIP_FILE);
#endif
loadingTexture = std::make_unique<Texture>(CreateTextureDataFromPng("resources/loading.png", CONST_ZIP_FILE));
loadingTexture = std::make_unique<Texture>(CreateTextureDataFromPng("resources/loading.png", ""));
float minDimension;
float width = Environment::projectionWidth;
@@ -139,22 +140,28 @@ namespace ZL
renderer.shaderManager.AddShaderFromFiles("spark", "resources/shaders/spark.vertex", "resources/shaders/spark_desktop.fragment", CONST_ZIP_FILE);
#endif
std::cout << "Load resurces step 4" << std::endl;
roomTexture = std::make_unique<Texture>(CreateTextureDataFromPng("resources/w/room005.png", CONST_ZIP_FILE));
roomMesh.data = LoadFromTextFile02("resources/w/room001.txt", CONST_ZIP_FILE);
roomMesh.data.RotateByMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-M_PI*0.5, Eigen::Vector3f::UnitY())).toRotationMatrix());
roomMesh.RefreshVBO();
std::cout << "Load resurces step 5" << std::endl;
fireboxTexture = std::make_unique<Texture>(CreateTextureDataFromPng("resources/w/Cube001.png", CONST_ZIP_FILE));
fireboxMesh.data = LoadFromTextFile02("resources/w/firebox.txt", CONST_ZIP_FILE);
fireboxMesh.data.RotateByMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-M_PI * 0.5, Eigen::Vector3f::UnitY())).toRotationMatrix());
fireboxMesh.RefreshVBO();
std::cout << "Load resurces step 6" << std::endl;
inaiTexture = std::make_unique<Texture>(CreateTextureDataFromPng("resources/w/inai001.png", CONST_ZIP_FILE));
std::cout << "Load resurces step 6.1" << std::endl;
inaiMesh.data = LoadFromTextFile02("resources/w/inai001.txt", CONST_ZIP_FILE);
inaiMesh.data.RotateByMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-M_PI * 0.5, Eigen::Vector3f::UnitY())).toRotationMatrix());
inaiMesh.data.Move({ 2.5, 1.4, -9.9 });
inaiMesh.RefreshVBO();
std::cout << "Load resurces step 7" << std::endl;
benchTexture = std::make_unique<Texture>(CreateTextureDataFromPng("resources/w/bench001opt.png", CONST_ZIP_FILE));
benchMesh.data = LoadFromTextFile02("resources/w/bench002opt.txt", CONST_ZIP_FILE);
benchMesh.data.Scale(3.f);
@@ -162,6 +169,8 @@ namespace ZL
benchMesh.data.Move({ -2.1, 0.5, -7.9 });
benchMesh.RefreshVBO();
std::cout << "Load resurces step 8" << std::endl;
auto violaTexture = std::make_shared<Texture>(CreateTextureDataFromPng("resources/viola.png", CONST_ZIP_FILE));
// Player (Viola)
@@ -176,39 +185,51 @@ namespace ZL
Eigen::Quaternionf(Eigen::AngleAxisf(-M_PI * 0.5f, Eigen::Vector3f::UnitX())) *
Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitZ()));
std::cout << "Load resurces step 9" << std::endl;
auto defaultTexture = std::make_shared<Texture>(CreateTextureDataFromPng("resources/w/default_skin001.png", CONST_ZIP_FILE));
auto npc01 = std::make_unique<Character>();
npc01->loadAnimation(AnimationState::IDLE, "resources/w/default_idle002.txt", CONST_ZIP_FILE);
npc01->loadAnimation(AnimationState::WALK, "resources/w/default_walk001.txt", CONST_ZIP_FILE);
//npc01->loadAnimation(AnimationState::IDLE, "resources/idleviola_uv010.txt", CONST_ZIP_FILE);
//npc01->loadAnimation(AnimationState::WALK, "resources/walkviola_uv010.txt", CONST_ZIP_FILE);
npc01->setTexture(defaultTexture);
npc01->walkSpeed = 1.5f;
npc01->rotationSpeed = 8.0f;
npc01->modelScale = 0.01f;
//npc01->modelScale = 0.1f;
npc01->modelCorrectionRotation = Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitY()));
npc01->position = Eigen::Vector3f(0.f, 0.f, -45.f);
std::cout << "Load resurces step 10" << std::endl;
npc01->position = Eigen::Vector3f(0.f, 0.f, -10.f);
npc01->setTarget(npc01->position);
npcs.push_back(std::move(npc01));
auto ghostTexture = std::make_shared<Texture>(CreateTextureDataFromPng("resources/w/ghost_skin001.png", CONST_ZIP_FILE));
std::cout << "Load resurces step 11" << std::endl;
auto npc02 = std::make_unique<Character>();
//npc02->loadAnimation(AnimationState::IDLE, "resources/w/default_float001.txt", CONST_ZIP_FILE);
npc02->loadAnimation(AnimationState::IDLE, "resources/w/float_attack003.txt", CONST_ZIP_FILE);
npc02->loadAnimation(AnimationState::IDLE, "resources/w/default_float001.txt", CONST_ZIP_FILE);
//npc02->loadAnimation(AnimationState::IDLE, "resources/w/float_attack003.txt", CONST_ZIP_FILE);
//npc02->loadAnimation(AnimationState::IDLE, "resources/idleviola_uv010.txt", CONST_ZIP_FILE);
npc02->setTexture(ghostTexture);
npc02->walkSpeed = 1.5f;
npc02->rotationSpeed = 8.0f;
npc02->modelScale = 0.01f;
//npc02->modelScale = 0.1f;
npc02->modelCorrectionRotation = Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitY()));
npc02->position = Eigen::Vector3f(0.f, 0.f, -20.f);
npc02->setTarget(npc02->position);
npcs.push_back(std::move(npc02));
std::cout << "Load resurces step 12" << std::endl;
loadingCompleted = true;
scriptEngine.init(this);
std::cout << "Load resurces step 13" << std::endl;
}
+43 -57
View File
@@ -1,74 +1,60 @@
#include "ScriptEngine.h"
#include "Game.h"
#include <pybind11/embed.h>
#include <iostream>
#include <fstream>
namespace py = pybind11;
// Static pointer used by the embedded module (set before interpreter starts).
static ZL::Game* s_game = nullptr;
// The embedded module must be defined at file scope before the interpreter
// is started. It exposes a minimal surface: one function per scripting command.
PYBIND11_EMBEDDED_MODULE(game_api, m) {
m.doc() = "Game scripting API";
// npc_walk_to(index, x, y, z, on_arrived=None)
// Tells the NPC at `index` to walk to (x,y,z).
// on_arrived is an optional Python callable invoked once when the NPC arrives.
// It can call npc_walk_to again (or anything else) to chain behaviour.
m.def("npc_walk_to", [](int index, float x, float y, float z, py::object on_arrived) {
if (!s_game) {
std::cerr << "[script] game_api.npc_walk_to: engine not ready\n";
return;
}
auto& npcs = s_game->npcs;
if (index < 0 || index >= static_cast<int>(npcs.size())) {
std::cerr << "[script] game_api.npc_walk_to: index " << index
<< " out of range (0.." << npcs.size() - 1 << ")\n";
return;
}
std::function<void()> cb;
if (!on_arrived.is_none()) {
cb = [on_arrived]() {
try {
on_arrived();
} catch (const py::error_already_set& e) {
std::cerr << "[script] on_arrived callback error:\n" << e.what() << "\n";
}
};
}
npcs[index]->setTarget(Eigen::Vector3f(x, y, z), std::move(cb));
},
py::arg("index"), py::arg("x"), py::arg("y"), py::arg("z"),
py::arg("on_arrived") = py::none(),
"Command NPC[index] to walk to (x,y,z). on_arrived is called when the NPC arrives.");
}
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
namespace ZL {
struct ScriptEngine::Impl {
sol::state lua;
};
ScriptEngine::ScriptEngine() = default;
ScriptEngine::~ScriptEngine() = default;
void ScriptEngine::init(Game* game) {
s_game = game;
interpreter = std::make_unique<py::scoped_interpreter>();
runScript("resources/start.py");
impl = std::make_unique<Impl>();
sol::state& lua = impl->lua;
lua.open_libraries(sol::lib::base, sol::lib::math, sol::lib::string, sol::lib::table);
auto api = lua.create_named_table("game_api");
// npc_walk_to(index, x, y, z [, on_arrived])
// on_arrived is an optional Lua function called when the NPC reaches the target.
// It can call npc_walk_to again (or anything else) to chain behaviour.
api.set_function("npc_walk_to",
[game](int index, float x, float y, float z, sol::object on_arrived) {
auto& npcs = game->npcs;
if (index < 0 || index >= static_cast<int>(npcs.size())) {
std::cerr << "[script] npc_walk_to: index " << index
<< " out of range (0.." << npcs.size() - 1 << ")\n";
return;
}
std::function<void()> cb;
if (on_arrived.is<sol::protected_function>()) {
sol::protected_function fn = on_arrived.as<sol::protected_function>();
cb = [fn]() mutable {
auto result = fn();
if (!result.valid()) {
sol::error err = result;
std::cerr << "[script] on_arrived error: " << err.what() << "\n";
}
};
}
npcs[index]->setTarget(Eigen::Vector3f(x, y, z), std::move(cb));
});
runScript("resources/start.lua");
}
void ScriptEngine::runScript(const std::string& path) {
std::ifstream file(path);
if (!file.is_open()) {
std::cerr << "[script] Could not open script: " << path << "\n";
return;
}
std::string source((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
try {
py::exec(source);
} catch (const py::error_already_set& e) {
std::cerr << "[script] Error in " << path << ":\n" << e.what() << "\n";
auto result = impl->lua.safe_script_file(path, sol::script_pass_on_error);
if (!result.valid()) {
sol::error err = result;
std::cerr << "[script] Error in " << path << ": " << err.what() << "\n";
}
}
+3 -5
View File
@@ -2,9 +2,6 @@
#include <string>
#include <memory>
// Forward-declare the heavy pybind11 type so including this header stays cheap.
namespace pybind11 { class scoped_interpreter; }
namespace ZL {
class Game;
@@ -17,11 +14,12 @@ public:
// Must be called once, after the Game's NPCs are ready.
void init(Game* game);
// Execute a Python script file. Logs errors to stderr.
// Execute a Lua script file. Logs errors to stderr.
void runScript(const std::string& path);
private:
std::unique_ptr<pybind11::scoped_interpreter> interpreter;
struct Impl;
std::unique_ptr<Impl> impl;
};
} // namespace ZL
+13 -14
View File
@@ -51,6 +51,7 @@ namespace ZL
numberVertices = std::stoi(number_str);
}
else {
std::cout << "No number found in the input string: " << tempLine << std::endl;
throw std::runtime_error("No number found in the input string.");
}
@@ -85,7 +86,8 @@ namespace ZL
numberTriangles = std::stoi(number_str);
}
else {
throw std::runtime_error("No number found in the input string.");
std::cout << "-No number found in the input string: " << tempLine << std::endl;
throw std::runtime_error("-No number found in the input string.");
}
@@ -105,11 +107,13 @@ namespace ZL
uvCount = std::stoi(number_str);
}
else {
throw std::runtime_error("No number found in the input string.");
std::cout << "2 No number found in the input string: " << tempLine << std::endl;
throw std::runtime_error("2 No number found in the input string.");
}
if (uvCount != 3)
{
std::cout << "UV count is not 3 for triangle " << i << ": " << uvCount << std::endl;
throw std::runtime_error("more than 3 uvs");
}
@@ -129,6 +133,7 @@ namespace ZL
if (floatValues.size() != 2)
{
std::cout << "UV count is not 2: " << j << " " << floatValues.size() << std::endl;
throw std::runtime_error("more than 2 uvs---");
}
@@ -136,7 +141,7 @@ namespace ZL
}
}
std::cout << "Normals go" << std::endl;
//std::cout << "Normals go" << std::endl;
std::getline(f, tempLine); //===Normals:
@@ -160,7 +165,7 @@ namespace ZL
normals[i] = Vector3f{ floatValues[0], floatValues[1], floatValues[2] };
}
std::cout << "Triangles go:" << std::endl;
//std::cout << "Triangles go:" << std::endl;
std::getline(f, tempLine); //===Triangles: 3974
@@ -198,11 +203,6 @@ namespace ZL
result.PositionData.push_back(vertices[triangles[i][1]]);
result.PositionData.push_back(vertices[triangles[i][2]]);
/*
result.NormalData.push_back(normals[triangles[i][0]]);
result.NormalData.push_back(normals[triangles[i][1]]);
result.NormalData.push_back(normals[triangles[i][2]]);
*/
result.TexCoordData.push_back(uvCoords[i][0]);
result.TexCoordData.push_back(uvCoords[i][1]);
result.TexCoordData.push_back(uvCoords[i][2]);
@@ -280,6 +280,7 @@ namespace ZL
numberVertices = std::stoi(match.str());
}
else {
std::cout << "Vertices header not found or invalid: " << tempLine << std::endl;
throw std::runtime_error("Vertices header not found or invalid.");
}
@@ -314,14 +315,10 @@ namespace ZL
// UV - [7], [8]
if (floatValues.size() < 9) {
std::cout << "Malformed vertex line at index " << i << ": " << tempLine << std::endl;
throw std::runtime_error("Malformed vertex line at index " + std::to_string(i));
}
/*if (floatValues[2] > 1.f)
{
std::cout << "got" << std::endl;
}*/
tempPositions[i] = Vector3f{ floatValues[1], floatValues[2], floatValues[3] };
tempNormals[i] = Vector3f{ floatValues[4], floatValues[5], floatValues[6] };
tempUVs[i] = Vector2f{ floatValues[7], floatValues[8] };
@@ -339,6 +336,7 @@ namespace ZL
numberTriangles = std::stoi(match.str());
}
else {
std::cout << "Triangles header not found or invalid: " << tempLine << std::endl;
throw std::runtime_error("Triangles header not found.");
}
@@ -363,6 +361,7 @@ namespace ZL
}
if (indices.size() != 3) {
std::cout << "Malformed triangle line at index " << i << ": " << tempLine << std::endl;
throw std::runtime_error("Malformed triangle line at index " + std::to_string(i));
}