Compare commits

...

2 Commits

Author SHA1 Message Date
OusmBlueNinja
7a51dad87f Fixed Formatting 2024-12-31 14:29:20 -06:00
OusmBlueNinja
20635140fe Optimsed OBJ Loader from ~60 seconds to ~3 2024-12-31 14:16:53 -06:00
9 changed files with 362 additions and 349 deletions

View File

@ -12,9 +12,9 @@ local rotationSpeed = 25 -- Degrees per second for spinning
local new_rotation = 0
-- Variables for bobbing effect
local initial_position = {x = 0, y = 0, z = 0} -- To store the gun's initial position
local bobAmplitude = 5 -- Amplitude of the bobbing (units)
local bobFrequency = 0.5 -- Frequency of the bobbing (oscillations per second)
local initial_position = { x = 0, y = 0, z = 0 } -- To store the gun's initial position
local bobAmplitude = 5 -- Amplitude of the bobbing (units)
local bobFrequency = 0.5 -- Frequency of the bobbing (oscillations per second)
-- Reference to the Gun GameObject and its Transform component
local gun = nil
@ -22,9 +22,21 @@ local transform = nil
local TAU = Math.constants.TAU
function OnInit()
local startTime = os.clock()
Engine.Log("Init START", {1.0,1.0,1.0,1.0})
Engine.Expose("GameObjectName", GameObjectName)
Engine.Expose("new_rotation", new_rotation)
Engine.Expose("elapsedTime", elapsedTime)
Engine.Expose("bobAmplitude", bobAmplitude)
Engine.Expose("bobFrequency", bobFrequency)
Engine.Log("Init START", { 1.0, 1.0, 1.0, 1.0 })
@ -34,41 +46,43 @@ function OnInit()
transform = gun:GetComponent("Transform")
if transform then
local pos = transform:GetPosition()
initial_position = {x = pos.x, y = pos.y, z = pos.z}
Engine.Log("Gun found and initial position updated.", {1, 1, 1, 1})
initial_position = { x = pos.x, y = pos.y, z = pos.z }
Engine.Log("Gun found and initial position updated.", { 1, 1, 1, 1 })
else
Engine.Log("Transform component not found on Gun.", {1, 1, 0, 1})
Engine.Log("Transform component not found on Gun.", { 1, 1, 0, 1 })
return
end
else
Engine.Log("Gun GameObject still not found.", {1, 1, 0, 1})
Engine.Log("Gun GameObject still not found.", { 1, 1, 0, 1 })
return
end
elseif not transform then
transform = gun:GetComponent("Transform")
if transform then
local pos = transform:GetPosition()
initial_position = {x = pos.x, y = pos.y, z = pos.z}
Engine.Log("Transform component found and initial position updated.", {1, 1, 1, 1})
initial_position = { x = pos.x, y = pos.y, z = pos.z }
Engine.Log("Transform component found and initial position updated.", { 1, 1, 1, 1 })
else
Engine.Log("Transform component still not found on Gun.", {1, 1, 0, 1})
Engine.Log("Transform component still not found on Gun.", { 1, 1, 0, 1 })
return
end
end
Engine.Log("Init OK", {0.0,1.0,0.0,1.0})
Engine.Log("Init OK", { 0.0, 1.0, 0.0, 1.0 })
local endTime = os.clock()
Engine.Log(string.format("Time to load: %f", endTime-startTime))
Engine.Log(string.format("Time to load: %fms", (endTime - startTime)*1000))
end
-- Update function called every frame
function OnUpdate(deltaTime)
Engine.Expose("GameObjectName", GameObjectName)
Engine.Expose("new_rotation", new_rotation)
Engine.Expose("elapsedTime", elapsedTime)
Engine.Expose("bobAmplitude", bobAmplitude)
Engine.Expose("bobFrequency", bobFrequency)
-- Ensure that the Gun and its Transform component are valid
if not gun then
gun = Engine.GetGameObjectByTag(GameObjectName)
@ -76,10 +90,10 @@ function OnUpdate(deltaTime)
transform = gun:GetComponent("Transform")
if transform then
local pos = transform:GetPosition()
initial_position = {x = pos.x, y = pos.y, z = pos.z}
Engine.Log("Gun found and initial position updated.", {1, 1, 1, 1})
initial_position = { x = pos.x, y = pos.y, z = pos.z }
Engine.Log("Gun found and initial position updated.", { 1, 1, 1, 1 })
else
Engine.Log("Transform component not found on Gun.", {1, 1, 0, 1})
Engine.Log("Transform component not found on Gun.", { 1, 1, 0, 1 })
return
end
else
@ -89,8 +103,8 @@ function OnUpdate(deltaTime)
transform = gun:GetComponent("Transform")
if transform then
local pos = transform:GetPosition()
initial_position = {x = pos.x, y = pos.y, z = pos.z}
Engine.Log("Transform component found and initial position updated.", {1, 1, 1, 1})
initial_position = { x = pos.x, y = pos.y, z = pos.z }
Engine.Log("Transform component found and initial position updated.", { 1, 1, 1, 1 })
else
return
end
@ -110,9 +124,9 @@ function OnUpdate(deltaTime)
-- Define the new rotation (spinning around the Y-axis)
local rotation = {
x = 0, -- Preserving existing rotation on X-axis
x = 0, -- Preserving existing rotation on X-axis
y = new_rotation, -- Updated rotation on Y-axis for spinning
z = 0 -- Preserving existing rotation on Z-axis
z = 0 -- Preserving existing rotation on Z-axis
}
-- Apply the new rotation to the Transform component
@ -124,9 +138,9 @@ function OnUpdate(deltaTime)
-- Define the new position by adding the bobbing offset to the initial Y position
local new_position = {
x = initial_position.x, -- No change on X-axis
x = initial_position.x, -- No change on X-axis
y = initial_position.y + bobOffset, -- Bouncing up and down on Y-axis
z = initial_position.z -- No change on Z-axis
z = initial_position.z -- No change on Z-axis
}
-- Apply the new position to the Transform component

