parent
b3c20f5956
commit
c337565b28
Binary file not shown.
|
@ -9,6 +9,7 @@ set(SRCS
|
|||
VoxFormat.h VoxFormat.cpp
|
||||
QBTFormat.h QBTFormat.cpp
|
||||
QBFormat.h QBFormat.cpp
|
||||
QBCLFormat.h QBCLFormat.cpp
|
||||
QEFFormat.h QEFFormat.cpp
|
||||
MCRFormat.h MCRFormat.cpp
|
||||
VXMFormat.h VXMFormat.cpp
|
||||
|
@ -31,6 +32,7 @@ set(TEST_SRCS
|
|||
tests/VoxFormatTest.cpp
|
||||
tests/QBTFormatTest.cpp
|
||||
tests/QBFormatTest.cpp
|
||||
tests/QBCLFormatTest.cpp
|
||||
tests/QEFFormatTest.cpp
|
||||
tests/CubFormatTest.cpp
|
||||
tests/CSMFormatTest.cpp
|
||||
|
@ -44,6 +46,7 @@ set(TEST_FILES
|
|||
tests/qubicle.qb
|
||||
tests/qubicle.qbt
|
||||
tests/qubicle.qef
|
||||
tests/qubicle.qbcl
|
||||
tests/testload.qef
|
||||
tests/aceofspades.vxl
|
||||
tests/chronovox-studio.csm
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
/**
|
||||
* @file
|
||||
*/
|
||||
|
||||
#include "QBCLFormat.h"
|
||||
#include "core/ArrayLength.h"
|
||||
#include "core/Enum.h"
|
||||
#include "core/FourCC.h"
|
||||
#include "core/Zip.h"
|
||||
#include "core/Color.h"
|
||||
#include "core/Assert.h"
|
||||
#include "core/Log.h"
|
||||
|
||||
namespace voxel {
|
||||
|
||||
#define wrap(read) \
|
||||
if ((read) != 0) { \
|
||||
Log::error("Could not load qbcl file: Not enough data in stream " CORE_STRINGIFY(read) " - still %i bytes left", (int)stream.remaining()); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define wrapBool(read) \
|
||||
if ((read) == false) { \
|
||||
Log::error("Could not load qbcl file: Not enough data in stream " CORE_STRINGIFY(read) " - still %i bytes left", (int)stream.remaining()); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
bool QBCLFormat::saveGroups(const VoxelVolumes& volumes, const io::FilePtr& file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static bool readString(io::FileStream &stream, core::String &dest) {
|
||||
uint32_t size;
|
||||
wrap(stream.readInt(size))
|
||||
if (size > 1024) {
|
||||
Log::warn("Found big string - ignore it");
|
||||
stream.skip(size);
|
||||
return false;
|
||||
}
|
||||
dest.reserve(size);
|
||||
for (uint32_t i = 0; i < size; ++i) {
|
||||
uint8_t chr;
|
||||
wrap(stream.readByte(chr))
|
||||
dest.append(chr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool QBCLFormat::readMatrix(io::FileStream &stream) {
|
||||
uint32_t mx; // 32
|
||||
uint32_t my;
|
||||
uint32_t mz;
|
||||
wrap(stream.readInt(mx))
|
||||
wrap(stream.readInt(my))
|
||||
wrap(stream.readInt(mz))
|
||||
Log::debug("QBCL: matrix size %u:%u:%u", mx, my, mz);
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QBCLFormat::readModel(io::FileStream &stream) {
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
uint32_t z;
|
||||
|
||||
wrap(stream.readInt(x))
|
||||
wrap(stream.readInt(y))
|
||||
wrap(stream.readInt(z))
|
||||
Log::debug("QBCL: model size %u:%u:%u", x, y, z);
|
||||
|
||||
uint32_t r[6];
|
||||
for (int i = 0; i < lengthof(r); ++i) {
|
||||
wrap(stream.readInt(r[i]))
|
||||
Log::debug("QBCL: r[%i] = %u", i, r[i]);
|
||||
}
|
||||
uint32_t n;
|
||||
uint32_t u;
|
||||
uint32_t v;
|
||||
|
||||
wrap(stream.readInt(n))
|
||||
wrap(stream.readInt(u))
|
||||
wrap(stream.readInt(v))
|
||||
Log::debug("QBCL: n: %u, u: %u, v: %u", n, u, v);
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QBCLFormat::readCompound(io::FileStream &stream) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QBCLFormat::loadGroups(const io::FilePtr& file, VoxelVolumes& volumes) {
|
||||
if (!(bool)file || !file->exists()) {
|
||||
Log::error("Could not load qb file: File doesn't exist");
|
||||
return false;
|
||||
}
|
||||
io::FileStream stream(file.get());
|
||||
uint32_t magic;
|
||||
wrap(stream.readInt(magic))
|
||||
if (magic != FourCC('Q', 'B', 'C', 'L')) {
|
||||
Log::error("Invalid magic found - no qbcl file");
|
||||
return false;
|
||||
}
|
||||
wrap(stream.readInt(_version))
|
||||
uint32_t flags;
|
||||
wrap(stream.readInt(flags))
|
||||
uint32_t thumbWidth;
|
||||
wrap(stream.readInt(thumbWidth))
|
||||
uint32_t thumbHeight;
|
||||
wrap(stream.readInt(thumbHeight))
|
||||
wrapBool(stream.skip(thumbWidth * thumbHeight * 4))
|
||||
|
||||
#if 0
|
||||
core::String title;
|
||||
wrapBool(readString(stream, title))
|
||||
core::String desc;
|
||||
wrapBool(readString(stream, desc))
|
||||
core::String metadata;
|
||||
wrapBool(readString(stream, metadata))
|
||||
core::String author;
|
||||
wrapBool(readString(stream, author))
|
||||
core::String company;
|
||||
wrapBool(readString(stream, company))
|
||||
core::String website;
|
||||
wrapBool(readString(stream, website))
|
||||
core::String copyright;
|
||||
wrapBool(readString(stream, copyright))
|
||||
uint8_t guid[16];
|
||||
wrap(stream.readBuf(guid, lengthof(guid)))
|
||||
|
||||
uint32_t unknown;
|
||||
stream.readInt(unknown);
|
||||
Log::debug("QBCL: unknown value %u at offset %u", unknown, (uint32_t)stream.pos());
|
||||
stream.readInt(unknown);
|
||||
Log::debug("QBCL: unknown value %u at offset %u", unknown, (uint32_t)stream.pos());
|
||||
|
||||
while (stream.remaining() > 0) {
|
||||
core::String type;
|
||||
wrapBool(readString(stream, type))
|
||||
uint8_t unknownByte;
|
||||
wrap(stream.readByte(unknownByte))
|
||||
Log::debug("QBCL: unknown value %u at offset %u", unknownByte, (uint32_t)stream.pos());
|
||||
wrap(stream.readByte(unknownByte))
|
||||
Log::debug("QBCL: unknown value %u at offset %u", unknownByte, (uint32_t)stream.pos());
|
||||
wrap(stream.readByte(unknownByte))
|
||||
Log::debug("QBCL: unknown value %u at offset %u", unknownByte, (uint32_t)stream.pos());
|
||||
if (type == "Model") {
|
||||
wrapBool(readModel(stream))
|
||||
} else if (type == "Matrix") {
|
||||
wrapBool(readMatrix(stream))
|
||||
} else if (type == "Compound") {
|
||||
wrapBool(readCompound(stream))
|
||||
} else {
|
||||
Log::warn("Unknown type found: '%s'", type.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#undef wrap
|
||||
#undef wrapBool
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* @file
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "VoxFileFormat.h"
|
||||
#include "io/FileStream.h"
|
||||
|
||||
namespace voxel {
|
||||
|
||||
/**
|
||||
* @brief Qubicle project file (qbcl) format.
|
||||
*
|
||||
* Not yet implemented
|
||||
*/
|
||||
class QBCLFormat : public VoxFileFormat {
|
||||
private:
|
||||
uint32_t _version;
|
||||
|
||||
bool readMatrix(io::FileStream &stream);
|
||||
bool readModel(io::FileStream &stream);
|
||||
bool readCompound(io::FileStream &stream);
|
||||
public:
|
||||
bool loadGroups(const io::FilePtr& file, VoxelVolumes& volumes) override;
|
||||
bool saveGroups(const VoxelVolumes& volumes, const io::FilePtr& file) override;
|
||||
};
|
||||
|
||||
}
|
|
@ -11,6 +11,7 @@
|
|||
#include "voxelformat/VoxFormat.h"
|
||||
#include "voxelformat/QBTFormat.h"
|
||||
#include "voxelformat/QBFormat.h"
|
||||
#include "voxelformat/QBCLFormat.h"
|
||||
#include "voxelformat/QEFFormat.h"
|
||||
#include "voxelformat/VXMFormat.h"
|
||||
#include "voxelformat/VXRFormat.h"
|
||||
|
@ -28,8 +29,9 @@ namespace voxelformat {
|
|||
// this is the list of supported voxel volume formats that are have importers implemented
|
||||
const io::FormatDescription SUPPORTED_VOXEL_FORMATS_LOAD[] = {
|
||||
{"MagicaVoxel", "vox"},
|
||||
{"Qubicle", "qbt"},
|
||||
{"Qubicle", "qb"},
|
||||
{"Qubicle Binary Tree", "qbt"},
|
||||
{"Qubicle Binary", "qb"},
|
||||
//{"Qubicle", "qbcl"},
|
||||
{"Sandbox VoxEdit", "vxm"},
|
||||
{"Sandbox VoxEdit", "vxr"},
|
||||
{"BinVox", "binvox"},
|
||||
|
@ -37,7 +39,7 @@ const io::FormatDescription SUPPORTED_VOXEL_FORMATS_LOAD[] = {
|
|||
{"Build engine", "kvx"},
|
||||
{"Ace of Spades", "kv6"},
|
||||
{"Tiberian Sun", "vxl"},
|
||||
{"Qubicle", "qef"},
|
||||
{"Qubicle Exchange", "qef"},
|
||||
{"Chronovox", "csm"},
|
||||
{"Nicks Voxel Model", "nvm"},
|
||||
{nullptr, nullptr}
|
||||
|
@ -47,14 +49,15 @@ const char *SUPPORTED_VOXEL_FORMATS_LOAD_LIST[] = { "qb", "vox", nullptr };
|
|||
// this is the list of supported voxel or mesh formats that have exporters implemented
|
||||
const io::FormatDescription SUPPORTED_VOXEL_FORMATS_SAVE[] = {
|
||||
{"MagicaVoxel", "vox"},
|
||||
{"Qubicle", "qbt"},
|
||||
{"Qubicle", "qb"},
|
||||
{"Qubicle Binary Tree", "qbt"},
|
||||
{"Qubicle Binary", "qb"},
|
||||
//{"Qubicle", "qbcl"},
|
||||
{"Sandbox VoxEdit", "vxm"},
|
||||
{"BinVox", "binvox"},
|
||||
{"CubeWorld", "cub"},
|
||||
{"Build engine", "kvx"},
|
||||
{"Tiberian Sun", "vxl"},
|
||||
{"Qubicle", "qef"},
|
||||
{"Qubicle Exchange", "qef"},
|
||||
{"WaveFront OBJ", "obj"},
|
||||
{"Polygon File Format", "ply"},
|
||||
{nullptr, nullptr}
|
||||
|
@ -150,6 +153,11 @@ bool loadVolumeFormat(const io::FilePtr& filePtr, voxel::VoxelVolumes& newVolume
|
|||
if (!f.loadGroups(filePtr, newVolumes)) {
|
||||
voxelformat::clearVolumes(newVolumes);
|
||||
}
|
||||
} else if (ext == "qbcl" || magic == FourCC('Q','B','C','L')) {
|
||||
voxel::QBCLFormat f;
|
||||
if (!f.loadGroups(filePtr, newVolumes)) {
|
||||
voxelformat::clearVolumes(newVolumes);
|
||||
}
|
||||
} else {
|
||||
Log::error("Failed to load model file %s - unsupported file format for extension '%s'",
|
||||
filePtr->name().c_str(), ext.c_str());
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* @file
|
||||
*/
|
||||
|
||||
#include "AbstractVoxFormatTest.h"
|
||||
#include "voxelformat/QBCLFormat.h"
|
||||
#include "voxelformat/VolumeFormat.h"
|
||||
|
||||
namespace voxel {
|
||||
|
||||
class QBCLFormatTest: public AbstractVoxFormatTest {
|
||||
};
|
||||
|
||||
TEST_F(QBCLFormatTest, DISABLED_testLoad) {
|
||||
QBCLFormat f;
|
||||
std::unique_ptr<RawVolume> volume(load("qubicle.qbcl", f));
|
||||
ASSERT_NE(nullptr, volume) << "Could not load qbcl file";
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue