VOXELFORMAT: hopefully fixed uv coordinates for palettes that don't have 256 colors
parent
2396a881ff
commit
ad0e30841a
|
@ -152,7 +152,7 @@ Objects: {
|
||||||
|
|
||||||
if (withTexCoords) {
|
if (withTexCoords) {
|
||||||
// 1 x 256 is the texture format that we are using for our palette
|
// 1 x 256 is the texture format that we are using for our palette
|
||||||
const float texcoord = 1.0f / (float)palette.colorCount;
|
const float texcoord = 1.0f / (float)voxel::PaletteMaxColors;
|
||||||
// it is only 1 pixel high - sample the middle
|
// it is only 1 pixel high - sample the middle
|
||||||
const float v1 = 0.5f;
|
const float v1 = 0.5f;
|
||||||
wrapBool(stream.writeString("\t\tLayerElementUV: 0 {\n", false))
|
wrapBool(stream.writeString("\t\tLayerElementUV: 0 {\n", false))
|
||||||
|
|
|
@ -160,7 +160,7 @@ bool GLTFFormat::saveMeshes(const core::Map<int, int> &meshIdxNodeMap, const Sce
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// 1 x 256 is the texture format that we are using for our palette
|
// 1 x 256 is the texture format that we are using for our palette
|
||||||
const float texcoord = 1.0f / (float)palette.colorCount;
|
const float texcoord = 1.0f / (float)voxel::PaletteMaxColors;
|
||||||
|
|
||||||
int meshExtIdx = 0;
|
int meshExtIdx = 0;
|
||||||
meshIdxNodeMap.get(nodeId, meshExtIdx);
|
meshIdxNodeMap.get(nodeId, meshExtIdx);
|
||||||
|
|
|
@ -33,24 +33,18 @@ namespace voxelformat {
|
||||||
return false; \
|
return false; \
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OBJFormat::writeMtlFile(const core::String &mtlName, const core::String &paletteName) const {
|
bool OBJFormat::writeMtlFile(io::SeekableWriteStream &stream, const core::String &mtlId, const core::String &mapKd) const {
|
||||||
const io::FilePtr &file = io::filesystem()->open(mtlName, io::FileMode::SysWrite);
|
if (!stream.writeStringFormat(false, "\nnewmtl %s\n", mtlId.c_str())) {
|
||||||
if (!file->validHandle()) {
|
Log::error("Failed to write obj newmtl");
|
||||||
Log::error("Failed to create mtl file at %s", file->name().c_str());
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
io::FileStream stream(file);
|
wrapBool(stream.writeString("Ka 1.000000 1.000000 1.000000\n", false))
|
||||||
wrapBool(stream.writeStringFormat(false, "# version " PROJECT_VERSION " github.com/mgerhardy/vengi\n"))
|
wrapBool(stream.writeString("Kd 1.000000 1.000000 1.000000\n", false))
|
||||||
wrapBool(stream.writeStringFormat(false, "\n"))
|
wrapBool(stream.writeString("Ks 0.000000 0.000000 0.000000\n", false))
|
||||||
wrapBool(stream.writeStringFormat(false, "newmtl palette\n"))
|
wrapBool(stream.writeString("Tr 1.000000\n", false))
|
||||||
wrapBool(stream.writeStringFormat(false, "Ka 1.000000 1.000000 1.000000\n"))
|
wrapBool(stream.writeString("illum 1\n", false))
|
||||||
wrapBool(stream.writeStringFormat(false, "Kd 1.000000 1.000000 1.000000\n"))
|
wrapBool(stream.writeString("Ns 0.000000\n", false))
|
||||||
wrapBool(stream.writeStringFormat(false, "Ks 0.000000 0.000000 0.000000\n"))
|
if (!stream.writeStringFormat(false, "map_Kd %s\n", mapKd.c_str())) {
|
||||||
wrapBool(stream.writeStringFormat(false, "Tr 1.000000\n"))
|
|
||||||
wrapBool(stream.writeStringFormat(false, "illum 1\n"))
|
|
||||||
wrapBool(stream.writeStringFormat(false, "Ns 0.000000\n"))
|
|
||||||
const core::String& paletteFilename = core::string::extractFilenameWithExtension(paletteName);
|
|
||||||
if (!stream.writeStringFormat(false, "map_Kd %s\n", paletteFilename.c_str())) {
|
|
||||||
Log::error("Failed to write obj map_Kd");
|
Log::error("Failed to write obj map_Kd");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -66,6 +60,21 @@ bool OBJFormat::saveMeshes(const core::Map<int, int> &, const SceneGraph &sceneG
|
||||||
|
|
||||||
Log::debug("Exporting %i layers", (int)meshes.size());
|
Log::debug("Exporting %i layers", (int)meshes.size());
|
||||||
|
|
||||||
|
core::String mtlname = core::string::stripExtension(filename);
|
||||||
|
mtlname.append(".mtl");
|
||||||
|
Log::debug("Use mtl file: %s", mtlname.c_str());
|
||||||
|
|
||||||
|
const io::FilePtr &file = io::filesystem()->open(mtlname, io::FileMode::SysWrite);
|
||||||
|
if (!file->validHandle()) {
|
||||||
|
Log::error("Failed to create mtl file at %s", file->name().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
io::FileStream matlstream(file);
|
||||||
|
wrapBool(matlstream.writeString("# version " PROJECT_VERSION " github.com/mgerhardy/vengi\n", false))
|
||||||
|
wrapBool(matlstream.writeString("\n", false))
|
||||||
|
|
||||||
|
core::Map<uint64_t, int> paletteMaterialIndices((int)sceneGraph.size());
|
||||||
|
|
||||||
int idxOffset = 0;
|
int idxOffset = 0;
|
||||||
int texcoordOffset = 0;
|
int texcoordOffset = 0;
|
||||||
for (const auto &meshExt : meshes) {
|
for (const auto &meshExt : meshes) {
|
||||||
|
@ -80,17 +89,10 @@ bool OBJFormat::saveMeshes(const core::Map<int, int> &, const SceneGraph &sceneG
|
||||||
const SceneGraphNode &graphNode = sceneGraph.node(meshExt.nodeId);
|
const SceneGraphNode &graphNode = sceneGraph.node(meshExt.nodeId);
|
||||||
const voxel::Palette &palette = graphNode.palette();
|
const voxel::Palette &palette = graphNode.palette();
|
||||||
|
|
||||||
core::String mtlname = core::string::stripExtension(filename);
|
|
||||||
mtlname.append(core::String::format("%" PRIu64, palette.hash()));
|
|
||||||
mtlname.append(".mtl");
|
|
||||||
|
|
||||||
const core::String hashId = core::String::format("%" PRIu64, palette.hash());
|
const core::String hashId = core::String::format("%" PRIu64, palette.hash());
|
||||||
core::String palettename = core::string::stripExtension(filename);
|
|
||||||
palettename.append(hashId);
|
|
||||||
palettename.append(".png");
|
|
||||||
|
|
||||||
// 1 x 256 is the texture format that we are using for our palette
|
// 1 x 256 is the texture format that we are using for our palette
|
||||||
const float texcoord = 1.0f / (float)palette.colorCount;
|
const float texcoord = 1.0f / (float)voxel::PaletteMaxColors;
|
||||||
// it is only 1 pixel high - sample the middle
|
// it is only 1 pixel high - sample the middle
|
||||||
const float v1 = 0.5f;
|
const float v1 = 0.5f;
|
||||||
const glm::vec3 offset(mesh->getOffset());
|
const glm::vec3 offset(mesh->getOffset());
|
||||||
|
@ -102,7 +104,10 @@ bool OBJFormat::saveMeshes(const core::Map<int, int> &, const SceneGraph &sceneG
|
||||||
}
|
}
|
||||||
stream.writeStringFormat(false, "o %s\n", objectName);
|
stream.writeStringFormat(false, "o %s\n", objectName);
|
||||||
stream.writeStringFormat(false, "mtllib %s\n", core::string::extractFilenameWithExtension(mtlname).c_str());
|
stream.writeStringFormat(false, "mtllib %s\n", core::string::extractFilenameWithExtension(mtlname).c_str());
|
||||||
wrapBool(stream.writeStringFormat(false, "usemtl palette\n"))
|
if (!stream.writeStringFormat(false, "usemtl %s\n", hashId.c_str())) {
|
||||||
|
Log::error("Failed to write obj usemtl %s\n", hashId.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < nv; ++i) {
|
for (int i = 0; i < nv; ++i) {
|
||||||
const voxel::VoxelVertex &v = vertices[i];
|
const voxel::VoxelVertex &v = vertices[i];
|
||||||
|
@ -175,11 +180,18 @@ bool OBJFormat::saveMeshes(const core::Map<int, int> &, const SceneGraph &sceneG
|
||||||
}
|
}
|
||||||
idxOffset += nv;
|
idxOffset += nv;
|
||||||
|
|
||||||
if (!writeMtlFile(mtlname, palettename)) {
|
if (paletteMaterialIndices.find(palette.hash()) == paletteMaterialIndices.end()) {
|
||||||
return false;
|
core::String palettename = core::string::stripExtension(filename);
|
||||||
}
|
palettename.append(hashId);
|
||||||
if (!palette.save(palettename.c_str())) {
|
palettename.append(".png");
|
||||||
return false;
|
paletteMaterialIndices.put(palette.hash(), 1);
|
||||||
|
const core::String &mapKd = core::string::extractFilenameWithExtension(palettename);
|
||||||
|
if (!writeMtlFile(matlstream, hashId, mapKd)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!palette.save(palettename.c_str())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "MeshFormat.h"
|
#include "MeshFormat.h"
|
||||||
|
#include "io/Stream.h"
|
||||||
|
|
||||||
namespace tinyobj {
|
namespace tinyobj {
|
||||||
struct mesh_t;
|
struct mesh_t;
|
||||||
|
@ -18,7 +19,7 @@ namespace voxelformat {
|
||||||
*/
|
*/
|
||||||
class OBJFormat : public MeshFormat {
|
class OBJFormat : public MeshFormat {
|
||||||
private:
|
private:
|
||||||
bool writeMtlFile(const core::String& mtlName, const core::String &paletteName) const;
|
bool writeMtlFile(io::SeekableWriteStream &stream, const core::String &mtlId, const core::String &mapKd) const;
|
||||||
static void calculateAABB(const tinyobj::mesh_t &mesh, const tinyobj::attrib_t &attrib, glm::vec3 &mins,
|
static void calculateAABB(const tinyobj::mesh_t &mesh, const tinyobj::attrib_t &attrib, glm::vec3 &mins,
|
||||||
glm::vec3 &maxs);
|
glm::vec3 &maxs);
|
||||||
static void subdivideShape(const tinyobj::mesh_t &mesh, const core::StringMap<image::ImagePtr> &textures,
|
static void subdivideShape(const tinyobj::mesh_t &mesh, const core::StringMap<image::ImagePtr> &textures,
|
||||||
|
|
|
@ -65,7 +65,7 @@ bool PLYFormat::saveMeshes(const core::Map<int, int> &, const SceneGraph &sceneG
|
||||||
const SceneGraphNode &graphNode = sceneGraph.node(meshExt.nodeId);
|
const SceneGraphNode &graphNode = sceneGraph.node(meshExt.nodeId);
|
||||||
const voxel::Palette &palette = graphNode.palette();
|
const voxel::Palette &palette = graphNode.palette();
|
||||||
// 1 x 256 is the texture format that we are using for our palette
|
// 1 x 256 is the texture format that we are using for our palette
|
||||||
const float texcoord = 1.0f / (float)palette.colorCount;
|
const float texcoord = 1.0f / (float)voxel::PaletteMaxColors;
|
||||||
// it is only 1 pixel high - sample the middle
|
// it is only 1 pixel high - sample the middle
|
||||||
const float v1 = 0.5f;
|
const float v1 = 0.5f;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue