Implement Q3DO export.
We plan to use flatbuffers in the future for the next generation of the .slvs file format, so flatbuffers are built unconditionally; and the Q3DO exporter itself is tiny.pull/144/head
parent
9d1601eea9
commit
3a3a2755bf
|
@ -20,3 +20,9 @@
|
|||
[submodule "extlib/angle"]
|
||||
path = extlib/angle
|
||||
url = https://github.com/solvespace/angle
|
||||
[submodule "extlib/flatbuffers"]
|
||||
path = extlib/flatbuffers
|
||||
url = https://github.com/google/flatbuffers
|
||||
[submodule "extlib/q3d"]
|
||||
path = extlib/q3d
|
||||
url = https://github.com/q3k/q3d
|
||||
|
|
|
@ -42,6 +42,10 @@ New export/import features:
|
|||
* Wavefront OBJ: a material file is exported alongside the model, containing
|
||||
mesh color information.
|
||||
* DXF/DWG: 3D DXF files are imported as construction entities, in 3d.
|
||||
* Q3D: [Q3D](https://github.com/q3k/q3d/) triangle meshes can now be
|
||||
exported. This format allows to easily hack on triangle mesh data created
|
||||
in SolveSpace, supports colour information and is more space efficient than
|
||||
most other formats.
|
||||
|
||||
New rendering features:
|
||||
* The "Show/hide hidden lines" button is now a tri-state button that allows
|
||||
|
|
|
@ -103,6 +103,17 @@ endif()
|
|||
message(STATUS "Using in-tree libdxfrw")
|
||||
add_subdirectory(extlib/libdxfrw)
|
||||
|
||||
message(STATUS "Using in-tree flatbuffers")
|
||||
set(FLATBUFFERS_BUILD_FLATLIB ON CACHE BOOL "")
|
||||
set(FLATBUFFERS_BUILD_FLATC ON CACHE BOOL "")
|
||||
set(FLATBUFFERS_BUILD_FLATHASH OFF CACHE BOOL "")
|
||||
set(FLATBUFFERS_BUILD_TESTS OFF CACHE BOOL "")
|
||||
add_subdirectory(extlib/flatbuffers EXCLUDE_FROM_ALL)
|
||||
|
||||
message(STATUS "Using in-tree q3d")
|
||||
add_subdirectory(extlib/q3d)
|
||||
set(Q3D_INCLUDE_DIR ${CMAKE_BINARY_DIR}/extlib/q3d)
|
||||
|
||||
if(WIN32 OR APPLE)
|
||||
# On Win32 and macOS we use vendored packages, since there is little to no benefit
|
||||
# to trying to find system versions. In particular, trying to link to libraries from
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit a1f14005ab823adc1300754fd37c01e9842ed4bc
|
|
@ -0,0 +1 @@
|
|||
Subproject commit fe71514837af1c627e9e1054d1aa0193a06d3488
|
|
@ -79,7 +79,8 @@ include_directories(
|
|||
${ZLIB_INCLUDE_DIR}
|
||||
${PNG_PNG_INCLUDE_DIR}
|
||||
${FREETYPE_INCLUDE_DIRS}
|
||||
${CAIRO_INCLUDE_DIRS})
|
||||
${CAIRO_INCLUDE_DIRS}
|
||||
${Q3D_INCLUDE_DIR})
|
||||
|
||||
if(Backtrace_FOUND)
|
||||
include_directories(
|
||||
|
@ -211,12 +212,16 @@ add_library(solvespace-core STATIC
|
|||
${solvespace_core_HEADERS}
|
||||
${solvespace_core_SOURCES})
|
||||
|
||||
add_dependencies(solvespace-core
|
||||
q3d_header)
|
||||
|
||||
target_link_libraries(solvespace-core
|
||||
dxfrw
|
||||
${util_LIBRARIES}
|
||||
${ZLIB_LIBRARY}
|
||||
${PNG_LIBRARY}
|
||||
${FREETYPE_LIBRARY})
|
||||
${FREETYPE_LIBRARY}
|
||||
flatbuffers)
|
||||
|
||||
if(Backtrace_FOUND)
|
||||
target_link_libraries(solvespace-core
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
// Copyright 2008-2013 Jonathan Westhues.
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "solvespace.h"
|
||||
#include "config.h"
|
||||
|
||||
void SolveSpaceUI::ExportSectionTo(const Platform::Path &filename) {
|
||||
Vector gn = (SS.GW.projRight).Cross(SS.GW.projUp);
|
||||
|
@ -826,6 +827,8 @@ void SolveSpaceUI::ExportMeshTo(const Platform::Path &filename) {
|
|||
ExportMeshAsObjTo(f, fMtl, m);
|
||||
|
||||
fclose(fMtl);
|
||||
} else if(filename.HasExtension("q3do")) {
|
||||
ExportMeshAsQ3doTo(f, m);
|
||||
} else if(filename.HasExtension("js") ||
|
||||
filename.HasExtension("html")) {
|
||||
SOutlineList *e = &(SK.GetGroup(SS.GW.activeGroup)->displayOutlines);
|
||||
|
@ -877,6 +880,54 @@ void SolveSpaceUI::ExportMeshAsStlTo(FILE *f, SMesh *sm) {
|
|||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Export the mesh as a Q3DO (https://github.com/q3k/q3d) file.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "object_generated.h"
|
||||
void SolveSpaceUI::ExportMeshAsQ3doTo(FILE *f, SMesh *sm) {
|
||||
flatbuffers::FlatBufferBuilder builder(1024);
|
||||
double s = SS.exportScale;
|
||||
|
||||
// Create a material for every colour used, keep note of triangles belonging to color/material.
|
||||
std::map<RgbaColor, flatbuffers::Offset<q3d::Material>, RgbaColorCompare> materials;
|
||||
std::map<RgbaColor, std::vector<flatbuffers::Offset<q3d::Triangle>>, RgbaColorCompare> materialTriangles;
|
||||
for (const STriangle &t : sm->l) {
|
||||
auto color = t.meta.color;
|
||||
if (materials.find(color) == materials.end()) {
|
||||
auto name = builder.CreateString(ssprintf("Color #%02x%02x%02x%02x", color.red, color.green, color.blue, color.alpha));
|
||||
auto co = q3d::CreateColor(builder, color.red, color.green, color.blue, color.alpha);
|
||||
auto mo = q3d::CreateMaterial(builder, name, co);
|
||||
materials.emplace(color, mo);
|
||||
}
|
||||
|
||||
Vector faceNormal = t.Normal();
|
||||
auto a = q3d::Vector3(t.a.x/s, t.a.y/s, t.a.z/s);
|
||||
auto b = q3d::Vector3(t.b.x/s, t.b.y/s, t.b.z/s);
|
||||
auto c = q3d::Vector3(t.c.x/s, t.c.y/s, t.c.z/s);
|
||||
auto fn = q3d::Vector3(faceNormal.x, faceNormal.y, faceNormal.x);
|
||||
auto n1 = q3d::Vector3(t.normals[0].x, t.normals[0].y, t.normals[0].z);
|
||||
auto n2 = q3d::Vector3(t.normals[1].x, t.normals[1].y, t.normals[1].z);
|
||||
auto n3 = q3d::Vector3(t.normals[2].x, t.normals[2].y, t.normals[2].z);
|
||||
auto tri = q3d::CreateTriangle(builder, &a, &b, &c, &fn, &n1, &n2, &n3);
|
||||
materialTriangles[color].push_back(tri);
|
||||
}
|
||||
|
||||
// Build all meshes sorted by material.
|
||||
std::vector<flatbuffers::Offset<q3d::Mesh>> meshes;
|
||||
for (auto &it : materials) {
|
||||
auto &mato = it.second;
|
||||
auto to = builder.CreateVector(materialTriangles[it.first]);
|
||||
auto mo = q3d::CreateMesh(builder, to, mato);
|
||||
meshes.push_back(mo);
|
||||
}
|
||||
|
||||
auto mo = builder.CreateVector(meshes);
|
||||
auto o = q3d::CreateObject(builder, mo);
|
||||
q3d::FinishObjectBuffer(builder, o);
|
||||
fwrite(builder.GetBufferPointer(), builder.GetSize(), 1, f);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Export the mesh as Wavefront OBJ format. This requires us to reduce all the
|
||||
// identical vertices to the same identifier, so do that first.
|
||||
|
|
|
@ -94,6 +94,7 @@ std::vector<FileFilter> MeshFileFilters = {
|
|||
{ CN_("file-type", "Wavefront OBJ mesh"), { "obj" } },
|
||||
{ CN_("file-type", "Three.js-compatible mesh, with viewer"), { "html" } },
|
||||
{ CN_("file-type", "Three.js-compatible mesh, mesh only"), { "js" } },
|
||||
{ CN_("file-type", "Q3D Object file"), { "q3do" } },
|
||||
};
|
||||
|
||||
std::vector<FileFilter> SurfaceFileFilters = {
|
||||
|
|
|
@ -693,6 +693,7 @@ public:
|
|||
void ExportAsPngTo(const Platform::Path &filename);
|
||||
void ExportMeshTo(const Platform::Path &filename);
|
||||
void ExportMeshAsStlTo(FILE *f, SMesh *sm);
|
||||
void ExportMeshAsQ3doTo(FILE *f, SMesh *sm);
|
||||
void ExportMeshAsObjTo(FILE *fObj, FILE *fMtl, SMesh *sm);
|
||||
void ExportMeshAsThreeJsTo(FILE *f, const Platform::Path &filename,
|
||||
SMesh *sm, SOutlineList *sol);
|
||||
|
|
Loading…
Reference in New Issue