Compare commits

..

1 Commits

Author SHA1 Message Date
OusmBlueNinja
696554c4f5 Nothing really 2025-01-01 13:04:56 -06:00
63 changed files with 3332 additions and 2015 deletions

6
.gitmodules vendored
View File

@ -1,6 +0,0 @@
[submodule "vendor/gcml"]
path = vendor/gcml
url = https://dock-it.dev/GigabiteStudios/gcml.git
[submodule "vendor/ImGuizmo"]
path = vendor/ImGuizmo
url = https://github.com/CedricGuillemet/ImGuizmo.git

151
Makefile
View File

@ -1,95 +1,27 @@
# --------------------------------------------------------------------------- # Makefile
# Compiler and Base Flags
# --------------------------------------------------------------------------- # Compiler and Flags
CXX := g++ CXX := g++
CXXFLAGS := -Wall -Wextra -std=c++17 -g -DDEBUG -DTIMERS
# Common flags (for both Debug and Release)
CXXFLAGS_BASE := -Wall -Wextra -std=c++17
# Debug flags (includes TIMERS and DEBUG, plus -g)
CXXFLAGS_DEBUG := $(CXXFLAGS_BASE) -g -DDEBUG -DTIMERS
# Release flags (optimized, no debug macros, no timers)
CXXFLAGS_RELEASE := $(CXXFLAGS_BASE) -O2 -DNDEBUG
# By default, we build in Debug mode:
BUILD_TYPE ?= debug
# Well dynamically set BUILD_DIR and CXXFLAGS based on BUILD_TYPE
ifeq ($(BUILD_TYPE),debug)
BUILD_DIR := build
CXXFLAGS := $(CXXFLAGS_DEBUG)
else ifeq ($(BUILD_TYPE),release)
BUILD_DIR := release
CXXFLAGS := $(CXXFLAGS_RELEASE)
else
$(error Unknown BUILD_TYPE '$(BUILD_TYPE)'. Valid options: debug or release)
endif
# ---------------------------------------------------------------------------
# Detect Platform
# ---------------------------------------------------------------------------
ifeq ($(OS),Windows_NT)
# -------------------- Windows --------------------
EXE_EXT := .exe
# Example paths (adjust if you have your libs somewhere else):
GLFW_INCLUDE := C:/libs/glfw/include
GLEW_INCLUDE := C:/libs/glew/include
LIB_PATHS := -LC:/libs/glfw/lib \
-LC:/libs/glew/lib \
-Llib
LIBS := -lglfw3 -lopengl32 -lgdi32 -limm32 -lole32 -loleaut32 -luuid \
-lwinmm -lglew32 -lglu32 -lyaml-cpp -llua54
define MKDIR_P
if not exist "$(1)" mkdir "$(1)" >nul 2>&1
endef
else
# -------------------- Linux (or other Unix-likes) --------------------
EXE_EXT :=
GLFW_INCLUDE := /usr/include
GLEW_INCLUDE := /usr/include
LIB_PATHS :=
LIBS := -lglfw -lGL -lGLEW -lGLU -lyaml-cpp -llua
define MKDIR_P
mkdir -p "$(1)"
endef
endif
# ---------------------------------------------------------------------------
# Directories # Directories
# ---------------------------------------------------------------------------
SRC_DIR := src SRC_DIR := src
VENDOR_DIRS := vendor/imgui-docking vendor/stb vendor/ImGuizmo VENDOR_DIRS := vendor/imgui-docking vendor/stb
# BUILD_DIR is determined by $(BUILD_TYPE) above: either `build` or `release` BUILD_DIR := build
# ---------------------------------------------------------------------------
# Include Directories # Include Directories
# --------------------------------------------------------------------------- GLFW_INCLUDE := C:/libraries/glfw/include
INCLUDE_DIRS := \ INCLUDE_DIRS := $(SRC_DIR) $(VENDOR_DIRS) $(GLFW_INCLUDE) vendor/stb/include C:\msys64\mingw64\include vendor/lua vendor/gcml
$(SRC_DIR) \ INCLUDES := $(addprefix -I, $(INCLUDE_DIRS))
$(VENDOR_DIRS) \
$(GLFW_INCLUDE) \
$(GLEW_INCLUDE) \
vendor/stb/include \
vendor/lua \
vendor/ImGuizmo \
vendor/gcml
CXXFLAGS += $(foreach inc,$(INCLUDE_DIRS),-I$(inc)) # Update compiler flags with include paths
CXXFLAGS += $(INCLUDES)
# --------------------------------------------------------------------------- # -------------------------------------------------------------------------
# Source Files # Source Files
# --------------------------------------------------------------------------- # 1) Recursively gather *.cpp in src (including subfolders).
# 2) Gather *.cpp from vendor/imgui-docking, vendor/stb, etc.
# -------------------------------------------------------------------------
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp) \ SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp) \
$(wildcard $(SRC_DIR)/**/*.cpp) $(wildcard $(SRC_DIR)/**/*.cpp)
@ -97,51 +29,46 @@ VENDOR_SRC := $(foreach dir, $(VENDOR_DIRS), $(wildcard $(dir)/*.cpp))
STB_SRC := $(wildcard vendor/stb/src/*.cpp) # If stb has .cpp files STB_SRC := $(wildcard vendor/stb/src/*.cpp) # If stb has .cpp files
ALL_SRC := $(SRC_FILES) $(VENDOR_SRC) $(STB_SRC) ALL_SRC := $(SRC_FILES) $(VENDOR_SRC) $(STB_SRC)
# --------------------------------------------------------------------------- # -------------------------------------------------------------------------
# Object Files # Object Files
# --------------------------------------------------------------------------- # Convert each .cpp to a corresponding .o under the build/ directory.
OBJ_FILES := $(patsubst %.cpp,$(BUILD_DIR)/%.o,$(ALL_SRC)) # For example:
# src/Engine.cpp -> build/src/Engine.o
# src/Windows/LoggerWindow.cpp -> build/src/Windows/LoggerWindow.o
# -------------------------------------------------------------------------
OBJ_FILES := $(patsubst %.cpp, $(BUILD_DIR)/%.o, $(ALL_SRC))
# --------------------------------------------------------------------------- # Target executable name
# Target (goes into the same directory as object files) TARGET := TesseractEngine.exe
# ---------------------------------------------------------------------------
TARGET := $(BUILD_DIR)/TesseractEngine$(EXE_EXT) # Libraries
LIBS := -LC:/libraries/glfw/lib -Llib -lglfw3 -lopengl32 -lgdi32 -limm32 -lole32 -loleaut32 -luuid -lwinmm -lglew32 -lglu32 -lyaml-cpp -llua54
# ---------------------------------------------------------------------------
# Phony Targets # Phony Targets
# --------------------------------------------------------------------------- .PHONY: all clean copy_assets
.PHONY: all clean debug release
# Default target uses whatever BUILD_TYPE is (default = debug) # Default target
all: $(TARGET) all: copy_assets $(TARGET)
## "debug" target => override BUILD_TYPE # Copy assets/fonts to build/assets/fonts
debug: copy_assets:
@$(MAKE) BUILD_TYPE=debug all @echo Copying font assets...
xcopy /E /I /Y "assets\fonts" "$(BUILD_DIR)\assets\fonts" >nul
## "release" target => override BUILD_TYPE
release:
@$(MAKE) BUILD_TYPE=release all
# ---------------------------------------------------------------------------
# Link all object files to create the executable # Link all object files to create the executable
# ---------------------------------------------------------------------------
$(TARGET): $(OBJ_FILES) $(TARGET): $(OBJ_FILES)
@echo Linking $@... @echo Linking $@...
$(CXX) $(CXXFLAGS) -o $@ $^ $(LIB_PATHS) $(LIBS) $(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS)
# ---------------------------------------------------------------------------
# Pattern rule to compile .cpp files to .o files # Pattern rule to compile .cpp files to .o files
# --------------------------------------------------------------------------- # Note the mkdir on the $(dir $@) ensures subfolders under build/ exist.
$(BUILD_DIR)/%.o: %.cpp $(BUILD_DIR)/%.o: %.cpp
@$(call MKDIR_P,$(dir $@)) @mkdir "$(dir $@)" >nul 2>&1 || echo Directory exists
@echo Compiling $<... @echo Compiling $<...
$(CXX) $(CXXFLAGS) -c $< -o $@ $(CXX) $(CXXFLAGS) -c $< -o $@
# ---------------------------------------------------------------------------
# Clean build artifacts # Clean build artifacts
# ---------------------------------------------------------------------------
clean: clean:
@echo Cleaning up... @echo Cleaning up...
rm -rf build if exist "$(BUILD_DIR)" rmdir /s /q "$(BUILD_DIR)"
rm -rf release if exist "$(TARGET)" del /q "$(TARGET)"

View File

@ -8,9 +8,6 @@
Tesseract-Engine is a lightweight and powerful game engine designed for developers working on small to medium-sized projects. With a simple and visually appealing interface, it offers a LUA scripting environment and is built in C++ for optimal performance. Tesseract-Engine is a lightweight and powerful game engine designed for developers working on small to medium-sized projects. With a simple and visually appealing interface, it offers a LUA scripting environment and is built in C++ for optimal performance.
Join The Discord!
[https://discord.gg/qAc4RrYH](https://discord.gg/qAc4RrYH)
--- ---
## Features ## Features
@ -34,41 +31,6 @@ Join The Discord!
### Note: Screenshots are sorted by version. ### Note: Screenshots are sorted by version.
## **Version 0.0.131**
**Updates:**
- Added Guizmos
- Added Mesh Visualisers
- Added Global Settings
- Lua Changes
- Added Intelisence Headers for Engine and KeyCodes
- Changed Lua `require` to not need a path
- Added Culling
- Fixed GLCalls Count
- Removed Unused Code (TestMesh.cpp)
**Screenshot:**
![](./assets/images/SS-Dev2_5-Fixed.png)
## **Version 0.0.102**
**Updates:**
- Added More Themes
- Added `Engine.KeyDown()`
- Added `KeyCode` "Returns a Bool if the key is down"
- `local KeyCode = require("keycode")`
- `KeyCode:Space`
- `KeyCode:A`
- Fixed Primary Camera on Load
- Remade Transform Inspector
- Remade Camera Inspector
- Remade Play/Pause Button
- Added -DTIMERS to include more Profiler Timers (May slow down Engine)
- Remade Mesh Componenet Inspector to be cleaner
**Screenshot:**
![](./assets/images/SS-Dev2_4.png)
### **Version 0.0.93** ### **Version 0.0.93**
**Updates:** **Updates:**
- Added support for OBJ Files with MTL Textures - Added support for OBJ Files with MTL Textures

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

View File

@ -1,6 +1,6 @@
-- script.lua -- script.lua
local Math = require("math") -- Require the enhanced math module local Math = require("./assets/scripts/math") -- Require the enhanced math module
local Engine = require("engine") local Engine = require("./assets/scripts/engine")
local GameObjectName = "Bacround" local GameObjectName = "Bacround"

View File

@ -1,118 +1,55 @@
local Engine = require("engine") local Engine = require("./assets/scripts/engine")
local KeyCode = require("keycode") local KeyCode = require("./assets/scripts/keycode")
local transform = nil local transform = nil
local currentRotation = 0 -- Current Y-axis rotation in degrees local new_rotation = 0
local rotationSpeed = 240 -- Degrees per second local new_rotationSpeed = 15
local moveSpeed = 600 -- Units per second local Move_Speec = 300
function OnInit() function OnInit()
local gameObject = Engine.GetGameObjectByTag("Camera") local gameObject = Engine.GetGameObjectByTag("Camera")
if not gameObject then
Engine.Log("Error: Camera GameObject not found!")
return
end
transform = gameObject:GetComponent("Transform") transform = gameObject:GetComponent("Transform")
if not transform then Engine.Log("Init Done")
Engine.Log("Error: Transform component not found on Camera!")
return
end
-- Initialize currentRotation based on the transform's current rotation
local rotation = transform:GetRotation()
currentRotation = rotation.y
Engine.Expose("Position X", rotation.x)
Engine.Expose("Position Z", rotation.z)
Engine.Expose("Rotation Y", currentRotation)
Engine.Log("Init Done", {0,1,0,1})
end end
function OnUpdate(deltaTime) function OnUpdate(deltaTime)
if not transform then local gameObject = Engine.GetGameObjectByTag("Camera")
Engine.Log("Warning: Transform is not initialized.") transform = gameObject:GetComponent("Transform")
return
end
-- Retrieve current rotation and position local old_rotation = transform:GetRotation()
local rotation = transform:GetRotation()
local position = transform:GetPosition()
-- Update currentRotation based on input
if Engine.KeyDown(KeyCode.Q) then
currentRotation = currentRotation - (deltaTime * rotationSpeed)
end
if Engine.KeyDown(KeyCode.E) then
currentRotation = currentRotation + (deltaTime * rotationSpeed)
end
-- Normalize rotation to [0, 360) degrees local Position = transform:GetPosition()
if currentRotation >= 360 then
currentRotation = currentRotation - 360
elseif currentRotation < 0 then
currentRotation = currentRotation + 360
end
-- Apply the updated rotation to the Transform component
local newRotation = {
x = rotation.x, -- Preserving existing rotation on X-axis
y = currentRotation, -- Updated rotation on Y-axis
z = rotation.z -- Preserving existing rotation on Z-axis
}
transform:SetRotation(newRotation)
-- Calculate movement direction based on currentRotation
local rotationRad = math.rad(currentRotation)
-- Forward vector (positive Z direction)
local forward = {
x = math.cos(rotationRad),
z = math.sin(rotationRad)
}
-- Right vector (positive X direction)
local right = {
x = math.sin(rotationRad),
z = -math.cos(rotationRad)
}
-- Initialize movement deltas
local deltaX = 0
local deltaZ = 0
if Engine.KeyDown(KeyCode.W) then if Engine.KeyDown(KeyCode.W) then
-- Move forward Position.x = Position.x + (deltaTime * Move_Speec)
deltaX = deltaX + forward.x * moveSpeed * deltaTime
deltaZ = deltaZ + forward.z * moveSpeed * deltaTime
end end
if Engine.KeyDown(KeyCode.S) then if Engine.KeyDown(KeyCode.S) then
-- Move backward Position.x = Position.x - (deltaTime * Move_Speec)
deltaX = deltaX - forward.x * moveSpeed * deltaTime
deltaZ = deltaZ - forward.z * moveSpeed * deltaTime
end
if Engine.KeyDown(KeyCode.A) then
-- Move right
deltaX = deltaX + right.x * moveSpeed * deltaTime
deltaZ = deltaZ + right.z * moveSpeed * deltaTime
end end
if Engine.KeyDown(KeyCode.D) then if Engine.KeyDown(KeyCode.D) then
-- Move left Position.z = Position.z + (deltaTime * Move_Speec)
deltaX = deltaX - right.x * moveSpeed * deltaTime end
deltaZ = deltaZ - right.z * moveSpeed * deltaTime if Engine.KeyDown(KeyCode.A) then
Position.z = Position.z - (deltaTime * Move_Speec)
end end
-- Update position based on calculated deltas transform:SetPosition(Position)
position.x = position.x + deltaX
position.z = position.z + deltaZ
transform:SetPosition(position)
-- Expose updated position and rotation
Engine.Expose("Position X", position.x)
Engine.Expose("Position Z", rotation.z) local rotation = {
Engine.Expose("Rotation Y", currentRotation) x = old_rotation.x, -- Preserving existing new_rotation on X-axis
y = new_rotation, -- Updated new_rotation on Y-axis for spinning
z = old_rotation.z -- Preserving existing new_rotation on Z-axis
}
-- Apply the new new_rotation to the Transform component
transform:SetRotation(rotation)
new_rotation = new_rotation + (deltaTime * new_rotationSpeed)
if new_rotation >= 360 then
new_rotation = 0
end
end end

View File

@ -1,76 +1 @@
--@module Engine return _T_Engine_Table -- This just returns the Global Table that the engine creates
--[[
Engine.lua serves as the Lua interface for your engine's functionalities.
It maps C++ bound functions from `_T_Engine_Table` to a Lua `Engine` table,
enriched with EmmyLua annotations for enhanced IntelliSense support.
]]
---@class Color
---@field r number Red component (0-1)
---@field g number Green component (0-1)
---@field b number Blue component (0-1)
---@field a number Alpha component (0-1)
---@class Vector3
---@field x number
---@field y number
---@field z number
---@class Transform
---@field position Vector3 The position of the Transform.
---@field rotation Vector3 The rotation of the Transform.
---@field scale Vector3 The scale of the Transform.
---@class Camera
---@field fieldOfView number The camera's field of view.
---@field nearClipPlane number The near clipping plane distance.
---@field farClipPlane number The far clipping plane distance.
---@class Mesh
---@field vertices Vector3[] The vertices of the mesh.
---@field indices number[] The indices defining the mesh's triangles.
---@class GameObject
local GameObject = {}
---Retrieves a component attached to the GameObject.
---@param componentName string The name of the component to retrieve ("Transform", "Camera", "Mesh")
---@return Transform|Camera|Mesh|nil The requested component or `nil` if not found.
function GameObject:GetComponent(componentName)
-- The actual implementation is bound in C++.
-- This is just for IntelliSense support.
end
---@class Engine
local Engine = {}
---Logs a message with an optional color and alpha.
---@param message string The message to log.
---@param color? Color Optional color and alpha for the log message.
---@return void
Engine.Log = _T_Engine_Table.Log
---Exposes a variable to the engine.
---@param name string The identifier name of the variable.
---@param label string A human-readable label for the variable.
---@param value number|string|boolean|nil The value to expose (int, float, bool, string, nil).
---@return void
Engine.Expose = _T_Engine_Table.Expose
---Checks if a specific key is currently pressed.
---@param keyCode KeyCode The key code to check.
---@return boolean True if the key is pressed, false otherwise.
Engine.KeyDown = _T_Engine_Table.KeyDown
---Retrieves the name of the current script.
---@return string The name of the script.
Engine.ScriptName = _T_Engine_Table.ScriptName
---Gets a GameObject by its tag.
---@param tag string The tag associated with the GameObject.
---@return GameObject|nil The GameObject with the specified tag, or `nil` if not found.
Engine.GetGameObjectByTag = _T_Engine_Table.GetGameObjectByTag
return Engine

View File

@ -1,249 +1 @@
--@module KeyCodes return _T_KeyCode_Table
local _Engine_KeyCodes = _T_KeyCode_Table
---@class KeyCode
---@field Space number
---@field Apostrophe number
---@field Comma number
---@field Minus number
---@field Period number
---@field Slash number
---@field D0 number
---@field D1 number
---@field D2 number
---@field D3 number
---@field D4 number
---@field D5 number
---@field D6 number
---@field D7 number
---@field D8 number
---@field D9 number
---@field Semicolon number
---@field Equal number
---@field A number
---@field B number
---@field C number
---@field D number
---@field E number
---@field F number
---@field G number
---@field H number
---@field I number
---@field J number
---@field K number
---@field L number
---@field M number
---@field N number
---@field O number
---@field P number
---@field Q number
---@field R number
---@field S number
---@field T number
---@field U number
---@field V number
---@field W number
---@field X number
---@field Y number
---@field Z number
---@field LeftBracket number
---@field Backslash number
---@field RightBracket number
---@field GraveAccent number
---@field World1 number
---@field World2 number
---@field Escape number
---@field Enter number
---@field Tab number
---@field Backspace number
---@field Insert number
---@field Delete number
---@field Right number
---@field Left number
---@field Down number
---@field Up number
---@field PageUp number
---@field PageDown number
---@field Home number
---@field End number
---@field CapsLock number
---@field ScrollLock number
---@field NumLock number
---@field PrintScreen number
---@field Pause number
---@field F1 number
---@field F2 number
---@field F3 number
---@field F4 number
---@field F5 number
---@field F6 number
---@field F7 number
---@field F8 number
---@field F9 number
---@field F10 number
---@field F11 number
---@field F12 number
---@field F13 number
---@field F14 number
---@field F15 number
---@field F16 number
---@field F17 number
---@field F18 number
---@field F19 number
---@field F20 number
---@field F21 number
---@field F22 number
---@field F23 number
---@field F24 number
---@field F25 number
---@field KP0 number
---@field KP1 number
---@field KP2 number
---@field KP3 number
---@field KP4 number
---@field KP5 number
---@field KP6 number
---@field KP7 number
---@field KP8 number
---@field KP9 number
---@field KPDecimal number
---@field KPDivide number
---@field KPMultiply number
---@field KPSubtract number
---@field KPAdd number
---@field KPEnter number
---@field KPEqual number
---@field LeftShift number
---@field LeftControl number
---@field LeftAlt number
---@field LeftSuper number
---@field RightShift number
---@field RightControl number
---@field RightAlt number
---@field RightSuper number
---@field Menu number
local KeyCodes = {
Space = _Engine_KeyCodes.Space,
Apostrophe = _Engine_KeyCodes.Apostrophe,
Comma = _Engine_KeyCodes.Comma,
Minus = _Engine_KeyCodes.Minus,
Period = _Engine_KeyCodes.Period,
Slash = _Engine_KeyCodes.Slash,
D0 = _Engine_KeyCodes.D0,
D1 = _Engine_KeyCodes.D1,
D2 = _Engine_KeyCodes.D2,
D3 = _Engine_KeyCodes.D3,
D4 = _Engine_KeyCodes.D4,
D5 = _Engine_KeyCodes.D5,
D6 = _Engine_KeyCodes.D6,
D7 = _Engine_KeyCodes.D7,
D8 = _Engine_KeyCodes.D8,
D9 = _Engine_KeyCodes.D9,
Semicolon = _Engine_KeyCodes.Semicolon,
Equal = _Engine_KeyCodes.Equal,
A = _Engine_KeyCodes.A,
B = _Engine_KeyCodes.B,
C = _Engine_KeyCodes.C,
D = _Engine_KeyCodes.D,
E = _Engine_KeyCodes.E,
F = _Engine_KeyCodes.F,
G = _Engine_KeyCodes.G,
H = _Engine_KeyCodes.H,
I = _Engine_KeyCodes.I,
J = _Engine_KeyCodes.J,
K = _Engine_KeyCodes.K,
L = _Engine_KeyCodes.L,
M = _Engine_KeyCodes.M,
N = _Engine_KeyCodes.N,
O = _Engine_KeyCodes.O,
P = _Engine_KeyCodes.P,
Q = _Engine_KeyCodes.Q,
R = _Engine_KeyCodes.R,
S = _Engine_KeyCodes.S,
T = _Engine_KeyCodes.T,
U = _Engine_KeyCodes.U,
V = _Engine_KeyCodes.V,
W = _Engine_KeyCodes.W,
X = _Engine_KeyCodes.X,
Y = _Engine_KeyCodes.Y,
Z = _Engine_KeyCodes.Z,
LeftBracket = _Engine_KeyCodes.LeftBracket,
Backslash = _Engine_KeyCodes.Backslash,
RightBracket = _Engine_KeyCodes.RightBracket,
GraveAccent = _Engine_KeyCodes.GraveAccent,
World1 = _Engine_KeyCodes.World1,
World2 = _Engine_KeyCodes.World2,
Escape = _Engine_KeyCodes.Escape,
Enter = _Engine_KeyCodes.Enter,
Tab = _Engine_KeyCodes.Tab,
Backspace = _Engine_KeyCodes.Backspace,
Insert = _Engine_KeyCodes.Insert,
Delete = _Engine_KeyCodes.Delete,
Right = _Engine_KeyCodes.Right,
Left = _Engine_KeyCodes.Left,
Down = _Engine_KeyCodes.Down,
Up = _Engine_KeyCodes.Up,
PageUp = _Engine_KeyCodes.PageUp,
PageDown = _Engine_KeyCodes.PageDown,
Home = _Engine_KeyCodes.Home,
End = _Engine_KeyCodes.End,
CapsLock = _Engine_KeyCodes.CapsLock,
ScrollLock = _Engine_KeyCodes.ScrollLock,
NumLock = _Engine_KeyCodes.NumLock,
PrintScreen = _Engine_KeyCodes.PrintScreen,
Pause = _Engine_KeyCodes.Pause,
F1 = _Engine_KeyCodes.F1,
F2 = _Engine_KeyCodes.F2,
F3 = _Engine_KeyCodes.F3,
F4 = _Engine_KeyCodes.F4,
F5 = _Engine_KeyCodes.F5,
F6 = _Engine_KeyCodes.F6,
F7 = _Engine_KeyCodes.F7,
F8 = _Engine_KeyCodes.F8,
F9 = _Engine_KeyCodes.F9,
F10 = _Engine_KeyCodes.F10,
F11 = _Engine_KeyCodes.F11,
F12 = _Engine_KeyCodes.F12,
F13 = _Engine_KeyCodes.F13,
F14 = _Engine_KeyCodes.F14,
F15 = _Engine_KeyCodes.F15,
F16 = _Engine_KeyCodes.F16,
F17 = _Engine_KeyCodes.F17,
F18 = _Engine_KeyCodes.F18,
F19 = _Engine_KeyCodes.F19,
F20 = _Engine_KeyCodes.F20,
F21 = _Engine_KeyCodes.F21,
F22 = _Engine_KeyCodes.F22,
F23 = _Engine_KeyCodes.F23,
F24 = _Engine_KeyCodes.F24,
F25 = _Engine_KeyCodes.F25,
KP0 = _Engine_KeyCodes.KP0,
KP1 = _Engine_KeyCodes.KP1,
KP2 = _Engine_KeyCodes.KP2,
KP3 = _Engine_KeyCodes.KP3,
KP4 = _Engine_KeyCodes.KP4,
KP5 = _Engine_KeyCodes.KP5,
KP6 = _Engine_KeyCodes.KP6,
KP7 = _Engine_KeyCodes.KP7,
KP8 = _Engine_KeyCodes.KP8,
KP9 = _Engine_KeyCodes.KP9,
KPDecimal = _Engine_KeyCodes.KPDecimal,
KPDivide = _Engine_KeyCodes.KPDivide,
KPMultiply = _Engine_KeyCodes.KPMultiply,
KPSubtract = _Engine_KeyCodes.KPSubtract,
KPAdd = _Engine_KeyCodes.KPAdd,
KPEnter = _Engine_KeyCodes.KPEnter,
KPEqual = _Engine_KeyCodes.KPEqual,
LeftShift = _Engine_KeyCodes.LeftShift,
LeftControl = _Engine_KeyCodes.LeftControl,
LeftAlt = _Engine_KeyCodes.LeftAlt,
LeftSuper = _Engine_KeyCodes.LeftSuper,
RightShift = _Engine_KeyCodes.RightShift,
RightControl = _Engine_KeyCodes.RightControl,
RightAlt = _Engine_KeyCodes.RightAlt,
RightSuper = _Engine_KeyCodes.RightSuper,
Menu = _Engine_KeyCodes.Menu
}
return KeyCodes

View File

@ -1,7 +1,10 @@
-- script.lua -- script.lua
local Engine = require("engine") local Math = require("./assets/scripts/math")
local Engine = require("./assets/scripts/engine")
local itterator = 0
local ticks = 0
local new_rotation = 0 local new_rotation = 0
local speed = 50 local speed = 50

View File

@ -0,0 +1,240 @@
-- unitTests.lua
-- Unit Tests for C++ Lua API and Game Engine
local Math = require("./assets/scripts/math")
local Engine = require("./assets/scripts/engine")
local function OnInit()
-- Log a message with a custom red color
Engine.Log("This is a red message.", {1.0, 0.0, 0.0, 1.0})
-- Log a message with a custom green color
Engine.Log("This is a green message.", {0.0, 1.0, 0.0, 1.0})
-- Log a message with a custom blue color
Engine.Log("This is a blue message.", {0.0, 0.0, 1.0, 1.0})
end
-- Simple Test Framework
local Tests = {}
local passed = 0
local failed = 0
-- Assertion Functions
local function assertEquals(expected, actual, message)
if expected ~= actual then
error(message or string.format("Assertion Failed: expected '%s', got '%s'", tostring(expected), tostring(actual)))
end
end
local function assertTableEquals(expected, actual, message)
if type(expected) ~= "table" or type(actual) ~= "table" then
error(message or "Assertion Failed: One of the values is not a table.")
end
for k, v in pairs(expected) do
if actual[k] ~= v then
error(message or string.format("Assertion Failed: For key '%s', expected '%s', got '%s'", tostring(k), tostring(v), tostring(actual[k])))
end
end
end
local function assertNotNil(value, message)
if value == nil then
error(message or "Assertion Failed: value is nil.")
end
end
local function assertTrue(condition, message)
if not condition then
error(message or "Assertion Failed: condition is not true.")
end
end
-- Helper Function to Capture Logs
local capturedLogs = {}
local originalLog = Engine.Log
local function mockLog(message, color)
table.insert(capturedLogs, {message = message, color = color})
end
-- Register Test Cases
function Tests.testEngineLog()
-- Replace Engine.Log with mockLog
Engine.Log = mockLog
-- Call OnInit to generate logs
OnInit()
-- Restore original Engine.Log
Engine.Log = originalLog
-- Assertions
assertEquals(3, #capturedLogs, "OnInit should log exactly 3 messages.")
-- Check first log (Red Message)
assertEquals("This is a red message.", capturedLogs[1].message)
assertTableEquals({1.0, 0.0, 0.0, 1.0}, capturedLogs[1].color, "First log color mismatch.")
-- Check second log (Green Message)
assertEquals("This is a green message.", capturedLogs[2].message)
assertTableEquals({0.0, 1.0, 0.0, 1.0}, capturedLogs[2].color, "Second log color mismatch.")
-- Check third log (Blue Message)
assertEquals("This is a blue message.", capturedLogs[3].message)
assertTableEquals({0.0, 0.0, 1.0, 1.0}, capturedLogs[3].color, "Third log color mismatch.")
end
function Tests.testGetGameObjectByTag()
-- Assume "Player" and "Gun" GameObjects exist
local player = Engine.GetGameObjectByTag("Player")
assertNotNil(player, "Player GameObject should exist.")
local gun = Engine.GetGameObjectByTag("Gun")
assertNotNil(gun, "Gun GameObject should exist.")
-- Test for a non-existent tag
local nonExistent = Engine.GetGameObjectByTag("NonExistentTag")
assertEquals(nil, nonExistent, "Non-existent GameObject should return nil.")
end
function Tests.testGameObjectGetName()
local player = Engine.GetGameObjectByTag("Player")
assertNotNil(player, "Player GameObject should exist.")
local name = player:GetName()
assertEquals("Player", name, "Player GameObject name should be 'Player'.")
end
function Tests.testGameObjectGetComponent()
local player = Engine.GetGameObjectByTag("Player")
assertNotNil(player, "Player GameObject should exist.")
local transform = player:GetComponent("Transform")
assertNotNil(transform, "Player should have a Transform component.")
local nonExistentComponent = player:GetComponent("NonExistentComponent")
assertEquals(nil, nonExistentComponent, "Non-existent component should return nil.")
end
function Tests.testTransformComponentPosition()
local player = Engine.GetGameObjectByTag("Player")
assertNotNil(player, "Player GameObject should exist.")
local transform = player:GetComponent("Transform")
assertNotNil(transform, "Player should have a Transform component.")
-- Get initial position
local position = transform:GetPosition()
assertNotNil(position, "Transform:GetPosition should return a position table.")
assertEquals(0.0, position.x, "Initial X position should be 0.0.")
assertEquals(2.0, position.y, "Initial Y position should be 2.0.")
assertEquals(-12.0, position.z, "Initial Z position should be -12.0.")
-- Set new position
local newPosition = {x = 5.0, y = 10.0, z = -15.0}
transform:SetPosition(newPosition)
-- Get updated position
local updatedPosition = transform:GetPosition()
assertTableEquals(newPosition, updatedPosition, "Transform:SetPosition did not update position correctly.")
end
function Tests.testTransformComponentRotation()
local player = Engine.GetGameObjectByTag("Player")
assertNotNil(player, "Player GameObject should exist.")
local transform = player:GetComponent("Transform")
assertNotNil(transform, "Player should have a Transform component.")
-- Get initial rotation
local rotation = transform:GetRotation()
assertNotNil(rotation, "Transform:GetRotation should return a rotation table.")
-- Set new rotation
local newRotation = {x = 45.0, y = 90.0, z = 135.0}
transform:SetRotation(newRotation)
-- Get updated rotation
local updatedRotation = transform:GetRotation()
assertTableEquals(newRotation, updatedRotation, "Transform:SetRotation did not update rotation correctly.")
end
function Tests.testOnUpdateFunctionality()
-- Mock GameObject and Transform
local mockPlayer = {
GetName = function() return "Player" end,
GetComponent = function(componentName)
if componentName == "Transform" then
return {
GetRotation = function()
return {x = new_rotation, y = new_rotation, z = new_rotation}
end,
SetRotation = function(rotation)
new_rotation = rotation.x
end
}
end
return nil
end
}
-- Replace Engine.GetGameObjectByTag to return mockPlayer
local originalGetGameObjectByTag = Engine.GetGameObjectByTag
Engine.GetGameObjectByTag = function(tag)
if tag == "Player" then
return mockPlayer
end
return originalGetGameObjectByTag(tag)
end
-- Initialize rotation
new_rotation = 0
speed = 50
-- Call OnUpdate with deltaTime = 1
OnUpdate(1)
-- Check new_rotation
assertEquals(50, new_rotation, "After first OnUpdate, new_rotation should be 50.")
-- Call OnUpdate with deltaTime = 14 (to exceed 720)
OnUpdate(14)
-- new_rotation should reset to 0 after exceeding 720
assertEquals(720 + 50 - 720, new_rotation, "After exceeding 720, new_rotation should reset appropriately.")
-- Restore original Engine.GetGameObjectByTag
Engine.GetGameObjectByTag = originalGetGameObjectByTag
end
-- Add more test functions below as needed
-- Test Runner
local function runTests()
print("Starting Unit Tests...\n")
for testName, testFunc in pairs(Tests) do
io.write(string.format("Running %s... ", testName))
local status, err = pcall(testFunc)
if status then
print("PASSED")
passed = passed + 1
else
print("FAILED")
print(" Error:", err)
failed = failed + 1
end
end
print(string.format("\nUnit Tests Completed: %d Passed, %d Failed", passed, failed))
end
-- Execute Tests
runTests()

View File

@ -1,5 +1,6 @@
#version 330 core #version 330 core
void main() void main()
{ {
// No color output; only depth is recorded // Depth is automatically written to the depth buffer
} }

View File

@ -1,10 +1,12 @@
#version 330 core #version 330 core
layout(location = 0) in vec3 aPos; layout(location = 0) in vec3 aPos;
uniform mat4 lightSpaceMatrix; uniform mat4 uModel;
uniform mat4 model; uniform mat4 uLightView;
uniform mat4 uLightProj;
void main() void main()
{ {
gl_Position = lightSpaceMatrix * model * vec4(aPos, 1.0); gl_Position = uLightProj * uLightView * uModel * vec4(aPos, 1.0);
} }

View File

@ -0,0 +1,12 @@
#version 330 core
in vec2 TexCoords;
out vec4 FragColor;
uniform sampler2D depthMap;
void main()
{
float depthValue = texture(depthMap, TexCoords).r;
FragColor = vec4(vec3(depthValue), 1.0);
}

View File

@ -0,0 +1,12 @@
#version 330 core
layout(location = 0) in vec2 aPos;
layout(location = 1) in vec2 aTexCoords;
out vec2 TexCoords;
void main()
{
TexCoords = aTexCoords;
gl_Position = vec4(aPos, 0.0, 1.0);
}

View File

@ -1,6 +0,0 @@
#version 330 core
out vec4 FragColor;
uniform vec4 uColor;
void main() {
FragColor = uColor;
}

View File

@ -1,8 +0,0 @@
#version 330 core
layout (location = 0) in vec3 aPos;
uniform mat4 uMVP;
void main() {
gl_Position = uMVP * vec4(aPos, 1.0);
}

View File

@ -2,29 +2,62 @@
struct TextureArray { struct TextureArray {
sampler2D texture_diffuse[32]; // Array of diffuse textures sampler2D texture_diffuse[32]; // Array of diffuse textures
// You can add more texture types here (e.g., specular, normal) if needed // Add more texture types if needed
}; };
uniform TextureArray uTextures; // Array of textures uniform TextureArray uTextures; // Array of textures
uniform int uNumDiffuseTextures; // Number of active diffuse textures uniform int uNumDiffuseTextures; // Number of active diffuse textures
uniform mat4 uLightSpaceMatrix; // Light space matrix
uniform sampler2D uShadowMap; // Shadow map texture
in vec2 TexCoord; // From vertex shader in vec2 TexCoord; // From vertex shader
in vec3 Normal; // From vertex shader in vec3 Normal; // From vertex shader
in vec3 FragPos; // From vertex shader in vec3 FragPos; // From vertex shader
in vec4 FragPosLightSpace; // From vertex shader
out vec4 FragColor; // Final fragment color out vec4 FragColor; // Final fragment color
// Example lighting parameters // Lighting parameters
uniform vec3 lightPos; // Position of the light source struct Light {
vec3 direction;
vec3 position;
};
uniform Light light;
uniform vec3 viewPos; // Position of the camera/viewer uniform vec3 viewPos; // Position of the camera/viewer
float ShadowCalculation(vec4 fragPosLightSpace)
{
// Perform perspective divide
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
// Transform to [0,1] range
projCoords = projCoords * 0.5 + 0.5;
// Get closest depth value from light's perspective
float closestDepth = texture(uShadowMap, projCoords.xy).r;
// Get current fragment's depth
float currentDepth = projCoords.z;
// Check whether current frag pos is in shadow
float bias = 0.005;
float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
// Keep the shadow at 0.0 when outside the far plane region of the light's orthographic projection
if(projCoords.z > 1.0)
shadow = 0.0;
return shadow;
}
void main() void main()
{ {
// Normalize the normal vector // Normalize the normal vector
vec3 norm = normalize(Normal); vec3 norm = normalize(Normal);
// Calculate the direction from the fragment to the light // Calculate the direction from the fragment to the light
vec3 lightDir = normalize(lightPos - FragPos); vec3 lightDir = normalize(light.direction);
// Compute the diffuse intensity // Compute the diffuse intensity
float diff = max(dot(norm, lightDir), 0.0); float diff = max(dot(norm, lightDir), 0.0);
@ -44,6 +77,10 @@ void main()
// Simple ambient lighting // Simple ambient lighting
vec3 ambient = 0.1 * diffuseColor.rgb; vec3 ambient = 0.1 * diffuseColor.rgb;
// Final color combining ambient and diffuse components // Calculate shadow
FragColor = vec4(ambient + diffuseColor.rgb, diffuseColor.a); float shadow = ShadowCalculation(FragPosLightSpace);
// Final color combining ambient and shadowed diffuse components
vec3 lighting = ambient + (1.0 - shadow) * diffuseColor.rgb;
FragColor = vec4(lighting, diffuseColor.a);
} }

View File

@ -4,12 +4,14 @@ layout(location = 0) in vec3 aPos; // Vertex position
layout(location = 1) in vec2 aTexCoord; // Texture coordinate layout(location = 1) in vec2 aTexCoord; // Texture coordinate
layout(location = 2) in vec3 aNormal; // Vertex normal layout(location = 2) in vec3 aNormal; // Vertex normal
uniform mat4 uMVP; // Model-View-Projection matrix uniform mat4 uMVP; // Model-View-Projection matrix
uniform mat4 uModel; // Model matrix uniform mat4 uModel; // Model matrix
uniform mat4 uLightSpaceMatrix; // Light space matrix
out vec2 TexCoord; // Passed to fragment shader out vec2 TexCoord; // Passed to fragment shader
out vec3 Normal; // Passed to fragment shader out vec3 Normal; // Passed to fragment shader
out vec3 FragPos; // Passed to fragment shader out vec3 FragPos; // Passed to fragment shader
out vec4 FragPosLightSpace; // Passed to fragment shader
void main() void main()
{ {
@ -22,6 +24,9 @@ void main()
// Pass through the texture coordinate // Pass through the texture coordinate
TexCoord = aTexCoord; TexCoord = aTexCoord;
// Transform the fragment position to light space
FragPosLightSpace = uLightSpaceMatrix * vec4(FragPos, 1.0);
// Final vertex position // Final vertex position
gl_Position = uMVP * vec4(aPos, 1.0); gl_Position = uMVP * vec4(aPos, 1.0);
} }

132
examples/BounceingItem.lua Normal file
View File

@ -0,0 +1,132 @@
--
-- This lua makes a Game object bounce a nd spin like a minecraft item.
local GameObjectName = "Gun" -- This is the tag of the game object you want it to modify
--
--
--
local Math = require("./assets/scripts/math") -- Require the enhanced math module
local Engine = require("./assets/scripts/engine")
-- Variables to track elapsed time and rotation
local elapsedTime = 0
local rotationSpeed = 90 -- 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 = 0.1 -- 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
local transform = nil
local TAU = Math.constants.TAU
-- Update function called every frame
function OnUpdate(deltaTime)
-- Ensure that the Gun and its Transform component are valid
-- this was made after OnInit was depricated
if not gun then
gun = Engine.GetGameObjectByTag(GameObjectName)
if gun 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("Gun found and initial position updated.", {1, 1, 1, 1})
else
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})
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})
else
Engine.Log("Transform component still not found on Gun.", {1, 1, 0, 1})
return
end
end
-- Increment elapsed time
elapsedTime = elapsedTime + deltaTime
-- === Spinning the Gun ===
-- Update the rotation angle based on rotationSpeed and deltaTime
new_rotation = new_rotation + (deltaTime * rotationSpeed)
-- Keep the rotation angle within 0-360 degrees to prevent overflow
if new_rotation >= 360 then
new_rotation = new_rotation - 360
end
-- Define the new rotation (spinning around the Y-axis)
local rotation = {
x = -180, -- Preserving existing rotation on X-axis
y = new_rotation, -- Updated rotation on Y-axis for spinning
z = 0 -- Preserving existing rotation on Z-axis
}
-- Apply the new rotation to the Transform component
transform:SetRotation(rotation)
-- === Bobbing the Gun Up and Down ===
-- Calculate the bobbing offset using a sine wave
local bobOffset = bobAmplitude * math.sin(TAU * bobFrequency * elapsedTime)
-- 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
y = initial_position.y + bobOffset, -- Bouncing up and down on Y-axis
z = initial_position.z -- No change on Z-axis
}
-- Apply the new position to the Transform component
transform:SetPosition(new_position)
-- === Optional: Log Current Rotation and Position ===
-- Uncomment the following lines if you wish to log the gun's current rotation and position
-- local current_rotation = transform:GetRotation()
-- Engine.Log(string.format("Gun Rotation: (X: %.2f, Y: %.2f, Z: %.2f)", current_rotation.x, current_rotation.y, current_rotation.z), {1, 1, 1, 1})
-- local current_position = transform:GetPosition()
-- Engine.Log(string.format("Gun Position: (X: %.2f, Y: %.2f, Z: %.2f)", current_position.x, current_position.y, current_position.z), {1, 1, 1, 1})
end

View File

@ -1,10 +1,10 @@
[Window][DockSpace] [Window][DockSpace]
Pos=0,0 Pos=0,0
Size=1280,720 Size=1920,1177
Collapsed=0 Collapsed=0
[Window][Debug##Default] [Window][Debug##Default]
ViewportPos=1168,966 ViewportPos=926,1030
ViewportId=0x16723995 ViewportId=0x16723995
Size=400,400 Size=400,400
Collapsed=0 Collapsed=0
@ -80,8 +80,8 @@ Collapsed=0
DockId=0x0000001F,0 DockId=0x0000001F,0
[Window][Performance##performance] [Window][Performance##performance]
Pos=8,360 Pos=8,706
Size=335,352 Size=322,463
Collapsed=0 Collapsed=0
DockId=0x0000001C,0 DockId=0x0000001C,0
@ -105,7 +105,7 @@ DockId=0x0000000F,0
[Window][Scene Window##SceneWindow] [Window][Scene Window##SceneWindow]
Pos=8,28 Pos=8,28
Size=335,330 Size=322,676
Collapsed=0 Collapsed=0
DockId=0x0000001B,0 DockId=0x0000001B,0
@ -134,34 +134,34 @@ Collapsed=0
DockId=0x0000001E,0 DockId=0x0000001E,0
[Window][ Logger##logger] [Window][ Logger##logger]
Pos=345,282 Pos=1070,811
Size=265,430 Size=454,358
Collapsed=0 Collapsed=0
DockId=0x00000021,0 DockId=0x00000024,0
[Window][ Editor##EditorWindow] [Window][ Editor##EditorWindow]
Pos=345,28 Pos=332,28
Size=530,252 Size=1192,781
Collapsed=0 Collapsed=0
DockId=0x0000001F,0 DockId=0x0000001F,0
[Window][ Inspector##InspectorWindow] [Window][ Inspector##InspectorWindow]
Pos=877,28 Pos=1526,28
Size=395,684 Size=386,767
Collapsed=0 Collapsed=0
DockId=0x00000022,0 DockId=0x00000025,0
[Window][ Profiler] [Window][ Profiler]
Pos=612,282 Pos=332,811
Size=263,430 Size=736,358
Collapsed=0 Collapsed=0
DockId=0x00000023,0 DockId=0x00000023,0
[Window][Logger Window] [Window][Shadow Map Preview]
Pos=345,282 Pos=1526,797
Size=530,430 Size=386,372
Collapsed=0 Collapsed=0
DockId=0x00000023,1 DockId=0x00000026,0
[Table][0xE9E836E4,4] [Table][0xE9E836E4,4]
Column 0 Weight=1.2999 Column 0 Weight=1.2999
@ -170,23 +170,18 @@ Column 2 Weight=0.6474
Column 3 Weight=1.0088 Column 3 Weight=1.0088
[Table][0x08173DEA,4] [Table][0x08173DEA,4]
Column 0 Weight=1.4299 Column 0 Weight=1.2209
Column 1 Weight=0.9086 Column 1 Weight=1.1411
Column 2 Weight=0.9665 Column 2 Weight=1.2270
Column 3 Weight=0.6950 Column 3 Weight=0.4110
[Table][0x801835C4,2]
RefScale=16
Column 0 Width=30
Column 1 Weight=1.0000
[Docking][Data] [Docking][Data]
DockSpace ID=0x14621557 Window=0x3DA2F1DE Pos=250,293 Size=1264,684 Split=X Selected=0xF7365A5A DockSpace ID=0x14621557 Window=0x3DA2F1DE Pos=8,51 Size=1904,1141 Split=X Selected=0xF7365A5A
DockNode ID=0x00000020 Parent=0x14621557 SizeRef=884,684 Split=X DockNode ID=0x00000021 Parent=0x14621557 SizeRef=1516,1141 Split=X
DockNode ID=0x00000013 Parent=0x00000020 SizeRef=335,1142 Split=Y Selected=0x818D04BB DockNode ID=0x00000013 Parent=0x00000021 SizeRef=322,1142 Split=Y Selected=0x818D04BB
DockNode ID=0x0000001B Parent=0x00000013 SizeRef=264,551 HiddenTabBar=1 Selected=0x1D5D92B6 DockNode ID=0x0000001B Parent=0x00000013 SizeRef=264,675 HiddenTabBar=1 Selected=0x1D5D92B6
DockNode ID=0x0000001C Parent=0x00000013 SizeRef=264,588 HiddenTabBar=1 Selected=0x818D04BB DockNode ID=0x0000001C Parent=0x00000013 SizeRef=264,463 HiddenTabBar=1 Selected=0x818D04BB
DockNode ID=0x00000014 Parent=0x00000020 SizeRef=547,1142 Split=X DockNode ID=0x00000014 Parent=0x00000021 SizeRef=552,1142 Split=X
DockNode ID=0x00000015 Parent=0x00000014 SizeRef=1158,1142 Split=X DockNode ID=0x00000015 Parent=0x00000014 SizeRef=1158,1142 Split=X
DockNode ID=0x00000011 Parent=0x00000015 SizeRef=265,1142 Selected=0x1D5D92B6 DockNode ID=0x00000011 Parent=0x00000015 SizeRef=265,1142 Selected=0x1D5D92B6
DockNode ID=0x00000012 Parent=0x00000015 SizeRef=1259,1142 Split=X DockNode ID=0x00000012 Parent=0x00000015 SizeRef=1259,1142 Split=X
@ -202,11 +197,11 @@ DockSpace ID=0x14621557 Window=0x3DA2F1DE Pos=250,293
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=1202,849 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=0x0000000D Parent=0x00000003 SizeRef=1202,571 Split=Y Selected=0xDFF75B3F
DockNode ID=0x00000017 Parent=0x0000000D SizeRef=1202,776 Split=Y Selected=0xDFF75B3F DockNode ID=0x00000017 Parent=0x0000000D SizeRef=1202,776 Split=Y Selected=0xDFF75B3F
DockNode ID=0x0000001D Parent=0x00000017 SizeRef=518,720 Split=Y Selected=0x9A7B23B9 DockNode ID=0x0000001D Parent=0x00000017 SizeRef=518,720 Split=Y Selected=0xDFF75B3F
DockNode ID=0x0000001F Parent=0x0000001D SizeRef=549,709 CentralNode=1 HiddenTabBar=1 Selected=0x9A7B23B9 DockNode ID=0x0000001F Parent=0x0000001D SizeRef=518,779 CentralNode=1 Selected=0x9A7B23B9
DockNode ID=0x00000025 Parent=0x0000001D SizeRef=549,430 Split=X Selected=0x1F29F1F5 DockNode ID=0x00000020 Parent=0x0000001D SizeRef=518,358 Split=X Selected=0x7A66B86B
DockNode ID=0x00000021 Parent=0x00000025 SizeRef=586,323 Selected=0x1F29F1F5 DockNode ID=0x00000023 Parent=0x00000020 SizeRef=736,358 HiddenTabBar=1 Selected=0x7A66B86B
DockNode ID=0x00000023 Parent=0x00000025 SizeRef=582,323 Selected=0x7A66B86B DockNode ID=0x00000024 Parent=0x00000020 SizeRef=454,358 HiddenTabBar=1 Selected=0x1F29F1F5
DockNode ID=0x0000001E Parent=0x00000017 SizeRef=518,417 Selected=0xC74E1AEE DockNode ID=0x0000001E Parent=0x00000017 SizeRef=518,417 Selected=0xC74E1AEE
DockNode ID=0x00000018 Parent=0x0000000D SizeRef=1202,364 Split=X Selected=0x1C0788A1 DockNode ID=0x00000018 Parent=0x0000000D SizeRef=1202,364 Split=X Selected=0x1C0788A1
DockNode ID=0x00000019 Parent=0x00000018 SizeRef=601,364 Selected=0x1C0788A1 DockNode ID=0x00000019 Parent=0x00000018 SizeRef=601,364 Selected=0x1C0788A1
@ -215,7 +210,9 @@ DockSpace ID=0x14621557 Window=0x3DA2F1DE Pos=250,293
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=1202,291 Selected=0x9DD4E196 DockNode ID=0x00000004 Parent=0x00000001 SizeRef=1202,291 Selected=0x9DD4E196
DockNode ID=0x00000002 Parent=0x00000008 SizeRef=334,1142 HiddenTabBar=1 Selected=0x36DC96AB DockNode ID=0x00000002 Parent=0x00000008 SizeRef=334,1142 HiddenTabBar=1 Selected=0x36DC96AB
DockNode ID=0x00000016 Parent=0x00000014 SizeRef=420,1142 Selected=0x8D0E8380 DockNode ID=0x00000016 Parent=0x00000014 SizeRef=420,1142 Selected=0x8D0E8380
DockNode ID=0x00000022 Parent=0x14621557 SizeRef=395,684 HiddenTabBar=1 Selected=0xD1D25642 DockNode ID=0x00000022 Parent=0x14621557 SizeRef=386,1141 Split=Y Selected=0xD1D25642
DockNode ID=0x00000025 Parent=0x00000022 SizeRef=386,767 Selected=0xD1D25642
DockNode ID=0x00000026 Parent=0x00000022 SizeRef=386,372 HiddenTabBar=1 Selected=0x65AE91BD
DockSpace ID=0xC6145A92 Pos=8,27 Size=1904,1142 Split=X DockSpace ID=0xC6145A92 Pos=8,27 Size=1904,1142 Split=X
DockNode ID=0x0000000F Parent=0xC6145A92 SizeRef=301,1142 Selected=0xA8433A03 DockNode ID=0x0000000F Parent=0xC6145A92 SizeRef=301,1142 Selected=0xA8433A03
DockNode ID=0x00000010 Parent=0xC6145A92 SizeRef=1601,1142 CentralNode=1 DockNode ID=0x00000010 Parent=0xC6145A92 SizeRef=1601,1142 CentralNode=1

View File

@ -10,7 +10,7 @@ Entities:
MeshPath: assets/models/sponza.obj MeshPath: assets/models/sponza.obj
submeshes_len: 26 submeshes_len: 26
submeshes: submeshes:
- vao: 1 - vao: 2
indexCount: 43452 indexCount: 43452
textures: textures:
- id: 24 - id: 24
@ -22,139 +22,139 @@ Entities:
- id: 25 - id: 25
type: texture_diffuse type: texture_diffuse
path: textures/vase_dif.tga path: textures/vase_dif.tga
- vao: 5 - vao: 4
indexCount: 33024 indexCount: 33024
textures: textures:
- id: 15 - id: 15
type: texture_diffuse type: texture_diffuse
path: textures/sponza_fabric_diff.tga path: textures/sponza_fabric_diff.tga
- vao: 7 - vao: 5
indexCount: 54 indexCount: 54
textures: ~ textures: ~
- vao: 9 - vao: 6
indexCount: 12258 indexCount: 12258
textures: textures:
- id: 5 - id: 5
type: texture_diffuse type: texture_diffuse
path: textures/background.tga path: textures/background.tga
- vao: 11 - vao: 7
indexCount: 10416 indexCount: 10416
textures: textures:
- id: 6 - id: 6
type: texture_diffuse type: texture_diffuse
path: textures/vase_plant.tga path: textures/vase_plant.tga
- vao: 13 - vao: 8
indexCount: 49536 indexCount: 49536
textures: textures:
- id: 17 - id: 17
type: texture_diffuse type: texture_diffuse
path: textures/sponza_fabric_blue_diff.tga path: textures/sponza_fabric_blue_diff.tga
- vao: 15 - vao: 9
indexCount: 94308 indexCount: 94308
textures: textures:
- id: 23 - id: 23
type: texture_diffuse type: texture_diffuse
path: textures/sponza_thorn_diff.tga path: textures/sponza_thorn_diff.tga
- vao: 17 - vao: 10
indexCount: 49536 indexCount: 49536
textures: textures:
- id: 18 - id: 18
type: texture_diffuse type: texture_diffuse
path: textures/sponza_fabric_green_diff.tga path: textures/sponza_fabric_green_diff.tga
- vao: 19 - vao: 11
indexCount: 17628 indexCount: 17628
textures: textures:
- id: 9 - id: 9
type: texture_diffuse type: texture_diffuse
path: textures/sponza_ceiling_a_diff.tga path: textures/sponza_ceiling_a_diff.tga
- vao: 21 - vao: 12
indexCount: 30504 indexCount: 30504
textures: textures:
- id: 7 - id: 7
type: texture_diffuse type: texture_diffuse
path: textures/sponza_arch_diff.tga path: textures/sponza_arch_diff.tga
- vao: 23 - vao: 13
indexCount: 53064 indexCount: 53064
textures: textures:
- id: 27 - id: 27
type: texture_diffuse type: texture_diffuse
path: textures/vase_round.tga path: textures/vase_round.tga
- vao: 25 - vao: 14
indexCount: 69624 indexCount: 69624
textures: textures:
- id: 12 - id: 12
type: texture_diffuse type: texture_diffuse
path: textures/sponza_column_b_diff.tga path: textures/sponza_column_b_diff.tga
- vao: 27 - vao: 15
indexCount: 2640 indexCount: 2640
textures: textures:
- id: 14 - id: 14
type: texture_diffuse type: texture_diffuse
path: textures/sponza_details_diff.tga path: textures/sponza_details_diff.tga
- vao: 29 - vao: 16
indexCount: 43008 indexCount: 43008
textures: textures:
- id: 20 - id: 20
type: texture_diffuse type: texture_diffuse
path: textures/sponza_curtain_blue_diff.tga path: textures/sponza_curtain_blue_diff.tga
- vao: 31 - vao: 17
indexCount: 0 indexCount: 0
textures: ~ textures: ~
- vao: 33 - vao: 18
indexCount: 2388 indexCount: 2388
textures: textures:
- id: 8 - id: 8
type: texture_diffuse type: texture_diffuse
path: textures/spnza_bricks_a_diff.tga path: textures/spnza_bricks_a_diff.tga
- vao: 35 - vao: 19
indexCount: 21264 indexCount: 21264
textures: textures:
- id: 13 - id: 13
type: texture_diffuse type: texture_diffuse
path: textures/sponza_column_c_diff.tga path: textures/sponza_column_c_diff.tga
- vao: 37 - vao: 20
indexCount: 63 indexCount: 63
textures: textures:
- id: 22 - id: 22
type: texture_diffuse type: texture_diffuse
path: textures/sponza_floor_a_diff.tga path: textures/sponza_floor_a_diff.tga
- vao: 39 - vao: 21
indexCount: 43008 indexCount: 43008
textures: textures:
- id: 19 - id: 19
type: texture_diffuse type: texture_diffuse
path: textures/sponza_curtain_green_diff.tga path: textures/sponza_curtain_green_diff.tga
- vao: 41 - vao: 22
indexCount: 9126 indexCount: 9126
textures: textures:
- id: 4 - id: 4
type: texture_diffuse type: texture_diffuse
path: textures/lion.tga path: textures/lion.tga
- vao: 43 - vao: 23
indexCount: 96 indexCount: 96
textures: textures:
- id: 10 - id: 10
type: texture_diffuse type: texture_diffuse
path: textures/chain_texture.tga path: textures/chain_texture.tga
- vao: 45 - vao: 24
indexCount: 56832 indexCount: 56832
textures: textures:
- id: 16 - id: 16
type: texture_diffuse type: texture_diffuse
path: textures/sponza_curtain_diff.tga path: textures/sponza_curtain_diff.tga
- vao: 47 - vao: 25
indexCount: 8448 indexCount: 8448
textures: textures:
- id: 11 - id: 11
type: texture_diffuse type: texture_diffuse
path: textures/sponza_column_a_diff.tga path: textures/sponza_column_a_diff.tga
- vao: 49 - vao: 26
indexCount: 49488 indexCount: 49488
textures: textures:
- id: 21 - id: 21
type: texture_diffuse type: texture_diffuse
path: textures/sponza_flagpole_diff.tga path: textures/sponza_flagpole_diff.tga
- vao: 51 - vao: 27
indexCount: 59484 indexCount: 59484
textures: textures:
- id: 26 - id: 26
@ -163,12 +163,12 @@ Entities:
- ID: 1 - ID: 1
Name: Camera Name: Camera
Components: Components:
Transform:
Position: [0, 200, 0]
Rotation: [0, 1.02622044, 0]
Scale: [1, 1, 1]
ScriptComponent: ScriptComponent:
ScriptPath: assets/scripts/camera.lua ScriptPath: assets/scripts/camera.lua
Transform:
Position: [881.214233, 200, -162.832016]
Rotation: [0, 170.205078, 0]
Scale: [1, 1, 1]
CameraComponent: CameraComponent:
IsPerspective: true IsPerspective: true
DefaultRuntimeCamera: true DefaultRuntimeCamera: true
@ -176,17 +176,3 @@ Entities:
AspectRatio: 1.75 AspectRatio: 1.75
NearPlane: 0.100000001 NearPlane: 0.100000001
FarPlane: 7000 FarPlane: 7000
- ID: 2
Name: Grey Cube
Components:
Mesh:
MeshPath: assets/models/DefaultMesh.obj
submeshes_len: 1
submeshes:
- vao: 53
indexCount: 36
textures: ~
Transform:
Position: [-3.43110847, 248.891235, 0]
Rotation: [0, -0, 0]
Scale: [25, 25, 25]

View File

@ -140,7 +140,7 @@ void MeshComponent::Deserialize(const YAML::Node &node)
if (submeshes_len != static_cast<int>(model->submeshes.size())) if (submeshes_len != static_cast<int>(model->submeshes.size()))
{ {
g_LoggerWindow->AddLog(LogLevel::Error, "[Mesh] Size Mismatch [%d:%d]: Check for Curupted Scene Files", submeshes_len, static_cast<int>(submeshes.size())); g_LoggerWindow->AddLog("[Mesh] Size Mismatch [%d:%d]: Check for Curupted Scene Files", submeshes_len, static_cast<int>(submeshes.size()));
} }
// Assign submeshes // Assign submeshes
@ -182,7 +182,7 @@ void MeshComponent::Deserialize(const YAML::Node &node)
} }
if (submeshes_len != static_cast<int>(submeshes.size())) if (submeshes_len != static_cast<int>(submeshes.size()))
{ {
g_LoggerWindow->AddLog(LogLevel::Error,"[Mesh] Size Mismatch [%d:%d]: Check for Curupted Scene Files", submeshes_len, static_cast<int>(submeshes.size())); g_LoggerWindow->AddLog("[Mesh] Size Mismatch [%d:%d]: Check for Curupted Scene Files", submeshes_len, static_cast<int>(submeshes.size()));
} }
} }
} }

View File

@ -0,0 +1,88 @@
// TransformComponent.cpp
#include "Transform.h"
const std::string TransformComponent::name = "Transform";
TransformComponent::TransformComponent()
: position(0.0f), rotation(0.0f), scale(1.0f)
{
position = glm::vec3(0.0f, 0.0f, 0.0f);
rotation = glm::vec3(0.0f, 0.0f, 0.0f);
scale = glm::vec3(1.0f, 1.0f, 1.0f);
}
const std::string& TransformComponent::GetName() const
{
return name;
}
const std::string& TransformComponent::GetStaticName()
{
return name;
}
void TransformComponent::Update(float _deltaTime)
{
(void)_deltaTime; // Suppress unused parameter warning
return;
}
YAML::Node TransformComponent::Serialize()
{
YAML::Node node;
// Position
{
YAML::Node posNode;
posNode.SetStyle(YAML::EmitterStyle::Flow);
posNode.push_back(position.x);
posNode.push_back(position.y);
posNode.push_back(position.z);
node["Position"] = posNode;
}
// Rotation
{
YAML::Node rotNode;
rotNode.SetStyle(YAML::EmitterStyle::Flow);
rotNode.push_back(rotation.x);
rotNode.push_back(rotation.y);
rotNode.push_back(rotation.z);
node["Rotation"] = rotNode;
}
// Scale
{
YAML::Node scaleNode;
scaleNode.SetStyle(YAML::EmitterStyle::Flow);
scaleNode.push_back(scale.x);
scaleNode.push_back(scale.y);
scaleNode.push_back(scale.z);
node["Scale"] = scaleNode;
}
return node;
}
void TransformComponent::Deserialize(const YAML::Node& node)
{
if (node["Position"])
{
auto pos = node["Position"].as<std::vector<float>>();
if (pos.size() == 3)
position = glm::vec3(pos[0], pos[1], pos[2]);
}
if (node["Rotation"])
{
auto rot = node["Rotation"].as<std::vector<float>>();
if (rot.size() == 3)
rotation = glm::vec3(rot[0], rot[1], rot[2]);
}
if (node["Scale"])
{
auto scl = node["Scale"].as<std::vector<float>>();
if (scl.size() == 3)
scale = glm::vec3(scl[0], scl[1], scl[2]);
}
}

View File

@ -1,17 +1,9 @@
// Transform.h // Transform.h
#pragma once #pragma once
#define GLM_ENABLE_EXPERIMENTAL
#include "Component.h" #include "Component.h"
#include <yaml-cpp/yaml.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp> // For glm::lookAt #include <yaml-cpp/yaml.h>
#include <glm/gtc/quaternion.hpp> // For glm::quat
#include <glm/gtx/quaternion.hpp> // For glm::quat_cast
#include <glm/gtc/constants.hpp> // For glm::pi
#include <glm/gtc/matrix_access.hpp> // For glm::eulerAngles
class TransformComponent : public Component class TransformComponent : public Component
{ {
@ -40,14 +32,6 @@ public:
rotation = {x, y, z}; rotation = {x, y, z};
} }
/**
* @brief Orients the transform to face the target position.
*
* @param target The target position to look at.
* @param up The up vector to use for orientation.
*/
void LookAt(const glm::vec3& target, const glm::vec3& up);
TransformComponent(); TransformComponent();
virtual const std::string &GetName() const override; virtual const std::string &GetName() const override;
static const std::string &GetStaticName(); static const std::string &GetStaticName();
@ -57,8 +41,6 @@ public:
// Serialization methods // Serialization methods
virtual YAML::Node Serialize() override; virtual YAML::Node Serialize() override;
virtual void Deserialize(const YAML::Node &node) override; virtual void Deserialize(const YAML::Node &node) override;
glm::mat4 GetTransformMatrix() const;
void SetTransformMatrix(const glm::mat4& transform);
private: private:
static const std::string name; static const std::string name;

View File

@ -1,155 +0,0 @@
// TransformComponent.cpp
#include "Transform.h"
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>
const std::string TransformComponent::name = "Transform";
TransformComponent::TransformComponent()
: position(0.0f), rotation(0.0f), scale(1.0f)
{
position = glm::vec3(0.0f, 0.0f, 0.0f);
rotation = glm::vec3(0.0f, 0.0f, 0.0f);
scale = glm::vec3(1.0f, 1.0f, 1.0f);
}
const std::string &TransformComponent::GetName() const
{
return name;
}
const std::string &TransformComponent::GetStaticName()
{
return name;
}
void TransformComponent::Update(float _deltaTime)
{
(void)_deltaTime; // Suppress unused parameter warning
return;
}
void TransformComponent::LookAt(const glm::vec3& target, const glm::vec3& up) {
// Calculate the direction vector from position to target
glm::vec3 direction = glm::normalize(target - position);
// Handle the case when direction is parallel to up vector
if (glm::length(direction) == 0.0f) {
// Cannot look at the same position; no rotation needed
return;
}
// Create a lookAt matrix
glm::mat4 lookAtMatrix = glm::lookAt(position, target, up);
// Extract the rotation part of the matrix
glm::mat4 rotationMatrix = glm::mat4(glm::mat3(lookAtMatrix));
// Convert the rotation matrix to a quaternion
glm::quat rotationQuat = glm::quat_cast(rotationMatrix);
// Extract Euler angles from the quaternion
glm::vec3 eulerRadians = glm::eulerAngles(rotationQuat);
// Convert radians to degrees and set the rotation
rotation = glm::degrees(eulerRadians);
}
// New Methods
glm::mat4 TransformComponent::GetTransformMatrix() const
{
glm::mat4 translation = glm::translate(glm::mat4(1.0f), position);
// Convert Euler angles (in degrees) to a quaternion and then to a rotation matrix
glm::quat quatRotation = glm::quat(glm::radians(rotation));
glm::mat4 rotationMatrix = glm::toMat4(quatRotation);
glm::mat4 scaling = glm::scale(glm::mat4(1.0f), scale);
// Note: The order is Scale -> Rotate -> Translate
return translation * rotationMatrix * scaling;
}
void TransformComponent::SetTransformMatrix(const glm::mat4 &transform)
{
// Extract translation
position = glm::vec3(transform[3]);
// Extract scale factors
scale.x = glm::length(glm::vec3(transform[0]));
scale.y = glm::length(glm::vec3(transform[1]));
scale.z = glm::length(glm::vec3(transform[2]));
// Remove scale from rotation matrix
glm::mat4 rotationMatrix = transform;
rotationMatrix[0] /= scale.x;
rotationMatrix[1] /= scale.y;
rotationMatrix[2] /= scale.z;
// Convert rotation matrix to quaternion and then to Euler angles (in degrees)
glm::quat quatRotation = glm::quat_cast(rotationMatrix);
glm::vec3 euler = glm::degrees(glm::eulerAngles(quatRotation));
rotation = euler;
}
YAML::Node TransformComponent::Serialize()
{
YAML::Node node;
// Position
{
YAML::Node posNode;
posNode.SetStyle(YAML::EmitterStyle::Flow);
posNode.push_back(position.x);
posNode.push_back(position.y);
posNode.push_back(position.z);
node["Position"] = posNode;
}
// Rotation
{
YAML::Node rotNode;
rotNode.SetStyle(YAML::EmitterStyle::Flow);
rotNode.push_back(rotation.x);
rotNode.push_back(rotation.y);
rotNode.push_back(rotation.z);
node["Rotation"] = rotNode;
}
// Scale
{
YAML::Node scaleNode;
scaleNode.SetStyle(YAML::EmitterStyle::Flow);
scaleNode.push_back(scale.x);
scaleNode.push_back(scale.y);
scaleNode.push_back(scale.z);
node["Scale"] = scaleNode;
}
return node;
}
void TransformComponent::Deserialize(const YAML::Node &node)
{
if (node["Position"])
{
auto pos = node["Position"].as<std::vector<float>>();
if (pos.size() == 3)
position = glm::vec3(pos[0], pos[1], pos[2]);
}
if (node["Rotation"])
{
auto rot = node["Rotation"].as<std::vector<float>>();
if (rot.size() == 3)
rotation = glm::vec3(rot[0], rot[1], rot[2]);
}
if (node["Scale"])
{
auto scl = node["Scale"].as<std::vector<float>>();
if (scl.size() == 3)
scale = glm::vec3(scl[0], scl[1], scl[2]);
}
}

View File

@ -36,11 +36,11 @@
#include "Engine/InputManager.h" #include "Engine/InputManager.h"
#include "Engine/ScopedTimer.h" #include "Engine/ScopedTimer.h"
#include "Engine/Profiler.h" #include "Engine/Profiler.h"
#include "Engine/Settings.h"
// #define YAML_CPP_STATIC_DEFINE // #define YAML_CPP_STATIC_DEFINE
#include <yaml-cpp/yaml.h> #include <yaml-cpp/yaml.h>
#include "TestModel.h"
AssetManager g_AssetManager; AssetManager g_AssetManager;
@ -50,16 +50,12 @@ SceneManager g_SceneManager;
InputManager g_InputManager; InputManager g_InputManager;
Settings g_SettingsManager;
std::vector<std::shared_ptr<GameObject>> g_GameObjects; std::vector<std::shared_ptr<GameObject>> g_GameObjects;
std::shared_ptr<CameraComponent> g_RuntimeCameraObject; std::shared_ptr<CameraComponent> g_RuntimeCameraObject;
int g_GPU_Triangles_drawn_to_screen = 0; int g_GPU_Triangles_drawn_to_screen = 0;
int g_GPU_Draw_Calls = 0;
bool DrawBBBO;
GameObject *g_SelectedObject; // Pointer to the currently selected object GameObject *g_SelectedObject; // Pointer to the currently selected object
@ -68,10 +64,6 @@ int m_GameRunning = 0;
bool MyEngine::Init(int width, int height, const std::string &title) bool MyEngine::Init(int width, int height, const std::string &title)
{ {
DEBUG_PRINT("[START] Engine Init"); DEBUG_PRINT("[START] Engine Init");
g_SettingsManager.S_LineColor = glm::vec4(1.0f, 0.27058823529f, 0.0f, 1.0f);
// ------------------------------------------ // ------------------------------------------
// 1) Initialize GLFW // 1) Initialize GLFW
// ------------------------------------------ // ------------------------------------------
@ -118,7 +110,6 @@ bool MyEngine::Init(int width, int height, const std::string &title)
#ifdef DEBUG #ifdef DEBUG
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_DockingEnable | ImGuiConfigFlags_ViewportsEnable; ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_DockingEnable | ImGuiConfigFlags_ViewportsEnable;
#endif #endif
// Path to your font files // Path to your font files
@ -178,24 +169,18 @@ bool MyEngine::Init(int width, int height, const std::string &title)
m_FirstTickGameRunning = true; m_FirstTickGameRunning = true;
m_showProfiler = true; m_showProfiler = true;
DrawBBBO = false;
g_LoggerWindow = m_LoggerWindow.get(); g_LoggerWindow = m_LoggerWindow.get();
// Optionally, call 'onInit' Lua function // Optionally, call 'onInit' Lua function
// Some initial logs // Some initial logs
m_LoggerWindow->AddLog("Engine initialized.");
m_LoggerWindow->AddLog("Welcome to Tesseract Engine!"); m_LoggerWindow->AddLog("Welcome to Tesseract Engine!");
m_Running = true; m_Running = true;
m_LastTime = glfwGetTime(); m_LastTime = glfwGetTime();
DEBUG_PRINT("[OK] Engine Init "); DEBUG_PRINT("[OK] Engine Init ");
#ifdef DEBUG
g_LoggerWindow->AddLog(LogLevel::Warning, "Warning: You are in Debug Mode. Switch to Releace for more performance");
#endif
return true; return true;
} }
@ -220,6 +205,8 @@ void MyEngine::Run()
glfwPollEvents(); glfwPollEvents();
} }
{ {
SCOPE_TIMER("InputManagerUpdate"); SCOPE_TIMER("InputManagerUpdate");
g_InputManager.Update(m_Window); g_InputManager.Update(m_Window);
@ -304,7 +291,7 @@ void MyEngine::Run()
{ {
ScopedTimer timer("RenderGame"); ScopedTimer timer("RenderGame");
m_RenderWindow->Show(&m_GameRunning, m_Ms); // The spinning triangle as ImGui::Image m_RenderWindow->Show(&m_GameRunning); // The spinning triangle as ImGui::Image
} }
{ {
ScopedTimer timer("ShowEditor"); ScopedTimer timer("ShowEditor");
@ -322,7 +309,7 @@ void MyEngine::Run()
} }
// After rendering // After rendering
m_PerformanceWindow->UpdatePerformanceStats(g_GPU_Draw_Calls, g_GPU_Triangles_drawn_to_screen); m_PerformanceWindow->UpdatePerformanceStats(-1, g_GPU_Triangles_drawn_to_screen);
// End frame // End frame
EndFrame(); EndFrame();
@ -444,24 +431,6 @@ void MyEngine::ShowDockSpace()
ImGui::Checkbox("Show Profiler", &m_showProfiler); // Add a checkbox to toggle the profiler ImGui::Checkbox("Show Profiler", &m_showProfiler); // Add a checkbox to toggle the profiler
ImGui::EndMenu(); ImGui::EndMenu();
} }
if (ImGui::BeginMenu("Settings"))
{
// A checkbox to enable/disable bounding boxes
ImGui::Checkbox("Show Submeshs", &DrawBBBO);
// On the same line, we place a small color edit widget
ImGui::SameLine();
ImGui::ColorEdit4("Box Color",
reinterpret_cast<float *>(&g_SettingsManager.S_LineColor),
ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel);
// Explanation of Flags:
// - ImGuiColorEditFlags_NoInputs hides numeric RGBA input fields
// - ImGuiColorEditFlags_NoLabel hides the default label, since we already have "Box Color"
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Engine")) if (ImGui::BeginMenu("Engine"))
{ {

View File

@ -12,9 +12,9 @@
#include "Windows/LuaEditorWindow.h" #include "Windows/LuaEditorWindow.h"
#include "Windows/ProfilerWindow.h" #include "Windows/ProfilerWindow.h"
#include "Components/GameObject.h" #include "Componenets/GameObject.h"
#include "Components/Mesh.h" #include "Componenets/Mesh.h"
#include "Components/Transform.h" #include "Componenets/Transform.h"
#include "Engine/AssetManager.h" #include "Engine/AssetManager.h"
#include "Engine/ThemeManager.h" #include "Engine/ThemeManager.h"
@ -22,6 +22,7 @@
#include "Engine/LuaAPI.h" #include "Engine/LuaAPI.h"
#include "Engine/Utilitys.h" #include "Engine/Utilitys.h"
#include "TestModel.h"
#include "gcml.h" #include "gcml.h"

View File

@ -520,7 +520,6 @@ Model *LoadModelFromList(const std::string &path)
// Initialize OpenGL buffers for the submesh // Initialize OpenGL buffers for the submesh
submesh.Initialize(); submesh.Initialize();
} }
if (materialToSubmesh.empty()) if (materialToSubmesh.empty())

View File

@ -82,31 +82,10 @@ struct Submesh
std::vector<unsigned int> indices; std::vector<unsigned int> indices;
std::vector<Texture> textures; std::vector<Texture> textures;
GLuint vao = 0, vbo = 0, ebo = 0; GLuint vao = 0, vbo = 0, ebo = 0;
unsigned int bboxVAO, bboxVBO;
GLsizei bboxVertexCount;
glm::vec3 minExtents;
glm::vec3 maxExtents;
// Initialize OpenGL buffers for the submesh // Initialize OpenGL buffers for the submesh
void Initialize() void Initialize()
{ {
glm::vec3 minExtents(FLT_MAX);
glm::vec3 maxExtents(-FLT_MAX);
for (auto &v : vertices)
{
minExtents.x = std::min(minExtents.x, v.position[0]);
minExtents.y = std::min(minExtents.y, v.position[1]);
minExtents.z = std::min(minExtents.z, v.position[2]);
maxExtents.x = std::max(maxExtents.x, v.position[0]);
maxExtents.y = std::max(maxExtents.y, v.position[1]);
maxExtents.z = std::max(maxExtents.z, v.position[2]);
}
// Store in the submesh
this->minExtents = minExtents;
this->maxExtents = maxExtents;
glGenVertexArrays(1, &vao); glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo); glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo); glGenBuffers(1, &ebo);
@ -130,58 +109,6 @@ struct Submesh
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)(5 * sizeof(float))); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)(5 * sizeof(float)));
glBindVertexArray(0); glBindVertexArray(0);
std::vector<glm::vec3> bboxLines = {
// bottom face
{minExtents.x, minExtents.y, minExtents.z},
{maxExtents.x, minExtents.y, minExtents.z},
{maxExtents.x, minExtents.y, minExtents.z},
{maxExtents.x, minExtents.y, maxExtents.z},
{maxExtents.x, minExtents.y, maxExtents.z},
{minExtents.x, minExtents.y, maxExtents.z},
{minExtents.x, minExtents.y, maxExtents.z},
{minExtents.x, minExtents.y, minExtents.z},
// top face
{minExtents.x, maxExtents.y, minExtents.z},
{maxExtents.x, maxExtents.y, minExtents.z},
{maxExtents.x, maxExtents.y, minExtents.z},
{maxExtents.x, maxExtents.y, maxExtents.z},
{maxExtents.x, maxExtents.y, maxExtents.z},
{minExtents.x, maxExtents.y, maxExtents.z},
{minExtents.x, maxExtents.y, maxExtents.z},
{minExtents.x, maxExtents.y, minExtents.z},
// vertical edges
{minExtents.x, minExtents.y, minExtents.z},
{minExtents.x, maxExtents.y, minExtents.z},
{maxExtents.x, minExtents.y, minExtents.z},
{maxExtents.x, maxExtents.y, minExtents.z},
{maxExtents.x, minExtents.y, maxExtents.z},
{maxExtents.x, maxExtents.y, maxExtents.z},
{minExtents.x, minExtents.y, maxExtents.z},
{minExtents.x, maxExtents.y, maxExtents.z}};
glGenVertexArrays(1, &bboxVAO);
glGenBuffers(1, &bboxVBO);
glBindVertexArray(bboxVAO);
glBindBuffer(GL_ARRAY_BUFFER, bboxVBO);
glBufferData(
GL_ARRAY_BUFFER,
bboxLines.size() * sizeof(glm::vec3),
bboxLines.data(),
GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(
0, 3, GL_FLOAT, GL_FALSE,
sizeof(glm::vec3), (void *)0);
glBindVertexArray(0);
bboxVAO = bboxVAO;
bboxVBO = bboxVBO;
bboxVertexCount = (GLsizei)bboxLines.size();
} }
// Render the submesh // Render the submesh
@ -273,9 +200,9 @@ public:
// Debug: Log the variant type // Debug: Log the variant type
if (std::holds_alternative<std::shared_ptr<T>>(it->second)) if (std::holds_alternative<std::shared_ptr<T>>(it->second))
{ {
#ifdef DEBUG #ifdef DEBUG
DebugAssetMap(); DebugAssetMap();
#endif #endif
std::cout << "[AssetManager] Retrieved asset from cache: " << key << std::endl; std::cout << "[AssetManager] Retrieved asset from cache: " << key << std::endl;
return std::get<std::shared_ptr<T>>(it->second); return std::get<std::shared_ptr<T>>(it->second);
} }

View File

@ -1,92 +1,29 @@
// InputManager.cpp // InputManager.cpp
#include "InputManager.h" #include "InputManager.h"
#include <algorithm> // For std::clamp #include <GLFW/glfw3.h>
// Constructor
InputManager::InputManager()
: m_MouseDeltaX(0.0f), m_MouseDeltaY(0.0f), m_ScrollDelta(0.0f) void InputManager::Update(GLFWwindow* window)
{ {
Initialize(); if (!window)
} {
// Initialize method to set up state vectors
void InputManager::Initialize() {
// Initialize key states
m_KeyStates.resize(GLFW_KEY_LAST + 1, false);
m_PreviousKeyStates.resize(GLFW_KEY_LAST + 1, false);
// Initialize mouse button states
m_MouseButtonStates.resize(GLFW_MOUSE_BUTTON_LAST + 1, false);
m_PreviousMouseButtonStates.resize(GLFW_MOUSE_BUTTON_LAST + 1, false);
}
// Update method to poll input states
void InputManager::Update(GLFWwindow* window) {
if (!window) {
return; return;
} }
// Update previous key states // Update the state of each key
m_PreviousKeyStates = m_KeyStates; for (int key = 0; key <= GLFW_KEY_LAST; ++key)
{
// Update current key states
for (int key = 0; key <= GLFW_KEY_LAST; ++key) {
m_KeyStates[key] = glfwGetKey(window, key) == GLFW_PRESS; m_KeyStates[key] = glfwGetKey(window, key) == GLFW_PRESS;
} }
// Update previous mouse button states
m_PreviousMouseButtonStates = m_MouseButtonStates;
// Update current mouse button states
for (int button = 0; button <= GLFW_MOUSE_BUTTON_LAST; ++button) {
m_MouseButtonStates[button] = glfwGetMouseButton(window, button) == GLFW_PRESS;
}
// Reset mouse deltas and scroll delta for this frame
m_MouseDeltaX = 0.0f;
m_MouseDeltaY = 0.0f;
m_ScrollDelta = 0.0f;
} }
// Keyboard input query bool InputManager::IsKeyPressed(KeyCode key) const
bool InputManager::IsKeyPressed(KeyCode key) const { {
int keyInt = static_cast<int>(key); int keyInt = static_cast<int>(key);
if (keyInt >= 0 && keyInt <= GLFW_KEY_LAST) { if (keyInt >= 0 && keyInt <= GLFW_KEY_LAST)
{
return m_KeyStates[keyInt]; return m_KeyStates[keyInt];
} }
return false; return false;
} }
// Mouse button input query
bool InputManager::IsMouseButtonPressed(MouseButton button) const {
int buttonInt = static_cast<int>(button);
if (buttonInt >= 0 && buttonInt <= GLFW_MOUSE_BUTTON_LAST) {
return m_MouseButtonStates[buttonInt];
}
return false;
}
// Mouse button just pressed (edge detection)
bool InputManager::IsMouseButtonJustPressed(MouseButton button) const {
int buttonInt = static_cast<int>(button);
if (buttonInt >= 0 && buttonInt <= GLFW_MOUSE_BUTTON_LAST) {
return m_MouseButtonStates[buttonInt] && !m_PreviousMouseButtonStates[buttonInt];
}
return false;
}
// Mouse button just released (edge detection)
bool InputManager::IsMouseButtonJustReleased(MouseButton button) const {
int buttonInt = static_cast<int>(button);
if (buttonInt >= 0 && buttonInt <= GLFW_MOUSE_BUTTON_LAST) {
return !m_MouseButtonStates[buttonInt] && m_PreviousMouseButtonStates[buttonInt];
}
return false;
}
// Reset deltas after handling input
void InputManager::ResetDeltas() {
m_MouseDeltaX = 0.0f;
m_MouseDeltaY = 0.0f;
m_ScrollDelta = 0.0f;
}

View File

@ -3,50 +3,18 @@
#include "KeyCode.h" #include "KeyCode.h"
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <vector>
class InputManager {
class InputManager
{
public: public:
// Constructor // Update key states (to be called every frame)
InputManager();
// Update method to poll input states
void Update(GLFWwindow* window); void Update(GLFWwindow* window);
// Keyboard input query // Check if a key is pressed
bool IsKeyPressed(KeyCode key) const; bool IsKeyPressed(KeyCode key) const;
// Mouse button input queries
bool IsMouseButtonPressed(MouseButton button) const;
bool IsMouseButtonJustPressed(MouseButton button) const;
bool IsMouseButtonJustReleased(MouseButton button) const;
// Mouse movement deltas
float GetMouseDeltaX() const { return m_MouseDeltaX; }
float GetMouseDeltaY() const { return m_MouseDeltaY; }
// Scroll delta
float GetScrollDelta() const { return m_ScrollDelta; }
// Call this after handling input to reset deltas
void ResetDeltas();
private: private:
// Storage for key states // Array or map storing key states
std::vector<bool> m_KeyStates; bool m_KeyStates[GLFW_KEY_LAST + 1] = { false };
std::vector<bool> m_PreviousKeyStates;
// Storage for mouse button states
std::vector<bool> m_MouseButtonStates;
std::vector<bool> m_PreviousMouseButtonStates;
// Mouse movement deltas
float m_MouseDeltaX;
float m_MouseDeltaY;
// Scroll delta
float m_ScrollDelta;
// Initialization helper
void Initialize();
}; };

