VOXELFORMAT: csm format support #56
parent
76b22af829
commit
76af2d04c5
Binary file not shown.
|
@ -7,9 +7,11 @@ vengi (0.0.7.0-1) UNRELEASED; urgency=low
|
|||
* Added stacktrace support for windows
|
||||
* Refactored module structure (split app and core)
|
||||
* Optimized character animations
|
||||
* Hot reload character animation C++ source changes in debug builds
|
||||
* Added quaternion lua support
|
||||
* Updated external dependencies
|
||||
* Refactored lua bindings
|
||||
* Support Chronovox-Studio files (csm)
|
||||
|
||||
* VoxEdit:
|
||||
* Converted some voxel generation functions to lua
|
||||
|
|
|
@ -12,9 +12,11 @@ General:
|
|||
- Added stacktrace support for windows
|
||||
- Refactored module structure (split app and core)
|
||||
- Optimized character animations
|
||||
- Hot reload character animation C++ source changes in debug builds
|
||||
- Added quaternion lua support
|
||||
- Updated external dependencies
|
||||
- Refactored lua bindings
|
||||
- Support Chronovox-Studio files (csm)
|
||||
|
||||
VoxEdit:
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ set(LIB voxelformat)
|
|||
set(SRCS
|
||||
AoSVXLFormat.h AoSVXLFormat.cpp
|
||||
BinVoxFormat.h BinVoxFormat.cpp
|
||||
CSMFormat.h CSMFormat.cpp
|
||||
KVXFormat.h KVXFormat.cpp
|
||||
KV6Format.h KV6Format.cpp
|
||||
VoxFileFormat.h VoxFileFormat.cpp
|
||||
|
@ -28,6 +29,7 @@ set(TEST_SRCS
|
|||
tests/QBFormatTest.cpp
|
||||
tests/QEFFormatTest.cpp
|
||||
tests/CubFormatTest.cpp
|
||||
tests/CSMFormatTest.cpp
|
||||
tests/KVXFormatTest.cpp
|
||||
tests/KV6FormatTest.cpp
|
||||
tests/VXLFormatTest.cpp
|
||||
|
@ -38,6 +40,7 @@ set(TEST_FILES
|
|||
tests/qubicle.qbt
|
||||
tests/qubicle.qef
|
||||
tests/aceofspades.vxl
|
||||
tests/chronovox-studio.csm
|
||||
tests/cc.vxl
|
||||
tests/test.binvox
|
||||
tests/test.kvx
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
/**
|
||||
* @file
|
||||
*/
|
||||
|
||||
#include "CSMFormat.h"
|
||||
#include "core/Color.h"
|
||||
#include "core/FourCC.h"
|
||||
#include "core/Log.h"
|
||||
#include "glm/common.hpp"
|
||||
#include "io/FileStream.h"
|
||||
#include "voxel/MaterialColor.h"
|
||||
#include "voxel/Voxel.h"
|
||||
|
||||
namespace voxel {
|
||||
|
||||
#define wrap(read) \
|
||||
if ((read) != 0) { \
|
||||
Log::error("Could not load csm file: Not enough data in stream " CORE_STRINGIFY(read) " - still %i bytes left", (int)stream.remaining()); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define wrapBool(read) \
|
||||
if (!(read)) { \
|
||||
Log::debug("Error: " CORE_STRINGIFY(read) " at " SDL_FILE ":%i", SDL_LINE); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
static bool readString(io::FileStream& stream, core::String& str, int version) {
|
||||
if (version < 4) {
|
||||
uint8_t length;
|
||||
wrap(stream.readByte(length))
|
||||
char name[256];
|
||||
wrapBool(stream.readString(length, name))
|
||||
name[length] = '\0';
|
||||
str = name;
|
||||
} else {
|
||||
uint32_t length;
|
||||
wrap(stream.readInt(length))
|
||||
if (length > 4096) {
|
||||
// sanity check
|
||||
return false;
|
||||
}
|
||||
char name[4096];
|
||||
wrapBool(stream.readString(length, name))
|
||||
name[length] = '\0';
|
||||
str = name;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSMFormat::loadGroups(const io::FilePtr &file, VoxelVolumes &volumes) {
|
||||
if (!(bool)file || !file->exists()) {
|
||||
Log::error("Could not load csm file: File doesn't exist");
|
||||
return false;
|
||||
}
|
||||
|
||||
const MaterialColorArray& materialColors = getMaterialColors();
|
||||
|
||||
io::FileStream stream(file.get());
|
||||
uint32_t magic, version, blank, matrixCount;
|
||||
wrap(stream.readInt(magic))
|
||||
wrap(stream.readInt(version))
|
||||
wrap(stream.readInt(blank))
|
||||
wrap(stream.readInt(matrixCount))
|
||||
for (uint16_t i = 0u; (uint16_t)i < matrixCount; ++i) {
|
||||
core::String name;
|
||||
core::String parent;
|
||||
wrapBool(readString(stream, name, version))
|
||||
if (version > 1) {
|
||||
wrapBool(readString(stream, parent, version))
|
||||
}
|
||||
uint16_t posx, posy, posz;
|
||||
wrap(stream.readShort(posx))
|
||||
wrap(stream.readShort(posy))
|
||||
wrap(stream.readShort(posz))
|
||||
|
||||
uint16_t sizex, sizey, sizez;
|
||||
wrap(stream.readShort(sizex))
|
||||
wrap(stream.readShort(sizey))
|
||||
wrap(stream.readShort(sizez))
|
||||
|
||||
if (sizex > MaxRegionSize || sizey > MaxRegionSize || sizez > MaxRegionSize) {
|
||||
Log::error("Volume exceeds the max allowed size: %i:%i:%i", sizex, sizey, sizez);
|
||||
return false;
|
||||
}
|
||||
|
||||
const voxel::Region region(0, 0, 0, sizex - 1, sizey - 1, sizez - 1);
|
||||
if (!region.isValid()) {
|
||||
Log::error("Invalid region: %i:%i:%i", sizex, sizey, sizez);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t voxels = sizex * sizey * sizez;
|
||||
uint32_t matrixIndex = 0u;
|
||||
|
||||
RawVolume *volume = new RawVolume(region);
|
||||
volumes.push_back(VoxelVolume{volume, name, true});
|
||||
|
||||
while (matrixIndex < voxels) {
|
||||
uint8_t count;
|
||||
wrap(stream.readByte(count))
|
||||
uint8_t r;
|
||||
wrap(stream.readByte(r))
|
||||
uint8_t g;
|
||||
wrap(stream.readByte(g))
|
||||
uint8_t b;
|
||||
wrap(stream.readByte(b))
|
||||
uint8_t interactiontype;
|
||||
wrap(stream.readByte(interactiontype))
|
||||
if (interactiontype == 0u) {
|
||||
matrixIndex += count;
|
||||
continue;
|
||||
}
|
||||
const glm::vec4& color = core::Color::fromRGBA(r, g, b, 255);
|
||||
const int index = core::Color::getClosestMatch(color, materialColors);
|
||||
const voxel::Voxel& voxel = voxel::createVoxel(voxel::VoxelType::Generic, index);
|
||||
|
||||
for (uint32_t v = matrixIndex; v < matrixIndex + count; ++v) {
|
||||
const int x = glm::mod((float)glm::floor((float)v / (float)(sizez * sizey)), (float)sizex);
|
||||
const int y = glm::mod((float)glm::floor((float)v / (float)(sizez)), (float)sizey);
|
||||
const int z = glm::mod((float)v, (float)sizez);
|
||||
volume->setVoxel(x, y, z, voxel);
|
||||
}
|
||||
|
||||
matrixIndex += count;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#undef wrap
|
||||
#undef wrapBool
|
||||
|
||||
bool CSMFormat::saveGroups(const VoxelVolumes &volumes, const io::FilePtr &file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* @file
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "VoxFileFormat.h"
|
||||
#include "io/FileStream.h"
|
||||
#include "io/File.h"
|
||||
#include "core/String.h"
|
||||
|
||||
namespace voxel {
|
||||
|
||||
/**
|
||||
* @brief Chronovox Studio Model
|
||||
*/
|
||||
class CSMFormat : public VoxFileFormat {
|
||||
public:
|
||||
bool loadGroups(const io::FilePtr& file, VoxelVolumes& volumes) override;
|
||||
bool saveGroups(const VoxelVolumes& volumes, const io::FilePtr& file) override;
|
||||
};
|
||||
|
||||
}
|
|
@ -17,11 +17,12 @@
|
|||
#include "KVXFormat.h"
|
||||
#include "KV6Format.h"
|
||||
#include "AoSVXLFormat.h"
|
||||
#include "voxelformat/CSMFormat.h"
|
||||
|
||||
namespace voxelformat {
|
||||
|
||||
// this is the list of supported voxel volume formats that are have importers implemented
|
||||
const char *SUPPORTED_VOXEL_FORMATS_LOAD = "vox,qbt,qb,vxm,binvox,cub,kvx,kv6,vxl,qef";
|
||||
const char *SUPPORTED_VOXEL_FORMATS_LOAD = "vox,qbt,qb,vxm,binvox,cub,kvx,kv6,vxl,qef,csm";
|
||||
// this is the list of internal formats that are supported engine-wide (the format we save our own models in)
|
||||
const char *SUPPORTED_VOXEL_FORMATS_LOAD_LIST[] = { "qb", "vox", nullptr };
|
||||
// this is the list of supported voxel volume formats that have exporters implemented
|
||||
|
@ -89,6 +90,11 @@ bool loadVolumeFormat(const io::FilePtr& filePtr, voxel::VoxelVolumes& newVolume
|
|||
if (!f.loadGroups(filePtr, newVolumes)) {
|
||||
voxelformat::clearVolumes(newVolumes);
|
||||
}
|
||||
} else if (ext == "csm" || magic == FourCC('.','C','S','M')) {
|
||||
voxel::CSMFormat f;
|
||||
if (!f.loadGroups(filePtr, newVolumes)) {
|
||||
voxelformat::clearVolumes(newVolumes);
|
||||
}
|
||||
} else if (ext == "binvox" || magic == FourCC('#','b','i','n')) {
|
||||
voxel::BinVoxFormat f;
|
||||
if (!f.loadGroups(filePtr, newVolumes)) {
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* @file
|
||||
*/
|
||||
|
||||
#include "AbstractVoxFormatTest.h"
|
||||
#include "voxelformat/CSMFormat.h"
|
||||
|
||||
namespace voxel {
|
||||
|
||||
class CSMFormatTest: public AbstractVoxFormatTest {
|
||||
};
|
||||
|
||||
TEST_F(CSMFormatTest, testLoad) {
|
||||
CSMFormat f;
|
||||
std::unique_ptr<RawVolume> volume(load("chronovox-studio.csm", f));
|
||||
ASSERT_NE(nullptr, volume) << "Could not load volume";
|
||||
}
|
||||
|
||||
}
|
|
@ -13,6 +13,7 @@ class CubFormatTest: public AbstractVoxFormatTest {
|
|||
TEST_F(CubFormatTest, testLoad) {
|
||||
CubFormat f;
|
||||
std::unique_ptr<RawVolume> volume(load("cw.cub", f));
|
||||
ASSERT_NE(nullptr, volume) << "Could not load volume";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ class KV6FormatTest: public AbstractVoxFormatTest {
|
|||
TEST_F(KV6FormatTest, testLoad) {
|
||||
KV6Format f;
|
||||
std::unique_ptr<RawVolume> volume(load("test.kv6", f));
|
||||
ASSERT_NE(nullptr, volume) << "Could not load volume";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ class KVXFormatTest: public AbstractVoxFormatTest {
|
|||
TEST_F(KVXFormatTest, testLoad) {
|
||||
KVXFormat f;
|
||||
std::unique_ptr<RawVolume> volume(load("test.kvx", f));
|
||||
ASSERT_NE(nullptr, volume) << "Could not load volume";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue