Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 150 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# *********************************
# ************ cmake **************
# *********************************
CMAKE_MINIMUM_REQUIRED(VERSION 3.0 FATAL_ERROR)
CMAKE_POLICY(SET CMP0043 NEW)
CMAKE_POLICY(SET CMP0048 NEW)

# Enable debug symbols by default
# must be done before project() statement
SET(CMAKE_BUILD_TYPE_INIT Release)
# (you can also set it on the command line: -D CMAKE_BUILD_TYPE=Debug)

# *********************************
# ************ Project ************
# *********************************

STRING(TIMESTAMP VERSION %y.%U.%w.%H UTC)

MESSAGE(STATUS "HMM - HeightMap Meshing utility V${VERSION}")

PROJECT(hmm VERSION ${VERSION})

INCLUDE(GNUInstallDirs)

# ======== For config.h.in =========
SET(PACKAGE_MAINTAINER "fogleman")
#SET(PACKAGE_BUGREPORT "")
SET(PACKAGE_URL "https://github.com/fogleman/hmm")

FIND_PROGRAM(LSB_RELEASE_EXE NAMES lsb_release)
IF (DEFINED LSB_RELEASE_EXE)
EXECUTE_PROCESS(COMMAND ${LSB_RELEASE_EXE} -d OUTPUT_VARIABLE LSB_RELEASE OUTPUT_STRIP_TRAILING_WHITESPACE)
MESSAGE(STATUS ${LSB_RELEASE})
ENDIF()

# *********************************
# ********* Requirements **********
# *********************************

# =========== pkg-config ============
FIND_PACKAGE(PkgConfig)
FIND_PACKAGE(PackageHandleStandardArgs)

# =========== libraries =============

#SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})

# *********************************
# *********** Compiler ************
# *********************************

SET(CMAKE_CXX_STANDARD 11)

SET(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -flto -Wall -Winit-self -Wpointer-arith \
-Wcast-align -Wformat=2 -Woverloaded-virtual \
-Wnon-virtual-dtor -Wshadow -Wno-unknown-pragmas")

#SET(CMAKE_CXX_FLAGS
# "${CMAKE_CXX_FLAGS} \
# )

# -------------------------------------------------------
# Inlclude the main source AND build dir itself
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
#SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)

# ********************************************************
# ********************* Resources ************************
# ********************************************************

INCLUDE(CheckIncludeFileCXX)

CHECK_INCLUDE_FILE_CXX(glm/glm.hpp FOUND_GLM)

IF(NOT FOUND_GLM)
MESSAGE(FATAL_ERROR "glm/glm.hpp can not found, can not be included")
ENDIF()

ADD_EXECUTABLE(hmm
src/main.cpp
src/heightmap.cpp
src/triangulator.cpp
src/base.cpp
src/blur.cpp
src/stl.cpp)

# *********************************
# ********** Installation *********
# *********************************

#SET(PKG_SHARE "${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}")
#SET(PKG_APPS "${CMAKE_INSTALL_DATAROOTDIR}/applications")
#SET(PKG_PIXMAPS "${CMAKE_INSTALL_DATAROOTDIR}/pixmaps")

INSTALL(TARGETS hmm DESTINATION "${CMAKE_INSTALL_LIBDIR}")

# *********************************
# ************ Packaging **********
# *********************************

# ======== General packaging ======
# https://cmake.org/cmake/help/latest/module/CPack.html

INCLUDE(InstallRequiredSystemLibraries)

# SET(CPACK_STRIP_FILES ON) # Strip debug sysmbold from files

SET(CPACK_PACKAGE_VERSION "${hmm_VERSION}")
SET(CPACK_PACKAGE_CONTACT "${PACKAGE_BUGREPORT}")
SET(CPACK_PACKAGE_MAINTAINER "${PACKAGE_MAINTAINER}")
#SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
#SET(CPACK_PACKAGE_VENDOR "Me, myself, and I")

#SET(CPACK_SOURCE_IGNORE_FILES "/old/;/build/;/[.].*/;/autom4te[.]cache/;.*~;.log$")

# Maybe the text displayed in synaptic?
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README.md")
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "HMM - HeightMap Meshing utilitiy")
#CPACK_RESOURCE_FILE_README ReadMe file to be embedded in the installer.

SET(CPACK_GENERATOR TBZ2 DEB) # TGZ
SET(CPACK_SOURCE_GENERATOR TBZ2) # TGZ
#SET(CPACK_PROJECT_CONFIG_FILE ${CMAKE_SOURCE_DIR}/cmake/Package.txt)
#SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/Copyright.txt")


# ======== Debian packaging =======
# https://cmake.org/cmake/help/latest/module/CPackDeb.html
# https://www.debian.org/doc/debian-policy

#SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libao4 (>=1.0), libsfm-system2.3v5 (>=2.3), libsfml-graphicsv2.3v5 (>=2.3), libsfml-audio2.3v5 (>=2.3), libsfm-window2.3v5 (>2.3)")
SET(CPACK_DEBIAN_PACKAGE_SHLIBDEPS 1) # generate better (atomatic?) dependecies
SET(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS_POLICY ">=")
SET(CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION TRUE)
SET(CPACK_DEBIAN_PACKAGE_SECTION utils)
SET(CPACK_DEBIAN_PACKAGE_HOMEPAGE "${PACKAGE_URL}")
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "${PACKAGE_MAINTAINER}")
SET(CPACK_DEBIAN_PACKAGE_DESCRIPTION
"${CPACK_PACKAGE_DESCRIPTION_SUMMARY}
hmm is a modern implementation of a nice algorithm from the 1995 paper
Fast Polygonal Approximation of Terrains and Height Fields by Garland
and Heckbert. The meshes produced by hmm satisfy the Delaunay condition
and can satisfy a specified maximal error or maximal number of
triangles or vertices. It's also very fast.")

#CPACK_INSTALL_CMAKE_PROJECTS
#List of four values that specify what project to install. Build directory, Project Name, Project Component, Directory.

INCLUDE(CPack)
14 changes: 7 additions & 7 deletions src/base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ void AddBase(
std::unordered_map<glm::vec3, int> lookup;

// find points along each edge
for (int i = 0; i < points.size(); i++) {
for (size_t i = 0; i < points.size(); i++) {
const auto &p = points[i];
bool edge = false;
if (p.x == 0) {
Expand Down Expand Up @@ -49,9 +49,9 @@ void AddBase(
std::vector<std::pair<int, float>> sy1s(y1s.begin(), y1s.end());

const auto pointIndex = [&lookup, &points](
const float x, const float y, const float z)
const float x, const float y, const float _z)
{
const glm::vec3 point(x, y, z);
const glm::vec3 point(x, y, _z);
if (lookup.find(point) == lookup.end()) {
lookup[point] = points.size();
points.push_back(point);
Expand All @@ -63,7 +63,7 @@ void AddBase(
const int center = pointIndex(w * 0.5f, h * 0.5f, z);

// edge x = 0
for (int i = 1; i < sx0s.size(); i++) {
for (size_t i = 1; i < sx0s.size(); i++) {
const int y0 = sx0s[i-1].first;
const int y1 = sx0s[i].first;
const float z0 = sx0s[i-1].second;
Expand All @@ -78,7 +78,7 @@ void AddBase(
}

// edge x = w1
for (int i = 1; i < sx1s.size(); i++) {
for (size_t i = 1; i < sx1s.size(); i++) {
const int y0 = sx1s[i-1].first;
const int y1 = sx1s[i].first;
const float z0 = sx1s[i-1].second;
Expand All @@ -93,7 +93,7 @@ void AddBase(
}

// edge y = 0
for (int i = 1; i < sy0s.size(); i++) {
for (size_t i = 1; i < sy0s.size(); i++) {
const int x0 = sy0s[i-1].first;
const int x1 = sy0s[i].first;
const float z0 = sy0s[i-1].second;
Expand All @@ -108,7 +108,7 @@ void AddBase(
}

// edge y = h1
for (int i = 1; i < sy1s.size(); i++) {
for (size_t i = 1; i < sy1s.size(); i++) {
const int x0 = sy1s[i-1].first;
const int x1 = sy1s[i].first;
const float z0 = sy1s[i-1].second;
Expand Down
34 changes: 17 additions & 17 deletions src/cmdline.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ inline std::string readable_typename<std::string>()

class cmdline_error : public std::exception {
public:
cmdline_error(const std::string &msg): msg(msg){}
cmdline_error(const std::string &_msg): msg(_msg){}
~cmdline_error() throw() {}
const char *what() const throw() { return msg.c_str(); }
private:
Expand All @@ -151,7 +151,7 @@ struct default_reader{

template <class T>
struct range_reader{
range_reader(const T &low, const T &high): low(low), high(high) {}
range_reader(const T &_low, const T &_high): low(_low), high(_high) {}
T operator()(const std::string &s) const {
T ret=default_reader<T>()(s);
if (!(ret>=low && ret<=high)) throw cmdline::cmdline_error("range_error");
Expand Down Expand Up @@ -642,8 +642,8 @@ class parser{
public:
option_without_value(const std::string &name,
char short_name,
const std::string &desc)
:nam(name), snam(short_name), desc(desc), has(false){
const std::string &_desc)
:nam(name), snam(short_name), desc(_desc), has(false){
}
~option_without_value(){}

Expand Down Expand Up @@ -698,12 +698,12 @@ class parser{
public:
option_with_value(const std::string &name,
char short_name,
bool need,
const T &def,
const std::string &desc)
: nam(name), snam(short_name), need(need), has(false)
, def(def), actual(def) {
this->desc=full_description(desc);
bool _need,
const T &_def,
const std::string &_desc)
: nam(name), snam(short_name), need(_need), has(false)
, def(_def), actual(_def) {
desc=full_description(_desc);
}
~option_with_value(){}

Expand Down Expand Up @@ -758,9 +758,9 @@ class parser{
}

protected:
std::string full_description(const std::string &desc){
std::string full_description(const std::string &_desc){
return
desc+" ("+detail::readable_typename<T>()+
_desc+" ("+detail::readable_typename<T>()+
(need?"":" [="+detail::default_value<T>(def)+"]")
+")";
}
Expand All @@ -782,11 +782,11 @@ class parser{
public:
option_with_value_with_reader(const std::string &name,
char short_name,
bool need,
const T def,
const std::string &desc,
F reader)
: option_with_value<T>(name, short_name, need, def, desc), reader(reader){
bool _need,
const T _def,
const std::string &_desc,
F _reader)
: option_with_value<T>(name, short_name, _need, _def, _desc), reader(_reader){
}

private:
Expand Down
8 changes: 4 additions & 4 deletions src/heightmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,26 +43,26 @@ Heightmap::Heightmap(
void Heightmap::AutoLevel() {
float lo = m_Data[0];
float hi = m_Data[0];
for (int i = 0; i < m_Data.size(); i++) {
for (size_t i = 0; i < m_Data.size(); i++) {
lo = std::min(lo, m_Data[i]);
hi = std::max(hi, m_Data[i]);
}
if (hi == lo) {
return;
}
for (int i = 0; i < m_Data.size(); i++) {
for (size_t i = 0; i < m_Data.size(); i++) {
m_Data[i] = (m_Data[i] - lo) / (hi - lo);
}
}

void Heightmap::Invert() {
for (int i = 0; i < m_Data.size(); i++) {
for (size_t i = 0; i < m_Data.size(); i++) {
m_Data[i] = 1.f - m_Data[i];
}
}

void Heightmap::GammaCurve(const float gamma) {
for (int i = 0; i < m_Data.size(); i++) {
for (size_t i = 0; i < m_Data.size(); i++) {
m_Data[i] = std::pow(m_Data[i], gamma);
}
}
Expand Down
12 changes: 8 additions & 4 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ int main(int argc, char **argv) {
p.add<int>("border-size", '\0', "border size in pixels", false, 0);
p.add<float>("border-height", '\0', "border z height", false, 1);
p.add<std::string>("normal-map", '\0', "path to write normal map png", false, "");
p.add<float>("scale-x", '\0', "scale x axis", false, 1);
p.add<float>("scale-y", '\0', "scale y axis", false, 1);
p.add("quiet", 'q', "suppress console output");
p.footer("infile outfile.stl");
p.parse_check(argc, argv);
Expand All @@ -55,6 +57,8 @@ int main(int argc, char **argv) {
const int borderSize = p.get<int>("border-size");
const float borderHeight = p.get<float>("border-height");
const std::string normalmapPath = p.get<std::string>("normal-map");
const float scale_x = p.get<float>("scale-x");
const float scale_y = p.get<float>("scale-y");
const bool quiet = p.exist("quiet");

// helper function to display elapsed time of each step
Expand All @@ -66,10 +70,10 @@ int main(int argc, char **argv) {
}
printf("%s... ", message.c_str());
fflush(stdout);
const auto startTime = std::chrono::steady_clock::now();
return [message, startTime]() {
const auto startTime1 = std::chrono::steady_clock::now();
return [message, startTime1]() {
const std::chrono::duration<double> elapsed =
std::chrono::steady_clock::now() - startTime;
std::chrono::steady_clock::now() - startTime1;
printf("%gs\n", elapsed.count());
};
};
Expand Down Expand Up @@ -151,7 +155,7 @@ int main(int argc, char **argv) {

// write output file
done = timed("writing output");
SaveBinarySTL(outFile, points, triangles);
SaveBinarySTL(outFile, points, triangles, scale_x, scale_y);
done();

// compute normal map
Expand Down
22 changes: 17 additions & 5 deletions src/stl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
void SaveBinarySTL(
const std::string &path,
const std::vector<glm::vec3> &points,
const std::vector<glm::ivec3> &triangles)
const std::vector<glm::ivec3> &triangles,
const float &scale_x,
const float &scale_y)
{
// TODO: properly handle endian-ness

Expand All @@ -20,10 +22,20 @@ void SaveBinarySTL(
memcpy(dst + 80, &count, 4);

for (uint32_t i = 0; i < triangles.size(); i++) {
const glm::ivec3 t = triangles[i];
const glm::vec3 p0 = points[t.x];
const glm::vec3 p1 = points[t.y];
const glm::vec3 p2 = points[t.z];
const glm::ivec3 &t = triangles[i];

glm::vec3 p0 = points[t.x];
glm::vec3 p1 = points[t.y];
glm::vec3 p2 = points[t.z];

p0.x *= scale_x;
p1.x *= scale_x;
p2.x *= scale_x;

p0.y *= scale_y;
p1.y *= scale_y;
p2.y *= scale_y;

const glm::vec3 normal = glm::triangleNormal(p0, p1, p2);
const uint64_t idx = 84 + i * 50;
memcpy(dst + idx, &normal, 12);
Expand Down
Loading