View File

@ -126,16 +126,3 @@ enum class KeyCode
RightSuper = GLFW_KEY_RIGHT_SUPER, RightSuper = GLFW_KEY_RIGHT_SUPER,
Menu = GLFW_KEY_MENU Menu = GLFW_KEY_MENU
}; };
// Enum for mouse buttons
enum class MouseButton {
LEFT = GLFW_MOUSE_BUTTON_LEFT,
RIGHT = GLFW_MOUSE_BUTTON_RIGHT,
MIDDLE = GLFW_MOUSE_BUTTON_MIDDLE,
BUTTON4 = GLFW_MOUSE_BUTTON_4,
BUTTON5 = GLFW_MOUSE_BUTTON_5,
BUTTON6 = GLFW_MOUSE_BUTTON_6,
BUTTON7 = GLFW_MOUSE_BUTTON_7,
BUTTON8 = GLFW_MOUSE_BUTTON_8,
LAST = GLFW_MOUSE_BUTTON_LAST
};

View File

@ -3,11 +3,11 @@
#include "LuaAPI.h" #include "LuaAPI.h"
#include "LuaMacros.h" // Include the macros for binding #include "LuaMacros.h" // Include the macros for binding
#include "gcml.h" // Include gcml.h for DEBUG_PRINT macros #include "gcml.h" // Include gcml.h for DEBUG_PRINT macros
#include "Components/Component.h" #include "Componenets/Component.h"
#include "Components/Transform.h" #include "Componenets/Transform.h"
#include "Components/Mesh.h" #include "Componenets/Mesh.h"
#include "Components/ScriptComponent.h" #include "Componenets/ScriptComponent.h"
#include "Components/GameObject.h" #include "Componenets/GameObject.h"
#include "Windows/LoggerWindow.h" #include "Windows/LoggerWindow.h"
#include "Engine/InputManager.h" #include "Engine/InputManager.h"

