A procedural geometry generation library for C++11

Overview

Generator - A procedural geometry generation library.

Examples

The purpose of this library is to easily generate procedural meshes of geometric primitives such as spheres, boxes, cones, cylinders etc.

Generator is not a graphics library. It will only produce data for any graphics library to use.

Compiling

To compile you will need a C++11 compatible compiler (tested with gcc 4.8) and cmake (tested with cmake 2.8).

Generator needs a vector math library to work. It will use GML. There are no other dependencies.

Compile with:

cmake .
make

If GML is not in the include path, you can give it's path with: -DGML_INCLUDE_DIR command line argument.

cmake . -DGML_INCLUDE_DIR=path/to/gml
make

The library libgenerator will be in the lib directory.

In images directory there is a program called generate that can generate svg test images.

You can generate documentation with Doxygen. Run generate in the images directory before doxygen as the documentation uses images generated by it.

Usage

Make sure that that Generator and the GML math library are in the include path.

To include all primitives use:

#include <generator/generator.hpp>

To include individual primitives include a header file that has the same name as the primitive class.

#include <generator/SphereMesh.hpp>
#include <generator/HelixPath.hpp>
#include <generator/CircleShape.hpp>

If you'd prefer to use GLM, a similar (but more heavyweight) library, build with the #define GENERATOR_USE_GLM.

Everything in the library is under the namespace generator. The examples in this document will omit this namespace.

You will also need to link with libgenerator.

Coordinate systems

Generator uses a right handed coordinate system, just like OpenGL does.

All angles are in radians positive, with the direction being counterclockwise when looking towards the axis.

Vertices in triangles are in counterclockwise order.

All calculations are done double precision.

Concepts

There are two main concepts in the library: "primitives" and "generators".

Primitives produce generators. Generators generate values such as vertex coordinates.

Primitives

There are three types of primitives: "shapes", "paths" and "meshes". All primitive class names end with their type e.g. SphereMesh, HelixPath or CircleShape.

Shapes

Shapes are a set of ShapeVertexes on the 2d xy-plane and a set of Edges connecting them.

class ShapeVertex {
public:
	gml::dvec2 position;
	gml::dvec2 tangent;
	gml::dvec2 normal() const noexcept;
	double texCoord;
};
class Edge {
public:
	gml::uvec2 vertices;
};

All shapes have these methods:

EdgeGenerator edges() const noexcept;
VertexGenerator vertices() const noexcept;

Where EdgeGenerator and VertexGenerator can be a arbitrary types. The shape must outlive the generators it produces. If the shape is mutated the generators are invalidated. Shapes can be mutated only via assignment. The are no setter methods.

Available shapes are:

  • BezierShape
  • CircleShape
  • GridShape
  • LineShape
  • ParametricShape
  • RectangleShape
  • RoundedRectangleShape

Paths

Paths are a set of PathVertexes in 3d space and a set of Edges connecting them.

class PathVertex {
public:
	gml::dvec3 position;
	gml::dvec3 tangent;
	gml::dvec3 normal;
	gml::dvec3 binormal() const noexcept;
	double texCoord;
};

All paths have these methods:

EdgeGenerator edges() const noexcept;
VertexGenerator vertices() const noexcept;

EdgeGenerator and VertexGenerator are arbitrary types.

Available paths are:

  • HelixPath
  • KnotPath
  • LinePath
  • ParametricPath

Meshes

Meshes are a set of MeshVertexes in 3d space and a set of Triangles connecting them.

class MeshVertex {
public:
	gml::dvec3 position;
	gml::dvec3 normal;
	gml::dvec2 texCoord;
};
class Triangle {
public:
	gml::uvec3 vertices;
};

All meshes have these methods:

TriangleGenerator triangles() const noexcept;
VertexGenerator vertices() const noexcept;

Again, TriangleGenerator and VertexGenerator can be any type.

Available meshes are:

  • BezierMesh
  • BoxMesh
  • CappedConeMesh
  • CappedCylinderMesh
  • CappedTubeMesh
  • CapsuleMesh
  • ConeMesh
  • ConvexPolygonMesh
  • CylinderMesh
  • DiskMesh
  • DodecahedronMesh
  • PlaneMesh
  • IcosahedronMesh
  • IcoSphereMesh
  • ParametricMesh
  • RoundedBoxMesh
  • SphereMesh
  • SphericalConeMesh
  • SphericalTriangleMesh
  • SpringMesh
  • TeapotMesh
  • TorusMesh
  • TorusKnotMesh
  • TriangleMesh
  • TubeMesh

Generators

Except for cached values (which should be considered an implementation detail), primitives don't store any data (vertices etc). All data is generated on the fly with generators.

Generators are made by calling edges(), triangles() or vertices() on the primitive. Generators are lightweight objects analogous to iterators. They typically only contain a pointer back to the Primitive and state info for iteration. Any number of generators for the same primitive can exist at the same time.

Generators can have arbitrary types. Use the keyword auto to avoid the need to explicitly specify them.

SphereMesh sphere{};
auto vertices = sphere.vertices();

For cases where auto cannot be used, the helper class templates EdgeGeneratorType, TriangleGeneratorType and VertexGeneratorType are provided in util.hpp.

typename VertexGeneratorType<SphereMesh>::Type vertices = sphere.vertices();

If the generator type is known only at runtime, the type-erasing class template AnyGenerator can be used (in AnyGenerator.hpp).

AnyGenerator<MeshVertex> vertices = sphere.vertices();

If the generator's primitive type is known at compile time, the AnyShape, AnyPath, and AnyMesh types may be used for respectively storing shapes, path and meshes.

All generators have the following methods:

bool done() const noexcept;
Value generate() const;
void next();

Where Value can be Edge, Triangle, ShapeVertex, PathVertex or MeshVertex.

These methods can be used to iterate over all values in the generators.

SphereMesh sphere{};
auto vertices = sphere.vertices();
while (!vertices.done()) {
	MeshVertex vertex = vertices.generate();
	// Do something with vertex
	vertices.next();
}

Once done() returns true, calling next() or generate() will throw std::out_of_bounds. There is no way to rewind the generator.

If the vertex/edge/triangle count needs to be known before iteration use the helper function count from util.hpp.

count(sphere.vertices());

Iterators

It is possible to use an iterator to drive a generator. Use free functions begin and end on the generator to get the iterators. If the generator is deleted the iterators are invalid.

SphereMesh sphere{};
auto vertices = sphere.vertices();
std::for_each(begin(vertices), end(vertices), [] (const MeshVertex& vertex) {
	// do something with vertex
});

for loops will also work.

SphereMesh sphere{};
for (const MeshVertex& vertex : sphere.vertices()) {
	// do something with vertex
}

NOTE: Be aware of a lifetime issue with a temporary primitive and the for loop.

for (const MeshVertex& vertex : SphereMesh{}.vertices()) {
	// Error! Undefined behaviour!
}

Modifiers

Some primitives such as TranslateMesh do not generate data of their own. Instead they modify data generated by another primitives. They are called "modifiers".

Modifiers store the primitive they modify.

TranslateMesh<SphereMesh> translatedSphere{SphereMesh{}, {1.0f, 0.0f, 0.0f}};
for (const auto& vertex : translatedSphere.vertices()) { }

Multiple modifiers can be nested.

Each modifier also has a function to make one. The function form has the same name as the class but starts with a lower case letter. translateMesh instead of TranslateMesh etc. This makes template argument deduction possible.

