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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#pragma once
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
constexpr size_t ModelPathLen = 256;
constexpr size_t ModelNameLen = 64;
constexpr size_t ModelMaxObjects = 256; // uint8_t
constexpr size_t ModelMaxMaterials = 256; // uint8_t
constexpr size_t ModelMaxVerts = 4294967296; // uint32_t
constexpr size_t ModelMaxFaces = 4294967296; // uint32_t
typedef uint16_t mdIdx;
typedef struct mdVert { mdIdx position, texcoord, normal; } mdVert;
typedef struct mdTri { mdVert v0, v1, v2; } mdTri;
typedef struct mdVec2 { float x, y; } mdVec2;
typedef struct mdVec3 { float x, y, z; } mdVec3;
typedef struct ModelObject {
uint32_t offset; // FlatModel: offset into indices. IndexedModel: offset into tris.
uint32_t count; // FloatModel: number of indices. IndexedModel: number of tris.
uint8_t material; // Material index.
uint8_t pad[3];
char name[ModelNameLen];
} ModelObject;
typedef struct ModelMaterial {
char name[ModelNameLen];
char diffuseTexture[ModelPathLen];
} ModelMaterial;
// Every three indices form a triangle, and each index indexes all attribute
// arrays simultaneously. This is best for a fast, linear-scan rendering.
// This is what you would render with glDrawElements().
typedef struct FlatModel {
// Counts.
uint32_t numIdxs;
uint32_t numVerts;
// Offsets.
uint32_t offsetIdxs;
uint32_t offsetPositions;
uint32_t offsetTexcoords;
uint32_t offsetNormals;
/*
[objects] -- numObjects Object
[materials] -- numMaterials Material
[indices] -- numIdxs mdIdx
[positions] -- numVerts mdVec3
[texcoords] -- numVerts mdVec2
[normals] -- numVerts mdVec3
*/
uint8_t data[];
} FlatModel;
// Every triangle is made up of three vertices, and each vertex holds one index
// for each of the attribute arrays. This allows for a smaller representation of
// some models by virtue of being able to re-use attributes across vertices.
// This is the sort of format that OBJ follows, where the indices to each array
// given by a face may be non-uniform.
typedef struct IndexedModel {
// Counts.
uint32_t numTris;
uint32_t numPositions;
uint32_t numTexcoords;
uint32_t numNormals;
// Offsets.
uint32_t offsetTris;
uint32_t offsetPositions;
uint32_t offsetTexcoords;
uint32_t offsetNormals;
/*
[objects] -- numObjects Object
[materials] -- numMaterials Material
[triangles] -- numTris mdTri
[positions] -- numPositions mdVec3
[texcoords] -- numTexcoords mdVec2
[normals] -- numNormals mdVec3
*/
uint8_t data[];
} IndexedModel;
typedef enum ModelType {
ModelTypeFlat,
ModelTypeIndexed
} ModelType;
typedef struct Model {
uint32_t type;
// Counts.
uint8_t numObjects;
uint8_t numMaterials;
uint8_t pad[2];
// Offsets.
uint32_t offsetObjects;
uint32_t offsetMaterials;
// Model details.
union {
FlatModel flat;
IndexedModel indexed;
};
} Model;
static inline const ModelObject* modelObjects(const Model* model) {
assert(model);
switch (model->type) {
case ModelTypeIndexed:
return (const ModelObject*)(model->indexed.data + model->offsetObjects);
case ModelTypeFlat:
return (const ModelObject*)(model->flat.data + model->offsetObjects);
default:
assert(false);
break;
}
}
static inline const ModelMaterial* modelMaterials(const Model* model) {
assert(model);
switch (model->type) {
case ModelTypeIndexed:
return (const ModelMaterial*)(model->indexed.data + model->offsetMaterials);
case ModelTypeFlat:
return (const ModelMaterial*)(model->flat.data + model->offsetMaterials);
default:
assert(false);
break;
}
}
|