summaryrefslogtreecommitdiff
path: root/src/3d
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-08 07:00:28 +0100
committerskal <pascal.massimino@gmail.com>2026-02-08 07:00:28 +0100
commit1bc1cf8cd2c66bbae615a5ddba883b7cd55bd67f (patch)
tree15d989e9ff31c1a691bfaa840f661f3eed92a6b2 /src/3d
parentef3839ac767057d80feb55aaaf3f4ededfe69e91 (diff)
feat(3d): Implement Blender export and binary scene loading pipeline
Diffstat (limited to 'src/3d')
-rw-r--r--src/3d/scene_loader.cc108
-rw-r--r--src/3d/scene_loader.h14
2 files changed, 122 insertions, 0 deletions
diff --git a/src/3d/scene_loader.cc b/src/3d/scene_loader.cc
new file mode 100644
index 0000000..69079ef
--- /dev/null
+++ b/src/3d/scene_loader.cc
@@ -0,0 +1,108 @@
+#include "3d/scene_loader.h"
+#include "util/asset_manager.h"
+#include "generated/assets.h"
+#include "util/mini_math.h"
+#include <cstring>
+#include <cstdio>
+#include <vector>
+
+bool SceneLoader::LoadScene(Scene& scene, const uint8_t* data, size_t size) {
+ if (!data || size < 16) { // Header size check
+ printf("SceneLoader: Data too small\n");
+ return false;
+ }
+
+ // Check Magic
+ if (std::memcmp(data, "SCN1", 4) != 0) {
+ printf("SceneLoader: Invalid magic (expected SCN1)\n");
+ return false;
+ }
+
+ size_t offset = 4;
+
+ uint32_t num_objects = *reinterpret_cast<const uint32_t*>(data + offset); offset += 4;
+ uint32_t num_cameras = *reinterpret_cast<const uint32_t*>(data + offset); offset += 4;
+ uint32_t num_lights = *reinterpret_cast<const uint32_t*>(data + offset); offset += 4;
+
+ // printf("SceneLoader: Loading %d objects, %d cameras, %d lights\n", num_objects, num_cameras, num_lights);
+
+ for (uint32_t i = 0; i < num_objects; ++i) {
+ if (offset + 64 > size) return false; // Name check
+
+ char name[65] = {0};
+ std::memcpy(name, data + offset, 64); offset += 64;
+
+ if (offset + 4 > size) return false;
+ uint32_t type_val = *reinterpret_cast<const uint32_t*>(data + offset); offset += 4;
+ ObjectType type = (ObjectType)type_val;
+
+ if (offset + 12 + 16 + 12 + 16 > size) return false; // Transforms + Color
+
+ float px = *reinterpret_cast<const float*>(data + offset); offset += 4;
+ float py = *reinterpret_cast<const float*>(data + offset); offset += 4;
+ float pz = *reinterpret_cast<const float*>(data + offset); offset += 4;
+ vec3 pos(px, py, pz);
+
+ float rx = *reinterpret_cast<const float*>(data + offset); offset += 4;
+ float ry = *reinterpret_cast<const float*>(data + offset); offset += 4;
+ float rz = *reinterpret_cast<const float*>(data + offset); offset += 4;
+ float rw = *reinterpret_cast<const float*>(data + offset); offset += 4;
+ quat rot(rx, ry, rz, rw);
+
+ float sx = *reinterpret_cast<const float*>(data + offset); offset += 4;
+ float sy = *reinterpret_cast<const float*>(data + offset); offset += 4;
+ float sz = *reinterpret_cast<const float*>(data + offset); offset += 4;
+ vec3 scale(sx, sy, sz);
+
+ float cr = *reinterpret_cast<const float*>(data + offset); offset += 4;
+ float cg = *reinterpret_cast<const float*>(data + offset); offset += 4;
+ float cb = *reinterpret_cast<const float*>(data + offset); offset += 4;
+ float ca = *reinterpret_cast<const float*>(data + offset); offset += 4;
+ vec4 color(cr, cg, cb, ca);
+
+ // Mesh Asset Name Length
+ if (offset + 4 > size) return false;
+ uint32_t name_len = *reinterpret_cast<const uint32_t*>(data + offset); offset += 4;
+
+ AssetId mesh_id = (AssetId)0; // Default or INVALID (if 0 is invalid)
+
+ if (name_len > 0) {
+ if (offset + name_len > size) return false;
+ char mesh_name[128] = {0};
+ if (name_len < 128) {
+ std::memcpy(mesh_name, data + offset, name_len);
+ }
+ offset += name_len;
+
+ // Resolve Asset ID
+ mesh_id = GetAssetIdByName(mesh_name);
+ if (mesh_id == AssetId::ASSET_LAST_ID) {
+ printf("SceneLoader: Warning: Mesh asset '%s' not found for object '%s'\n", mesh_name, name);
+ }
+ }
+
+ // Physics properties
+ if (offset + 4 + 4 + 4 > size) return false;
+ float mass = *reinterpret_cast<const float*>(data + offset); offset += 4;
+ float restitution = *reinterpret_cast<const float*>(data + offset); offset += 4;
+ uint32_t is_static_u32 = *reinterpret_cast<const uint32_t*>(data + offset); offset += 4;
+ bool is_static = (is_static_u32 != 0);
+
+ // Create Object3D
+ Object3D obj(type);
+ obj.position = pos;
+ obj.rotation = rot;
+ obj.scale = scale;
+ obj.color = color;
+ obj.mesh_asset_id = mesh_id;
+ obj.mass = mass;
+ obj.restitution = restitution;
+ obj.is_static = is_static;
+ // user_data is nullptr by default
+
+ // Add to scene
+ scene.add_object(obj);
+ }
+
+ return true;
+} \ No newline at end of file
diff --git a/src/3d/scene_loader.h b/src/3d/scene_loader.h
new file mode 100644
index 0000000..15f08c7
--- /dev/null
+++ b/src/3d/scene_loader.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "3d/scene.h"
+#include <cstdint>
+#include <cstddef>
+
+// SceneLoader handles parsing of binary scene files (.bin) exported from Blender.
+// It populates a Scene object with objects, lights, and cameras.
+class SceneLoader {
+ public:
+ // Loads a scene from a binary buffer.
+ // Returns true on success, false on failure (e.g., invalid magic, version mismatch).
+ static bool LoadScene(Scene& scene, const uint8_t* data, size_t size);
+};