auto result = translateMesh(
	rotateMesh(
		scaleMesh(TorusMesh{}, {0.5f, 1.0f, 1.0}),
		gml::radians(90.0), Axis::Y
	),
	{1.0f, 0.0f, 0.0f}
);
for (const MeshVertex& vertex : result.vertices()) { }

Available modifiers for shapes are:

  • AxisSwapShape
  • FlipShape
  • MergeShape
  • RepeatShape
  • RotateShape
  • ScaleShape
  • SubdivideShape
  • TransformShape
  • TranslateShape

Available modifiers for paths are:

  • AxisSwapPath
  • FlipPath
  • MergePath
  • RepeatPath
  • RotatePath
  • ScalePath
  • SubdividePath
  • TransformPath
  • TranslatePath

Available modifiers for meshes are:

  • AxisSwapMesh
  • ExtrudeMesh
  • FlipMesh
  • LatheMesh
  • MergeMesh
  • RepeatMesh
  • RotateMesh
  • ScaleMesh
  • SpherifyMesh
  • SubdivideMesh
  • TransformMesh
  • TranslateMesh
  • UvSwapMesh

Preview and debug

For preview and debug purposes generator has class SvgWriter that can create SVG images of primitives.

It also has class ObjWriter that can write OBJ files of meshes that can be viewed with most 3d programs such as Blender.

