mirror of https://github.com/bjornbytes/lovr.git
Support STL models;
Only binary STL files are supported right now, ASCII is more challenging.
This commit is contained in:
parent
a430ae06b8
commit
72a54bce2f
|
@ -12,6 +12,8 @@ ModelData* lovrModelDataCreate(Blob* source, ModelDataIO* io) {
|
||||||
return model;
|
return model;
|
||||||
} else if (lovrModelDataInitObj(model, source, io)) {
|
} else if (lovrModelDataInitObj(model, source, io)) {
|
||||||
return model;
|
return model;
|
||||||
|
} else if (lovrModelDataInitStl(model, source, io)) {
|
||||||
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
lovrThrow("Unable to load model from '%s'", source->name);
|
lovrThrow("Unable to load model from '%s'", source->name);
|
||||||
|
|
|
@ -221,5 +221,6 @@ typedef void* ModelDataIO(const char* filename, size_t* bytesRead);
|
||||||
ModelData* lovrModelDataCreate(struct Blob* blob, ModelDataIO* io);
|
ModelData* lovrModelDataCreate(struct Blob* blob, ModelDataIO* io);
|
||||||
ModelData* lovrModelDataInitGltf(ModelData* model, struct Blob* blob, ModelDataIO* io);
|
ModelData* lovrModelDataInitGltf(ModelData* model, struct Blob* blob, ModelDataIO* io);
|
||||||
ModelData* lovrModelDataInitObj(ModelData* model, struct Blob* blob, ModelDataIO* io);
|
ModelData* lovrModelDataInitObj(ModelData* model, struct Blob* blob, ModelDataIO* io);
|
||||||
|
ModelData* lovrModelDataInitStl(ModelData* model, struct Blob* blob, ModelDataIO* io);
|
||||||
void lovrModelDataDestroy(void* ref);
|
void lovrModelDataDestroy(void* ref);
|
||||||
void lovrModelDataAllocate(ModelData* model);
|
void lovrModelDataAllocate(ModelData* model);
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
#include "data/modelData.h"
|
||||||
|
#include "data/blob.h"
|
||||||
|
#include "core/maf.h"
|
||||||
|
#include "core/util.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static ModelData* lovrModelDataInitStlAscii(ModelData* model, Blob* source, ModelDataIO* io) {
|
||||||
|
lovrThrow("ASCII STL files are not supported yet");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The binary format has an 80 byte header, followed by a u32 triangle count, followed by 50 byte
|
||||||
|
// triangles. Each triangle has a vec3 normal, 3 vec3 vertices, and 2 bytes of padding.
|
||||||
|
extern ModelData* lovrModelDataInitStlBinary(ModelData* model, Blob* source, ModelDataIO* io, uint32_t triangleCount) {
|
||||||
|
char* data = (char*) source->data + 84;
|
||||||
|
|
||||||
|
uint32_t vertexCount = triangleCount * 3;
|
||||||
|
size_t vertexBufferSize = vertexCount * 6 * sizeof(float);
|
||||||
|
float* vertices = malloc(vertexBufferSize);
|
||||||
|
lovrAssert(vertices, "Out of memory");
|
||||||
|
|
||||||
|
model->blobCount = 1;
|
||||||
|
model->bufferCount = 1;
|
||||||
|
model->attributeCount = 2;
|
||||||
|
model->primitiveCount = 1;
|
||||||
|
model->nodeCount = 1;
|
||||||
|
|
||||||
|
lovrModelDataAllocate(model);
|
||||||
|
|
||||||
|
model->blobs[0] = lovrBlobCreate(vertices, vertexBufferSize, "stl vertex data");
|
||||||
|
model->buffers[0] = (ModelBuffer) { .data = (char*) vertices, .size = vertexBufferSize, .stride = 6 * sizeof(float) };
|
||||||
|
model->attributes[0] = (ModelAttribute) { .count = vertexCount, .components = 3, .type = F32, .offset = 0 * sizeof(float) };
|
||||||
|
model->attributes[1] = (ModelAttribute) { .count = vertexCount, .components = 3, .type = F32, .offset = 3 * sizeof(float) };
|
||||||
|
model->primitives[0] = (ModelPrimitive) {
|
||||||
|
.mode = DRAW_TRIANGLES,
|
||||||
|
.material = ~0u,
|
||||||
|
.attributes = {
|
||||||
|
[ATTR_POSITION] = &model->attributes[0],
|
||||||
|
[ATTR_NORMAL] = &model->attributes[1]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
model->nodes[0] = (ModelNode) {
|
||||||
|
.matrix = true,
|
||||||
|
.transform.matrix = MAT4_IDENTITY,
|
||||||
|
.primitiveCount = 1,
|
||||||
|
.skin = ~0u
|
||||||
|
};
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < triangleCount; i++) {
|
||||||
|
memcpy(vertices + 3, data, 12);
|
||||||
|
memcpy(vertices + 9, data, 12);
|
||||||
|
memcpy(vertices + 15, data, 12), data += 12;
|
||||||
|
memcpy(vertices + 0, data, 12), data += 12;
|
||||||
|
memcpy(vertices + 6, data, 12), data += 12;
|
||||||
|
memcpy(vertices + 12, data, 12), data += 12;
|
||||||
|
vertices += 18;
|
||||||
|
data += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelData* lovrModelDataInitStl(ModelData* model, Blob* source, ModelDataIO* io) {
|
||||||
|
if (source->size > strlen("solid ") && !memcmp(source->data, "solid ", strlen("solid "))) {
|
||||||
|
return lovrModelDataInitStlAscii(model, source, io);
|
||||||
|
} else if (source->size > 84) {
|
||||||
|
uint32_t triangleCount;
|
||||||
|
memcpy(&triangleCount, (char*) source->data + 80, sizeof(triangleCount));
|
||||||
|
if (source->size == 84 + 50 * triangleCount) {
|
||||||
|
return lovrModelDataInitStlBinary(model, source, io, triangleCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -130,7 +130,8 @@ Model* lovrModelCreate(ModelData* data) {
|
||||||
model->meshes = calloc(data->primitiveCount, sizeof(Mesh*));
|
model->meshes = calloc(data->primitiveCount, sizeof(Mesh*));
|
||||||
for (uint32_t i = 0; i < data->primitiveCount; i++) {
|
for (uint32_t i = 0; i < data->primitiveCount; i++) {
|
||||||
ModelPrimitive* primitive = &data->primitives[i];
|
ModelPrimitive* primitive = &data->primitives[i];
|
||||||
model->meshes[i] = lovrMeshCreate(primitive->mode, NULL, 0);
|
uint32_t vertexCount = primitive->attributes[ATTR_POSITION] ? primitive->attributes[ATTR_POSITION]->count : 0;
|
||||||
|
model->meshes[i] = lovrMeshCreate(primitive->mode, NULL, vertexCount);
|
||||||
|
|
||||||
if (primitive->material != ~0u) {
|
if (primitive->material != ~0u) {
|
||||||
lovrMeshSetMaterial(model->meshes[i], model->materials[primitive->material]);
|
lovrMeshSetMaterial(model->meshes[i], model->materials[primitive->material]);
|
||||||
|
|
Loading…
Reference in New Issue