OBJ groups/materials;

This commit is contained in:
bjorn 2019-01-30 18:56:17 -08:00 committed by Bjorn Swenson
parent 6857b01ac0
commit 4373e29bea
6 changed files with 271 additions and 139 deletions

View File

@ -16,8 +16,8 @@ void lovrModelDataDestroy(void* ref) {
for (int i = 0; i < model->blobCount; i++) {
lovrRelease(model->blobs[i]);
}
for (int i = 0; i < model->imageCount; i++) {
lovrRelease(model->images[i]);
for (int i = 0; i < model->textureCount; i++) {
lovrRelease(model->textures[i]);
}
free(model->data);
}
@ -25,37 +25,35 @@ void lovrModelDataDestroy(void* ref) {
// Note: this code is a scary optimization
void lovrModelDataAllocate(ModelData* model) {
size_t totalSize = 0;
size_t sizes[14];
size_t sizes[13];
totalSize += sizes[0] = model->blobCount * sizeof(Blob*);
totalSize += sizes[1] = model->imageCount * sizeof(TextureData*);
totalSize += sizes[2] = model->animationCount * sizeof(ModelAnimation);
totalSize += sizes[3] = model->attributeCount * sizeof(ModelAttribute);
totalSize += sizes[4] = model->bufferCount * sizeof(ModelBuffer);
totalSize += sizes[5] = model->textureCount * sizeof(ModelTexture);
totalSize += sizes[6] = model->materialCount * sizeof(ModelMaterial);
totalSize += sizes[7] = model->primitiveCount * sizeof(ModelPrimitive);
totalSize += sizes[1] = model->bufferCount * sizeof(ModelBuffer);
totalSize += sizes[2] = model->textureCount * sizeof(TextureData*);
totalSize += sizes[3] = model->materialCount * sizeof(ModelMaterial);
totalSize += sizes[4] = model->attributeCount * sizeof(ModelAttribute);
totalSize += sizes[5] = model->primitiveCount * sizeof(ModelPrimitive);
totalSize += sizes[6] = model->animationCount * sizeof(ModelAnimation);
totalSize += sizes[7] = model->skinCount * sizeof(ModelSkin);
totalSize += sizes[8] = model->nodeCount * sizeof(ModelNode);
totalSize += sizes[9] = model->skinCount * sizeof(ModelSkin);
totalSize += sizes[10] = model->channelCount * sizeof(ModelAnimationChannel);
totalSize += sizes[11] = model->childCount * sizeof(uint32_t);
totalSize += sizes[12] = model->jointCount * sizeof(uint32_t);
totalSize += sizes[13] = model->charCount * sizeof(char);
totalSize += sizes[9] = model->channelCount * sizeof(ModelAnimationChannel);
totalSize += sizes[10] = model->childCount * sizeof(uint32_t);
totalSize += sizes[11] = model->jointCount * sizeof(uint32_t);
totalSize += sizes[12] = model->charCount * sizeof(char);
size_t offset = 0;
char* p = model->data = calloc(1, totalSize);
lovrAssert(model->data, "Out of memory");
model->blobs = (Blob**) (p + offset), offset += sizes[0];
model->images = (TextureData**) (p + offset), offset += sizes[1];
model->animations = (ModelAnimation*) (p + offset), offset += sizes[2];
model->attributes = (ModelAttribute*) (p + offset), offset += sizes[3];
model->buffers = (ModelBuffer*) (p + offset), offset += sizes[4];
model->textures = (ModelTexture*) (p + offset), offset += sizes[5];
model->materials = (ModelMaterial*) (p + offset), offset += sizes[6];
model->primitives = (ModelPrimitive*) (p + offset), offset += sizes[7];
model->buffers = (ModelBuffer*) (p + offset), offset += sizes[1];
model->textures = (TextureData**) (p + offset), offset += sizes[2];
model->materials = (ModelMaterial*) (p + offset), offset += sizes[3];
model->attributes = (ModelAttribute*) (p + offset), offset += sizes[4];
model->primitives = (ModelPrimitive*) (p + offset), offset += sizes[5];
model->animations = (ModelAnimation*) (p + offset), offset += sizes[6];
model->skins = (ModelSkin*) (p + offset), offset += sizes[7];
model->nodes = (ModelNode*) (p + offset), offset += sizes[8];
model->skins = (ModelSkin*) (p + offset), offset += sizes[9];
model->channels = (ModelAnimationChannel*) (p + offset), offset += sizes[10];
model->children = (uint32_t*) (p + offset), offset += sizes[11];
model->joints = (uint32_t*) (p + offset), offset += sizes[12];
model->chars = (char*) (p + offset), offset += sizes[13];
model->channels = (ModelAnimationChannel*) (p + offset), offset += sizes[9];
model->children = (uint32_t*) (p + offset), offset += sizes[10];
model->joints = (uint32_t*) (p + offset), offset += sizes[11];
model->chars = (char*) (p + offset), offset += sizes[12];
}

View File

@ -136,6 +136,8 @@ typedef struct {
float scalars[MAX_MATERIAL_SCALARS];
Color colors[MAX_MATERIAL_COLORS];
int textures[MAX_MATERIAL_TEXTURES];
TextureFilter filters[MAX_MATERIAL_TEXTURES];
TextureWrap wraps[MAX_MATERIAL_TEXTURES];
} ModelMaterial;
typedef struct {
@ -164,26 +166,25 @@ typedef struct {
Ref ref;
void* data;
Blob** blobs;
TextureData** images;
ModelAnimation* animations;
ModelAttribute* attributes;
ModelBuffer* buffers;
ModelTexture* textures;
TextureData** textures;
ModelMaterial* materials;
ModelAttribute* attributes;
ModelPrimitive* primitives;
ModelNode* nodes;
ModelAnimation* animations;
ModelSkin* skins;
ModelNode* nodes;
int rootNode;
int blobCount;
int imageCount;
int animationCount;
int attributeCount;
int bufferCount;
int textureCount;
int materialCount;
int attributeCount;
int primitiveCount;
int nodeCount;
int animationCount;
int skinCount;
int rootNode;
int nodeCount;
ModelAnimationChannel* channels;
uint32_t* children;

View File

@ -51,6 +51,11 @@ typedef struct {
TextureWrap wrap;
} gltfSampler;
typedef struct {
int image;
int sampler;
} gltfTexture;
typedef struct {
uint32_t node;
uint32_t nodeCount;
@ -89,11 +94,14 @@ static jsmntok_t* aggregate(const char* json, jsmntok_t* token, const char* targ
return token;
}
static jsmntok_t* parseTextureInfo(const char* json, jsmntok_t* token, int* dest) {
static jsmntok_t* resolveTexture(const char* json, jsmntok_t* token, ModelMaterial* material, MaterialTexture type, gltfTexture* textures, gltfSampler* samplers) {
for (int k = (token++)->size; k > 0; k--) {
gltfString key = NOM_STR(json, token);
if (STR_EQ(key, "index")) {
*dest = NOM_INT(json, token);
int index = NOM_INT(json, token);
material->textures[type] = textures[index].image;
material->filters[type] = samplers[textures[index].sampler].filter;
material->wraps[type] = samplers[textures[index].sampler].wrap;
} else if (STR_EQ(key, "texCoord")) {
lovrAssert(NOM_INT(json, token) == 0, "Only one set of texture coordinates is supported");
} else {
@ -148,10 +156,12 @@ ModelData* lovrModelDataInitGltf(ModelData* model, Blob* source, ModelDataIO io)
if ((tokenCount = jsmn_parse(&parser, json, jsonLength, stackTokens, MAX_STACK_TOKENS)) == JSMN_ERROR_NOMEM) {
size_t capacity = MAX_STACK_TOKENS;
jsmn_init(&parser); // This shouldn't be necessary but not doing it caused an infinite loop?
do {
capacity *= 2;
lovrAssert(heapTokens = realloc(heapTokens, capacity), "Out of memory");
heapTokens = realloc(heapTokens, capacity * sizeof(jsmntok_t));
lovrAssert(heapTokens, "Out of memory");
tokenCount = jsmn_parse(&parser, json, jsonLength, heapTokens, capacity);
} while (tokenCount == JSMN_ERROR_NOMEM);
@ -172,7 +182,6 @@ ModelData* lovrModelDataInitGltf(ModelData* model, Blob* source, ModelDataIO io)
jsmntok_t* buffers;
jsmntok_t* bufferViews;
jsmntok_t* images;
jsmntok_t* textures;
jsmntok_t* materials;
jsmntok_t* meshes;
jsmntok_t* nodes;
@ -184,6 +193,7 @@ ModelData* lovrModelDataInitGltf(ModelData* model, Blob* source, ModelDataIO io)
gltfAnimationSampler* animationSamplers = NULL;
gltfMesh* meshes = NULL;
gltfSampler* samplers = NULL;
gltfTexture* textures = NULL;
gltfScene* scenes = NULL;
int rootScene = 0;
@ -256,7 +266,7 @@ ModelData* lovrModelDataInitGltf(ModelData* model, Blob* source, ModelDataIO io)
} else if (STR_EQ(key, "images")) {
info.images = token;
model->imageCount = token->size;
model->textureCount = token->size;
token += NOM_VALUE(json, token);
} else if (STR_EQ(key, "samplers")) {
@ -304,9 +314,21 @@ ModelData* lovrModelDataInitGltf(ModelData* model, Blob* source, ModelDataIO io)
}
} else if (STR_EQ(key, "textures")) {
info.textures = token;
model->textureCount = token->size;
token += NOM_VALUE(json, token);
textures = malloc(token->size * sizeof(gltfTexture));
lovrAssert(textures, "Out of memory");
gltfTexture* texture = textures;
for (int i = (token++)->size; i > 0; i--, texture++) {
for (int k = (token++)->size; k > 0; k--) {
gltfString key = NOM_STR(json, token);
if (STR_EQ(key, "source")) {
texture->image = NOM_INT(json, token);
} else if (STR_EQ(key, "sampler")) {
texture->sampler = NOM_INT(json, token);
} else {
token += NOM_VALUE(json, token);
}
}
}
} else if (STR_EQ(key, "materials")) {
info.materials = token;
@ -561,17 +583,17 @@ ModelData* lovrModelDataInitGltf(ModelData* model, Blob* source, ModelDataIO io)
}
}
// Images
if (model->imageCount > 0) {
// Textures (glTF images)
if (model->textureCount > 0) {
jsmntok_t* token = info.images;
TextureData** image = model->images;
for (int i = (token++)->size; i > 0; i--, image++) {
TextureData** texture = model->textures;
for (int i = (token++)->size; i > 0; i--, texture++) {
for (int k = (token++)->size; k > 0; k--) {
gltfString key = NOM_STR(json, token);
if (STR_EQ(key, "bufferView")) {
ModelBuffer* buffer = &model->buffers[NOM_INT(json, token)];
Blob* blob = lovrBlobCreate(buffer->data, buffer->size, NULL);
*image = lovrTextureDataCreateFromBlob(blob, false);
*texture = lovrTextureDataCreateFromBlob(blob, false);
blob->data = NULL; // FIXME
lovrRelease(blob);
} else if (STR_EQ(key, "uri")) {
@ -580,10 +602,10 @@ ModelData* lovrModelDataInitGltf(ModelData* model, Blob* source, ModelDataIO io)
gltfString uri = NOM_STR(json, token);
lovrAssert(strncmp("data:", uri.data, strlen("data:")), "Base64 URIs aren't supported yet");
snprintf(filename, 1024, "%s/%.*s%c", basePath, (int) uri.length, uri.data, 0);
void* data = io.read(filename, &size);
lovrAssert(data && size > 0, "Unable to read image from '%s'", filename);
void* data = lovrFilesystemRead(filename, &size);
lovrAssert(data && size > 0, "Unable to read texture from '%s'", filename);
Blob* blob = lovrBlobCreate(data, size, NULL);
*image = lovrTextureDataCreateFromBlob(blob, false);
*texture = lovrTextureDataCreateFromBlob(blob, false);
lovrRelease(blob);
} else {
token += NOM_VALUE(json, token);
@ -592,27 +614,6 @@ ModelData* lovrModelDataInitGltf(ModelData* model, Blob* source, ModelDataIO io)
}
}
// Textures
if (model->textureCount > 0) {
jsmntok_t* token = info.textures;
ModelTexture* texture = model->textures;
for (int i = (token++)->size; i > 0; i--, texture++) {
texture->filter.mode = FILTER_TRILINEAR;
texture->wrap.s = texture->wrap.t = WRAP_REPEAT;
for (int k = (token++)->size; k > 0; k--) {
gltfString key = NOM_STR(json, token);
if (STR_EQ(key, "source")) {
texture->imageIndex = NOM_INT(json, token);
} else if (STR_EQ(key, "sampler")) {
gltfSampler* sampler = &samplers[NOM_INT(json, token)];
texture->filter = sampler->filter;
texture->wrap = sampler->wrap;
}
else { token += NOM_VALUE(json, token); }
}
}
}
// Materials
if (model->materialCount > 0) {
jsmntok_t* token = info.materials;
@ -636,24 +637,26 @@ ModelData* lovrModelDataInitGltf(ModelData* model, Blob* source, ModelDataIO io)
material->colors[COLOR_DIFFUSE].b = NOM_FLOAT(json, token);
material->colors[COLOR_DIFFUSE].a = NOM_FLOAT(json, token);
} else if (STR_EQ(key, "baseColorTexture")) {
token = parseTextureInfo(json, token, &material->textures[TEXTURE_DIFFUSE]);
token = resolveTexture(json, token, material, TEXTURE_DIFFUSE, textures, samplers);
} else if (STR_EQ(key, "metallicFactor")) {
material->scalars[SCALAR_METALNESS] = NOM_FLOAT(json, token);
} else if (STR_EQ(key, "roughnessFactor")) {
material->scalars[SCALAR_ROUGHNESS] = NOM_FLOAT(json, token);
} else if (STR_EQ(key, "metallicRoughnessTexture")) {
token = parseTextureInfo(json, token, &material->textures[TEXTURE_METALNESS]);
token = resolveTexture(json, token, material, TEXTURE_METALNESS, textures, samplers);
material->textures[TEXTURE_ROUGHNESS] = material->textures[TEXTURE_METALNESS];
material->filters[TEXTURE_ROUGHNESS] = material->filters[TEXTURE_METALNESS];
material->wraps[TEXTURE_ROUGHNESS] = material->wraps[TEXTURE_METALNESS];
} else {
token += NOM_VALUE(json, token);
}
}
} else if (STR_EQ(key, "normalTexture")) {
token = parseTextureInfo(json, token, &material->textures[TEXTURE_NORMAL]);
token = resolveTexture(json, token, material, TEXTURE_NORMAL, textures, samplers);
} else if (STR_EQ(key, "occlusionTexture")) {
token = parseTextureInfo(json, token, &material->textures[TEXTURE_OCCLUSION]);
token = resolveTexture(json, token, material, TEXTURE_OCCLUSION, textures, samplers);
} else if (STR_EQ(key, "emissiveTexture")) {
token = parseTextureInfo(json, token, &material->textures[TEXTURE_EMISSIVE]);
token = resolveTexture(json, token, material, TEXTURE_EMISSIVE, textures, samplers);
} else if (STR_EQ(key, "emissiveFactor")) {
token++; // Enter array
material->colors[COLOR_EMISSIVE].r = NOM_FLOAT(json, token);
@ -852,6 +855,7 @@ ModelData* lovrModelDataInitGltf(ModelData* model, Blob* source, ModelDataIO io)
free(animationSamplers);
free(meshes);
free(samplers);
free(textures);
free(scenes);
free(heapTokens);
return model;

View File

@ -1,27 +1,116 @@
#include "data/modelData.h"
#include "filesystem/filesystem.h"
#include "lib/math.h"
#include <stdio.h>
#include <ctype.h>
typedef vec_t(ModelMaterial) vec_material_t;
typedef struct {
int material;
int start;
int count;
} objGroup;
typedef vec_t(objGroup) vec_group_t;
#define STARTS_WITH(a, b) !strncmp(a, b, strlen(b))
ModelData* lovrModelDataInitObj(ModelData* model, Blob* source, ModelDataIO io) {
static void parseMtl(char* path, vec_void_t* textures, vec_material_t* materials, map_int_t* names, char* base) {
size_t length = 0;
char* data = lovrFilesystemRead(path, &length);
lovrAssert(data && length > 0, "Unable to read mtl from '%s'", path);
char* s = data;
while (length > 0) {
int lineLength = 0;
if (STARTS_WITH(s, "newmtl ")) {
char name[128];
bool hasName = sscanf(s + 7, "%s\n%n", name, &lineLength);
lovrAssert(hasName, "Bad OBJ: Expected a material name");
map_set(names, name, materials->length);
vec_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 }
}));
memset(&vec_last(materials).textures, 0xff, MAX_MATERIAL_TEXTURES * sizeof(int));
} else if (STARTS_WITH(s, "Kd")) {
float r, g, b;
int count = sscanf(s + 2, "%f %f %f\n%n", &r, &g, &b, &lineLength);
lovrAssert(count == 3, "Bad OBJ: Expected 3 components for diffuse color");
ModelMaterial* material = &vec_last(materials);
material->colors[COLOR_DIFFUSE] = (Color) { r, g, b, 1.f };
} else if (STARTS_WITH(s, "map_Kd")) {
// Read file
char filename[128];
bool hasFilename = sscanf(s + 7, "%s\n%n", filename, &lineLength);
lovrAssert(hasFilename, "Bad OBJ: Expected a texture filename");
char path[1024];
snprintf(path, 1023, "%s/%s", base, filename);
size_t size = 0;
void* data = lovrFilesystemRead(path, &size);
lovrAssert(data && size > 0, "Unable to read texture from %s", path);
Blob* blob = lovrBlobCreate(data, size, NULL);
// Load texture, assign to material
TextureData* texture = lovrTextureDataCreateFromBlob(blob, true);
lovrAssert(materials->length > 0, "Tried to set a material property without declaring a material first");
ModelMaterial* material = &vec_last(materials);
material->textures[TEXTURE_DIFFUSE] = textures->length;
material->filters[TEXTURE_DIFFUSE].mode = FILTER_TRILINEAR;
material->wraps[TEXTURE_DIFFUSE] = (TextureWrap) { .s = WRAP_REPEAT, .t = WRAP_REPEAT };
vec_push(textures, texture);
lovrRelease(blob);
} else {
char* newline = memchr(s, '\n', length);
lineLength = newline - s + 1;
}
s += lineLength;
length -= lineLength;
while (length && isspace(*s)) length--, s++;
}
free(data);
}
ModelData* lovrModelDataInitObj(ModelData* model, Blob* source) {
char* data = (char*) source->data;
size_t length = source->size;
vec_float_t vertexBuffer;
vec_int_t indexBuffer;
vec_group_t groups;
vec_void_t textures;
vec_material_t materials;
map_int_t materialNames;
vec_float_t vertexBlob;
vec_int_t indexBlob;
map_int_t vertexMap;
vec_float_t vertices;
vec_float_t positions;
vec_float_t normals;
vec_float_t uvs;
vec_init(&vertexBuffer);
vec_init(&indexBuffer);
vec_init(&groups);
vec_init(&textures);
vec_init(&materials);
map_init(&materialNames);
vec_init(&vertexBlob);
vec_init(&indexBlob);
map_init(&vertexMap);
vec_init(&vertices);
vec_init(&positions);
vec_init(&normals);
vec_init(&uvs);
vec_push(&groups, ((objGroup) { .material = -1 }));
char base[1024];
strncpy(base, source->name, 1023);
char* slash = strrchr(base, '/');
if (slash) *slash = 0;
while (length > 0) {
int lineLength = 0;
@ -29,7 +118,7 @@ ModelData* lovrModelDataInitObj(ModelData* model, Blob* source, ModelDataIO io)
float x, y, z;
int count = sscanf(data + 2, "%f %f %f\n%n", &x, &y, &z, &lineLength);
lovrAssert(count == 3, "Bad OBJ: Expected 3 coordinates for vertex position");
vec_pusharr(&vertices, ((float[3]) { x, y, z }), 3);
vec_pusharr(&positions, ((float[3]) { x, y, z }), 3);
} else if (STARTS_WITH(data, "vn ")) {
float x, y, z;
int count = sscanf(data + 3, "%f %f %f\n%n", &x, &y, &z, &lineLength);
@ -49,25 +138,29 @@ ModelData* lovrModelDataInitObj(ModelData* model, Blob* source, ModelDataIO io)
*space = '\0'; // I'll be back
int* index = map_get(&vertexMap, s);
if (index) {
vec_push(&indexBuffer, *index);
vec_push(&indexBlob, *index);
} else {
int v, vt, vn;
int newIndex = vertexBuffer.length / 8;
vec_push(&indexBuffer, newIndex);
int newIndex = vertexBlob.length / 8;
vec_push(&indexBlob, newIndex);
map_set(&vertexMap, s, newIndex);
// Can be improved
if (sscanf(s, "%d/%d/%d", &v, &vt, &vn) == 3) {
vec_pusharr(&vertexBuffer, vertices.data + 3 * (v - 1), 3);
vec_pusharr(&vertexBuffer, normals.data + 3 * (vn - 1), 3);
vec_pusharr(&vertexBuffer, uvs.data + 2 * (vt - 1), 2);
vec_pusharr(&vertexBlob, positions.data + 3 * (v - 1), 3);
vec_pusharr(&vertexBlob, normals.data + 3 * (vn - 1), 3);
vec_pusharr(&vertexBlob, uvs.data + 2 * (vt - 1), 2);
} else if (sscanf(s, "%d//%d", &v, &vn) == 2) {
vec_pusharr(&vertexBuffer, vertices.data + 3 * (v - 1), 3);
vec_pusharr(&vertexBuffer, normals.data + 3 * (vn - 1), 3);
vec_pusharr(&vertexBuffer, ((float[2]) { 0 }), 2);
vec_pusharr(&vertexBlob, positions.data + 3 * (v - 1), 3);
vec_pusharr(&vertexBlob, normals.data + 3 * (vn - 1), 3);
vec_pusharr(&vertexBlob, ((float[2]) { 0 }), 2);
} else if (sscanf(s, "%d/%d", &v, &vt) == 2) {
vec_pusharr(&vertexBlob, positions.data + 3 * (v - 1), 3);
vec_pusharr(&vertexBlob, ((float[3]) { 0 }), 3);
vec_pusharr(&vertexBlob, uvs.data + 2 * (vt - 1), 2);
} else if (sscanf(s, "%d", &v) == 1) {
vec_pusharr(&vertexBuffer, vertices.data + 3 * (v - 1), 3);
vec_pusharr(&vertexBuffer, ((float[5]) { 0 }), 5);
vec_pusharr(&vertexBlob, positions.data + 3 * (v - 1), 3);
vec_pusharr(&vertexBlob, ((float[5]) { 0 }), 5);
} else {
lovrThrow("Bad OBJ: Unknown face format");
}
@ -76,7 +169,33 @@ ModelData* lovrModelDataInitObj(ModelData* model, Blob* source, ModelDataIO io)
s = space + 1;
}
}
vec_last(&groups).count += 3;
lineLength = s - data;
} else if (STARTS_WITH(data, "mtllib ")) {
char filename[1024];
bool hasName = sscanf(data + 7, "%1024s\n%n", filename, &lineLength);
lovrAssert(hasName, "Bad OBJ: Expected filename after mtllib");
char path[1024];
snprintf(path, 1023, "%s/%s", base, filename);
parseMtl(path, &textures, &materials, &materialNames, base);
} else if (STARTS_WITH(data, "usemtl ")) {
char name[128];
bool hasName = sscanf(data + 7, "%s\n%n", name, &lineLength);
int* material = map_get(&materialNames, name);
lovrAssert(hasName && material, "Bad OBJ: Expected a material name");
// If the last group didn't have any faces, just reuse it, otherwise make a new group
objGroup* group = &vec_last(&groups);
if (group->count > 0) {
int start = group->start + group->count; // Don't put this in the compound literal (realloc)
vec_push(&groups, ((objGroup) {
.material = *material,
.start = start,
.count = 0
}));
} else {
group->material = *material;
}
} else {
char* newline = memchr(data, '\n', length);
lineLength = newline - data + 1;
@ -84,17 +203,20 @@ ModelData* lovrModelDataInitObj(ModelData* model, Blob* source, ModelDataIO io)
data += lineLength;
length -= lineLength;
while (length && isspace(*data)) length--, data++;
}
model->blobCount = 2;
model->bufferCount = 2;
model->attributeCount = 4;
model->primitiveCount = 1;
model->attributeCount = 3 + groups.length;
model->primitiveCount = groups.length;
model->nodeCount = 1;
model->textureCount = textures.length;
model->materialCount = materials.length;
lovrModelDataAllocate(model);
model->blobs[0] = lovrBlobCreate(vertexBuffer.data, vertexBuffer.length * sizeof(float), "obj vertex data");
model->blobs[1] = lovrBlobCreate(indexBuffer.data, indexBuffer.length * sizeof(int), "obj index data");
model->blobs[0] = lovrBlobCreate(vertexBlob.data, vertexBlob.length * sizeof(float), "obj vertex data");
model->blobs[1] = lovrBlobCreate(indexBlob.data, indexBlob.length * sizeof(int), "obj index data");
model->buffers[0] = (ModelBuffer) {
.data = model->blobs[0]->data,
@ -108,10 +230,13 @@ ModelData* lovrModelDataInitObj(ModelData* model, Blob* source, ModelDataIO io)
.stride = sizeof(int)
};
memcpy(model->textures, textures.data, model->textureCount * sizeof(TextureData*));
memcpy(model->materials, materials.data, model->materialCount * sizeof(ModelMaterial));
model->attributes[0] = (ModelAttribute) {
.buffer = 0,
.offset = 0,
.count = vertexBuffer.length / 8,
.count = vertexBlob.length / 8,
.type = F32,
.components = 3
};
@ -119,7 +244,7 @@ ModelData* lovrModelDataInitObj(ModelData* model, Blob* source, ModelDataIO io)
model->attributes[1] = (ModelAttribute) {
.buffer = 0,
.offset = 3 * sizeof(float),
.count = vertexBuffer.length / 8,
.count = vertexBlob.length / 8,
.type = F32,
.components = 3
};
@ -127,38 +252,48 @@ ModelData* lovrModelDataInitObj(ModelData* model, Blob* source, ModelDataIO io)
model->attributes[2] = (ModelAttribute) {
.buffer = 0,
.offset = 6 * sizeof(float),
.count = vertexBuffer.length / 8,
.count = vertexBlob.length / 8,
.type = F32,
.components = 2
};
model->attributes[3] = (ModelAttribute) {
.buffer = 1,
.offset = 0,
.count = indexBuffer.length,
.type = U32,
.components = 1
};
for (int i = 0; i < groups.length; i++) {
objGroup* group = &groups.data[i];
model->attributes[3 + i] = (ModelAttribute) {
.buffer = 1,
.offset = group->start * sizeof(int),
.count = group->count,
.type = U32,
.components = 1
};
}
model->primitives[0] = (ModelPrimitive) {
.mode = DRAW_TRIANGLES,
.attributes = {
[ATTR_POSITION] = &model->attributes[0],
[ATTR_NORMAL] = &model->attributes[1],
[ATTR_TEXCOORD] = &model->attributes[2]
},
.indices = &model->attributes[3],
.material = -1
};
for (int i = 0; i < groups.length; i++) {
objGroup* group = &groups.data[i];
model->primitives[i] = (ModelPrimitive) {
.mode = DRAW_TRIANGLES,
.attributes = {
[ATTR_POSITION] = &model->attributes[0],
[ATTR_NORMAL] = &model->attributes[1],
[ATTR_TEXCOORD] = &model->attributes[2]
},
.indices = &model->attributes[3 + i],
.material = group->material
};
}
model->nodes[0] = (ModelNode) {
.transform = MAT4_IDENTITY,
.primitiveIndex = 0,
.primitiveCount = 1
.primitiveCount = groups.length
};
vec_deinit(&groups);
vec_deinit(&textures);
vec_deinit(&materials);
map_deinit(&materialNames);
map_deinit(&vertexMap);
vec_deinit(&vertices);
vec_deinit(&positions);
vec_deinit(&normals);
vec_deinit(&uvs);
return model;

View File

@ -137,7 +137,7 @@ Model* lovrModelInit(Model* model, ModelData* data) {
if (data->materialCount > 0) {
model->materials = malloc(data->materialCount * sizeof(Material*));
if (data->imageCount > 0) {
if (data->textureCount > 0) {
model->textures = calloc(data->textureCount, sizeof(Texture*));
}
@ -157,12 +157,11 @@ Model* lovrModelInit(Model* model, ModelData* data) {
if (index != -1) {
if (!model->textures[index]) {
ModelTexture* texture = &data->textures[index];
TextureData* image = data->images[texture->imageIndex];
TextureData* textureData = data->textures[index];
bool srgb = j == TEXTURE_DIFFUSE || j == TEXTURE_EMISSIVE;
model->textures[index] = lovrTextureCreate(TEXTURE_2D, &image, 1, srgb, true, 0);
lovrTextureSetFilter(model->textures[index], texture->filter);
lovrTextureSetWrap(model->textures[index], texture->wrap);
model->textures[index] = lovrTextureCreate(TEXTURE_2D, &textureData, 1, srgb, true, 0);
lovrTextureSetFilter(model->textures[index], data->materials[i].filters[j]);
lovrTextureSetWrap(model->textures[index], data->materials[i].wraps[j]);
}
lovrMaterialSetTexture(material, j, model->textures[index]);

View File

@ -405,7 +405,6 @@ static ModelData* openvrControllerNewModelData(Controller* controller) {
model->bufferCount = 2;
model->attributeCount = 4;
model->imageCount = 1;
model->textureCount = 1;
model->materialCount = 1;
model->primitiveCount = 1;
@ -457,17 +456,13 @@ static ModelData* openvrControllerNewModelData(Controller* controller) {
};
RenderModel_TextureMap_t* vrTexture = state.deviceTextures[id];
model->images[0] = lovrTextureDataCreate(vrTexture->unWidth, vrTexture->unHeight, 0, FORMAT_RGBA);
memcpy(model->images[0]->blob.data, vrTexture->rubTextureMapData, vrTexture->unWidth * vrTexture->unHeight * 4);
model->textures[0] = (ModelTexture) {
.imageIndex = 0,
.filter = lovrGraphicsGetDefaultFilter()
};
model->textures[0] = lovrTextureDataCreate(vrTexture->unWidth, vrTexture->unHeight, 0, FORMAT_RGBA);
memcpy(model->textures[0]->blob.data, vrTexture->rubTextureMapData, vrTexture->unWidth * vrTexture->unHeight * 4);
model->materials[0] = (ModelMaterial) {
.colors[COLOR_DIFFUSE] = { 1.f, 1.f, 1.f, 1.f },
.textures[TEXTURE_DIFFUSE] = 0
.textures[TEXTURE_DIFFUSE] = 0,
.filters[TEXTURE_DIFFUSE] = lovrGraphicsGetDefaultFilter()
};
model->primitives[0] = (ModelPrimitive) {