View File

@ -12,7 +12,7 @@ struct ProfileResult {
class Profiler { class Profiler {
public: public:
static Profiler& Get() { // Singleton ... LLLLLL static Profiler& Get() {
static Profiler instance; static Profiler instance;
return instance; return instance;
} }

View File

@ -1,9 +1,9 @@
#include "SceneManager.h" #include "SceneManager.h"
#include "./Components/Component.h" #include "./Componenets/Component.h"
#include "./Components/Transform.h" #include "./Componenets/Transform.h"
#include "./Components/Mesh.h" #include "./Componenets/Mesh.h"
#include "./Components/GameObject.h" #include "./Componenets/GameObject.h"
#include "imgui.h" #include "imgui.h"

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include "Components/GameObject.h" #include "Componenets/GameObject.h"
class SceneManager class SceneManager

View File

@ -1,6 +0,0 @@
#include "imgui.h"
#include <glm/gtc/matrix_transform.hpp>
struct Settings {
glm::vec4 S_LineColor;
};

View File

@ -152,12 +152,6 @@ void Shader::SetVec3(const std::string &name, const glm::vec3 &value) const
glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
} }
void Shader::SetVec4(const std::string &name, const glm::vec4 &value) const
{
glUseProgram(ID); // Ensure the shader program is active
glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
}
void Shader::SetSampler2D(const std::string &name, int textureUnit) const void Shader::SetSampler2D(const std::string &name, int textureUnit) const
{ {
glUseProgram(ID); // Ensure the shader program is active glUseProgram(ID); // Ensure the shader program is active

View File

@ -26,8 +26,6 @@ public:
void SetMat4(const std::string &name, const glm::mat4 &mat) const; // For setting 4x4 matrices void SetMat4(const std::string &name, const glm::mat4 &mat) const; // For setting 4x4 matrices
void SetSampler2D(const std::string &name, int textureUnit) const; void SetSampler2D(const std::string &name, int textureUnit) const;
void SetVec3(const std::string &name, const glm::vec3 &value) const; void SetVec3(const std::string &name, const glm::vec3 &value) const;
void SetVec4(const std::string &name, const glm::vec4 &value) const;
private: private:
// Caching uniform locations for performance // Caching uniform locations for performance

103
src/TestModel.cpp Normal file
View File

@ -0,0 +1,103 @@
#include "TestModel.h"
#include <GL/glew.h>
#include <cstdio>
GLuint CreateCubeVAO()
{
// Define cube vertices (Position + UVs)
static float g_CubeVertices[] =
{
// Front face
-1.f, -1.f, 1.f, 0.f, 0.f,
1.f, -1.f, 1.f, 1.f, 0.f,
1.f, 1.f, 1.f, 1.f, 1.f,
-1.f, 1.f, 1.f, 0.f, 1.f,
// Back face
-1.f, -1.f, -1.f, 1.f, 0.f,
1.f, -1.f, -1.f, 0.f, 0.f,
1.f, 1.f, -1.f, 0.f, 1.f,
-1.f, 1.f, -1.f, 1.f, 1.f,
// Left face
-1.f, -1.f, -1.f, 0.f, 0.f,
-1.f, -1.f, 1.f, 1.f, 0.f,
-1.f, 1.f, 1.f, 1.f, 1.f,
-1.f, 1.f, -1.f, 0.f, 1.f,
// Right face
1.f, -1.f, -1.f, 1.f, 0.f,
1.f, -1.f, 1.f, 0.f, 0.f,
1.f, 1.f, 1.f, 0.f, 1.f,
1.f, 1.f, -1.f, 1.f, 1.f,
// Top face
-1.f, 1.f, -1.f, 0.f, 0.f,
1.f, 1.f, -1.f, 1.f, 0.f,
1.f, 1.f, 1.f, 1.f, 1.f,
-1.f, 1.f, 1.f, 0.f, 1.f,
// Bottom face
-1.f, -1.f, -1.f, 1.f, 0.f,
1.f, -1.f, -1.f, 0.f, 0.f,
1.f, -1.f, 1.f, 0.f, 1.f,
-1.f, -1.f, 1.f, 1.f, 1.f,
};
// Define cube indices
static unsigned int g_CubeIndices[] =
{
// Front face
0, 1, 2, 2, 3, 0,
// Back face
4, 5, 6, 6, 7, 4,
// Left face
8, 9, 10, 10, 11, 8,
// Right face
12, 13, 14, 14, 15, 12,
// Top face
16, 17, 18, 18, 19, 16,
// Bottom face
20, 21, 22, 22, 23, 20
};
GLuint VAO, VBO, EBO;
// Generate and bind VAO
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
// Generate and bind VBO
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_CubeVertices), g_CubeVertices, GL_STATIC_DRAW);
// Generate and bind EBO
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(g_CubeIndices), g_CubeIndices, GL_STATIC_DRAW);
// Define vertex attributes
// Position attribute (location = 0)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// UV attribute (location = 1)
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE,
5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// Unbind VAO (not EBO!)
glBindVertexArray(0);
// Optionally, unbind VBO and EBO for cleanliness
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// Debug: Print VAO ID
printf("[MeshUtils] Initialized CubeVAO with ID: %u\n", VAO);
return VAO;
}

