Parsing improvements;

This commit is contained in:
bjorn 2018-12-18 20:57:47 -08:00 committed by Bjorn Swenson
parent e8a2ac8063
commit b1b6ec0f6d
3 changed files with 47 additions and 39 deletions

View File

@ -2,12 +2,14 @@
#include "lib/math.h" #include "lib/math.h"
#include "lib/jsmn/jsmn.h" #include "lib/jsmn/jsmn.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h>
#define MAGIC_glTF 0x46546c67 #define MAGIC_glTF 0x46546c67
#define MAGIC_JSON 0x4e4f534a #define MAGIC_JSON 0x4e4f534a
#define MAGIC_BIN 0x004e4942 #define MAGIC_BIN 0x004e4942
#define KEY_EQ(k, s) !strncmp(k.data, s, k.length) #define KEY_EQ(k, s) !strncmp(k.data, s, k.length)
#define NOM_VALUE(j, t) nomValue(j, t, 1, 0)
#define NOM_KEY(j, t) hashKey((char*) j + (t++)->start) #define NOM_KEY(j, t) hashKey((char*) j + (t++)->start)
#define NOM_INT(j, t) strtol(j + (t++)->start, NULL, 10) #define NOM_INT(j, t) strtol(j + (t++)->start, NULL, 10)
#define NOM_BOOL(j, t) (*(j + (t++)->start) == 't') #define NOM_BOOL(j, t) (*(j + (t++)->start) == 't')
@ -30,6 +32,17 @@ typedef struct {
int jointCount; int jointCount;
} gltfInfo; } gltfInfo;
typedef struct {
uint32_t magic;
uint32_t version;
uint32_t length;
} gltfHeader;
typedef struct {
uint32_t length;
uint32_t type;
} gltfChunkHeader;
static uint32_t hashKey(char* key) { static uint32_t hashKey(char* key) {
uint32_t hash = 0; uint32_t hash = 0;
for (int i = 0; key[i] != '"'; i++) { for (int i = 0; key[i] != '"'; i++) {
@ -57,7 +70,7 @@ static jsmntok_t* aggregate(const char* json, jsmntok_t* token, uint32_t hash, i
if (NOM_KEY(json, token) == hash) { if (NOM_KEY(json, token) == hash) {
*total += token->size; *total += token->size;
} }
token += nomValue(json, token, 1, 0); token += NOM_VALUE(json, token);
} }
} }
} }
@ -71,7 +84,7 @@ static void preparse(const char* json, jsmntok_t* tokens, int tokenCount, ModelD
info->accessors = token; info->accessors = token;
model->accessorCount = token->size; model->accessorCount = token->size;
info->totalSize += token->size * sizeof(ModelAccessor); info->totalSize += token->size * sizeof(ModelAccessor);
token += nomValue(json, token, 1, 0); token += NOM_VALUE(json, token);
break; break;
case HASH16("animations"): case HASH16("animations"):
info->animations = token; info->animations = token;
@ -88,7 +101,7 @@ static void preparse(const char* json, jsmntok_t* tokens, int tokenCount, ModelD
case HASH16("samplers"): model->animationSamplerCount += token->size; break; case HASH16("samplers"): model->animationSamplerCount += token->size; break;
default: break; default: break;
} }
token += nomValue(json, token, 1, 0); token += NOM_VALUE(json, token);
} }
} }
} }
@ -97,37 +110,37 @@ static void preparse(const char* json, jsmntok_t* tokens, int tokenCount, ModelD
info->blobs = token; info->blobs = token;
model->blobCount = token->size; model->blobCount = token->size;
info->totalSize += token->size * sizeof(ModelBlob); info->totalSize += token->size * sizeof(ModelBlob);
token += nomValue(json, token, 1, 0); token += NOM_VALUE(json, token);
break; break;
case HASH16("bufferViews"): case HASH16("bufferViews"):
info->views = token; info->views = token;
model->viewCount = token->size; model->viewCount = token->size;
info->totalSize += token->size * sizeof(ModelView); info->totalSize += token->size * sizeof(ModelView);
token += nomValue(json, token, 1, 0); token += NOM_VALUE(json, token);
break; break;
case HASH16("images"): case HASH16("images"):
info->images = token; info->images = token;
model->imageCount = token->size; model->imageCount = token->size;
info->totalSize += token->size * sizeof(TextureData); info->totalSize += token->size * sizeof(TextureData);
token += nomValue(json, token, 1, 0); token += NOM_VALUE(json, token);
break; break;
case HASH16("samplers"): case HASH16("samplers"):
info->samplers = token; info->samplers = token;
model->samplerCount = token->size; model->samplerCount = token->size;
info->totalSize += token->size * sizeof(ModelSampler); info->totalSize += token->size * sizeof(ModelSampler);
token += nomValue(json, token, 1, 0); token += NOM_VALUE(json, token);
break; break;
case HASH16("textures"): case HASH16("textures"):
info->samplers = token; info->samplers = token;
model->textureCount = token->size; model->textureCount = token->size;
info->totalSize += token->size * sizeof(ModelTexture); info->totalSize += token->size * sizeof(ModelTexture);
token += nomValue(json, token, 1, 0); token += NOM_VALUE(json, token);
break; break;
case HASH16("materials"): case HASH16("materials"):
info->materials = token; info->materials = token;
model->materialCount = token->size; model->materialCount = token->size;
info->totalSize += token->size * sizeof(ModelMaterial); info->totalSize += token->size * sizeof(ModelMaterial);
token += nomValue(json, token, 1, 0); token += NOM_VALUE(json, token);
break; break;
case HASH16("meshes"): case HASH16("meshes"):
info->meshes = token; info->meshes = token;
@ -150,7 +163,7 @@ static void preparse(const char* json, jsmntok_t* tokens, int tokenCount, ModelD
token = aggregate(json, token, HASH16("joints"), &info->jointCount); token = aggregate(json, token, HASH16("joints"), &info->jointCount);
info->totalSize += info->jointCount * sizeof(uint32_t); info->totalSize += info->jointCount * sizeof(uint32_t);
break; break;
default: token += nomValue(json, token, 1, 0); break; default: token += NOM_VALUE(json, token); break;
} }
} }
} }
@ -189,7 +202,7 @@ static void parseAccessors(const char* json, jsmntok_t* token, ModelData* model)
default: lovrThrow("Unsupported accessor type"); break; default: lovrThrow("Unsupported accessor type"); break;
} }
break; break;
default: token += nomValue(json, token, 1, 0); break; default: token += NOM_VALUE(json, token); break;
} }
} }
} }
@ -214,11 +227,11 @@ static jsmntok_t* parseAnimationChannel(const char* json, jsmntok_t* token, int
default: lovrThrow("Unknown animation target path"); break; default: lovrThrow("Unknown animation target path"); break;
} }
break; break;
default: token += nomValue(json, token, 1, 0); break; default: token += NOM_VALUE(json, token); break;
} }
} }
} }
default: token += nomValue(json, token, 1, 0); break; default: token += NOM_VALUE(json, token); break;
} }
} }
return token; return token;
@ -239,7 +252,7 @@ static jsmntok_t* parseAnimationSampler(const char* json, jsmntok_t* token, int
default: lovrThrow("Unknown animation sampler interpolation"); break; default: lovrThrow("Unknown animation sampler interpolation"); break;
} }
break; break;
default: token += nomValue(json, token, 1, 0); default: token += NOM_VALUE(json, token);
} }
} }
return token; return token;
@ -271,7 +284,7 @@ static void parseAnimations(const char* json, jsmntok_t* token, ModelData* model
token = parseAnimationSampler(json, token, samplerIndex++, model); token = parseAnimationSampler(json, token, samplerIndex++, model);
} }
break; break;
default: token += nomValue(json, token, 1, 0); break; default: token += NOM_VALUE(json, token); break;
} }
} }
} }
@ -299,7 +312,7 @@ static void parseBlobs(const char* json, jsmntok_t* token, ModelData* model, Mod
lovrAssert(blob->data, "Unable to read %s", filename); lovrAssert(blob->data, "Unable to read %s", filename);
filename[length] = '"'; filename[length] = '"';
break; break;
default: token += nomValue(json, token, 1, 0); break; default: token += NOM_VALUE(json, token); break;
} }
} }
@ -326,7 +339,7 @@ static void parseViews(const char* json, jsmntok_t* token, ModelData* model) {
case HASH16("byteOffset"): view->offset = NOM_INT(json, token); break; case HASH16("byteOffset"): view->offset = NOM_INT(json, token); break;
case HASH16("byteLength"): view->length = NOM_INT(json, token); break; case HASH16("byteLength"): view->length = NOM_INT(json, token); break;
case HASH16("byteStride"): view->stride = NOM_INT(json, token); break; case HASH16("byteStride"): view->stride = NOM_INT(json, token); break;
default: token += nomValue(json, token, 1, 0); break; default: token += NOM_VALUE(json, token); break;
} }
} }
} }
@ -364,7 +377,7 @@ static void parseImages(const char* json, jsmntok_t* token, ModelData* model, Mo
lovrRelease(blob); lovrRelease(blob);
break; break;
} }
default: token += nomValue(json, token, 1, 0); break; default: token += NOM_VALUE(json, token); break;
} }
} }
} }
@ -401,7 +414,7 @@ static void parseSamplers(const char* json, jsmntok_t* token, ModelData* model)
default: lovrThrow("Unknown sampler wrapT mode for sampler %d", i); default: lovrThrow("Unknown sampler wrapT mode for sampler %d", i);
} }
break; break;
default: token += nomValue(json, token, 1, 0); break; default: token += NOM_VALUE(json, token); break;
} }
} }
@ -428,7 +441,7 @@ static void parseTextures(const char* json, jsmntok_t* token, ModelData* model)
switch (NOM_KEY(json, token)) { switch (NOM_KEY(json, token)) {
case HASH16("source"): texture->image = NOM_INT(json, token); break; case HASH16("source"): texture->image = NOM_INT(json, token); break;
case HASH16("sampler"): texture->sampler = NOM_INT(json, token); break; case HASH16("sampler"): texture->sampler = NOM_INT(json, token); break;
default: token += nomValue(json, token, 1, 0); break; default: token += NOM_VALUE(json, token); break;
} }
} }
} }
@ -440,7 +453,7 @@ static jsmntok_t* parseTextureInfo(const char* json, jsmntok_t* token, int* dest
switch (NOM_KEY(json, token)) { switch (NOM_KEY(json, token)) {
case HASH16("index"): *dest = NOM_INT(json, token); break; case HASH16("index"): *dest = NOM_INT(json, token); break;
case HASH16("texCoord"): lovrAssert(NOM_INT(json, token) == 0, "Only one set of texture coordinates is supported"); break; case HASH16("texCoord"): lovrAssert(NOM_INT(json, token) == 0, "Only one set of texture coordinates is supported"); break;
default: token += nomValue(json, token, 1, 0); break; default: token += NOM_VALUE(json, token); break;
} }
} }
return token; return token;
@ -488,7 +501,7 @@ static void parseMaterials(const char* json, jsmntok_t* token, ModelData* model)
material->colors[COLOR_EMISSIVE].b = NOM_FLOAT(json, token); material->colors[COLOR_EMISSIVE].b = NOM_FLOAT(json, token);
material->colors[COLOR_EMISSIVE].a = NOM_FLOAT(json, token); material->colors[COLOR_EMISSIVE].a = NOM_FLOAT(json, token);
break; break;
default: token += nomValue(json, token, 1, 0); break; default: token += NOM_VALUE(json, token); break;
} }
} }
} }
@ -533,7 +546,7 @@ static jsmntok_t* parsePrimitive(const char* json, jsmntok_t* token, int index,
} }
break; break;
} }
default: token += nomValue(json, token, 1, 0); break; default: token += NOM_VALUE(json, token); break;
} }
} }
return token; return token;
@ -557,7 +570,7 @@ static void parseMeshes(const char* json, jsmntok_t* token, ModelData* model) {
token = parsePrimitive(json, token, primitiveIndex++, model); token = parsePrimitive(json, token, primitiveIndex++, model);
} }
break; break;
default: token += nomValue(json, token, 1, 0); break; default: token += NOM_VALUE(json, token); break;
} }
} }
} }
@ -613,7 +626,7 @@ static void parseNodes(const char* json, jsmntok_t* token, ModelData* model) {
scale[1] = NOM_FLOAT(json, token); scale[1] = NOM_FLOAT(json, token);
scale[2] = NOM_FLOAT(json, token); scale[2] = NOM_FLOAT(json, token);
break; break;
default: token += nomValue(json, token, 1, 0); break; default: token += NOM_VALUE(json, token); break;
} }
} }
@ -647,7 +660,7 @@ static void parseSkins(const char* json, jsmntok_t* token, ModelData* model) {
model->skinJoints[jointIndex++] = NOM_INT(json, token); model->skinJoints[jointIndex++] = NOM_INT(json, token);
} }
break; break;
default: token += nomValue(json, token, 1, 0); break; default: token += NOM_VALUE(json, token); break;
} }
} }
} }
@ -684,8 +697,10 @@ ModelData* lovrModelDataInit(ModelData* model, Blob* blob, ModelDataIO io) {
jsmn_parser parser; jsmn_parser parser;
jsmn_init(&parser); jsmn_init(&parser);
jsmntok_t tokens[1024]; // TODO malloc or token queue int tokenCount = jsmn_parse(&parser, jsonData, jsonLength, NULL, 0);
int tokenCount = jsmn_parse(&parser, jsonData, jsonLength, tokens, 1024); jsmntok_t* tokens = malloc(tokenCount * sizeof(jsmntok_t));
jsmn_init(&parser);
tokenCount = jsmn_parse(&parser, jsonData, jsonLength, tokens, tokenCount);
lovrAssert(tokenCount >= 0, "Invalid JSON"); lovrAssert(tokenCount >= 0, "Invalid JSON");
lovrAssert(tokens[0].type == JSMN_OBJECT, "No root object"); lovrAssert(tokens[0].type == JSMN_OBJECT, "No root object");
@ -724,6 +739,8 @@ ModelData* lovrModelDataInit(ModelData* model, Blob* blob, ModelDataIO io) {
parseNodes(jsonData, info.nodes, model); parseNodes(jsonData, info.nodes, model);
parseSkins(jsonData, info.skins, model); parseSkins(jsonData, info.skins, model);
free(tokens);
return model; return model;
} }

View File

@ -90,17 +90,6 @@ typedef enum {
typedef enum { I8, U8, I16, U16, I32, U32, F32 } AttributeType; typedef enum { I8, U8, I16, U16, I32, U32, F32 } AttributeType;
typedef struct {
uint32_t magic;
uint32_t version;
uint32_t length;
} gltfHeader;
typedef struct {
uint32_t length;
uint32_t type;
} gltfChunkHeader;
typedef struct { typedef struct {
int view; int view;
int count; int count;

View File

@ -1,6 +1,8 @@
#ifndef __JSMN_H_ #ifndef __JSMN_H_
#define __JSMN_H_ #define __JSMN_H_
#define JSMN_PARENT_LINKS
#include <stddef.h> #include <stddef.h>
#ifdef __cplusplus #ifdef __cplusplus