Comments
  • Segfault when generating a BoxMesh

    Segfault when generating a BoxMesh

    And possibly other types as well. This is while using GLM. Currently investigating. Here's a stack trace.

    Thread 2 (Thread 0x7fffe663d700 (LWP 29315)):
    #0  0x00007ffff30a888d in poll () at ../sysdeps/unix/syscall-template.S:81
    No locals.
    #1  0x00007fffecd0bbd2 in poll (__timeout=-1, __nfds=1, __fds=0x7fffe663ccc0) at /usr/include/x86_64-linux-gnu/bits/poll2.h:46
    No locals.
    #2  _xcb_conn_wait ([email protected]=0x96a100, [email protected]=0x96a140, [email protected]=0x0, [email protected]=0x0) at ../../src/xcb_conn.c:459
            ret = <optimized out>
            fd = {fd = 4, events = 1, revents = 0}
    #3  0x00007fffecd0d74f in xcb_wait_for_event (c=0x96a100) at ../../src/xcb_in.c:623
            ret = 0x0
    #4  0x00007fffe93d6a39 in QXcbEventReader::run (this=0x9782a0) at qxcbconnection.cpp:1105
            event = <optimized out>
    #5  0x00007ffff420c2be in QThreadPrivate::start (arg=0x9782a0) at thread/qthread_unix.cpp:337
            __clframe = {__cancel_routine = 0x7ffff420b3f0 <QThreadPrivate::finish(void*)>, __cancel_arg = 0x9782a0, __do_it = 1, __cancel_type = <optimized out>}
            thr = 0x9782a0
            data = 0x978600
            objectName = {static null = {<No data fields>}, d = 0x7ffff44bb500 <QArrayData::shared_null>}
    #6  0x00007ffff3c1f6aa in start_thread (arg=0x7fffe663d700) at pthread_create.c:333
            __res = <optimized out>
            pd = 0x7fffe663d700
            now = <optimized out>
            unwind_buf = {cancel_jmp_buf = {{jmp_buf = {140737058690816, -6877604504393972111, 0, 140737488343167, 140737058691520, 9930096, 6877590246699599473, 6877613077402125937}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}}
            not_first_call = <optimized out>
            pagesize_m1 = <optimized out>
            sp = <optimized out>
            freesize = <optimized out>
            __PRETTY_FUNCTION__ = "start_thread"
    #7  0x00007ffff30b3e9d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
    No locals.
    
    Thread 1 (Thread 0x7ffff7e24800 (LWP 29239)):
    #0  0x000000000042e8fa in std::function<generator::MeshVertex (glm::tvec2<double, (glm::precision)0> const&)>::function(std::function<generator::MeshVertex (glm::tvec2<double, (glm::precision)0> const&)> const&) (this=0x7fffffffd300, __x=...) at /usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/functional:2242
    No locals.
    #1  0x000000000042e87f in generator::ParametricMesh::ParametricMesh (this=0x7fffffffd300) at /usr/local/include/generator/ParametricMesh.hpp:21
    No locals.
    #2  0x000000000042e848 in generator::PlaneMesh::PlaneMesh (this=0x7fffffffd300) at /usr/local/include/generator/PlaneMesh.hpp:18
    No locals.
    #3  0x000000000042e7cd in generator::TransformMesh<generator::PlaneMesh>::TransformMesh (this=0x7fffffffd300) at /usr/local/include/generator/TransformMesh.hpp:21
    No locals.
    #4  0x000000000042e7a8 in generator::TranslateMesh<generator::PlaneMesh>::TranslateMesh (this=0x7fffffffd300) at /usr/local/include/generator/TranslateMesh.hpp:18
    No locals.
    #5  0x000000000042e528 in generator::detail::BoxFace::BoxFace (this=0x7fffffffd300) at /usr/local/include/generator/BoxMesh.hpp:24
    No locals.
    #6  0x00000000005dac4c in generator::MergeMesh<generator::detail::BoxFace, generator::UvFlipMesh<generator::FlipMesh<generator::detail::BoxFace> > >::MergeMesh (this=0x7fffffffd300, head=..., tail=...) at /home/jesse/Code/generator/include/generator/MergeMesh.hpp:107
    No locals.
    #7  0x00000000005da3d9 in generator::detail::BoxFaces::BoxFaces (this=0x7fffffffd300, size=..., segments=..., delta=1) at /home/jesse/Code/generator/src/BoxMesh.cpp:32
    No locals.
    #8  0x00000000005da596 in generator::BoxMesh::BoxMesh (this=0x7fffffffe070, size=..., segments=...) at /home/jesse/Code/generator/src/BoxMesh.cpp:51
    No locals.
    #9  0x0000000000428d81 in main (argc=1, argv=0x7fffffffe4d8) at ../../BALLS/BALLS/main.cpp:21
            balls = {<QGuiApplication> = {<QCoreApplication> = {<QObject> = {_vptr.QObject = 0x7ffff67aee48 <vtable for QApplication+16>, static staticMetaObject = {d = {superdata = 0x0, stringdata = 0x7ffff454eea0 <qt_meta_stringdata_QObject>, data = 0x7ffff454ed80 <qt_meta_data_QObject>, static_metacall = 0x7ffff4424a40 <QObject::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)>, relatedMetaObjects = 0x0, extradata = 0x0}}, d_ptr = {d = 0x95b750}, static staticQtMetaObject = {d = {superdata = 0x0, stringdata = 0x7ffff45966a0 <qt_meta_stringdata_Qt>, data = 0x7ffff4593e20 <qt_meta_data_Qt>, static_metacall = 0x0, relatedMetaObjects = 0x0, extradata = 0x0}}}, static staticMetaObject = {d = {superdata = 0x7ffff46190e0 <QObject::staticMetaObject>, stringdata = 0x7ffff45aa5c0 <qt_meta_stringdata_QCoreApplication>, data = 0x7ffff45aa4a0 <qt_meta_data_QCoreApplication>, static_metacall = 0x7ffff44954d0 <QCoreApplication::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)>, relatedMetaObjects = 0x0, extradata = 0x0}}, static self = 0x7fffffffe3d0}, static staticMetaObject = {d = {superdata = 0x7ffff461f560 <QCoreApplication::staticMetaObject>, stringdata = 0x7ffff5e88640 <qt_meta_stringdata_QGuiApplication>, data = 0x7ffff5e88440 <qt_meta_data_QGuiApplication>, static_metacall = 0x7ffff5aef190 <QGuiApplication::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)>, relatedMetaObjects = 0x0, extradata = 0x0}}}, static staticMetaObject = {d = {superdata = 0x7ffff5f2b320 <QGuiApplication::staticMetaObject>, stringdata = 0x7ffff6667440 <qt_meta_stringdata_QApplication>, data = 0x7ffff66672c0 <qt_meta_data_QApplication>, static_metacall = 0x7ffff62bb2e0 <QApplication::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)>, relatedMetaObjects = 0x0, extradata = 0x0}}}
            box = {<generator::MergeMesh<generator::AxisSwapMesh<generator::detail::BoxFaces>, generator::UvFlipMesh<generator::AxisSwapMesh<generator::detail::BoxFaces> >, generator::detail::BoxFaces>> = {head_ = {<generator::TransformMesh<generator::detail::BoxFaces>> = {<generator::detail::BoxFaces> = {<generator::MergeMesh<generator::detail::BoxFace, generator::UvFlipMesh<generator::FlipMesh<generator::detail::BoxFace> > >> = {head_ = {<generator::TranslateMesh<generator::PlaneMesh>> = {<generator::TransformMesh<generator::PlaneMesh>> = {<generator::PlaneMesh> = {<generator::ParametricMesh> = {eval_ = {<std::_Maybe_unary_or_binary_function<generator::MeshVertex, glm::tvec2<double> const&>> = {<std::unary_function<glm::tvec2<double> const&, generator::MeshVertex>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x7ffff7e63000, _M_const_object = 0x7ffff7e63000, _M_function_pointer = 0x7ffff7e63000, _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0x7ffff7e63000, this adjustment 140737276081888}, _M_pod_data = "\000\060\346\367\377\177\000\000\340\366X\363\377\177\000"}, _M_manager = 0x7ffff3591ea0}, _M_invoker = 0x7ffff7de3802 <do_lookup_x+2002>}, segments_ = {{x = 376, r = 376, s = 376}, {y = 0, g = 0, t = 0}}, delta_ = {{x = 6.9533453206363427e-310, r = 6.9533453206363427e-310, s = 6.9533453206363427e-310}, {y = 6.9533490930196414e-310, g = 6.9533490930196414e-310, t = 6.9533490930196414e-310}}}, <No data fields>}, mutate_ = {<std::_Maybe_unary_or_binary_function<void, generator::MeshVertex&>> = {<std::unary_function<generator::MeshVertex&, void>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x7fffffffe138, _M_const_object = 0x7fffffffe138, _M_function_pointer = 0x7fffffffe138, _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0x7fffffffe138, this adjustment 140737488347444}, _M_pod_data = "8\341\377\377\377\177\000\000\064\341\377\377\377\177\000"}, _M_manager = 0x7ffff7de3190 <do_lookup_x+352>}, _M_invoker = 0xffff800000001ef1}}, <No data fields>}, <No data fields>}, tail_ = {head_ = {<generator::TransformMesh<generator::FlipMesh<generator::detail::BoxFace> >> = {<generator::FlipMesh<generator::detail::BoxFace>> = {<generator::TransformMesh<generator::detail::BoxFace>> = {<generator::detail::BoxFace> = {<generator::TranslateMesh<generator::PlaneMesh>> = {<generator::TransformMesh<generator::PlaneMesh>> = {<generator::PlaneMesh> = {<generator::ParametricMesh> = {eval_ = {<std::_Maybe_unary_or_binary_function<generator::MeshVertex, glm::tvec2<double> const&>> = {<std::unary_function<glm::tvec2<double> const&, generator::MeshVertex>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x41209b, _M_const_object = 0x41209b, _M_function_pointer = 0x41209b, _M_member_pointer = &virtual table offset 4268186, this adjustment 4209664}, _M_pod_data = "\233 A\000\000\000\000\000\000<@\000\000\000\000"}, _M_manager = 0x7fffffffe138}, _M_invoker = 0xb889e1b}, segments_ = {{x = 3023480, r = 3023480, s = 3023480}, {y = 0, g = 0, t = 0}}, delta_ = {{x = 2.3341953701951973e-312, r = 2.3341953701951973e-312, s = 2.3341953701951973e-312}, {y = 6.9533558074563524e-310, g = 6.9533558074563524e-310, t = 6.9533558074563524e-310}}}, <No data fields>}, mutate_ = {<std::_Maybe_unary_or_binary_function<void, generator::MeshVertex&>> = {<std::unary_function<generator::MeshVertex&, void>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x7ffff3591ea0, _M_const_object = 0x7ffff3591ea0, _M_function_pointer = 0x7ffff3591ea0, _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0x7ffff3591ea0, this adjustment 140737488347444}, _M_pod_data = "\240\036Y\363\377\177\000\000\064\341\377\377\377\177\000"}, _M_manager = 0x7fffffffe200}, _M_invoker = 0x8ee410}}, <No data fields>}, <No data fields>}, mutate_ = {<std::_Maybe_unary_or_binary_function<void, generator::MeshVertex&>> = {<std::unary_function<generator::MeshVertex&, void>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x0, _M_const_object = 0x0, _M_function_pointer = 0x0, _M_member_pointer = NULL}, _M_pod_data = "\000\000\000\000\000\000\000\000N\000\000\000\000\000\000"}, _M_manager = 0x1}, _M_invoker = 0x0}}, <No data fields>}, mutate_ = {<std::_Maybe_unary_or_binary_function<void, generator::MeshVertex&>> = {<std::unary_function<generator::MeshVertex&, void>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x9456c0, _M_const_object = 0x9456c0, _M_function_pointer = 0x9456c0, _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0x9456c0, this adjustment 140737354130656}, _M_pod_data = "\300V\224\000\000\000\000\000\340\344\377\367\377\177\000"}, _M_manager = 0x7fffffffe2a0}, _M_invoker = 0x7ffff7e2b590}}, <No data fields>}, tail_ = {<generator::EmptyMesh> = {<No data fields>}, <No data fields>}}}, <No data fields>}, mutate_ = {<std::_Maybe_unary_or_binary_function<void, generator::MeshVertex&>> = {<std::unary_function<generator::MeshVertex&, void>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x0, _M_const_object = 0x0, _M_function_pointer = 0x0, _M_member_pointer = NULL}, _M_pod_data = "\000\000\000\000\000\000\000\000\310\342\377\377\377\177\000"}, _M_manager = 0x7ffff7de3c51 <_dl_lookup_symbol_x+337>}, _M_invoker = 0x1a}}, flip_ = 144}, tail_ = {head_ = {<generator::TransformMesh<generator::AxisSwapMesh<generator::detail::BoxFaces> >> = {<generator::AxisSwapMesh<generator::detail::BoxFaces>> = {<generator::TransformMesh<generator::detail::BoxFaces>> = {<generator::detail::BoxFaces> = {<generator::MergeMesh<generator::detail::BoxFace, generator::UvFlipMesh<generator::FlipMesh<generator::detail::BoxFace> > >> = {head_ = {<generator::TranslateMesh<generator::PlaneMesh>> = {<generator::TransformMesh<generator::PlaneMesh>> = {<generator::PlaneMesh> = {<generator::ParametricMesh> = {eval_ = {<std::_Maybe_unary_or_binary_function<generator::MeshVertex, glm::tvec2<double> const&>> = {<std::unary_function<glm::tvec2<double> const&, generator::MeshVertex>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x1, _M_const_object = 0x1, _M_function_pointer = 0x1, _M_member_pointer = &virtual table offset 0}, _M_pod_data = "\001", '\000' <repeats 14 times>}, _M_manager = 0x1}, _M_invoker = 0x7ffff7ffe188}, segments_ = {{x = 9646432, r = 9646432, s = 9646432}, {y = 0, g = 0, t = 0}}, delta_ = {{x = 6.9533461788204644e-310, r = 6.9533461788204644e-310, s = 6.9533461788204644e-310}, {y = 0, g = 0, t = 0}}}, <No data fields>}, mutate_ = {<std::_Maybe_unary_or_binary_function<void, generator::MeshVertex&>> = {<std::unary_function<generator::MeshVertex&, void>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x7ffff7ffe4e0, _M_const_object = 0x7ffff7ffe4e0, _M_function_pointer = 0x7ffff7ffe4e0, _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0x7ffff7ffe4e0, this adjustment 140737488347664}, _M_pod_data = "\340\344\377\367\377\177\000\000\020\342\377\377\377\177\000"}, _M_manager = 0x1f3031aab}, _M_invoker = 0x7ffff7ffe188}}, <No data fields>}, <No data fields>}, tail_ = {head_ = {<generator::TransformMesh<generator::FlipMesh<generator::detail::BoxFace> >> = {<generator::FlipMesh<generator::detail::BoxFace>> = {<generator::TransformMesh<generator::detail::BoxFace>> = {<generator::detail::BoxFace> = {<generator::TranslateMesh<generator::PlaneMesh>> = {<generator::TransformMesh<generator::PlaneMesh>> = {<generator::PlaneMesh> = {<generator::ParametricMesh> = {eval_ = {<std::_Maybe_unary_or_binary_function<generator::MeshVertex, glm::tvec2<double> const&>> = {<std::unary_function<glm::tvec2<double> const&, generator::MeshVertex>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x7fffffffe200, _M_const_object = 0x7fffffffe200, _M_function_pointer = 0x7fffffffe200, _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0x7fffffffe200, this adjustment 4268187}, _M_pod_data = "\000\342\377\377\377\177\000\000\233 A\000\000\000\000"}, _M_manager = 0xb889e1b}, _M_invoker = 0x7767}, segments_ = {{x = 0, r = 0, s = 0}, {y = 0, g = 0, t = 0}}, delta_ = {{x = 6.9533453205794263e-310, r = 6.9533453205794263e-310, s = 6.9533453205794263e-310}, {y = 6.9533490930196414e-310, g = 6.9533490930196414e-310, t = 6.9533490930196414e-310}}}, <No data fields>}, mutate_ = {<std::_Maybe_unary_or_binary_function<void, generator::MeshVertex&>> = {<std::unary_function<generator::MeshVertex&, void>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x7ffff4622990 <(anonymous namespace)::Q_QGS_resourceList::innerFunction()::holder>, _M_const_object = 0x7ffff4622990 <(anonymous namespace)::Q_QGS_resourceList::innerFunction()::holder>, _M_function_pointer = 0x7ffff4622990 <(anonymous namespace)::Q_QGS_resourceList::innerFunction()::holder>, _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0x7ffff4622990 <(anonymous namespace)::Q_QGS_resourceList::innerFunction()::holder>, this adjustment 140737293461904}, _M_pod_data = "\220)b\364\377\177\000\000\220)b\364\377\177\000"}, _M_manager = 0x1}, _M_invoker = 0x7}}, <No data fields>}, <No data fields>}, mutate_ = {<std::_Maybe_unary_or_binary_function<void, generator::MeshVertex&>> = {<std::unary_function<generator::MeshVertex&, void>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x6, _M_const_object = 0x6, _M_function_pointer = 0x6, _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0x6, this adjustment 140737289591231}, _M_pod_data = "\006\000\000\000\000\000\000\000\277\031'\364\377\177\000"}, _M_manager = 0x6e0000005b}, _M_invoker = 0x0}}, <No data fields>}, mutate_ = {<std::_Maybe_unary_or_binary_function<void, generator::MeshVertex&>> = {<std::unary_function<generator::MeshVertex&, void>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x0, _M_const_object = 0x0, _M_function_pointer = 0x0, _M_member_pointer = NULL}, _M_pod_data = "\000\000\000\000\000\000\000\000\006\000\000\000\000\000\000"}, _M_manager = 0x945690}, _M_invoker = 0x8cdf78 <[email protected]>}}, <No data fields>}, tail_ = {<generator::EmptyMesh> = {<No data fields>}, <No data fields>}}}, <No data fields>}, mutate_ = {<std::_Maybe_unary_or_binary_function<void, generator::MeshVertex&>> = {<std::unary_function<generator::MeshVertex&, void>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x7fffffffe4f0, _M_const_object = 0x7fffffffe4f0, _M_function_pointer = 0x7fffffffe4f0, _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0x7fffffffe4f0, this adjustment 140737488348376}, _M_pod_data = "\360\344\377\377\377\177\000\000\330\344\377\377\377\177\000"}, _M_manager = 0x2}, _M_invoker = 0x0}}, flip_ = 237}, mutate_ = {<std::_Maybe_unary_or_binary_function<void, generator::MeshVertex&>> = {<std::unary_function<generator::MeshVertex&, void>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x1, _M_const_object = 0x1, _M_function_pointer = 0x1, _M_member_pointer = &virtual table offset 0}, _M_pod_data = "\001", '\000' <repeats 14 times>}, _M_manager = 0x6}, _M_invoker = 0x7ffff3591a20}}, <No data fields>}, tail_ = {head_ = {<generator::MergeMesh<generator::detail::BoxFace, generator::UvFlipMesh<generator::FlipMesh<generator::detail::BoxFace> > >> = {head_ = {<generator::TranslateMesh<generator::PlaneMesh>> = {<generator::TransformMesh<generator::PlaneMesh>> = {<generator::PlaneMesh> = {<generator::ParametricMesh> = {eval_ = {<std::_Maybe_unary_or_binary_function<generator::MeshVertex, glm::tvec2<double> const&>> = {<std::unary_function<glm::tvec2<double> const&, generator::MeshVertex>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x3b, _M_const_object = 0x3b, _M_function_pointer = 0x3b, _M_member_pointer = &virtual table offset 58, this adjustment 140737488348048}, _M_pod_data = ";\000\000\000\000\000\000\000\220\343\377\377\377\177\000"}, _M_manager = 0x3f80000000000000}, _M_invoker = 0x7ffff35a0426 <__ieee754_pow_sse2+886>}, segments_ = {{x = 1202590843, r = 1202590843, s = 1202590843}, {y = 1065646817, g = 1065646817, t = 1065646817}}, delta_ = {{x = 6.9533460278735777e-310, r = 6.9533460278735777e-310, s = 6.9533460278735777e-310}, {y = 0, g = 0, t = 0}}}, <No data fields>}, mutate_ = {<std::_Maybe_unary_or_binary_function<void, generator::MeshVertex&>> = {<std::unary_function<generator::MeshVertex&, void>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x4024000000000000, _M_const_object = 0x4024000000000000, _M_function_pointer = 0x4024000000000000, _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0x4024000000000000, this adjustment -4611686018427387904}, _M_pod_data = "\000\000\000\000\000\[email protected]\000\000\000\000\000\000\000\300"}, _M_manager = 0x0}, _M_invoker = 0x41a0000002000000}}, <No data fields>}, <No data fields>}, tail_ = {head_ = {<generator::TransformMesh<generator::FlipMesh<generator::detail::BoxFace> >> = {<generator::FlipMesh<generator::detail::BoxFace>> = {<generator::TransformMesh<generator::detail::BoxFace>> = {<generator::detail::BoxFace> = {<generator::TranslateMesh<generator::PlaneMesh>> = {<generator::TransformMesh<generator::PlaneMesh>> = {<generator::PlaneMesh> = {<generator::ParametricMesh> = {eval_ = {<std::_Maybe_unary_or_binary_function<generator::MeshVertex, glm::tvec2<double> const&>> = {<std::unary_function<glm::tvec2<double> const&, generator::MeshVertex>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x3fe0000000000000, _M_const_object = 0x3fe0000000000000, _M_function_pointer = 0x3fe0000000000000, _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0x3fe0000000000000}, _M_pod_data = "\000\000\000\000\000\000\340?\000\000\000\000\000\000\000"}, _M_manager = 0x1fa000001fa0}, _M_invoker = 0x7fffffffe4f0}, segments_ = {{x = 59, r = 59, s = 59}, {y = 0, g = 0, t = 0}}, delta_ = {{x = 6.9533558074753245e-310, r = 6.9533558074753245e-310, s = 6.9533558074753245e-310}, {y = 6.9533453271838982e-310, g = 6.9533453271838982e-310, t = 6.9533453271838982e-310}}}, <No data fields>}, mutate_ = {<std::_Maybe_unary_or_binary_function<void, generator::MeshVertex&>> = {<std::unary_function<generator::MeshVertex&, void>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x4024000000000000, _M_const_object = 0x4024000000000000, _M_function_pointer = 0x4024000000000000, _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0x4024000000000000, this adjustment -4611686018427387904}, _M_pod_data = "\000\000\000\000\000\[email protected]\000\000\000\000\000\000\000\300"}, _M_manager = 0xd9}, _M_invoker = 0x5cb74d <_ZSt3powIiiEN9__gnu_cxx11__promote_2IT_T0_NS0_9__promoteIS2_Xsr3std12__is_integerIS2_EE7__valueEE6__typeENS4_IS3_Xsr3std12__is_integerIS3_EE7__valueEE6__typeEE6__typeES2_S3_+29>}}, <No data fields>}, <No data fields>}, mutate_ = {<std::_Maybe_unary_or_binary_function<void, generator::MeshVertex&>> = {<std::unary_function<generator::MeshVertex&, void>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x8c7580, _M_const_object = 0x8c7580, _M_function_pointer = 0x8c7580, _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0x8c7580, this adjustment 47244640254}, _M_pod_data = "\200u\214\000\000\000\000\000\376\377\377\377\n\000\000"}, _M_manager = 0x7fffffffe3a0}, _M_invoker = 0x428b43 <__cxx_global_var_init()+19>}}, <No data fields>}, mutate_ = {<std::_Maybe_unary_or_binary_function<void, generator::MeshVertex&>> = {<std::unary_function<generator::MeshVertex&, void>> = {<No data fields>}, <No data fields>}, <std::_Function_base> = {static _M_max_size = 16, static _M_max_align = 8, _M_functor = {_M_unused = {_M_object = 0x7fffffffe3b0, _M_const_object = 0x7fffffffe3b0, _M_function_pointer = 0x7fffffffe3b0, _M_member_pointer = (void (std::_Undefined_class::*)(std::_Undefined_class * const)) 0x7fffffffe3b0, this adjustment 4361065}, _M_pod_data = "\260\343\377\377\377\177\000\000i\213B\000\000\000\000"}, _M_manager = 0x3c}, _M_invoker = 0x5e26dd <__libc_csu_init+77>}}, <No data fields>}, tail_ = {<generator::EmptyMesh> = {<No data fields>}, <No data fields>}}}, <No data fields>}, tail_ = {<generator::EmptyMesh> = {<No data fields>}, <No data fields>}}}}, <No data fields>}
            any = {base_ = {_M_t = {<std::_Tuple_impl<0, generator::AnyMesh::Base*, std::default_delete<generator::AnyMesh::Base> >> = {<std::_Tuple_impl<1, std::default_delete<generator::AnyMesh::Base> >> = {<std::_Head_base<1, std::default_delete<generator::AnyMesh::Base>, true>> = {<std::default_delete<generator::AnyMesh::Base>> = {<No data fields>}, <No data fields>}, <No data fields>}, <std::_Head_base<0, generator::AnyMesh::Base*, false>> = {_M_head_impl = 0x7ffff2fbddc8}, <No data fields>}, <No data fields>}}}
            w = {<QMainWindow> = {<QWidget> = {<QObject> = {_vptr.QObject = 0x7fffffffe398, static staticMetaObject = {d = {superdata = 0x0, stringdata = 0x7ffff454eea0 <qt_meta_stringdata_QObject>, data = 0x7ffff454ed80 <qt_meta_data_QObject>, static_metacall = 0x7ffff4424a40 <QObject::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)>, relatedMetaObjects = 0x0, extradata = 0x0}}, d_ptr = {d = 0x7fffffffe398}, static staticQtMetaObject = {d = {superdata = 0x0, stringdata = 0x7ffff45966a0 <qt_meta_stringdata_Qt>, data = 0x7ffff4593e20 <qt_meta_data_Qt>, static_metacall = 0x0, relatedMetaObjects = 0x0, extradata = 0x0}}}, <QPaintDevice> = {_vptr.QPaintDevice = 0x7fffffffe398, painters = 58264, reserved = 0x7fffffffe398}, static staticMetaObject = {d = {superdata = 0x7ffff46190e0 <QObject::staticMetaObject>, stringdata = 0x7ffff6669580 <qt_meta_stringdata_QWidget>, data = 0x7ffff6668ea0 <qt_meta_data_QWidget>, static_metacall = 0x7ffff62f9310 <QWidget::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)>, relatedMetaObjects = 0x0, extradata = 0x0}}, data = 0x7fffffffe398}, static staticMetaObject = {d = {superdata = 0x7ffff67afba0 <QWidget::staticMetaObject>, stringdata = 0x7ffff66ef540 <qt_meta_stringdata_QMainWindow>, data = 0x7ffff66ef380 <qt_meta_data_QMainWindow>, static_metacall = 0x7ffff664c4e0 <QMainWindow::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)>, relatedMetaObjects = 0x7ffff67d0a90 <qt_meta_extradata_QMainWindow>, extradata = 0x0}}}, static staticMetaObject = {d = {superdata = 0x7ffff67d0a60 <QMainWindow::staticMetaObject>, stringdata = 0x5efbb0 <qt_meta_stringdata_balls__BallsWindow>, data = 0x5efd50 <qt_meta_data_balls__BallsWindow>, static_metacall = 0x5ba280 <balls::BallsWindow::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)>, relatedMetaObjects = 0x0, extradata = 0x0}}, ui = {<Ui_BallsWindow> = {actionNew_Project = 0x7fffffffe398, actionOpen = 0x7fffffffe398, actionSave = 0x7fffffffe398, actionSave_File = 0x7fffffffe398, actionSave_Project = 0x7fffffffe398, actionSave_Project_As = 0x7fffffffe398, actionQuit = 0x7fffffffe398, actionZoom_In = 0x7fffffffe398, actionZoom_Out = 0x7fffffffe398, actionReset_Zoom = 0x7fffffffe398, actionCompile = 0x7fffffffe398, actionAbout_BALLS = 0x7fffffffe398, actionReset_Camera = 0x7fffffffe398, actionOpenGL_Info = 0x7fffffffe398, actionList_of_Uniforms = 0x7fffffffe398, actionAbout_Qt = 0x7fffffffe398, actionDefault = 0x7fffffffe398, actionPhong_Lighting = 0x7fffffffe398, centralWidget = 0x7fffffffe398, windowLayout = 0x7fffffffe398, canvas = 0x7fffffffe398, menuBar = 0x7fffffffe398, menuFile = 0x7fffffffe398, menuExamples = 0x7fffffffe398, menuEdit = 0x7fffffffe398, menuProject = 0x7fffffffe398, menuAbout = 0x7fffffffe398, menuView = 0x7fffffffe398, statusBar = 0x7fffffffe398, editorDock = 0x7fffffffe398, editorDockContents = 0x7fffffffe398, editorDockLayout = 0x7fffffffe398, tabs = 0x7fffffffe398, vertexTab = 0x7fffffffe398, vertexLayout = 0x7fffffffe398, vertexEditor = 0x7fffffffe398, fragmentTab = 0x7fffffffe398, fragmentLayout = 0x7fffffffe398, fragmentEditor = 0x7fffffffe398, geometryTab = 0x7fffffffe398, geometryLayout = 0x7fffffffe398, geometryEditor = 0x7fffffffe398, logDock = 0x7fffffffe398, logDockContents = 0x7fffffffe398, gridLayout = 0x7fffffffe398, log = 0x7fffffffe398, uniformDock = 0x7fffffffe398, uniformDockContents = 0x7fffffffe398, gridLayout_2 = 0x7fffffffe398, uniformScroll = 0x7fffffffe398, uniformScrollContents = 0x7fffffffe398, uniformScrollCotentsLayout = 0x7fffffffe398, uniforms = 0x7fffffffe398, textureDock = 0x7fffffffe398, textureManager = 0x7fffffffe398, meshDock = 0x7fffffffe398, meshManager = 0x7fffffffe398}, <No data fields>}, _generatorsInitialized = 152, _settings = 0x7fffffffe398, _vertLexer = 0x7fffffffe398, _fragLexer = 0x7fffffffe398, _geomLexer = 0x7fffffffe398, _save = 0x7fffffffe398, _load = 0x7fffffffe398, _error = 0x7fffffffe398, m_uniforms = {<QObject> = {_vptr.QObject = 0x7fffffffe398, static staticMetaObject = {d = {superdata = 0x0, stringdata = 0x7ffff454eea0 <qt_meta_stringdata_QObject>, data = 0x7ffff454ed80 <qt_meta_data_QObject>, static_metacall = 0x7ffff4424a40 <QObject::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)>, relatedMetaObjects = 0x0, extradata = 0x0}}, d_ptr = {d = 0x7fffffffe398}, static staticQtMetaObject = {d = {superdata = 0x0, stringdata = 0x7ffff45966a0 <qt_meta_stringdata_Qt>, data = 0x7ffff4593e20 <qt_meta_data_Qt>, static_metacall = 0x0, relatedMetaObjects = 0x0, extradata = 0x0}}}, static staticMetaObject = {d = {superdata = 0x7ffff46190e0 <QObject::staticMetaObject>, stringdata = 0x5f1320 <qt_meta_stringdata_balls__Uniforms>, data = 0x5f15d0 <qt_meta_data_balls__Uniforms>, static_metacall = 0x5bf150 <balls::Uniforms::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)>, relatedMetaObjects = 0x0, extradata = 0x0}}, _meta = 0x7fffffffe398, _uniformList = {<std::_Vector_base<balls::util::types::UniformInfo, std::allocator<balls::util::types::UniformInfo> >> = {_M_impl = {<std::allocator<balls::util::types::UniformInfo>> = {<__gnu_cxx::new_allocator<balls::util::types::UniformInfo>> = {<No data fields>}, <No data fields>}, _M_start = 0x7fffffffe398, _M_finish = 0x7fffffffe398, _M_end_of_storage = 0x7fffffffe398}}, <No data fields>}, _model = {value = {{{x = -nan(0x7fe398), r = -nan(0x7fe398), s = -nan(0x7fe398)}, {y = 4.59163468e-41, g = 4.59163468e-41, t = 4.59163468e-41}, {z = -nan(0x7fe398), b = -nan(0x7fe398), p = -nan(0x7fe398)}, {w = 4.59163468e-41, a = 4.59163468e-41, q = 4.59163468e-41}}, {{x = -nan(0x7fe398), r = -nan(0x7fe398), s = -nan(0x7fe398)}, {y = 4.59163468e-41, g = 4.59163468e-41, t = 4.59163468e-41}, {z = -nan(0x7fe398), b = -nan(0x7fe398), p = -nan(0x7fe398)}, {w = 4.59163468e-41, a = 4.59163468e-41, q = 4.59163468e-41}}, {{x = -nan(0x7fe398), r = -nan(0x7fe398), s = -nan(0x7fe398)}, {y = 4.59163468e-41, g = 4.59163468e-41, t = 4.59163468e-41}, {z = -nan(0x7fe398), b = -nan(0x7fe398), p = -nan(0x7fe398)}, {w = 4.59163468e-41, a = 4.59163468e-41, q = 4.59163468e-41}}, {{x = -nan(0x7fe398), r = -nan(0x7fe398), s = -nan(0x7fe398)}, {y = 4.59163468e-41, g = 4.59163468e-41, t = 4.59163468e-41}, {z = -nan(0x7fe398), b = -nan(0x7fe398), p = -nan(0x7fe398)}, {w = 4.59163468e-41, a = 4.59163468e-41, q = 4.59163468e-41}}}}, _view = {value = {{{x = -nan(0x7fe398), r = -nan(0x7fe398), s = -nan(0x7fe398)}, {y = 4.59163468e-41, g = 4.59163468e-41, t = 4.59163468e-41}, {z = -nan(0x7fe398), b = -nan(0x7fe398), p = -nan(0x7fe398)}, {w = 4.59163468e-41, a = 4.59163468e-41, q = 4.59163468e-41}}, {{x = -nan(0x7fe398), r = -nan(0x7fe398), s = -nan(0x7fe398)}, {y = 4.59163468e-41, g = 4.59163468e-41, t = 4.59163468e-41}, {z = -nan(0x7fe398), b = -nan(0x7fe398), p = -nan(0x7fe398)}, {w = 4.59163468e-41, a = 4.59163468e-41, q = 4.59163468e-41}}, {{x = -nan(0x7fe398), r = -nan(0x7fe398), s = -nan(0x7fe398)}, {y = 4.59163468e-41, g = 4.59163468e-41, t = 4.59163468e-41}, {z = -nan(0x7fe398), b = -nan(0x7fe398), p = -nan(0x7fe398)}, {w = 4.59163468e-41, a = 4.59163468e-41, q = 4.59163468e-41}}, {{x = -nan(0x7fe398), r = -nan(0x7fe398), s = -nan(0x7fe398)}, {y = 4.59163468e-41, g = 4.59163468e-41, t = 4.59163468e-41}, {z = -nan(0x7fe398), b = -nan(0x7fe398), p = -nan(0x7fe398)}, {w = 4.59163468e-41, a = 4.59163468e-41, q = 4.59163468e-41}}}}, _projection = {value = {{{x = -nan(0x7fe398), r = -nan(0x7fe398), s = -nan(0x7fe398)}, {y = 4.59163468e-41, g = 4.59163468e-41, t = 4.59163468e-41}, {z = -nan(0x7fe398), b = -nan(0x7fe398), p = -nan(0x7fe398)}, {w = 4.59163468e-41, a = 4.59163468e-41, q = 4.59163468e-41}}, {{x = -nan(0x7fe398), r = -nan(0x7fe398), s = -nan(0x7fe398)}, {y = 4.59163468e-41, g = 4.59163468e-41, t = 4.59163468e-41}, {z = -nan(0x7fe398), b = -nan(0x7fe398), p = -nan(0x7fe398)}, {w = 4.59163468e-41, a = 4.59163468e-41, q = 4.59163468e-41}}, {{x = -nan(0x7fe398), r = -nan(0x7fe398), s = -nan(0x7fe398)}, {y = 4.59163468e-41, g = 4.59163468e-41, t = 4.59163468e-41}, {z = -nan(0x7fe398), b = -nan(0x7fe398), p = -nan(0x7fe398)}, {w = 4.59163468e-41, a = 4.59163468e-41, q = 4.59163468e-41}}, {{x = -nan(0x7fe398), r = -nan(0x7fe398), s = -nan(0x7fe398)}, {y = 4.59163468e-41, g = 4.59163468e-41, t = 4.59163468e-41}, {z = -nan(0x7fe398), b = -nan(0x7fe398), p = -nan(0x7fe398)}, {w = 4.59163468e-41, a = 4.59163468e-41, q = 4.59163468e-41}}}}, _trackball = {_start = {{x = -nan(0x7fe398), r = -nan(0x7fe398), s = -nan(0x7fe398)}, {y = 4.59163468e-41, g = 4.59163468e-41, t = 4.59163468e-41}, {z = -nan(0x7fe398), b = -nan(0x7fe398), p = -nan(0x7fe398)}}, _end = {{x = 4.59163468e-41, r = 4.59163468e-41, s = 4.59163468e-41}, {y = -nan(0x7fe398), g = -nan(0x7fe398), t = -nan(0x7fe398)}, {z = 4.59163468e-41, b = 4.59163468e-41, p = 4.59163468e-41}}, AdjustWidth = -nan(0x7fe398), AdjustHeight = 4.59163468e-41, _rotation = {x = -nan(0x7fe398), y = 4.59163468e-41, z = -nan(0x7fe398), w = 4.59163468e-41}, _matrix = {value = {{{x = -nan(0x7fe398), r = -nan(0x7fe398), s = -nan(0x7fe398)}, {y = 4.59163468e-41, g = 4.59163468e-41, t = 4.59163468e-41}, {z = -nan(0x7fe398), b = -nan(0x7fe398), p = -nan(0x7fe398)}, {w = 4.59163468e-41, a = 4.59163468e-41, q = 4.59163468e-41}}, {{x = -nan(0x7fe398), r = -nan(0x7fe398), s = -nan(0x7fe398)}, {y = 4.59163468e-41, g = 4.59163468e-41, t = 4.59163468e-41}, {z = -nan(0x7fe398), b = -nan(0x7fe398), p = -nan(0x7fe398)}, {w = 4.59163468e-41, a = 4.59163468e-41, q = 4.59163468e-41}}, {{x = -nan(0x7fe398), r = -nan(0x7fe398), s = -nan(0x7fe398)}, {y = 4.59163468e-41, g = 4.59163468e-41, t = 4.59163468e-41}, {z = -nan(0x7fe398), b = -nan(0x7fe398), p = -nan(0x7fe398)}, {w = 4.59163468e-41, a = 4.59163468e-41, q = 4.59163468e-41}}, {{x = -nan(0x7fe398), r = -nan(0x7fe398), s = -nan(0x7fe398)}, {y = 4.59163468e-41, g = 4.59163468e-41, t = 4.59163468e-41}, {z = -nan(0x7fe398), b = -nan(0x7fe398), p = -nan(0x7fe398)}, {w = 4.59163468e-41, a = 4.59163468e-41, q = 4.59163468e-41}}}}}, _mousePos = {{x = -7272, r = -7272, s = -7272}, {y = 32767, g = 32767, t = 32767}}, _lastMousePos = {{x = -7272, r = -7272, s = -7272}, {y = 32767, g = 32767, t = 32767}}, _canvasSize = {{x = 4294960024, r = 4294960024, s = 4294960024}, {y = 32767, g = 32767, t = 32767}}, _lastCanvasSize = {{x = 4294960024, r = 4294960024, s = 4294960024}, {y = 32767, g = 32767, t = 32767}}, _fov = -nan(0x7fe398), _farPlane = 4.59163468e-41, _nearPlane = -nan(0x7fe398), _elapsedTime = {t1 = 140737488348056, t2 = 140737488348056}}, m_meshes = {<QObject> = {_vptr.QObject = 0x7fffffffe398, static staticMetaObject = {d = {superdata = 0x0, stringdata = 0x7ffff454eea0 <qt_meta_stringdata_QObject>, data = 0x7ffff454ed80 <qt_meta_data_QObject>, static_metacall = 0x7ffff4424a40 <QObject::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)>, relatedMetaObjects = 0x0, extradata = 0x0}}, d_ptr = {d = 0x7fffffffe398}, static staticQtMetaObject = {d = {superdata = 0x0, stringdata = 0x7ffff45966a0 <qt_meta_stringdata_Qt>, data = 0x7ffff4593e20 <qt_meta_data_Qt>, static_metacall = 0x0, relatedMetaObjects = 0x0, extradata = 0x0}}}, static staticMetaObject = {d = {superdata = 0x7ffff46190e0 <QObject::staticMetaObject>, stringdata = 0x5f3db0 <qt_meta_stringdata_balls__Meshes>, data = 0x5f3ee0 <qt_meta_data_balls__Meshes>, static_metacall = 0x5c9ba0 <balls::Meshes::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)>, relatedMetaObjects = 0x0, extradata = 0x0}}, m_meshes = {<std::_Vector_base<balls::Mesh*, std::allocator<balls::Mesh*> >> = {_M_impl = {<std::allocator<balls::Mesh*>> = {<__gnu_cxx::new_allocator<balls::Mesh*>> = {<No data fields>}, <No data fields>}, _M_start = 0x7fffffffe398, _M_finish = 0x7fffffffe398, _M_end_of_storage = 0x7fffffffe398}}, <No data fields>}}}
    
    opened by JesseTG 19
  • Infinite loop when generating IcosahedronMesh or IcoSphereMesh

    Infinite loop when generating IcosahedronMesh or IcoSphereMesh

    This happens in my own code, but not in generate-glm. It could just be my own code, but I wanted to report this before I forget.

    Looks like it's in the generation of Triangles.

    Also may have something to do with an unsigned integer either not being initialized or over/underflowing.

    Also, this is with GLM.

    opened by JesseTG 10
  • msvc 2015 x64 compilation issue

    msvc 2015 x64 compilation issue

    Hi,

    we are trying to build your lib (with glm) on Windows with msvc 2015 (x64) and we have the following issue
    Error C2075 'generator::BezierMesh<4,4>::<lambda_02d0d7e77aad534a6c6983f51d8c6cae>::p' : array initialization needs curly braces

    in this part : /// @param p Control points /// @param segments Number of subdivisions along each axis explicit BezierMesh( const gml::dvec3 (&p)[D1][D0] = {}, const gml::uvec2 segments = {16u, 16u} ) : mParametricMesh{

            // Lambda capture the array by value.
            [p] (const gml::dvec2& t) {
                MeshVertex vertex;
    
                vertex.position = gml::bezier2(p, t);
    
                gml::dmat2x3 J = gml::bezier2Jacobian<1>(p, t);
                vertex.normal = gml::cross(J[0], J[1]);
    
                // If the normal was zero try a again near by.
                const double e = std::numeric_limits<double>::epsilon();
                if (dot(vertex.normal, vertex.normal) < e) {
                    J = gml::bezier2Jacobian<1>(p, t + 10.0 * e);
                    vertex.normal = gml::cross(J[0], J[1]);
                }
                vertex.normal = gml::normalize(vertex.normal);
    
                vertex.texCoord = t;
    
                return vertex;
            },
            segments
        }
    
    { }
    
    opened by qtnext 8
  • Make generator more msvc-friendly

    Make generator more msvc-friendly

    This PR makes generator able to compile in Visual C++ 2015 by doing the following:

    • ~~Changing all inheritance from private to public~~ I removed that commit
    • Adding some msvc-specific information to CMakeLists.txt
    opened by JesseTG 8
  • How set are you on using your own math library?

    How set are you on using your own math library?

    I think GLM would be a better fit, personally, as it's similarly lightweight and more maintained. But if you'd like, I can compromise and let the user pick between GLM and GML at compile-time.

    opened by JesseTG 2
  • Issues with SphereMesh

    Issues with SphereMesh

    Hello! I'm trying to use the sphere mesh and when looping over vertices, the first 32 positions are 0, 0, 1. This ends up generating something that looks kind of like an icecream cone. IcoSphereMesh works fine though. Have you seen this issue? screen shot 2018-07-22 at 11 43 24 am screen shot 2018-07-22 at 11 44 06 am

    opened by stollio 1
  • Fix some #include errors

    Fix some #include errors

    You'd think someone would have made a library for something like this a long time ago. Well, I don't feel like writing my own, so you're stuck with me contributing to yours. Looks like I could get some use out of it!

    opened by JesseTG 0
  • Add fix for MSVC 'no std::min/max' error

    Add fix for MSVC 'no std::min/max' error

    As far as I can tell, this project won't compile in Visual Studio without adding a reference to <algorithm> in the file that uses std::min and std::max.

    opened by heyx3 0
  • Generate closed cylinder

    Generate closed cylinder

    Cylinder generation is made by sweeping. If a solid cylinder is generated, the algorithm creates overlapping points at the beginning and the end. This way, the surface is not a closed one... It's there a way to fix this? Thanks

    opened by Albmargar1 0
  • Make GLM/GML compatibility layer in math.hpp more transparent

    Make GLM/GML compatibility layer in math.hpp more transparent

    I.e. make it more idiot-proof while changing the existing generator code as little as possible, and not changing gml at all. Also, better document the addition of more GML substitutes.

    opened by JesseTG 0
