221 lines
5.5 KiB
C++
221 lines
5.5 KiB
C++
#include <string>
|
|
#include <fstream>
|
|
#include <streambuf>
|
|
#include <sstream>
|
|
#include <QVector3D>
|
|
#include <QString>
|
|
#include <QCoreApplication>
|
|
#include "dust3d.h"
|
|
#include "meshgenerator.h"
|
|
#include "snapshot.h"
|
|
#include "snapshotxml.h"
|
|
#include "model.h"
|
|
#include "version.h"
|
|
|
|
struct _dust3d
|
|
{
|
|
void *userData = nullptr;
|
|
GeneratedCacheContext *cacheContext = nullptr;
|
|
Model *resultMesh = nullptr;
|
|
Snapshot *snapshot = nullptr;
|
|
Object *object = nullptr;
|
|
int error = DUST3D_ERROR;
|
|
};
|
|
|
|
DUST3D_DLL int DUST3D_API dust3dError(dust3d *ds3)
|
|
{
|
|
return ds3->error;
|
|
}
|
|
|
|
DUST3D_DLL void DUST3D_API dust3dClose(dust3d *ds3)
|
|
{
|
|
delete ds3->resultMesh;
|
|
ds3->resultMesh = nullptr;
|
|
|
|
delete ds3->cacheContext;
|
|
ds3->cacheContext = nullptr;
|
|
|
|
delete ds3->snapshot;
|
|
ds3->snapshot = nullptr;
|
|
|
|
delete ds3->object;
|
|
ds3->object = nullptr;
|
|
|
|
delete ds3;
|
|
}
|
|
|
|
DUST3D_DLL void DUST3D_API dust3dInitialize(int argc, char *argv[])
|
|
{
|
|
if (nullptr == QCoreApplication::instance())
|
|
new QCoreApplication(argc, argv);
|
|
}
|
|
|
|
DUST3D_DLL dust3d * DUST3D_API dust3dOpenFromMemory(const char *documentType, const char *buffer, int size)
|
|
{
|
|
dust3d *ds3 = new dust3d;
|
|
|
|
ds3->error = DUST3D_ERROR;
|
|
|
|
delete ds3->object;
|
|
ds3->object = new Object;
|
|
|
|
if (0 == strcmp(documentType, "xml")) {
|
|
QByteArray data(buffer, size);
|
|
|
|
QXmlStreamReader stream(data);
|
|
|
|
delete ds3->snapshot;
|
|
ds3->snapshot = new Snapshot;
|
|
|
|
loadSkeletonFromXmlStream(ds3->snapshot, stream);
|
|
|
|
ds3->error = DUST3D_OK;
|
|
} else {
|
|
ds3->error = DUST3D_UNSUPPORTED;
|
|
}
|
|
|
|
return ds3;
|
|
}
|
|
|
|
DUST3D_DLL dust3d * DUST3D_API dust3dOpen(const char *fileName)
|
|
{
|
|
std::string name = fileName;
|
|
auto dotIndex = name.rfind('.');
|
|
if (std::string::npos == dotIndex)
|
|
return nullptr;
|
|
|
|
std::string extension = name.substr(dotIndex + 1);
|
|
|
|
std::ifstream is(name, std::ifstream::binary);
|
|
if (!is)
|
|
return nullptr;
|
|
|
|
is.seekg (0, is.end);
|
|
int length = is.tellg();
|
|
is.seekg (0, is.beg);
|
|
|
|
char *buffer = new char[length + 1];
|
|
is.read(buffer, length);
|
|
is.close();
|
|
buffer[length] = '\0';
|
|
|
|
dust3d *ds3 = dust3dOpenFromMemory(extension.c_str(), buffer, length);
|
|
|
|
delete[] buffer;
|
|
|
|
return ds3;
|
|
}
|
|
|
|
DUST3D_DLL void DUST3D_API dust3dSetUserData(dust3d *ds3, void *userData)
|
|
{
|
|
ds3->userData = userData;
|
|
}
|
|
|
|
DUST3D_DLL void * DUST3D_API dust3dGetUserData(dust3d *ds3)
|
|
{
|
|
return ds3->userData;
|
|
}
|
|
|
|
DUST3D_DLL const char * DUST3D_API dust3dVersion()
|
|
{
|
|
return APP_NAME " " APP_HUMAN_VER;
|
|
}
|
|
|
|
DUST3D_DLL int DUST3D_API dust3dGenerateMesh(dust3d *ds3)
|
|
{
|
|
ds3->error = DUST3D_ERROR;
|
|
|
|
if (nullptr == ds3->snapshot)
|
|
return ds3->error;
|
|
|
|
if (nullptr == ds3->cacheContext)
|
|
ds3->cacheContext = new GeneratedCacheContext();
|
|
|
|
Snapshot *snapshot = ds3->snapshot;
|
|
ds3->snapshot = nullptr;
|
|
|
|
MeshGenerator *meshGenerator = new MeshGenerator(snapshot);
|
|
meshGenerator->setGeneratedCacheContext(ds3->cacheContext);
|
|
meshGenerator->generate();
|
|
|
|
delete ds3->object;
|
|
ds3->object = meshGenerator->takeObject();
|
|
if (nullptr == ds3->object)
|
|
ds3->object = new Object;
|
|
|
|
if (meshGenerator->isSuccessful())
|
|
ds3->error = DUST3D_OK;
|
|
|
|
delete meshGenerator;
|
|
|
|
return ds3->error;
|
|
}
|
|
|
|
DUST3D_DLL int DUST3D_API dust3dGetMeshVertexCount(dust3d *ds3)
|
|
{
|
|
return (int)ds3->object->vertices.size();
|
|
}
|
|
|
|
DUST3D_DLL int DUST3D_API dust3dGetMeshTriangleCount(dust3d *ds3)
|
|
{
|
|
return (int)ds3->object->triangles.size();
|
|
}
|
|
|
|
DUST3D_DLL void DUST3D_API dust3dGetMeshTriangleIndices(dust3d *ds3, int *indices)
|
|
{
|
|
for (const auto &it: ds3->object->triangles) {
|
|
*(indices++) = (int)it[0];
|
|
*(indices++) = (int)it[1];
|
|
*(indices++) = (int)it[2];
|
|
}
|
|
}
|
|
|
|
DUST3D_DLL void DUST3D_API dust3dGetMeshTriangleColors(dust3d *ds3, unsigned int *colors)
|
|
{
|
|
for (const auto &it: ds3->object->triangleColors) {
|
|
*(colors++) = ((unsigned int)it.red() << 16) | ((unsigned int)it.green() << 8) | ((unsigned int)it.blue() << 0);
|
|
}
|
|
}
|
|
|
|
DUST3D_DLL void DUST3D_API dust3dGetMeshVertexPosition(dust3d *ds3, int vertexIndex, float *x, float *y, float *z)
|
|
{
|
|
if (vertexIndex >= 0 && vertexIndex < ds3->object->vertices.size()) {
|
|
const auto &v = ds3->object->vertices[vertexIndex];
|
|
*x = v.x();
|
|
*y = v.y();
|
|
*z = v.z();
|
|
}
|
|
}
|
|
|
|
DUST3D_DLL void DUST3D_API dust3dGetMeshVertexSource(dust3d *ds3, int vertexIndex, unsigned char partId[16], unsigned char nodeId[16])
|
|
{
|
|
if (vertexIndex >= 0 && vertexIndex < ds3->object->vertices.size()) {
|
|
const auto &source = ds3->object->vertexSourceNodes[vertexIndex];
|
|
|
|
auto sourcePartUuid = source.first.toByteArray(QUuid::Id128);
|
|
memcpy(partId, sourcePartUuid.constData(), sizeof(partId));
|
|
|
|
auto sourceNodeUuid = source.second.toByteArray(QUuid::Id128);
|
|
memcpy(partId, sourceNodeUuid.constData(), sizeof(nodeId));
|
|
}
|
|
}
|
|
|
|
DUST3D_DLL int DUST3D_API dust3dGetMeshTriangleAndQuadCount(dust3d *ds3)
|
|
{
|
|
return (int)ds3->object->triangleAndQuads.size();
|
|
}
|
|
|
|
DUST3D_DLL void DUST3D_API dust3dGetMeshTriangleAndQuadIndices(dust3d *ds3, int *indices)
|
|
{
|
|
for (const auto &it: ds3->object->triangleAndQuads) {
|
|
*(indices++) = (int)it[0];
|
|
*(indices++) = (int)it[1];
|
|
*(indices++) = (int)it[2];
|
|
if (it.size() > 3)
|
|
*(indices++) = (int)it[3];
|
|
else
|
|
*(indices++) = (int)-1;
|
|
}
|
|
}
|
|
|