View File

@ -74,28 +74,28 @@ Collapsed=0
DockId=0x00000016,0
[Window][Editor##EditorWindow]
Pos=523,27
Size=1011,764
Pos=332,27
Size=1202,776
Collapsed=0
DockId=0x00000017,0
[Window][Performance##performance]
Pos=8,761
Size=513,408
Size=322,408
Collapsed=0
DockId=0x0000001C,0
[Window][Logger##logger]
Pos=8,395
Size=513,364
Pos=332,805
Size=1202,364
Collapsed=0
DockId=0x0000001A,0
DockId=0x00000019,0
[Window][Lua Text Editor##LuaEditor]
Pos=523,793
Size=1011,376
Pos=8,27
Size=322,732
Collapsed=0
DockId=0x00000018,0
DockId=0x0000001B,0
[Window][Scene Window@SceneWindow]
Pos=8,27
@ -105,9 +105,9 @@ DockId=0x0000000F,0
[Window][Scene Window##SceneWindow]
Pos=8,27
Size=513,366
Size=322,732
Collapsed=0
DockId=0x00000019,0
DockId=0x0000001B,0
[Window][Game Objects]
Pos=182,27
@ -116,10 +116,10 @@ Collapsed=0
DockId=0x00000011,0
[Window][Profiler]
Pos=523,793
Size=1011,376
Pos=935,805
Size=599,364
Collapsed=0
DockId=0x00000018,1
DockId=0x0000001A,0
[Table][0xE9E836E4,4]
Column 0 Weight=1.2999
@ -128,34 +128,34 @@ Column 2 Weight=0.6474
Column 3 Weight=1.0088
[Docking][Data]
DockSpace ID=0x14621557 Window=0x3DA2F1DE Pos=8,50 Size=1904,1142 Split=X Selected=0xF7365A5A
DockNode ID=0x00000013 Parent=0x14621557 SizeRef=513,1142 Split=Y Selected=0x818D04BB
DockNode ID=0x0000001B Parent=0x00000013 SizeRef=264,456 Split=Y Selected=0x1D5D92B6
DockNode ID=0x00000019 Parent=0x0000001B SizeRef=264,366 HiddenTabBar=1 Selected=0x1D5D92B6
DockNode ID=0x0000001A Parent=0x0000001B SizeRef=264,364 HiddenTabBar=1 Selected=0x1C0788A1
DockNode ID=0x0000001C Parent=0x00000013 SizeRef=264,254 HiddenTabBar=1 Selected=0x818D04BB
DockNode ID=0x00000014 Parent=0x14621557 SizeRef=749,1142 Split=X
DockNode ID=0x00000015 Parent=0x00000014 SizeRef=371,1142 Split=X
DockNode ID=0x00000011 Parent=0x00000015 SizeRef=265,1142 Selected=0x1D5D92B6
DockNode ID=0x00000012 Parent=0x00000015 SizeRef=1259,1142 Split=X
DockNode ID=0x00000009 Parent=0x00000012 SizeRef=364,1142 Split=Y Selected=0x3DC5AC3F
DockNode ID=0x00000005 Parent=0x00000009 SizeRef=364,745 Split=Y Selected=0x3DC5AC3F
DockNode ID=0x0000000B Parent=0x00000005 SizeRef=364,452 HiddenTabBar=1 Selected=0x3DC5AC3F
DockNode ID=0x0000000C Parent=0x00000005 SizeRef=364,291 Selected=0xAE3C694A
DockNode ID=0x00000006 Parent=0x00000009 SizeRef=364,395 HiddenTabBar=1 Selected=0x726D8899
DockNode ID=0x0000000A Parent=0x00000012 SizeRef=1538,1142 Split=X
DockNode ID=0x00000007 Parent=0x0000000A SizeRef=357,1142 Selected=0x7737E8B2
DockNode ID=0x00000008 Parent=0x0000000A SizeRef=1545,1142 Split=X
DockNode ID=0x00000001 Parent=0x00000008 SizeRef=1202,1142 Split=Y Selected=0xDF0EC458
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=1202,849 Split=Y Selected=0xDF0EC458
DockNode ID=0x0000000D Parent=0x00000003 SizeRef=1202,571 Split=Y Selected=0xDFF75B3F
DockNode ID=0x00000017 Parent=0x0000000D SizeRef=1303,764 CentralNode=1 HiddenTabBar=1 Selected=0xDFF75B3F
DockNode ID=0x00000018 Parent=0x0000000D SizeRef=1303,376 Selected=0x9B5D3198
DockNode ID=0x0000000E Parent=0x00000003 SizeRef=1202,569 Selected=0xE98146C5
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=1202,291 Selected=0x9DD4E196
DockNode ID=0x00000002 Parent=0x00000008 SizeRef=334,1142 HiddenTabBar=1 Selected=0x36DC96AB
DockNode ID=0x00000016 Parent=0x00000014 SizeRef=376,1142 HiddenTabBar=1 Selected=0x8D0E8380
DockSpace ID=0xC6145A92 Pos=8,27 Size=1904,1142 Split=X
DockNode ID=0x0000000F Parent=0xC6145A92 SizeRef=301,1142 Selected=0xA8433A03
DockNode ID=0x00000010 Parent=0xC6145A92 SizeRef=1601,1142 CentralNode=1
DockSpace ID=0x14621557 Window=0x3DA2F1DE Pos=8,50 Size=1904,1142 Split=X Selected=0xF7365A5A
DockNode ID=0x00000013 Parent=0x14621557 SizeRef=322,1142 Split=Y Selected=0x818D04BB
DockNode ID=0x0000001B Parent=0x00000013 SizeRef=264,456 HiddenTabBar=1 Selected=0x1D5D92B6
DockNode ID=0x0000001C Parent=0x00000013 SizeRef=264,254 HiddenTabBar=1 Selected=0x818D04BB
DockNode ID=0x00000014 Parent=0x14621557 SizeRef=1580,1142 Split=X
DockNode ID=0x00000015 Parent=0x00000014 SizeRef=1202,1142 Split=X
DockNode ID=0x00000011 Parent=0x00000015 SizeRef=265,1142 Selected=0x1D5D92B6
DockNode ID=0x00000012 Parent=0x00000015 SizeRef=1259,1142 Split=X
DockNode ID=0x00000009 Parent=0x00000012 SizeRef=364,1142 Split=Y Selected=0x3DC5AC3F
DockNode ID=0x00000005 Parent=0x00000009 SizeRef=364,745 Split=Y Selected=0x3DC5AC3F
DockNode ID=0x0000000B Parent=0x00000005 SizeRef=364,452 HiddenTabBar=1 Selected=0x3DC5AC3F
DockNode ID=0x0000000C Parent=0x00000005 SizeRef=364,291 Selected=0xAE3C694A
DockNode ID=0x00000006 Parent=0x00000009 SizeRef=364,395 HiddenTabBar=1 Selected=0x726D8899
DockNode ID=0x0000000A Parent=0x00000012 SizeRef=1538,1142 Split=X
DockNode ID=0x00000007 Parent=0x0000000A SizeRef=357,1142 Selected=0x7737E8B2
DockNode ID=0x00000008 Parent=0x0000000A SizeRef=1545,1142 Split=X
DockNode ID=0x00000001 Parent=0x00000008 SizeRef=1202,1142 Split=Y Selected=0xDF0EC458
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=1202,849 Split=Y Selected=0xDF0EC458
DockNode ID=0x0000000D Parent=0x00000003 SizeRef=1202,571 Split=Y Selected=0xDFF75B3F
DockNode ID=0x00000017 Parent=0x0000000D SizeRef=1202,776 CentralNode=1 Selected=0xDFF75B3F
DockNode ID=0x00000018 Parent=0x0000000D SizeRef=1202,364 Split=X Selected=0x1C0788A1
DockNode ID=0x00000019 Parent=0x00000018 SizeRef=601,364 Selected=0x1C0788A1
DockNode ID=0x0000001A Parent=0x00000018 SizeRef=599,364 Selected=0x9B5D3198
DockNode ID=0x0000000E Parent=0x00000003 SizeRef=1202,569 Selected=0xE98146C5
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=1202,291 Selected=0x9DD4E196
DockNode ID=0x00000002 Parent=0x00000008 SizeRef=334,1142 HiddenTabBar=1 Selected=0x36DC96AB
DockNode ID=0x00000016 Parent=0x00000014 SizeRef=376,1142 HiddenTabBar=1 Selected=0x8D0E8380
DockSpace ID=0xC6145A92 Pos=8,27 Size=1904,1142 Split=X
DockNode ID=0x0000000F Parent=0xC6145A92 SizeRef=301,1142 Selected=0xA8433A03
DockNode ID=0x00000010 Parent=0xC6145A92 SizeRef=1601,1142 CentralNode=1

View File

@ -6,13 +6,10 @@
#include "gcml.h"
// External pointer to LoggerWindow (Assuming it's defined globally)
extern LoggerWindow* g_LoggerWindow;
extern LoggerWindow *g_LoggerWindow;
const std::string ScriptComponent::name = "ScriptComponent";
ScriptComponent::ScriptComponent()
: ScriptPath("assets/scripts/script.lua"), m_LastErrorMessage("")
{
@ -45,17 +42,16 @@ YAML::Node ScriptComponent::Serialize()
return node;
}
void ScriptComponent::Deserialize(const YAML::Node& node)
void ScriptComponent::Deserialize(const YAML::Node &node)
{
if (node["ScriptPath"])
{
ScriptPath = node["ScriptPath"].as<std::string>();
}
}
DEBUG_PRINT("Script Path: %s", ScriptPath.c_str());
Initialize();
}
bool ScriptComponent::Initialize()
@ -80,8 +76,6 @@ bool ScriptComponent::Initialize()
return false;
}
m_LuaManager.PrintEngineVariables();
return true;
}
@ -91,9 +85,18 @@ void ScriptComponent::Update(float deltaTime)
m_LuaManager.Update(deltaTime);
}
void ScriptComponent::Init()
{
// Call the Update method of LuaManager
m_LuaManager.CallLuaFunction("OnInit");
}
void ScriptComponent::UpdateVariable(const std::string &name, const LuaManager::LuaExposedVariant &value)
{
m_LuaManager.UpdateVariable(name, value);
}
std::unordered_map<std::string, LuaManager::LuaExposedVariant> ScriptComponent::GetExposedVariables()
{
return m_LuaManager.GetExposedVariables();
}

View File

@ -7,6 +7,7 @@
#include <yaml-cpp/yaml.h>
#include "Windows/LoggerWindow.h"
#include "Engine/LuaAPI.h" // Include the LuaManager class
#include <unordered_map>
class ScriptComponent : public Component
{
@ -14,33 +15,31 @@ public:
ScriptComponent();
virtual ~ScriptComponent();
std::string ScriptPath; // Path to the Lua script
std::string ScriptPath; // Path to the Lua script
// Component interface implementation
virtual const std::string& GetName() const override;
static const std::string& GetStaticName();
virtual const std::string &GetName() const override;
static const std::string &GetStaticName();
virtual YAML::Node Serialize() override;
virtual void Deserialize(const YAML::Node& node) override;
virtual void Deserialize(const YAML::Node &node) override;
// Script management methods
bool Initialize();
virtual void Update(float deltaTime);
void Init();
void UpdateVariable(const std::string &name, const LuaManager::LuaExposedVariant &value);
std::unordered_map<std::string, LuaManager::LuaExposedVariant> GetExposedVariables();
private:
LuaManager m_LuaManager; // Instance of LuaManager
std::string m_LastErrorMessage; // To prevent duplicate error logs
LuaManager m_LuaManager; // Instance of LuaManager
std::string m_LastErrorMessage; // To prevent duplicate error logs
// block copying
ScriptComponent(const ScriptComponent&) = delete;
ScriptComponent& operator=(const ScriptComponent&) = delete;
ScriptComponent(const ScriptComponent &) = delete;
ScriptComponent &operator=(const ScriptComponent &) = delete;
static const std::string name;
};

View File

@ -260,7 +260,7 @@ void MyEngine::Run()
m_PerformanceWindow->Show(m_Fps, m_Ms); // FPS & ms
m_LoggerWindow->Show(); // Logs
m_SceneWindow->Show();
m_luaEditor->Show();
//m_luaEditor->Show();
if (m_showProfiler)
{

View File

@ -63,7 +63,7 @@ AssetManager::AssetVariant AssetManager::loadAssetFromDisk(AssetType type, const
}
case AssetType::SHADER:
{
Shader* shaderPtr = LoadShaderFromList(path); // Returns Shader*
Shader *shaderPtr = LoadShaderFromList(path); // Returns Shader*
if (shaderPtr != nullptr)
{
// It's essential to ensure that shaderPtr is dynamically allocated and not managed elsewhere
@ -76,7 +76,7 @@ AssetManager::AssetVariant AssetManager::loadAssetFromDisk(AssetType type, const
}
case AssetType::MODEL:
{
Model* modelPtr = LoadModelFromList(path); // Returns Model*
Model *modelPtr = LoadModelFromList(path); // Returns Model*
if (modelPtr != nullptr)
{
// It's essential to ensure that modelPtr is dynamically allocated and not managed elsewhere
@ -139,7 +139,7 @@ GLuint LoadTextureFromList(const std::string &path)
return texID;
}
Shader* LoadShaderFromList(const std::string &path)
Shader *LoadShaderFromList(const std::string &path)
{
// Build actual paths from the base path
@ -160,12 +160,6 @@ Shader* LoadShaderFromList(const std::string &path)
return newShader;
}
GLuint LoadTexture(const std::string &path, const std::string &directory)
{
std::string fullPath = directory + path;
@ -173,7 +167,7 @@ GLuint LoadTexture(const std::string &path, const std::string &directory)
unsigned char *data = stbi_load(fullPath.c_str(), &width, &height, &channels, 0);
if (!data)
{
DEBUG_PRINT("[AssetManager] failed to load texture: %s: %s", fullPath.c_str(),stbi_failure_reason());
DEBUG_PRINT("[AssetManager] failed to load texture: %s: %s", fullPath.c_str(), stbi_failure_reason());
return 0;
}
@ -190,15 +184,15 @@ GLuint LoadTexture(const std::string &path, const std::string &directory)
GLuint textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0,
format, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
// Set texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
@ -207,15 +201,31 @@ GLuint LoadTexture(const std::string &path, const std::string &directory)
return textureID;
}
#include <unordered_map>
Model* LoadModelFromList(const std::string &path)
// Custom hash function for Vertex
struct VertexHash
{
std::size_t operator()(const Vertex &v) const
{
std::size_t h1 = std::hash<float>{}(v.position[0]);
std::size_t h2 = std::hash<float>{}(v.position[1]);
std::size_t h3 = std::hash<float>{}(v.position[2]);
std::size_t h4 = std::hash<float>{}(v.texCoord[0]);
std::size_t h5 = std::hash<float>{}(v.texCoord[1]);
std::size_t h6 = std::hash<float>{}(v.normal[0]);
std::size_t h7 = std::hash<float>{}(v.normal[1]);
std::size_t h8 = std::hash<float>{}(v.normal[2]);
return h1 ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^ h7 ^ h8;
}
};
// Hash map for deduplication
std::unordered_map<Vertex, unsigned int, VertexHash> vertexCache;
Model *LoadModelFromList(const std::string &path)
{
auto start = std::chrono::high_resolution_clock::now();
std::ifstream objFile(path);
if (!objFile.is_open())
@ -227,6 +237,10 @@ Model* LoadModelFromList(const std::string &path)
std::vector<float> temp_texCoords;
std::vector<float> temp_normals;
temp_positions.reserve(100000);
temp_texCoords.reserve(100000);
temp_normals.reserve(100000);
std::string directory;
size_t lastSlash = path.find_last_of("/\\");
if (lastSlash != std::string::npos)
@ -234,7 +248,6 @@ Model* LoadModelFromList(const std::string &path)
else
directory = "";
std::string currentMaterial = "default";
// Map material name to Submesh
@ -243,7 +256,14 @@ Model* LoadModelFromList(const std::string &path)
std::string line;
std::string mtlFileName;
while (std::getline(objFile, line))
// Read file into memory for faster line parsing
std::stringstream fileBuffer;
fileBuffer << objFile.rdbuf();
objFile.close();
DEBUG_PRINT("OBJ READ");
while (std::getline(fileBuffer, line))
{
if (line.empty() || line[0] == '#')
continue; // Skip empty lines and comments
@ -296,32 +316,25 @@ Model* LoadModelFromList(const std::string &path)
while (iss >> vertexStr)
{
unsigned int vIdx = 0, tIdx = 0, nIdx = 0;
size_t firstSlash = vertexStr.find('/');
size_t secondSlash = vertexStr.find('/', firstSlash + 1);
const char *ptr = vertexStr.c_str();
if (firstSlash == std::string::npos)
// Parse vertex index (vIdx)
vIdx = std::strtol(ptr, const_cast<char **>(&ptr), 10);
if (*ptr == '/')
{
// Format: f v1 v2 v3
vIdx = std::stoi(vertexStr);
}
else if (secondSlash == std::string::npos)
{
// Format: f v1/vt1 v2/vt2 v3/vt3
vIdx = std::stoi(vertexStr.substr(0, firstSlash));
tIdx = std::stoi(vertexStr.substr(firstSlash + 1));
}
else if (secondSlash > firstSlash + 1)
{
// Format: f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3
vIdx = std::stoi(vertexStr.substr(0, firstSlash));
tIdx = std::stoi(vertexStr.substr(firstSlash + 1, secondSlash - firstSlash - 1));
nIdx = std::stoi(vertexStr.substr(secondSlash + 1));
}
else
{
// Format: f v1//vn1 v2//vn2 v3//vn3
vIdx = std::stoi(vertexStr.substr(0, firstSlash));
nIdx = std::stoi(vertexStr.substr(secondSlash + 1));
++ptr; // Skip the first '/'
if (*ptr != '/')
{
// Parse texture index (tIdx)
tIdx = std::strtol(ptr, const_cast<char **>(&ptr), 10);
}
if (*ptr == '/')
{
++ptr; // Skip the second '/'
// Parse normal index (nIdx)
nIdx = std::strtol(ptr, const_cast<char **>(&ptr), 10);
}
}
faceVertices.emplace_back(vIdx, tIdx, nIdx);
@ -333,8 +346,10 @@ Model* LoadModelFromList(const std::string &path)
// Current material's submesh
Submesh &currentSubmesh = materialToSubmesh[currentMaterial];
auto addVertex = [&](unsigned int v, unsigned int t, unsigned int n) -> unsigned int {
auto addVertex = [&](unsigned int v, unsigned int t, unsigned int n) -> unsigned int
{
Vertex vertex;
// OBJ indices are 1-based
vertex.position[0] = temp_positions[(v - 1) * 3];
vertex.position[1] = temp_positions[(v - 1) * 3 + 1];
@ -364,16 +379,18 @@ Model* LoadModelFromList(const std::string &path)
vertex.normal[2] = 0.0f;
}
// Check if the vertex already exists in the submesh
auto it = std::find(currentSubmesh.vertices.begin(), currentSubmesh.vertices.end(), vertex);
if (it != currentSubmesh.vertices.end())
// Use the hash map to check for duplicates
auto it = vertexCache.find(vertex);
if (it != vertexCache.end())
{
return static_cast<unsigned int>(std::distance(currentSubmesh.vertices.begin(), it));
return it->second;
}
else
{
unsigned int newIndex = static_cast<unsigned int>(currentSubmesh.vertices.size());
currentSubmesh.vertices.push_back(vertex);
return static_cast<unsigned int>(currentSubmesh.vertices.size() - 1);
vertexCache[vertex] = newIndex;
return newIndex;
}
};
@ -388,7 +405,10 @@ Model* LoadModelFromList(const std::string &path)
}
}
objFile.close();
temp_positions.shrink_to_fit();
temp_texCoords.shrink_to_fit();
temp_normals.shrink_to_fit();
DEBUG_PRINT("MTL READ");
// Load MTL file if specified
std::unordered_map<std::string, std::vector<Texture>> materialTexturesMap;
@ -476,6 +496,8 @@ Model* LoadModelFromList(const std::string &path)
{
}
DEBUG_PRINT("MTL SUBASSIGN");
// Assign textures to submeshes based on their material
for (auto &pair : materialToSubmesh)
{
@ -504,13 +526,18 @@ Model* LoadModelFromList(const std::string &path)
Model *model = new Model();
// Move submeshes to the model
DEBUG_PRINT("SUB MIGRATE");
for (auto &pair : materialToSubmesh)
{
model->submeshes.emplace_back(std::move(pair.second));
}
// Code to analyze
auto end = std::chrono::high_resolution_clock::now();
g_LoggerWindow->AddLog("[AssetManager] Loaded Mesh in %.6f seconds",
std::chrono::duration_cast<std::chrono::duration<double>>(end - start).count());
DEBUG_PRINT("[AssetManager] Loaded model with %lld submeshes.", model->submeshes.size());
return model;
}

View File

@ -25,6 +25,8 @@ extern LoggerWindow *g_LoggerWindow;
extern std::vector<std::unique_ptr<GameObject>> g_GameObjects;
std::string LuaManager::m_ScriptName = "LUA_UNDEFINED";
std::unordered_map<std::string, LuaManager::LuaExposedVariant> LuaManager::m_ExposedVariables;
// Constructor
LuaManager::LuaManager()
@ -92,6 +94,9 @@ bool LuaManager::Initialize(const std::string &scriptPath)
lua_pushcfunction(m_LuaState, Lua_Engine_Log);
lua_setfield(m_LuaState, -2, "Log");
lua_pushcfunction(m_LuaState, Lua_Engine_Expose);
lua_setfield(m_LuaState, -2, "Expose");
// Add the ScriptName binding
lua_pushcfunction(m_LuaState, Lua_Engine_ScriptName);
lua_setfield(m_LuaState, -2, "ScriptName");
@ -150,208 +155,122 @@ bool LuaManager::Initialize(const std::string &scriptPath)
return true;
}
// Implementation of GetGlobalVariables
std::vector<LuaManager::LuaGlobalVariant> LuaManager::GetGlobalVariables()
{
std::vector<LuaManager::LuaGlobalVariant> globals;
std::unordered_map<std::string, LuaManager::LuaExposedVariant> LuaManager::GetExposedVariables() {
return m_ExposedVariables;
}
void LuaManager::UpdateVariable(const std::string &name, const LuaManager::LuaExposedVariant &value) {
if (!m_LuaState)
{
// Handle error: Lua state not initialized
if (g_LoggerWindow)
{
g_LoggerWindow->AddLog("LuaManager: Lua state is not initialized.",
std::optional<ImVec4>(ImVec4(1.0f, 0.0f, 0.0f, 1.0f)));
}
else
{
DEBUG_PRINT("LuaManager: Lua state is not initialized.");
}
return globals;
return;
// Update the variable in the map
m_ExposedVariables[name] = value;
// Push the variable to the Lua global environment
lua_pushglobaltable(m_LuaState); // Push the global table
// Push the variable name
lua_pushstring(m_LuaState, name.c_str());
// Push the new value based on its type
if (std::holds_alternative<int>(value)) {
lua_pushinteger(m_LuaState, std::get<int>(value));
} else if (std::holds_alternative<float>(value)) {
lua_pushnumber(m_LuaState, std::get<float>(value));
} else if (std::holds_alternative<std::string>(value)) {
lua_pushstring(m_LuaState, std::get<std::string>(value).c_str());
} else if (std::holds_alternative<bool>(value)) {
lua_pushboolean(m_LuaState, std::get<bool>(value));
} else {
lua_pop(m_LuaState, 1); // Clean up stack
return;
}
// Push the global table onto the stack
#if LUA_VERSION_NUM >= 502
lua_pushglobaltable(m_LuaState);
#else
lua_pushvalue(m_LuaState, LUA_GLOBALSINDEX);
#endif
// Set the variable in the Lua global environment
lua_settable(m_LuaState, -3);
// Start iterating with a nil key
lua_pushnil(m_LuaState); // First key
// Clean up stack
lua_pop(m_LuaState, 1);
}
// Iterate over the global table
while (lua_next(m_LuaState, -2) != 0)
{
// Stack now contains key at -2 and value at -1
// Get the type of the value
int valueType = lua_type(m_LuaState, -1);
switch (valueType)
{
int LuaManager::Lua_Engine_Expose(lua_State* L) {
// Check that at least two arguments are passed: name and value
if (lua_gettop(L) < 2) {
luaL_error(L, "Expose function requires at least two arguments: name and value");
return 0;
}
// First argument: variable name (string)
if (!lua_isstring(L, 1)) {
luaL_error(L, "First argument to Expose must be a string (variable name)");
return 0;
}
const char* varName = lua_tostring(L, 1);
// Second argument: variable value (supports int, float, string, bool)
LuaExposedVariant varValue;
int type = lua_type(L, 2);
switch (type) {
case LUA_TNUMBER:
#if LUA_VERSION_NUM >= 503
if (lua_isinteger(m_LuaState, -1))
{
lua_Integer intVal = lua_tointeger(m_LuaState, -1);
// Assuming you want to store as int
globals.emplace_back(static_cast<int>(intVal));
}
else
{
lua_Number numVal = lua_tonumber(m_LuaState, -1);
// Store as float (you might choose double instead)
globals.emplace_back(static_cast<float>(numVal));
}
#else
{
lua_Number numVal = lua_tonumber(m_LuaState, -1);
// Lua 5.2 and earlier use double for all numbers
// Decide how to store: here, stored as float
globals.emplace_back(static_cast<float>(numVal));
}
if (lua_isinteger(L, 2)) {
varValue = static_cast<int>(lua_tointeger(L, 2));
} else
#endif
{
varValue = static_cast<float>(lua_tonumber(L, 2));
}
break;
case LUA_TSTRING:
{
size_t len = 0;
const char *str = lua_tolstring(m_LuaState, -1, &len);
if (str)
{
globals.emplace_back(std::string(str, len));
}
}
break;
// Optionally handle other types or skip them
// For example, you might skip tables, functions, booleans, etc.
default:
// Skip other types
varValue = std::string(lua_tostring(L, 2));
break;
}
// Pop the value, keep the key for the next iteration
lua_pop(m_LuaState, 1);
case LUA_TBOOLEAN:
varValue = static_cast<bool>(lua_toboolean(L, 2));
break;
default:
luaL_error(L, "Unsupported variable type for Expose");
return 0;
}
// Pop the global table from the stack
lua_pop(m_LuaState, 1);
// Store the variable in the static m_ExposedVariables map
m_ExposedVariables[varName] = varValue;
return globals;
// Push the variable to the Lua global environment
lua_pushglobaltable(L);
lua_pushstring(L, varName); // Push the variable name
// Push the value to Lua based on its type
if (std::holds_alternative<int>(varValue)) {
lua_pushinteger(L, std::get<int>(varValue));
} else if (std::holds_alternative<float>(varValue)) {
lua_pushnumber(L, std::get<float>(varValue));
} else if (std::holds_alternative<std::string>(varValue)) {
lua_pushstring(L, std::get<std::string>(varValue).c_str());
} else if (std::holds_alternative<bool>(varValue)) {
lua_pushboolean(L, std::get<bool>(varValue));
} else {
lua_pop(L, 1); // Clean up stack
return 0;
}
// Set the variable in Lua global environment
lua_settable(L, -3);
// Clean up stack
lua_pop(L, 1);
return 0;
}
// Implementation of PrintEngineVariables
void LuaManager::PrintEngineVariables() {
if (!m_LuaState) {
std::cerr << "LuaManager: Lua state is not initialized." << std::endl;
return;
}
// Push the _T_Engine_Variables table onto the stack
lua_getglobal(m_LuaState, "_T_Engine_Variables");
if (!lua_istable(m_LuaState, -1)) {
std::cerr << "LuaManager: _T_Engine_Variables is not a table or does not exist." << std::endl;
lua_pop(m_LuaState, 1); // Remove non-table value
return;
}
// Start iterating with a nil key
lua_pushnil(m_LuaState); // First key
std::cout << "Engine Variables:" << std::endl;
// Iterate over the _T_Engine_Variables table
while (lua_next(m_LuaState, -2) != 0) {
// Stack now contains key at -2 and value at -1
// Get the key
const char* key = nullptr;
if (lua_type(m_LuaState, -2) == LUA_TSTRING) {
key = lua_tostring(m_LuaState, -2);
} else {
// For non-string keys, skip
lua_pop(m_LuaState, 1); // Remove value, keep key for next iteration
continue;
}
// Get the type of the value
int valueType = lua_type(m_LuaState, -1);
// Print the key and value based on type
std::cout << key << " = ";
switch (valueType) {
case LUA_TNUMBER:
#if LUA_VERSION_NUM >= 503
if (lua_isinteger(m_LuaState, -1)) {
lua_Integer intVal = lua_tointeger(m_LuaState, -1);
std::cout << intVal;
} else
#endif
{
lua_Number numVal = lua_tonumber(m_LuaState, -1);
std::cout << numVal;
}
break;
case LUA_TSTRING:
{
const char* str = lua_tostring(m_LuaState, -1);
if (str) {
std::cout << "\"" << str << "\"";
} else {
std::cout << "nil";
}
}
break;
case LUA_TBOOLEAN:
{
int boolVal = lua_toboolean(m_LuaState, -1);
std::cout << (boolVal ? "true" : "false");
}
break;
case LUA_TTABLE:
std::cout << "table";
break;
case LUA_TFUNCTION:
std::cout << "function";
break;
case LUA_TUSERDATA:
std::cout << "userdata";
break;
case LUA_TLIGHTUSERDATA:
std::cout << "lightuserdata";
break;
case LUA_TTHREAD:
std::cout << "thread";
break;
case LUA_TNIL:
std::cout << "nil";
break;
default:
std::cout << "unknown";
break;
}
std::cout << std::endl;
// Pop the value, keep the key for the next iteration
lua_pop(m_LuaState, 1);
}
// Pop the _T_Engine_Variables table from the stack
lua_pop(m_LuaState, 1);
}
// Update function called every frame
void LuaManager::Update(float deltaTime)

View File

@ -14,6 +14,7 @@ extern "C"
#include <string>
#include <optional>
#include <variant>
#include <unordered_map>
#include <vector>
// Forward declarations to avoid circular dependencies
@ -59,10 +60,14 @@ public:
void CallLuaFunction(std::string functionName);
using LuaGlobalVariant = std::variant<int, float, std::string>;
using LuaExposedVariant = std::variant<int, float, std::string, bool>;
// Retrieve exposed variables
std::unordered_map<std::string, LuaExposedVariant> GetExposedVariables();
void UpdateVariable(const std::string& name, const LuaExposedVariant& value);
std::vector<LuaGlobalVariant> GetGlobalVariables();
void PrintEngineVariables();
private:
// Lua state
@ -72,6 +77,9 @@ private:
lua_State *m_LuaState;
static std::unordered_map<std::string, LuaExposedVariant> m_ExposedVariables;
// Last error message to prevent duplicate logging
std::string m_LastErrorMessage;
void RegisterAllMetatables();
@ -106,6 +114,9 @@ private:
// Binding functions for Engine table
static int Lua_Engine_Log(lua_State *L);
static int Lua_Engine_ScriptName(lua_State *L);
static int Lua_Engine_GetGameObjectByTag(lua_State *L);
static int Lua_Engine_Expose(lua_State* L);
};

View File

@ -558,7 +558,6 @@ void InspectorWindow::Show()
// Optionally, trigger reloading the mesh if the path changes
// Example:
std::shared_ptr<Model> model = g_AssetManager->loadAsset<Model>(AssetType::MODEL, mesh->MeshPath.c_str());
}
// --- Submeshes Information ---
@ -630,47 +629,88 @@ void InspectorWindow::Show()
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "No model loaded.");
}
}
ImGui::Separator();
}
ImGui::Spacing();
if (script && g_SelectedObject)
{
// Transform* transform = &g_SelectedObject->transform;
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
bool scriptOpen = ImGui::CollapsingHeader("Script##Main", ImGuiTreeNodeFlags_DefaultOpen);
ImGui::PopStyleColor();
// printf("%p\n", &transform);
if (scriptOpen)
{
// Define a maximum buffer size
// Define a maximum buffer size for script path
const size_t BUFFER_SIZE = 256;
// Allocate a buffer and initialize it with the current string
// Allocate a buffer and initialize it with the current script path
char buffer[BUFFER_SIZE];
strncpy(buffer, script->ScriptPath.c_str(), BUFFER_SIZE - 1);
buffer[BUFFER_SIZE - 1] = '\0'; // Ensure null-termination
// Render the InputText widget
// Render the InputText widget for editing the script path
if (ImGui::InputText("Script Path", buffer, BUFFER_SIZE))
{
// Update the string if user made changes
script->ScriptPath = buffer;
script->ScriptPath = buffer; // Update the script path if modified
}
// Reload Script Button
if (ImGui::Button("Reload Script"))
{
if (script->Initialize())
{
script->Init();
g_LoggerWindow->AddLog("Reloaded Script: %s", ImVec4(0.0f, 1.0f, 0.0f, 1.0f), script->ScriptPath.c_str());
}
}
// Assuming script->GetExposedVariables() returns std::unordered_map<std::string, LuaExposedVariant>
auto exposedVariables = script->GetExposedVariables();
for (const auto &[name, value] : exposedVariables)
{
ImGui::Text("%s:", name.c_str());
if (std::holds_alternative<int>(value))
{
int intValue = std::get<int>(value);
if (ImGui::InputInt(name.c_str(), &intValue))
{
script->UpdateVariable(name, intValue);
}
}
else if (std::holds_alternative<float>(value))
{
float floatValue = std::get<float>(value);
if (ImGui::InputFloat(name.c_str(), &floatValue))
{
script->UpdateVariable(name, floatValue);
}
}
else if (std::holds_alternative<std::string>(value))
{
const std::string &strValue = std::get<std::string>(value);
char buffer[256];
strncpy(buffer, strValue.c_str(), sizeof(buffer));
buffer[sizeof(buffer) - 1] = '\0'; // Ensure null termination
if (ImGui::InputText(name.c_str(), buffer, sizeof(buffer)))
{
script->UpdateVariable(name, std::string(buffer));
}
}
else if (std::holds_alternative<bool>(value))
{
bool boolValue = std::get<bool>(value);
if (ImGui::Checkbox(name.c_str(), &boolValue))
{
script->UpdateVariable(name, boolValue);
}
}
else
{
ImGui::TextDisabled("Unsupported Type");
}
}
}
}
}