Rearrange some ModelData stuff;

This commit is contained in:
bjorn 2022-06-15 23:16:46 -07:00
parent 7de6bdf242
commit fb42bf3fbb
5 changed files with 159 additions and 122 deletions

View File

@ -50,7 +50,7 @@ StringEntry lovrDrawMode[] = {
};
StringEntry lovrMaterialColor[] = {
[COLOR_DIFFUSE] = ENTRY("diffuse"),
[COLOR_BASE] = ENTRY("base"),
[COLOR_EMISSIVE] = ENTRY("emissive"),
{ 0 }
};
@ -63,7 +63,7 @@ StringEntry lovrMaterialScalar[] = {
};
StringEntry lovrMaterialTexture[] = {
[TEXTURE_DIFFUSE] = ENTRY("diffuse"),
[TEXTURE_COLOR] = ENTRY("color"),
[TEXTURE_EMISSIVE] = ENTRY("emissive"),
[TEXTURE_METALNESS] = ENTRY("metalness"),
[TEXTURE_ROUGHNESS] = ENTRY("roughness"),

View File

@ -392,11 +392,21 @@ static int l_lovrModelDataGetMaterialName(lua_State* L) {
static int l_lovrModelDataGetMaterialImage(lua_State* L) {
ModelData* model = luax_checktype(L, 1, ModelData);
ModelMaterial* material = luax_checkmaterial(L, 2, model);
MaterialTexture type = luax_checkenum(L, 3, MaterialTexture, "diffuse");
if (material->images[type] == ~0u) {
MaterialTexture type = luax_checkenum(L, 3, MaterialTexture, "color");
uint32_t index = ~0u;
switch (type) {
case TEXTURE_COLOR: index = material->colorTexture; break;
case TEXTURE_EMISSIVE: index = material->emissiveTexture; break;
case TEXTURE_METALNESS: index = material->metalnessRoughnessTexture; break;
case TEXTURE_ROUGHNESS: index = material->metalnessRoughnessTexture; break;
case TEXTURE_OCCLUSION: index = material->occlusionTexture; break;
case TEXTURE_NORMAL: index = material->normalTexture; break;
default: lovrUnreachable(); return 0;
}
if (index == ~0u) {
lua_pushnil(L);
} else {
lua_pushinteger(L, material->images[type] + 1);
lua_pushinteger(L, index + 1);
}
return 1;
}
@ -404,20 +414,33 @@ static int l_lovrModelDataGetMaterialImage(lua_State* L) {
static int l_lovrModelDataGetMaterialColor(lua_State* L) {
ModelData* model = luax_checktype(L, 1, ModelData);
ModelMaterial* material = luax_checkmaterial(L, 2, model);
MaterialColor type = luax_checkenum(L, 3, MaterialColor, "diffuse");
lua_pushnumber(L, material->colors[type][0]);
lua_pushnumber(L, material->colors[type][1]);
lua_pushnumber(L, material->colors[type][2]);
lua_pushnumber(L, material->colors[type][3]);
return 4;
MaterialColor type = luax_checkenum(L, 3, MaterialColor, "base");
switch (type) {
case COLOR_BASE:
lua_pushnumber(L, material->baseColor[0]);
lua_pushnumber(L, material->baseColor[1]);
lua_pushnumber(L, material->baseColor[2]);
lua_pushnumber(L, material->baseColor[3]);
return 4;
case COLOR_EMISSIVE:
lua_pushnumber(L, material->emissiveColor[0]);
lua_pushnumber(L, material->emissiveColor[1]);
lua_pushnumber(L, material->emissiveColor[2]);
lua_pushnumber(L, 1.f);
return 4;
default: lovrUnreachable(); return 0;
}
}
static int l_lovrModelDataGetMaterialValue(lua_State* L) {
ModelData* model = luax_checktype(L, 1, ModelData);
ModelMaterial* material = luax_checkmaterial(L, 2, model);
MaterialScalar type = luax_checkenum(L, 3, MaterialScalar, NULL);
lua_pushnumber(L, material->scalars[type]);
return 1;
switch (type) {
case SCALAR_METALNESS: lua_pushnumber(L, material->metalness); return 1;
case SCALAR_ROUGHNESS: lua_pushnumber(L, material->roughness); return 1;
default: lovrUnreachable(); return 0;
}
}
static int l_lovrModelDataGetAnimationCount(lua_State* L) {

View File

@ -5,11 +5,17 @@
#pragma once
#define MAX_BONES 48
struct Blob;
struct Image;
typedef struct {
uint32_t blob;
size_t offset;
size_t size;
size_t stride;
char* data;
} ModelBuffer;
typedef enum {
ATTR_POSITION,
ATTR_NORMAL,
@ -21,51 +27,6 @@ typedef enum {
MAX_DEFAULT_ATTRIBUTES
} DefaultAttribute;
typedef enum {
DRAW_POINTS,
DRAW_LINES,
DRAW_LINE_LOOP,
DRAW_LINE_STRIP,
DRAW_TRIANGLES,
DRAW_TRIANGLE_STRIP,
DRAW_TRIANGLE_FAN
} DrawMode;
typedef enum {
SCALAR_METALNESS,
SCALAR_ROUGHNESS,
SCALAR_ALPHA_CUTOFF,
MAX_MATERIAL_SCALARS
} MaterialScalar;
typedef enum {
COLOR_DIFFUSE,
COLOR_EMISSIVE,
MAX_MATERIAL_COLORS
} MaterialColor;
typedef enum {
TEXTURE_DIFFUSE,
TEXTURE_EMISSIVE,
TEXTURE_METALNESS,
TEXTURE_ROUGHNESS,
TEXTURE_OCCLUSION,
TEXTURE_NORMAL,
MAX_MATERIAL_TEXTURES
} MaterialTexture;
typedef enum {
SMOOTH_STEP,
SMOOTH_LINEAR,
SMOOTH_CUBIC
} SmoothMode;
typedef enum {
PROP_TRANSLATION,
PROP_ROTATION,
PROP_SCALE,
} AnimationProperty;
typedef enum { I8, U8, I16, U16, I32, U32, F32 } AttributeType;
typedef union {
@ -79,14 +40,6 @@ typedef union {
float* f32;
} AttributeData;
typedef struct {
uint32_t blob;
size_t offset;
size_t size;
size_t stride;
char* data;
} ModelBuffer;
typedef struct {
uint32_t offset;
uint32_t buffer;
@ -101,6 +54,72 @@ typedef struct {
float max[4];
} ModelAttribute;
typedef enum {
DRAW_POINTS,
DRAW_LINES,
DRAW_LINE_LOOP,
DRAW_LINE_STRIP,
DRAW_TRIANGLES,
DRAW_TRIANGLE_STRIP,
DRAW_TRIANGLE_FAN
} DrawMode;
typedef struct {
ModelAttribute* attributes[MAX_DEFAULT_ATTRIBUTES];
ModelAttribute* indices;
DrawMode mode;
uint32_t material;
} ModelPrimitive;
typedef enum {
SCALAR_METALNESS,
SCALAR_ROUGHNESS,
SCALAR_ALPHA_CUTOFF,
MAX_MATERIAL_SCALARS
} MaterialScalar;
typedef enum {
COLOR_BASE,
COLOR_EMISSIVE,
MAX_MATERIAL_COLORS
} MaterialColor;
typedef enum {
TEXTURE_COLOR,
TEXTURE_EMISSIVE,
TEXTURE_METALNESS,
TEXTURE_ROUGHNESS,
TEXTURE_OCCLUSION,
TEXTURE_NORMAL,
MAX_MATERIAL_TEXTURES
} MaterialTexture;
typedef struct {
const char* name;
float metalness;
float roughness;
float alphaCutoff;
float baseColor[4];
float emissiveColor[4];
uint32_t colorTexture;
uint32_t emissiveTexture;
uint32_t metalnessRoughnessTexture;
uint32_t occlusionTexture;
uint32_t normalTexture;
} ModelMaterial;
typedef enum {
PROP_TRANSLATION,
PROP_ROTATION,
PROP_SCALE,
} AnimationProperty;
typedef enum {
SMOOTH_STEP,
SMOOTH_LINEAR,
SMOOTH_CUBIC
} SmoothMode;
typedef struct {
uint32_t nodeIndex;
AnimationProperty property;
@ -118,18 +137,10 @@ typedef struct {
} ModelAnimation;
typedef struct {
const char* name;
float scalars[MAX_MATERIAL_SCALARS];
float colors[MAX_MATERIAL_COLORS][4];
uint32_t images[MAX_MATERIAL_TEXTURES];
} ModelMaterial;
typedef struct {
ModelAttribute* attributes[MAX_DEFAULT_ATTRIBUTES];
ModelAttribute* indices;
DrawMode mode;
uint32_t material;
} ModelPrimitive;
uint32_t* joints;
uint32_t jointCount;
float* inverseBindMatrices;
} ModelSkin;
typedef struct {
const char* name;
@ -149,32 +160,27 @@ typedef struct {
bool matrix;
} ModelNode;
typedef struct {
uint32_t* joints;
uint32_t jointCount;
float* inverseBindMatrices;
} ModelSkin;
typedef struct ModelData {
uint32_t ref;
void* data;
struct Blob** blobs;
ModelBuffer* buffers;
struct Image** images;
ModelMaterial* materials;
ModelBuffer* buffers;
ModelAttribute* attributes;
ModelPrimitive* primitives;
ModelMaterial* materials;
ModelAnimation* animations;
ModelSkin* skins;
ModelNode* nodes;
uint32_t rootNode;
uint32_t blobCount;
uint32_t bufferCount;
uint32_t imageCount;
uint32_t materialCount;
uint32_t bufferCount;
uint32_t attributeCount;
uint32_t primitiveCount;
uint32_t materialCount;
uint32_t animationCount;
uint32_t skinCount;
uint32_t nodeCount;

View File

@ -73,15 +73,15 @@ static int nomValue(const char* data, jsmntok_t* token, int count, int sum) {
}
}
static jsmntok_t* nomTexture(const char* json, jsmntok_t* token, ModelMaterial* material, MaterialTexture textureType, gltfTexture* textures) {
static jsmntok_t* nomTexture(const char* json, jsmntok_t* token, uint32_t* imageIndex, gltfTexture* textures) {
for (int k = (token++)->size; k > 0; k--) {
gltfString key = NOM_STR(json, token);
if (STR_EQ(key, "index")) {
uint32_t index = NOM_INT(json, token);
gltfTexture* texture = &textures[index];
material->images[textureType] = texture->image;
*imageIndex = texture->image;
} else if (STR_EQ(key, "texCoord")) {
lovrAssert(NOM_INT(json, token) == 0, "Only one set of texture coordinates is supported");
lovrAssert(NOM_INT(json, token) == 0, "Currently, only one set of texture coordinates is supported");
} else {
token += NOM_VALUE(json, token);
}
@ -643,12 +643,16 @@ ModelData* lovrModelDataInitGltf(ModelData* model, Blob* source, ModelDataIO* io
jsmntok_t* token = info.materials;
ModelMaterial* material = model->materials;
for (int i = (token++)->size; i > 0; i--, material++) {
material->scalars[SCALAR_METALNESS] = 1.f;
material->scalars[SCALAR_ROUGHNESS] = 1.f;
material->scalars[SCALAR_ALPHA_CUTOFF] = 0.f;
memcpy(material->colors[COLOR_DIFFUSE], (float[4]) { 1.f, 1.f, 1.f, 1.f }, 16);
memcpy(material->colors[COLOR_EMISSIVE], (float[4]) { 0.f, 0.f, 0.f, 0.f }, 16);
memset(material->images, 0xff, MAX_MATERIAL_TEXTURES * sizeof(uint32_t));
material->metalness = 1.f;
material->roughness = 1.f;
material->alphaCutoff = 0.f;
memcpy(material->baseColor, (float[4]) { 1.f, 1.f, 1.f, 1.f }, 16);
memcpy(material->emissiveColor, (float[4]) { 0.f, 0.f, 0.f, 0.f }, 16);
material->colorTexture = ~0u;
material->emissiveTexture = ~0u;
material->metalnessRoughnessTexture = ~0u;
material->occlusionTexture = ~0u;
material->normalTexture = ~0u;
for (int k = (token++)->size; k > 0; k--) {
gltfString key = NOM_STR(json, token);
@ -657,36 +661,35 @@ ModelData* lovrModelDataInitGltf(ModelData* model, Blob* source, ModelDataIO* io
gltfString key = NOM_STR(json, token);
if (STR_EQ(key, "baseColorFactor")) {
token++; // Enter array
material->colors[COLOR_DIFFUSE][0] = NOM_FLOAT(json, token);
material->colors[COLOR_DIFFUSE][1] = NOM_FLOAT(json, token);
material->colors[COLOR_DIFFUSE][2] = NOM_FLOAT(json, token);
material->colors[COLOR_DIFFUSE][3] = NOM_FLOAT(json, token);
material->baseColor[0] = NOM_FLOAT(json, token);
material->baseColor[1] = NOM_FLOAT(json, token);
material->baseColor[2] = NOM_FLOAT(json, token);
material->baseColor[3] = NOM_FLOAT(json, token);
} else if (STR_EQ(key, "baseColorTexture")) {
token = nomTexture(json, token, material, TEXTURE_DIFFUSE, textures);
token = nomTexture(json, token, &material->colorTexture, textures);
} else if (STR_EQ(key, "metallicFactor")) {
material->scalars[SCALAR_METALNESS] = NOM_FLOAT(json, token);
material->metalness = NOM_FLOAT(json, token);
} else if (STR_EQ(key, "roughnessFactor")) {
material->scalars[SCALAR_ROUGHNESS] = NOM_FLOAT(json, token);
material->roughness = NOM_FLOAT(json, token);
} else if (STR_EQ(key, "metallicRoughnessTexture")) {
token = nomTexture(json, token, material, TEXTURE_METALNESS, textures);
material->images[TEXTURE_ROUGHNESS] = material->images[TEXTURE_METALNESS];
token = nomTexture(json, token, &material->metalnessRoughnessTexture, textures);
} else {
token += NOM_VALUE(json, token);
}
}
} else if (STR_EQ(key, "normalTexture")) {
token = nomTexture(json, token, material, TEXTURE_NORMAL, textures);
token = nomTexture(json, token, &material->normalTexture, textures);
} else if (STR_EQ(key, "occlusionTexture")) {
token = nomTexture(json, token, material, TEXTURE_OCCLUSION, textures);
token = nomTexture(json, token, &material->occlusionTexture, textures);
} else if (STR_EQ(key, "emissiveTexture")) {
token = nomTexture(json, token, material, TEXTURE_EMISSIVE, textures);
token = nomTexture(json, token, &material->emissiveTexture, textures);
} else if (STR_EQ(key, "emissiveFactor")) {
token++; // Enter array
material->colors[COLOR_EMISSIVE][0] = NOM_FLOAT(json, token);
material->colors[COLOR_EMISSIVE][1] = NOM_FLOAT(json, token);
material->colors[COLOR_EMISSIVE][2] = NOM_FLOAT(json, token);
material->emissiveColor[0] = NOM_FLOAT(json, token);
material->emissiveColor[1] = NOM_FLOAT(json, token);
material->emissiveColor[2] = NOM_FLOAT(json, token);
} else if (STR_EQ(key, "alphaCutoff")) {
material->scalars[SCALAR_ALPHA_CUTOFF] = NOM_FLOAT(json, token);
material->alphaCutoff = NOM_FLOAT(json, token);
} else if (STR_EQ(key, "name")) {
gltfString name = NOM_STR(json, token);
map_set(&model->materialMap, hash64(name.data, name.length), model->materialCount - i);

View File

@ -47,12 +47,17 @@ static void parseMtl(char* path, char* base, ModelDataIO* io, arr_image_t* image
if (STARTS_WITH(line, "newmtl ")) {
map_set(names, hash64(line + 7, length - 7), materials->length);
arr_push(materials, ((ModelMaterial) {
.scalars[SCALAR_METALNESS] = 1.f,
.scalars[SCALAR_ROUGHNESS] = 1.f,
.colors[COLOR_DIFFUSE] = { 1.f, 1.f, 1.f, 1.f },
.colors[COLOR_EMISSIVE] = { 0.f, 0.f, 0.f, 0.f }
.metalness = 1.f,
.roughness = 1.f,
.alphaCutoff = 0.f,
.baseColor = { 1.f, 1.f, 1.f, 1.f },
.emissiveColor = { 0.f, 0.f, 0.f, 0.f },
.colorTexture = ~0u,
.emissiveTexture = ~0u,
.metalnessRoughnessTexture = ~0u,
.occlusionTexture = ~0u,
.normalTexture = ~0u
}));
memset(&materials->data[materials->length - 1].images, 0xff, MAX_MATERIAL_TEXTURES * sizeof(int));
} else if (line[0] == 'K' && line[1] == 'd' && line[2] == ' ') {
float r, g, b;
char* s = line + 3;
@ -60,7 +65,7 @@ static void parseMtl(char* path, char* base, ModelDataIO* io, arr_image_t* image
g = strtof(s, &s);
b = strtof(s, &s);
ModelMaterial* material = &materials->data[materials->length - 1];
memcpy(material->colors[COLOR_DIFFUSE], (float[4]) { r, g, b, 1.f }, 16);
memcpy(material->baseColor, (float[4]) { r, g, b, 1.f }, 16);
} else if (STARTS_WITH(line, "map_Kd ")) {
lovrAssert(base - path + (length - 7) < 1024, "Bad OBJ: Material image filename is too long");
memcpy(base, line + 7, length - 7);
@ -74,7 +79,7 @@ static void parseMtl(char* path, char* base, ModelDataIO* io, arr_image_t* image
Image* image = lovrImageCreateFromFile(blob);
lovrAssert(materials->length > 0, "Tried to set a material property without declaring a material first");
ModelMaterial* material = &materials->data[materials->length - 1];
material->images[TEXTURE_DIFFUSE] = (uint32_t) images->length;
material->colorTexture = (uint32_t) images->length;
arr_push(images, image);
lovrRelease(blob, lovrBlobDestroy);
}