#ifdef __cplusplus extern "C" { #endif #include //I fucking hate c++ typedef struct ftedracofuncs_s { void (*Release)(struct ftedracofuncs_s *ctx); //frees all memory struct ftedracoattr_s { void *ptr; int isnormalised; unsigned int type; //gl constants, because why not unsigned int components; //1-4 unsigned int bytestride; unsigned int usage; //typical usage type. unsigned int uniqueid; //annoying extra lookup. } *attrib; unsigned int num_attribs; //mesh data char triangleloop; unsigned int num_indexes; unsigned int *ptr_indexes, num_vertexes; } ftedracofuncs_t; ftedracofuncs_t *Draco_Decode(void *ptr, size_t size); #ifdef __cplusplus }; #endif #if !defined(DRACO_API_ONLY) && defined(HAVE_DRACO) #include struct dracofuncs_t : public ftedracofuncs_s { draco::Decoder decoder; draco::DecoderBuffer buffer; draco::Mesh mesh; static void DoRelease(ftedracofuncs_s *ctx) { auto d = reinterpret_cast(ctx); delete[] d->ptr_indexes; for (auto i = d->num_attribs; i --> 0; ) delete[] (char*)d->attrib[i].ptr; delete[] d->attrib; delete d; //do all the third-party destructor stuff too. } dracofuncs_t() { Release = DoRelease; } }; template static void CopyAttribute(unsigned int numpoints, draco::PointAttribute *attr, ftedracofuncs_s::ftedracoattr_s *oattr) { auto nc = oattr->components; auto *out = new attrtype[numpoints*nc]; for (size_t i = 0; i < numpoints; i++) attr->GetMappedValue(draco::PointIndex(i), &out[i*nc]); oattr->bytestride = sizeof(attrtype)*nc; //the output data is tightly packed. oattr->ptr = out; oattr->type = gltype; }; ftedracofuncs_t *Draco_Decode(void *ptr, size_t size) { size_t tris; dracofuncs_t *d = new dracofuncs_t(); d->buffer.Init((const char *)ptr, size); if (!d->decoder.DecodeBufferToGeometry(&d->buffer, &d->mesh).ok()) { //check for corruption... delete d; return NULL; } tris = d->mesh.num_faces(); d->num_indexes = tris*3; d->ptr_indexes = new unsigned int[d->num_indexes]; while (tris --> 0) { auto &tri = d->mesh.face(draco::FaceIndex(tris)); d->ptr_indexes[tris*3+0] = tri[0].value(); d->ptr_indexes[tris*3+1] = tri[1].value(); d->ptr_indexes[tris*3+2] = tri[2].value(); } d->num_vertexes = d->mesh.num_points(); d->num_attribs = d->mesh.num_attributes(); d->attrib = new struct ftedracofuncs_s::ftedracoattr_s[d->num_attribs]; for (unsigned int i = 0; i < d->num_attribs; i++) { draco::PointAttribute *attr = d->mesh.attribute(i); auto oattr = &d->attrib[i]; oattr->isnormalised = attr->normalized(); oattr->bytestride = attr->byte_stride(); oattr->components = attr->num_components(); oattr->usage = attr->attribute_type(); oattr->uniqueid = attr->unique_id(); #define GL_BYTE 0x1400 #define GL_UNSIGNED_BYTE 0x1401 #define GL_SHORT 0x1402 #define GL_UNSIGNED_SHORT 0x1403 #define GL_INT 0x1404 #define GL_UNSIGNED_INT 0x1405 #define GL_FLOAT 0x1406 #define GL_DOUBLE 0x140A #define GL_INT64_ARB 0x140E #define GL_UNSIGNED_INT64_ARB 0x140F switch(attr->data_type()) { default: memset(oattr, 0, sizeof(*oattr)); break; case draco::DataType::DT_INT8: CopyAttribute< int8_t, GL_BYTE >(d->num_vertexes, attr, oattr); break; case draco::DataType::DT_UINT8: CopyAttribute(d->num_vertexes, attr, oattr); break; case draco::DataType::DT_INT16: CopyAttribute< int16_t, GL_SHORT >(d->num_vertexes, attr, oattr); break; case draco::DataType::DT_UINT16: CopyAttribute(d->num_vertexes, attr, oattr); break; case draco::DataType::DT_INT32: CopyAttribute< int32_t, GL_INT >(d->num_vertexes, attr, oattr); break; case draco::DataType::DT_UINT32: CopyAttribute(d->num_vertexes, attr, oattr); break; case draco::DataType::DT_INT64: CopyAttribute< int64_t, GL_INT64_ARB >(d->num_vertexes, attr, oattr); break; case draco::DataType::DT_UINT64: CopyAttribute(d->num_vertexes, attr, oattr); break; case draco::DataType::DT_FLOAT32: CopyAttribute(d->num_vertexes, attr, oattr); break; case draco::DataType::DT_FLOAT64: CopyAttribute(d->num_vertexes, attr, oattr); break; } } return d; } #endif