6
src/TestModel.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once //
#include <GL/glew.h>
#include <cstdio>
GLuint CreateCubeVAO();

View File

@ -5,11 +5,11 @@
#include "imgui.h" #include "imgui.h"
#include "gcml.h" #include "gcml.h"
#include "Components/GameObject.h" #include "Componenets/GameObject.h"
#include "Components/Mesh.h" #include "Componenets/Mesh.h"
#include "Components/Transform.h" #include "Componenets/Transform.h"
#include "Components/ScriptComponent.h" #include "Componenets/ScriptComponent.h"
#include "Components/CameraComponent.h" #include "Componenets/CameraComponent.h"

View File

@ -6,9 +6,8 @@
#include <cstdio> #include <cstdio>
#include "Icons.h" #include "Icons.h"
#include "Engine/ScopedTimer.h" #include "Engine/ScopedTimer.h"
#include "Icons.h"
// Helper function to format strings
static std::string FormatString(const char *fmt, va_list args) static std::string FormatString(const char *fmt, va_list args)
{ {
char buffer[1024]; char buffer[1024];
@ -16,48 +15,6 @@ static std::string FormatString(const char *fmt, va_list args)
return std::string(buffer); return std::string(buffer);
} }
// Choose a default icon for each LogLevel
static const char* GetIconForLevel(LogLevel level)
{
switch (level)
{
case LogLevel::Warning: return ICON_FA_TRIANGLE_EXCLAMATION;
case LogLevel::Error: return ICON_FA_CIRCLE_EXCLAMATION;
case LogLevel::Info:
default: return ICON_FA_INFO;
}
}
// Choose a default color for each LogLevel if none is specified.
static ImVec4 GetDefaultColorForLevel(LogLevel level)
{
switch (level)
{
case LogLevel::Warning: return ImVec4(1.0f, 0.8f, 0.0f, 1.0f); // Yellow-ish
case LogLevel::Error: return ImVec4(1.0f, 0.2f, 0.2f, 1.0f); // Reddish
case LogLevel::Info:
default: return ImVec4(0.8f, 0.8f, 0.8f, 1.0f); // Light gray
}
}
void LoggerWindow::AddLog(const char *fmt, std::optional<ImVec4> color, ...)
{
va_list args;
va_start(args, fmt);
std::string formatted = FormatString(fmt, args);
va_end(args);
LogEntry entry;
entry.text = formatted;
entry.level = LogLevel::Info;
entry.color = color;
entry.icon = GetIconForLevel(entry.level);
m_Logs.emplace_back(entry);
m_ScrollToBottom = true;
}
// 1) Existing method (no LogLevel) — default to Info
void LoggerWindow::AddLog(const char *fmt, ...) void LoggerWindow::AddLog(const char *fmt, ...)
{ {
va_list args; va_list args;
@ -65,62 +22,27 @@ void LoggerWindow::AddLog(const char *fmt, ...)
std::string formatted = FormatString(fmt, args); std::string formatted = FormatString(fmt, args);
va_end(args); va_end(args);
LogEntry entry; m_Logs.emplace_back(formatted);
entry.text = formatted;
entry.level = LogLevel::Info;
entry.color = std::nullopt; // We'll use the default color
entry.icon = GetIconForLevel(entry.level);
m_Logs.emplace_back(entry);
m_ScrollToBottom = true; m_ScrollToBottom = true;
} }
// 2) New method for specifying LogLevel void LoggerWindow::AddLog(const char *fmt, std::optional<ImVec4> color, ...)
void LoggerWindow::AddLog(LogLevel level, const char *fmt, ...)
{ {
va_list args; va_list args;
va_start(args, fmt); va_start(args, color);
std::string formatted = FormatString(fmt, args); std::string formatted = FormatString(fmt, args);
va_end(args); va_end(args);
LogEntry entry; m_Logs.emplace_back(formatted, color);
entry.text = formatted;
entry.level = level;
entry.color = std::nullopt; // Use default color for this level
entry.icon = GetIconForLevel(level);
m_Logs.emplace_back(entry);
m_ScrollToBottom = true; m_ScrollToBottom = true;
} }
// 3) New method for specifying LogLevel + an explicit color override
void LoggerWindow::AddLog(LogLevel level, const ImVec4 &color, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
std::string formatted = FormatString(fmt, args);
va_end(args);
LogEntry entry;
entry.text = formatted;
entry.level = level;
entry.color = color; // Explicit color override
entry.icon = GetIconForLevel(level);
m_Logs.emplace_back(entry);
m_ScrollToBottom = true;
}
void LoggerWindow::Show() void LoggerWindow::Show()
{ {
SCOPE_TIMER("LoggerWindow::Show"); SCOPE_TIMER("LoggerWindow::Show");
// Window with an icon in the title
ImGui::Begin(ICON_FA_TERMINAL " Logger##logger"); ImGui::Begin(ICON_FA_TERMINAL " Logger##logger");
// Clear button
if (ImGui::Button("Clear")) if (ImGui::Button("Clear"))
{ {
m_Logs.clear(); m_Logs.clear();
@ -128,44 +50,24 @@ void LoggerWindow::Show()
ImGui::Separator(); ImGui::Separator();
// Child region for scrollable area // Begin a child region to enable scrolling
ImGui::BeginChild("LoggerScrollRegion", ImVec2(0, 0), false, ImGui::BeginChild("LoggerScrollRegion", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
ImGuiWindowFlags_HorizontalScrollbar);
if (ImGui::BeginTable("LogTable", 2, for (const auto &logEntry : m_Logs)
ImGuiTableFlags_SizingFixedFit |
ImGuiTableFlags_Borders |
ImGuiTableFlags_RowBg |
ImGuiTableFlags_Resizable))
{ {
// Optionally set up columns (width, name, etc.) if (logEntry.color.has_value())
ImGui::TableSetupColumn("Icon", ImGuiTableColumnFlags_WidthFixed, 30.0f); {
ImGui::TableSetupColumn("Message", ImGuiTableColumnFlags_WidthStretch); ImGui::PushStyleColor(ImGuiCol_Text, logEntry.color.value());
ImGui::TextUnformatted(logEntry.text.c_str());
// Loop over log entries ImGui::PopStyleColor();
for (const auto &logEntry : m_Logs) }
else
{ {
ImVec4 color = logEntry.color.value_or(GetDefaultColorForLevel(logEntry.level));
// Start a new row
ImGui::TableNextRow();
// Column 0: Icon
ImGui::TableNextColumn();
ImGui::TextColored(color, "%s", logEntry.icon.c_str());
// Column 1: Text
ImGui::TableNextColumn();
ImGui::TextUnformatted(logEntry.text.c_str()); ImGui::TextUnformatted(logEntry.text.c_str());
} }
ImGui::EndTable();
} }
// If you used PushStyleVar above, pop it here: // Auto-scroll to bottom if new logs are added
// ImGui::PopStyleVar();
// Auto-scroll to bottom if needed
if (m_ScrollToBottom) if (m_ScrollToBottom)
{ {
ImGui::SetScrollHereY(1.0f); ImGui::SetScrollHereY(1.0f);
@ -173,6 +75,6 @@ void LoggerWindow::Show()
} }
ImGui::EndChild(); ImGui::EndChild();
ImGui::End(); ImGui::End();
} }

View File

@ -6,31 +6,19 @@
#include <string> #include <string>
#include <optional> #include <optional>
#include <imgui.h> #include <imgui.h>
#include "Icons.h"
// Example: Different severity levels struct LogEntry {
enum class LogLevel std::string text;
{ std::optional<ImVec4> color;
Info,
Warning,
Error
};
struct LogEntry LogEntry(const std::string& msg, std::optional<ImVec4> col = std::nullopt)
{ : text(msg), color(col) {}
std::string text ;
LogLevel level;
std::optional<ImVec4> color;
std::string icon ;
}; };
class LoggerWindow { class LoggerWindow {
public: public:
void AddLog(const char* fmt, ...); void AddLog(const char* fmt, ...);
void AddLog(const char* fmt, std::optional<ImVec4> color, ...); void AddLog(const char* fmt, std::optional<ImVec4> color, ...);
void AddLog(LogLevel level, const char *fmt, ...);
void AddLog(LogLevel level, const ImVec4 &color, const char *fmt, ...);
void Show(); void Show();
private: private:

View File

@ -1,54 +1,52 @@
#include "PerformanceWindow.h" #include "PerformanceWindow.h"
#include "imgui.h" #include "imgui.h"
#include <algorithm> // for std::max #include <algorithm> // for std::max_element, etc.
#include <float.h> // for FLT_MAX
#include "Engine/ThemeManager.h" #include "Engine/ThemeManager.h"
#include "Engine/ScopedTimer.h" #include "Engine/ScopedTimer.h"
extern int LoadedAssets; extern int LoadedAssets;
extern int g_GPU_Triangles_drawn_to_screen; extern int g_GPU_Triangles_drawn_to_screen;
extern int g_GPU_Draw_Calls;
const char *polygonModeOptions[] = {"Fill", "Wireframe", "Points"}; const char *polygonModeOptions[] = {"Fill", "Wireframe", "Points"};
static int polygonMode = 0; const int numPolygonModes = sizeof(polygonModeOptions) / sizeof(polygonModeOptions[0]);
int polygonMode = 0;
// Initialize static members // Initialize static members
int PerformanceWindow::m_OpenGLCallCount = 0; int PerformanceWindow::m_OpenGLCallCount = 0;
int PerformanceWindow::m_TriangleCount = 0; int PerformanceWindow::m_TriangleCount = 0;
// We'll store up to 60 data points for each stat. // We'll store up to 60 data points for each stat.
static float s_FpsHistory[60] = {0.0f}; static float s_FpsHistory[60] = {0.0f};
static float s_MsHistory[60] = {0.0f}; static float s_MsHistory[60] = {0.0f};
static float s_CallsHistory[60] = {0.0f}; static float s_CallsHistory[60] = {0.0f};
static float s_TriangleHistory[60] = {0.0f}; static float s_TriangleHistory[60] = {0.0f};
// Current dynamic max scale for FPS and ms // Current dynamic max scale for FPS and ms
static float s_FpsScale = 120.0f; // default starting scale for FPS static float s_FpsScale = 120.0f; // default starting scale for FPS
static float s_MsScale = 25.0f; // default starting scale for ms static float s_MsScale = 25.0f; // default starting scale for ms
// Push new value into history, shifting old values left // This function shifts the old values left and appends a new value at the end.
static void PushValueToHistory(float* historyArray, int historySize, float newValue) static void PushValueToHistory(float *historyArray, int historySize, float newValue)
{ {
for (int i = 0; i < historySize - 1; i++) for (int i = 0; i < historySize - 1; i++)
{
historyArray[i] = historyArray[i + 1]; historyArray[i] = historyArray[i + 1];
}
historyArray[historySize - 1] = newValue; historyArray[historySize - 1] = newValue;
} }
// We'll track when we last pushed data to our history. // We'll track when we last pushed data to our history.
static double s_LastPushTime = 0.0; static double s_LastPushTime = 0.0;
// We'll also track when we last updated the scale // We'll also track when we last updated the scale
static double s_LastScaleUpdate = 0.0; static double s_LastScaleUpdate = 0.0;
// Update counters from the outside
void PerformanceWindow::UpdatePerformanceStats(int newCallCount, int newTriangleCount) void PerformanceWindow::UpdatePerformanceStats(int newCallCount, int newTriangleCount)
{ {
m_OpenGLCallCount = newCallCount; m_OpenGLCallCount = newCallCount;
m_TriangleCount = newTriangleCount; m_TriangleCount = newTriangleCount;
// Reset GPU counters each frame, or each time you show
g_GPU_Triangles_drawn_to_screen = 0; g_GPU_Triangles_drawn_to_screen = 0;
g_GPU_Draw_Calls = 0;
} }
void PerformanceWindow::Show(float fps, float ms) void PerformanceWindow::Show(float fps, float ms)
@ -58,7 +56,7 @@ void PerformanceWindow::Show(float fps, float ms)
// 1) Get current time from ImGui's internal clock // 1) Get current time from ImGui's internal clock
double currentTime = ImGui::GetTime(); double currentTime = ImGui::GetTime();
// 2) If at least 0.05s has passed, push new data (~20 times a second) // 2) If at least 0.05s has passed, push new data (about 20 updates per second)
if ((currentTime - s_LastPushTime) >= 0.05) if ((currentTime - s_LastPushTime) >= 0.05)
{ {
s_LastPushTime = currentTime; s_LastPushTime = currentTime;
@ -70,239 +68,141 @@ void PerformanceWindow::Show(float fps, float ms)
PushValueToHistory(s_TriangleHistory, 60, (float)m_TriangleCount); PushValueToHistory(s_TriangleHistory, 60, (float)m_TriangleCount);
} }
// We'll calculate a fallback max for calls // 3) Every 1 second, recalculate the max scale for FPS and ms
static float callsMax = 300.0f;
// 3) Every 1 second, recalculate the max scale for FPS, ms, and calls
if ((currentTime - s_LastScaleUpdate) >= 1.0) if ((currentTime - s_LastScaleUpdate) >= 1.0)
{ {
s_LastScaleUpdate = currentTime; s_LastScaleUpdate = currentTime;
// Recompute s_FpsScale // Find the maximum in s_FpsHistory
float maxFps = 0.0f; float maxFps = 0.0f;
for (int i = 0; i < 60; i++) for (int i = 0; i < 60; i++)
maxFps = std::max(maxFps, s_FpsHistory[i]); {
maxFps = std::max(1.0f, maxFps * 1.15f); // add ~15% headroom if (s_FpsHistory[i] > maxFps)
maxFps = s_FpsHistory[i];
}
// Scale it by +15%, ensure it's not below 1.0
maxFps *= 1.15f;
if (maxFps < 1.0f)
maxFps = 1.0f;
s_FpsScale = maxFps; s_FpsScale = maxFps;
// Recompute s_MsScale // Find the maximum in s_MsHistory
float maxMs = 0.0f; float maxMs = 0.0f;
for (int i = 0; i < 60; i++) for (int i = 0; i < 60; i++)
maxMs = std::max(maxMs, s_MsHistory[i]); {
maxMs = std::max(1.0f, maxMs * 1.15f); if (s_MsHistory[i] > maxMs)
maxMs = s_MsHistory[i];
}
// Scale it by +15%, ensure it's not below 1.0
maxMs *= 1.15f;
if (maxMs < 1.0f)
maxMs = 1.0f;
s_MsScale = maxMs; s_MsScale = maxMs;
// Recompute callsMax
float localMax = 0.0f;
for (int i = 0; i < 60; i++)
localMax = std::max(localMax, s_CallsHistory[i]);
if (localMax > 0.0f)
callsMax = localMax * 1.2f; // 20% headroom
else
callsMax = 300.0f; // default
} }
// Optional style adjustments // Optional style adjustments
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10, 10)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10, 10));
// Optionally make the window auto-resize or set constraints:
// ImGui::SetNextWindowSizeConstraints(ImVec2(350, 300), ImVec2(FLT_MAX, FLT_MAX));
// ImGui::Begin("Performance##performance", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
ImGui::Begin("Performance##performance"); ImGui::Begin("Performance##performance");
// A color-coded main header // Colored header
#ifdef DEBUG
ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.2f, 1.0f), "Performance Stats (DEBUG)");
#else
ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.2f, 1.0f), "Performance Stats"); ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.2f, 1.0f), "Performance Stats");
#endif
ImGui::Separator(); ImGui::Separator();
ImGui::Spacing();
// Show current FPS / ms in color // Show current FPS/ms
{ ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f), "FPS: %.1f", fps);
// Line 1: FPS (green) + MS (teal) ImGui::SameLine();
ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f), "FPS: %.1f", fps); ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.8f, 1.0f), "| ms: %.3f", ms);
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.8f, 1.0f), "| ms: %.3f", ms);
}
// Collapsible header for the performance graphs // Graphs for FPS + MS
if (ImGui::CollapsingHeader("Performance Graphs", ImGuiTreeNodeFlags_DefaultOpen)) // min = 0, max = s_FpsScale or s_MsScale
{ ImGui::PlotLines("FPS",
ImGui::Spacing(); s_FpsHistory,
IM_ARRAYSIZE(s_FpsHistory),
0,
nullptr,
0.0f,
s_FpsScale,
ImVec2(0, 60));
// --------- FPS & MS side by side ---------- ImGui::PlotHistogram("ms/frame",
ImGui::BeginGroup(); // left group s_MsHistory,
{ IM_ARRAYSIZE(s_MsHistory),
ImGui::Text("FPS"); 0,
ImGui::PushStyleColor(ImGuiCol_PlotLines, IM_COL32(0, 255, 0, 255)); // green nullptr,
ImGui::PushStyleColor(ImGuiCol_PlotLinesHovered, IM_COL32(255, 0, 0, 255)); // red on hover
ImGui::PlotLines("##FPS", // hidden label
s_FpsHistory, IM_ARRAYSIZE(s_FpsHistory),
0, // offset
nullptr, // overlay
0.0f,
s_FpsScale,
ImVec2(150, 60));
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("Frames per second over time");
ImGui::EndTooltip();
}
ImGui::PopStyleColor(2);
}
ImGui::EndGroup();
ImGui::SameLine();
ImGui::BeginGroup(); // right group
{
ImGui::Text("ms/frame");
ImGui::PlotHistogram("##ms/frame",
s_MsHistory,
IM_ARRAYSIZE(s_MsHistory),
0,
nullptr,
0.0f,
s_MsScale,
ImVec2(150, 60));
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("Frame time in milliseconds");
ImGui::EndTooltip();
}
}
ImGui::EndGroup();
ImGui::Spacing();
ImGui::Separator();
ImGui::Spacing();
// --------- OpenGL Calls & Indices -----------
// 1) GL Calls
ImGui::Text("OpenGL Calls: %d", m_OpenGLCallCount);
ImGui::PlotLines("##GL Calls",
s_CallsHistory,
IM_ARRAYSIZE(s_CallsHistory),
0, // offset
nullptr, // overlay text
0.0f, 0.0f,
callsMax, s_MsScale,
ImVec2(-1, 50)); // auto-fill width, fixed height=50 ImVec2(0, 60));
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("Number of GL draw calls per frame");
ImGui::EndTooltip();
}
ImGui::Spacing();
// 2) Indices
ImGui::Text("Indices: %d", m_TriangleCount);
// For Indices, we use a histogram. We could also do dynamic range like callsMax.
float indexHistMax = std::max(1.0f, (float)m_TriangleCount * 2.5f);
ImGui::PlotHistogram("##Indices",
s_TriangleHistory,
IM_ARRAYSIZE(s_TriangleHistory),
0,
nullptr,
0.0f,
indexHistMax,
ImVec2(-1, 50)); // auto-size width, height=50
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("Number of indices being rendered per frame");
ImGui::EndTooltip();
}
}
ImGui::Spacing();
ImGui::Separator(); ImGui::Separator();
ImGui::Spacing();
// -------------- Asset Count -------------- // Show OpenGL calls + Triangles
{ ImGui::Text("OpenGL Calls: %d", m_OpenGLCallCount);
ImGui::Text("Loaded Assets: "); ImGui::PlotLines("GL Calls",
ImGui::SameLine(); s_CallsHistory,
ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f), "%d", LoadedAssets); IM_ARRAYSIZE(s_CallsHistory),
} 0,
nullptr,
0.0f,
300.0f,
ImVec2(0, 50));
ImGui::Text("Indices: %d", m_TriangleCount);
ImGui::PlotHistogram("Indices",
s_TriangleHistory,
IM_ARRAYSIZE(s_TriangleHistory),
0,
nullptr,
0.0f,
m_TriangleCount * 2.5,
ImVec2(0, 50));
ImGui::Spacing();
ImGui::Separator(); ImGui::Separator();
ImGui::Spacing();
// -------------- Theme Combo Box -------------- // Show asset count
ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f), "Assets: %d", LoadedAssets);
ImGui::Separator();
const char *options[] = {"Bootsrap", "Duck Red", "Windark", "Deep Dark", "Tesseract Black"};
static int current_option = -1; // No selection initially
const char *preview_value = (current_option >= 0 && current_option < 3) ? options[current_option] : "Select an option";
if (ImGui::BeginCombo("Theme", preview_value))
{ {
const char* options[] = {"Bootstrap", "Duck Red", "Windark", "Deep Dark", "Tesseract Black"}; for (int n = 0; n < IM_ARRAYSIZE(options); n++)
static int current_option = -1;
const char* preview_value = (current_option >= 0 && current_option < IM_ARRAYSIZE(options))
? options[current_option]
: "Select an option";
ImGui::Text("Theme: ");
ImGui::SameLine();
if (ImGui::BeginCombo("##ThemeCombo", preview_value))
{ {
for (int n = 0; n < IM_ARRAYSIZE(options); n++) bool is_selected = (current_option == n);
if (ImGui::Selectable(options[n], is_selected))
{ {
bool is_selected = (current_option == n); current_option = n; // Update current option
if (ImGui::Selectable(options[n], is_selected)) ThemeManager_ChangeTheme(n); // Call the function with the selected option
{
current_option = n;
// Switch theme
ThemeManager_ChangeTheme(n);
}
if (is_selected)
ImGui::SetItemDefaultFocus();
} }
ImGui::EndCombo(); // Set the initial focus when opening the combo (optional)
if (is_selected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
if (ImGui::Combo("Polygon Mode", &polygonMode, polygonModeOptions, numPolygonModes))
{
switch (polygonMode)
{
case 0:
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
break;
case 1:
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
break;
case 2:
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
break;
default:
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
break;
} }
} }
ImGui::Spacing(); ImGui::End();
// -------------- Polygon Mode Combo Box --------------
{
ImGui::Text("Polygon Mode: ");
ImGui::SameLine();
if (ImGui::Combo("##PolygonMode", &polygonMode, polygonModeOptions, IM_ARRAYSIZE(polygonModeOptions)))
{
switch (polygonMode)
{
case 0: // Fill
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
break;
case 1: // Wireframe
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
break;
case 2: // Points
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
break;
default:
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
break;
}
}
}
ImGui::End(); // End of "Performance##performance"
// Pop the style var
ImGui::PopStyleVar(); ImGui::PopStyleVar();
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,54 +1,67 @@
// RenderWindow.h
#pragma once #pragma once
#include "../Rendering/FBO.h" #include "Rendering/Shader.h"
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <memory> #include <vector>
#include "Rendering/Shader.h" // #include "imgui.h"
#include "Components/CameraComponent.h" #define CAM_FOV 45.0f
#include "Components/GameObject.h" #define CAM_NEAR_PLAIN 0.1f
#include "Engine/InputManager.h" #define CAM_FAR_PLAIN 5000.0f
// Forward declarations for Camera and GameObject components
class CameraComponent;
class TransformComponent;
class MeshComponent;
class GameObject;
class RenderWindow class RenderWindow
{ {
public: public:
void Show(bool *GameRunning, double deltaTime); RenderWindow();
~RenderWindow();
void Show(bool *GameRunning);
private: private:
void InitGLResources(); void InitGLResources();
void RenderSceneToFBO(bool *GameRunning); void RenderSceneToFBO(bool *GameRunning);
void RenderShadowMapPreview();
std::shared_ptr<CameraComponent> m_ActiveCamera; // OpenGL Framebuffer Objects and Textures
GLuint m_FBO = 0;
GLuint m_ShadowFBO = 0;
GLuint m_ShadowMap = 0;
GLuint m_TextureID = 0; // Color texture for main FBO
// Shaders
Shader *m_ShaderPtr = nullptr; // Main shader
Shader *m_ShadowShaderPtr = nullptr; // Shadow pass shader
Shader *m_VisualizeShaderPtr = nullptr; // Shader for visualizing shadow map
// Light space matrices
glm::mat4 m_LightViewMatrix;
glm::mat4 m_LightProjMatrix;
glm::vec3 m_LightPosition = glm::vec3(-2.0f, 4.0f, -1.0f); // Default position
glm::vec3 m_LightRotation = glm::vec3(0.0f, 0.0f, 0.0f); // Default rotation (Euler angles in degrees)
// Offscreen render target
FBO m_FBO;
// Keep track if we've initialized // Keep track if we've initialized
bool m_Initialized = false; bool m_Initialized = false;
// GL objects for the cube // GL objects for the cube (example)
unsigned int m_VAO = 0; GLuint m_VAO = 0;
unsigned int m_VBO = 0; GLuint m_VBO = 0;
unsigned int m_EBO = 0; GLuint m_EBO = 0;
// GL objects for visualization quad
GLuint m_QuadVAO = 0, m_QuadVBO = 0;
// Spin // Spin
float m_RotationAngle = 0.f; float m_RotationAngle = 0.f;
int m_LastWidth = 0; int m_LastWidth = 800; // Default width
int m_LastHeight = 0; int m_LastHeight = 600; // Default height
// The loaded texture // The loaded texture
unsigned int m_TextureID = 0; GLuint m_TextureIDLoaded = 0;
// The loaded shader program (via AssetManager)
Shader* m_ShaderPtr = nullptr;
Shader* m_LineShaderPtr = nullptr;
std::shared_ptr<GameObject> m_EditorCamera;
}; };
struct Ray
{
glm::vec3 origin;
glm::vec3 direction; // Should be normalized
};

View File

@ -4,6 +4,7 @@
// Include your asset manager and any other necessary headers // Include your asset manager and any other necessary headers
#include "Engine/AssetManager.h" #include "Engine/AssetManager.h"
#include "TestModel.h"
#include "gcml.h" #include "gcml.h"
#include "Engine/ScopedTimer.h" #include "Engine/ScopedTimer.h"
@ -29,13 +30,6 @@ std::shared_ptr<GameObject> CreateDefaultCube()
void SceneWindow::Show() void SceneWindow::Show()
{ {
SCOPE_TIMER("SceneWindow::Show"); SCOPE_TIMER("SceneWindow::Show");
if (g_SelectedObject) {
if (ImGui::IsKeyPressed(ImGuiKey_Escape)) {
g_SelectedObject = nullptr;
}
}
if (ImGui::Begin("Scene Window##SceneWindow")) if (ImGui::Begin("Scene Window##SceneWindow"))
{ {
// Add Button // Add Button

View File

@ -3,7 +3,7 @@
#include <string> #include <string>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include "Components/GameObject.h" #include "Componenets/GameObject.h"
// SceneWindow class declaration // SceneWindow class declaration

View File

@ -13,13 +13,8 @@ int main()
MyEngine engine; MyEngine engine;
DEBUG_PRINT("[OK] Creating Global Engine "); DEBUG_PRINT("[OK] Creating Global Engine ");
#ifdef DEBUG
std::string title = "Tesseract Engine (DEBUG)";
#else
std::string title = "Tesseract Engine";
#endif
if (!engine.Init(1280, 720, title)) if (!engine.Init(1280, 720, "Tesseract Engine"))
{ {
fprintf(stderr, "Failed to initialize engine.\n"); fprintf(stderr, "Failed to initialize engine.\n");
return 1; return 1;

1409
vendor/IconsFontAwesome6.h vendored Normal file

File diff suppressed because it is too large Load Diff

1
vendor/ImGuizmo vendored

@ -1 +0,0 @@
Subproject commit b10e91756d32395f5c1fefd417899b657ed7cb88

1
vendor/gcml vendored

@ -1 +0,0 @@
Subproject commit f2112bb22ea5d9ea9cb7a008cc5467ec6b265c99

455
vendor/gcml/gcml.h vendored Normal file
View File

@ -0,0 +1,455 @@
#ifndef GCML_H
#define GCML_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// -------------------------
// General Utility Macros
// -------------------------
/**
* @brief Returns the minimum of two values.
*/
#define MIN(a, b) (( (a) < (b) ) ? (a) : (b))
/**
* @brief Returns the maximum of two values.
*/
#define MAX(a, b) (( (a) > (b) ) ? (a) : (b))
/**
* @brief Calculates the number of elements in an array.
*/
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
/**
* @brief Suppresses compiler warnings for unused variables.
*/
#define UNUSED(x) (void)(x)
/**
* @brief Aligns a value `x` up to the nearest multiple of `align`.
*/
#define ALIGN_UP(x, align) (((x) + ((align)-1)) & ~((align)-1))
/**
* @brief Aligns a value `x` down to the nearest multiple of `align`.
*/
#define ALIGN_DOWN(x, align) ((x) & ~((align)-1))
// -------------------------
// Debugging and Logging Macros
// -------------------------
#ifdef DEBUG
/**
* @brief Prints debug messages with file name, line number, and function name.
*/
#define DEBUG_PRINT(fmt, ...) \
fprintf(stderr, "%s:%d:%s(): " fmt "\n", \
__FILE__, __LINE__, __func__, ##__VA_ARGS__)
#else
#define DEBUG_PRINT(fmt, ...) // No operation in release builds
#endif
/**
* @brief Logs informational messages.
*/
#define LOG_INFO(fmt, ...) \
fprintf(stdout, "INFO: " fmt "\n", ##__VA_ARGS__)
/**
* @brief Logs warning messages.
*/
#define LOG_WARN(fmt, ...) \
fprintf(stderr, "WARNING: " fmt "\n", ##__VA_ARGS__)
/**
* @brief Logs error messages.
*/
#define LOG_ERROR(fmt, ...) \
fprintf(stderr, "ERROR: " fmt "\n", ##__VA_ARGS__)
/**
* @brief Logs fatal error messages and exits the program.
*/
#define LOG_FATAL(fmt, ...) do { \
fprintf(stderr, "FATAL: " fmt "\n", ##__VA_ARGS__); \
exit(EXIT_FAILURE); \
} while (0)
// -------------------------
// Assertion Macros
// -------------------------
/**
* @brief Asserts a condition and logs an error message if the condition is false.
*/
#ifndef NDEBUG
#define ASSERT(cond, fmt, ...) do { \
if (!(cond)) { \
fprintf(stderr, "Assertion failed: (%s), function %s, file %s, line %d.\n", \
#cond, __func__, __FILE__, __LINE__); \
fprintf(stderr, fmt "\n", ##__VA_ARGS__); \
abort(); \
} \
} while (0)
#else
#define ASSERT(cond, fmt, ...) ((void)0)
#endif
// -------------------------
// Stringification Macros
// -------------------------
/**
* @brief Converts a macro argument to a string.
*/
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
// -------------------------
// Token Pasting Macros
// -------------------------
/**
* @brief Concatenates two tokens.
*/
#define CONCAT(a, b) a ## b
/**
* @brief Concatenates three tokens.
*/
#define CONCAT3(a, b, c) a ## b ## c
// -------------------------
// Memory Management Macros
// -------------------------
/**
* @brief Allocates memory and checks for allocation failure.
* @param ptr The pointer to assign the allocated memory.
* @param size The size in bytes to allocate.
*/
#define SAFE_MALLOC(ptr, size) do { \
(ptr) = malloc(size); \
if ((ptr) == NULL) { \
LOG_FATAL("Memory allocation failed for size %zu", (size_t)(size)); \
} \
} while (0)
/**
* @brief Allocates zero-initialized memory and checks for allocation failure.
* @param ptr The pointer to assign the allocated memory.
* @param count The number of elements to allocate.
* @param type The type of each element.
*/
#define SAFE_CALLOC(ptr, count, type) do { \
(ptr) = calloc((count), sizeof(type)); \
if ((ptr) == NULL) { \
LOG_FATAL("Memory allocation (calloc) failed for count %zu of type %s", \
(size_t)(count), #type); \
} \
} while (0)
/**
* @brief Frees memory and sets the pointer to NULL.
* @param ptr The pointer to free.
*/
#define SAFE_FREE(ptr) do { \
free(ptr); \
ptr = NULL; \
} while(0)
// -------------------------
// Type Casting Macros
// -------------------------
/**
* @brief Safely casts a pointer to a specific type.
* @param ptr The pointer to cast.
* @param type The target type.
*/
#define SAFE_CAST(ptr, type) ((type)(ptr))
// -------------------------
// Bit Manipulation Macros
// -------------------------
/**
* @brief Sets a bit at a specific position.
* @param x The variable.
* @param pos The bit position.
*/
#define SET_BIT(x, pos) ((x) |= (1U << (pos)))
/**
* @brief Clears a bit at a specific position.
* @param x The variable.
* @param pos The bit position.
*/
#define CLEAR_BIT(x, pos) ((x) &= ~(1U << (pos)))
/**
* @brief Toggles a bit at a specific position.
* @param x The variable.
* @param pos The bit position.
*/
#define TOGGLE_BIT(x, pos) ((x) ^= (1U << (pos)))
/**
* @brief Checks if a bit at a specific position is set.
* @param x The variable.
* @param pos The bit position.
* @return Non-zero if the bit is set, zero otherwise.
*/
#define CHECK_BIT(x, pos) (((x) >> (pos)) & 1U)
// -------------------------
// Compile-Time Assertion Macro
// -------------------------
/**
* @brief Performs a compile-time assertion.
* @param expr The expression to evaluate.
* @param msg The message to display if the assertion fails.
*/
#define STATIC_ASSERT(expr, msg) _Static_assert(expr, msg)
// -------------------------
// Deprecation Warning Macros
// -------------------------
/**
* @brief Marks a function as deprecated with a custom message.
*/
#if defined(__GNUC__) || defined(__clang__)
#define DEPRECATED(msg) __attribute__((deprecated(msg)))
#elif defined(_MSC_VER)
#define DEPRECATED(msg) __declspec(deprecated(msg))
#else
#pragma message("WARNING: DEPRECATED macro is not supported for this compiler.")
#define DEPRECATED(msg)
#endif
// -------------------------
// Loop Macros
// -------------------------
/**
* @brief Iterates over each element in an array.
* @param item The loop variable.
* @param array The array to iterate over.
*/
#define FOREACH(item, array) \
for (size_t keep = 1, \
count = ARRAY_SIZE(array), \
i = 0; \
keep && i < count; \
keep = !keep, i++) \
for (item = (array) + i; keep; keep = !keep)
/**
* @brief Repeats a block of code `n` times.
* @param n The number of times to repeat.
* @param block The block of code to execute.
*/
#define REPEAT(n, block) \
for (size_t _i = 0; _i < (n); ++_i) { block; }
// -------------------------
// Swap Macro
// -------------------------
/**
* @brief Swaps two variables of the same type.
* @param a The first variable.
* @param b The second variable.
*/
#define SWAP(a, b) do { \
typeof(a) _swap_temp = (a); \
(a) = (b); \
(b) = _swap_temp; \
} while (0)
// -------------------------
// Execute Once Macro
// -------------------------
/**
* @brief Executes a block of code only once.
* @param block The block of code to execute.
*/
#define DO_ONCE(block) \
do { \
static int _do_once_flag = 0; \
if (!_do_once_flag) { \
_do_once_flag = 1; \
block \
} \
} while (0)
// -------------------------
// Utility Macros
// -------------------------
/**
* @brief Calculates the offset of a member within a struct.
* @param type The struct type.
* @param member The member within the struct.
*/
#define OFFSET_OF(type, member) ((size_t) &(((type *)0)->member))
/**
* @brief Retrieves the containing struct from a member pointer.
* @param ptr The pointer to the member.
* @param type The type of the containing struct.
* @param member The member within the struct.
*/
#define CONTAINER_OF(ptr, type, member) \
((type *)((char *)(ptr) - OFFSET_OF(type, member)))
// -------------------------
// Additional Utility Macros
// -------------------------
/**
* @brief Safely reallocates memory and checks for allocation failure.
* @param ptr The pointer to the previously allocated memory.
* @param size The new size in bytes to allocate.
*/
#define SAFE_REALLOC(ptr, size) do { \
void* _tmp = realloc((ptr), (size)); \
if ((_tmp) == NULL) { \
LOG_FATAL("Memory reallocation failed for size %zu", (size_t)(size)); \
} else { \
(ptr) = _tmp; \
} \
} while (0)
/**
* @brief Marks a function as unused to suppress compiler warnings.
*/
#define UNUSED_FUNCTION __attribute__((unused))
/**
* @brief Converts a value to a string at compile time.
* @param value The value to stringify.
* @return The string representation of the value.
*/
#define TO_STRING(value) TOSTRING(value)
/**
* @brief Generates a unique identifier by appending the line number.
* @param prefix The prefix for the identifier.
* @return A unique identifier.
*/
#define UNIQUE_ID(prefix) CONCAT(prefix, __LINE__)
/**
* @brief Forces a value to evaluate to a specific type without altering its binary representation.
* @param value The value to cast.
* @param type The target type.
* @return The value cast to the specified type.
*/
#define FORCE_CAST(value, type) (*(type*)&(value))
/**
* @brief Creates a do-while loop that executes exactly once.
* @param block The block of code to execute.
*/
#define EXECUTE_ONCE(block) do { block } while(0)
/**
* @brief Checks if a pointer is aligned to a specified boundary.
* @param ptr The pointer to check.
* @param align The alignment boundary (must be a power of two).
* @return Non-zero if aligned, zero otherwise.
*/
#define IS_ALIGNED(ptr, align) ((((uintptr_t)(const void*)(ptr)) & ((align) - 1)) == 0)
/**
* @brief Calculates the number of bits set to 1 in a variable.
* @param x The variable to count bits in.
* @return The number of bits set to 1.
*/
#define COUNT_SET_BITS(x) (__builtin_popcount(x))
/**
* @brief Calculates the ceiling of a division between two integers.
* @param numerator The numerator.
* @param denominator The denominator.
* @return The ceiling of the division.
*/
#define CEIL_DIV(numerator, denominator) (((numerator) + (denominator) - 1) / (denominator))
/**
* @brief Concatenates two tokens with an underscore.
* @param a The first token.
* @param b The second token.
* @return The concatenated token separated by an underscore.
*/
#define CONCAT_WITH_UNDERSCORE(a, b) CONCAT(a, _##b)
/**
* @brief Swaps two variables without using a temporary variable (only for integer types).
* @param a The first variable.
* @param b The second variable.
*/
#define SWAP_INPLACE(a, b) do { \
(a) ^= (b); \
(b) ^= (a); \
(a) ^= (b); \
} while (0)
// -------------------------
// Safe Reallocation Macro
// -------------------------
/**
* @brief Safely reallocates memory and checks for allocation failure.
* @param ptr The pointer to the previously allocated memory.
* @param size The new size in bytes to allocate.
*/
#define SAFE_REALLOC(ptr, size) do { \
void* _tmp = realloc((ptr), (size)); \
if ((_tmp) == NULL) { \
LOG_FATAL("Memory reallocation failed for size %zu", (size_t)(size)); \
} else { \
(ptr) = _tmp; \
} \
} while (0)
#define MAX_OF(...) MAX_OF_IMPL(__VA_ARGS__, MAX_OF_RSEQ_N())
#define MAX_OF_IMPL(...) MAX_OF_ARG_N(__VA_ARGS__)
#define MAX_OF_ARG_N(_1, _2, _3, _4, _5, N, ...) N
#define MAX_OF_RSEQ_N() 5,4,3,2,1,0
#define MIN_OF(...) MIN_OF_IMPL(__VA_ARGS__, MIN_OF_RSEQ_N())
#define MIN_OF_IMPL(...) MIN_OF_ARG_N(__VA_ARGS__)
#define MIN_OF_ARG_N(_1, _2, _3, _4, _5, N, ...) N
#define MIN_OF_RSEQ_N() 5,4,3,2,1,0
#define ZERO_STRUCT(s) memset(&(s), 0, sizeof(s))
#define PRINT_VAR(var) LOG_INFO(#var " = %d", var)
#endif // GCML_H