Owner
Ilmola
Ilmola
Procedural Generation Experiments

Procedural Generation Experiments What is this? This application is a tool to create and paint L-System in a fully interactive and dynamic way. “But,”

Thomas Munoz 107 Sep 28, 2022
An efficient texture-free GLSL procedural noise library

Wombat An efficient texture-free GLSL procedural noise library Source: https://github.com/BrianSharpe/Wombat Derived from: https://github.com/BrianSha

Brian Sharpe 196 Sep 24, 2022
Procedural world generator written in C++. Uses SFML for map rendering.

World Generator Archived as the code is a big mess and it'd be easier to start from scratch than to clean up this code. A procedural world generator i

moneyl 31 Aug 13, 2022
Procedural tree mesh generator (and editor)

ProcTree This is a liberally licensed procedural tree generator in c++, along with an editor HappyTree. (youtube video) The procedural generation itse

Jari Komppa 182 Sep 6, 2022
First open source android modding library for Geometry Dash Based on Hooking-and-Patching-android-template

Android-ML First open source android modding library for Geometry Dash Based on Hooking-and-Patching-android-template Installation Download this githu

BlackTea ML 21 Jul 17, 2022
Wykobi is an efficient, robust and simple to use multi-platform 2D/3D computational geometry library.

Description Wykobi is an efficient, robust and simple to use multi-platform 2D/3D computational geometry library. Wykobi provides a concise, predictab

