Skip to content

Commit

Permalink
Merge c6713a0 into 9d1601e
Browse files Browse the repository at this point in the history
  • Loading branch information
q3k committed Feb 25, 2019
2 parents 9d1601e + c6713a0 commit 0053d80
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitmodules
Expand Up @@ -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
25 changes: 25 additions & 0 deletions CMakeLists.txt
Expand Up @@ -37,6 +37,8 @@ set(ENABLE_COVERAGE OFF CACHE BOOL
"Whether code coverage information will be collected")
set(ENABLE_SANITIZERS OFF CACHE BOOL
"Whether to enable Clang's AddressSanitizer and UndefinedBehaviorSanitizer")
set(ENABLE_Q3D ON CACHE BOOL
"Whether to enable Q3D file export")

set(OPENGL 3 CACHE STRING "OpenGL version to use (one of: 1 3)")

Expand Down Expand Up @@ -298,6 +300,29 @@ if(ENABLE_COVERAGE)
set(COVERAGE_LIBRARY --coverage)
endif()

if(ENABLE_Q3D)
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
${CMAKE_CURRENT_BINARY_DIR}/extlib/flatbuffers
EXCLUDE_FROM_ALL)

set(q3d_schema ${CMAKE_CURRENT_SOURCE_DIR}/extlib/q3d/object.fbs)
set(q3d_outdir ${CMAKE_CURRENT_BINARY_DIR}/extlib/q3d)
set(q3d_header ${q3d_outdir}/object_generated.h)

add_custom_command(
OUTPUT ${q3d_header}
COMMAND $<TARGET_FILE:flatc> --cpp --no-includes -o ${q3d_outdir}
${q3d_schema}
DEPENDS flatc)

add_custom_target(gen_q3d_header DEPENDS ${q3d_header})
set(Q3D_INCLUDE_DIR ${q3d_outdir})
endif()

# application components

add_subdirectory(res)
Expand Down
1 change: 1 addition & 0 deletions extlib/flatbuffers
Submodule flatbuffers added at a1f140
1 change: 1 addition & 0 deletions extlib/q3d
Submodule q3d added at 43f618
11 changes: 11 additions & 0 deletions src/CMakeLists.txt
Expand Up @@ -13,6 +13,8 @@ endif()

set(HAVE_SPACEWARE ${SPACEWARE_FOUND})

set(HAVE_Q3D ${ENABLE_Q3D})

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/config.h)

Expand Down Expand Up @@ -221,11 +223,20 @@ target_link_libraries(solvespace-core
if(Backtrace_FOUND)
target_link_libraries(solvespace-core
${Backtrace_LIBRARY})
add_dependencies(solvespace-core gen_q3d_header)
endif()

if(ENABLE_Q3D)
target_link_libraries(solvespace-core
flatbuffers)
add_dependencies(solvespace-core gen_q3d_header)
include_directories(${Q3D_INCLUDE_DIR})
endif()

target_compile_options(solvespace-core
PRIVATE ${COVERAGE_FLAGS})


# solvespace translations

if(HAVE_GETTEXT)
Expand Down
3 changes: 3 additions & 0 deletions src/config.h.in
Expand Up @@ -16,4 +16,7 @@
#cmakedefine HAVE_BACKTRACE
#define BACKTRACE_HEADER @BACKTRACE_HEADER@

/* Do we have Q3D C++ stubs and the FlatBuffer library? */
#cmakedefine HAVE_Q3D

#endif
60 changes: 60 additions & 0 deletions src/export.cpp
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -877,6 +880,63 @@ void SolveSpaceUI::ExportMeshAsStlTo(FILE *f, SMesh *sm) {
}
}

//-----------------------------------------------------------------------------
// Export the mesh as a Q3DO (https://github.com/q3k/q3d) file.
//-----------------------------------------------------------------------------
#ifndef HAVE_Q3D

void SolveSpaceUI::ExportMeshAsQ3doTo(FILE *f, SMesh *sm) {
Error("SolveSpace has been built without Q3D(O) support.");
}

#else // HAVE_Q3D

#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);
}

#endif // HAVE_Q3D

//-----------------------------------------------------------------------------
// Export the mesh as Wavefront OBJ format. This requires us to reduce all the
// identical vertices to the same identifier, so do that first.
Expand Down
4 changes: 4 additions & 0 deletions src/platform/gui.cpp
Expand Up @@ -4,6 +4,7 @@
// Copyright 2018 whitequark
//-----------------------------------------------------------------------------
#include "solvespace.h"
#include "config.h"

namespace SolveSpace {
namespace Platform {
Expand Down Expand Up @@ -94,6 +95,9 @@ 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" } },
#ifdef HAVE_Q3D
{ CN_("file-type", "Q3D Object file"), { "q3do" } },
#endif
};

std::vector<FileFilter> SurfaceFileFilters = {
Expand Down
1 change: 1 addition & 0 deletions src/solvespace.h
Expand Up @@ -693,6 +693,7 @@ class SolveSpaceUI {
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);
Expand Down

0 comments on commit 0053d80

Please sign in to comment.