summaryrefslogtreecommitdiff
path: root/src/3d/scene_loader.cc
blob: 69079efd4ad86c00e76959d4adf3bef10dd90421 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
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;
}