Arash Partow 129 Sep 13, 2022
Automatic adds AFIX instructions for hydrogen atoms to SHELX input file based on geometry and residual desity

autoHFIX Adds AFIX instructions for hydrogen atoms to SHELX input files based on geometry and residual desity automatically Usage: autoHFIX.exe [-opti

Christian Hübschle 2 Oct 7, 2021
First open-source Geometry Dash cross-platform Modding SDK

BoolkaSDK First open-source Geometry Dash cross-platform Modding SDK Requirements CMake 3.21 Android NDK r23 LLVM x86 Java and ApkTool Building Open C

null 6 Jun 9, 2022
A Geometry Dash mod that lets you select the screen to run the game on

Screen Selector A mod that lets you select the screen to run Geometry Dash on Fully compatible with Mega Hack v6 (except the "Fullscreen" and "Borderl

ConfiG 8 Jun 3, 2022
Geometry Dash Open-Source Cheat

GDOC Geometry Dash Open-Source Cheat Building and Running Copy GDOC dir to the GD dir Generate Project With CMake (Visual Studio, x32) Add all files f

pixelsuft‮ 3 Jul 18, 2022
Adds MSAAx4 antialiasing to Geometry Dash.

GDAntiAliasing Adds MSAAx4 antialiasing to Geometry Dash. Currently only on Windows. Example Boom Slayer endscreen without antialiasing: Boom Slayer e

IliasHDZ 5 Sep 4, 2022
An 802.11 Frame Generation and Parsing Library in C

libwifi 802.11 Parsing / Generation library Build Status OS Architecture Linux x86_64 What is this? libwifi is a C library with a permissive license f

null 29 Aug 20, 2022
A static C++ library for the generation of discrete functions on a box-shaped domain

A static C++ library for the generation of discrete functions on a box-shaped domain. This is especially suited for the discretization of signed distance fields.

Interactive Computer Graphics 231 Sep 29, 2022
Stack-based texture generation tool written in C99!

Stack-based texture generation tool written in C99! Brought to you by @zaklaus and contributors Introduction zpl.texed is a cross-platform stack-based

zpl | pushing the boundaries of simplicity. 19 Sep 10, 2022
FluidNC - The next generation of motion control firmware

FluidNC (CNC Controller) For ESP32 Introduction FluidNC is the next generation of Grbl_ESP32. It has a lot of improvements over Grbl_ESP32 as listed b

null 575 Oct 2, 2022
🎻 Automatic Exploit Generation using symbolic execution

S2E Library This repository contains all the necessary components to build libs2e.so. This shared library is preloaded in QEMU to enable symbolic exec

ᴀᴇꜱᴏᴘʜᴏʀ 29 Jan 10, 2022
The ESP-BOX is a new generation AIoT development platform released by Espressif Systems.

中文版本 ESP-BOX AIoT Development Framework Important Note: We recommend updating the ESP32-S3-BOX firmware when you first receive the product to have the

Espressif Systems 138 Sep 24, 2022
Simple, fully external, smart, fast, JSON-configurated, feature-rich Windows x86 DLL Memory Dumper with Code Generation. Written in Modern C++.

altdumper Simple, fully external, smart, fast, JSON-configurated, feature-rich Windows x86 DLL Memory Dumper with Code Generation. Written in Modern C

cristei 14 Sep 9, 2022
A model checker for the Dynamic Logic of Propositional Assignments (DL-PA) with solving and parameterized random formula generation functionalities.

A model checker for the Dynamic Logic of Propositional Assignments (DL-PA) with solving and parameterized random formula generation functionalities.

Jeffrey Yang 7 Dec 31, 2021