Archive for the ‘glgeom’ Category

GLGeom v0.0.6 Released!

without comments

GLGeom v0.0.6 has been released!

GLGeom is the header-only C++ template math library developed in conjunction with LxEngine, modeled after and extending the GLM mathematics library. It provides strongly typed point, vector, and color classes, polygonal mesh and primitives classes (spheres, cylinders, etc.), bounding objects, intersection calculations, and more.

Release 0.0.6 contains many improvements and changes. The most significant changes may be to the glgeom_extension_primitive_buffer module, a module designed to provide a slightly higher-level, CPU-side take on a vertex array object: it stores a mesh (quads, triangles, lines, points) as well as optional arrays for face properties and vertex properties like normals, colors, and UVs. It now also includes some basic adjacency information. All of these properties can be set manually or, when possible, generated automatically.

The full release notes which includes download links, API documentation, and code diffs are located here:

GLGeom v0.0.6

As it will be for some time, it’s still a very early release but feedback is greatly appreciated. Leave a comment on the blog!

Example Code

// Use a utility method to create a basic shape
glgeom::primitive_buffer primitive = glgeom::create_sphere();
 
// Automatically compute face normals on the sphere 
glgeom::compute_face_normals(primitive);
 
//
// Generate some UV coordinates
//
// Use a spherical mapper with a scale transform of 10.
//
glgeom::compute_uv_mapping(
    primitive, 0,
    [](const glgeom::point3f& position, glgeom::vector3f& normal) -> glgeom::point2f {
         glgeom::point2f baseUV = glgeom::mapper_spherical(position);
         return glgeom::scale( baseUV, glgeom::vector2f(10, 10) );
});

And a look at the primitive buffer functions…

Obviously a little incomplete, but we’re still at 0.0.6!

//===========================================================================//
// GEOMETRY CREATION
//===========================================================================//
 
inline primitive_buffer     create_cube                 (void);
inline primitive_buffer     create_sphere               (void);
inline primitive_buffer     create_cylinder             (void);
inline primitive_buffer     create_cone                 (void);
inline primitive_buffer     create_torus                (void);
 
inline primitive_buffer     create_vertex_normals_mesh  (primitive_buffer& mesh);
inline primitive_buffer     create_face_normals_mesh    (primitive_buffer& mesh);
 
//===========================================================================//
// ITERATORS
//===========================================================================//
 
inline void                 iterate_indices             (primitive_buffer& primitive, 
                                                        std::function<void (size_t faceIndex, glgeom::uint16* vertexIndices)> f);
 
//===========================================================================//
// BOUNDS
//===========================================================================//
 
inline void                 compute_bounds              (primitive_buffer& primitive, glgeom::abbox3f& bbox);
inline void                 compute_bounds              (primitive_buffer& primitive, glgeom::bsphere3f& bsphere);
inline void                 compute_bounds              (primitive_buffer& primitive, glgeom::abbox3f& bbox, glgeom::bsphere3f& bsphere);
inline void                 compute_bounding_box        (primitive_buffer& primitive);
inline void                 compute_bounding_sphere     (primitive_buffer& primitive);
inline void                 compute_bounds              (primitive_buffer& primitive);
 
//===========================================================================//
// NORMALS
//===========================================================================//
 
inline void                 compute_face_normals        (primitive_buffer& primitive);
inline void                 compute_vertex_normals      (primitive_buffer& primitive);
inline void                 compute_uv_mapping          (primitive_buffer& primitive, 
                                                        size_t channel, 
                                                        std::function<glgeom::point2f (const glgeom::point3f&, const glgeom::vector3f&)> f);
 
//===========================================================================//
// ADJACENCY
//===========================================================================//
 
inline void                 compute_adjacency_vertex_to_faces   (primitive_buffer& primitive);
inline bool                 verify_adjacency_vertex_to_faces    (primitive_buffer& primitive, 
                                                                bool report = true);
 
//===========================================================================//
// MISC
//===========================================================================//
 
inline void                 reverse_winding_order       (primitive_buffer& primitive);

Written by arthur

April 12th, 2012 at 5:06 pm

Today’s Updates

without comments

What I’ve been working on today…

Created a stub for lxcore.lib

Currently, LxEngine is composed of the following:

  • glgeom (header-only library of math functions)
  • lxengine.lib (where the vast majority of the code is)
  • lxengineapp.exe (a small front-end that drives the code in lxengine.lib)

What I’d like it to be is:

  • glgeom (same as before)
  • lxcore.lib (low-level, standalone functions and data types from lxengine.lib)
  • lxframework.lib (the higher-level framework of Engine, Document, View, Element, classes)
  • lxengine.exe (slightly larger front-end that drives the framework in a flexible, configurable form)

That’s a bit of an over simplification since there’s also extension libraries like lxrasterizer.lib and plug-ins like soundAL.dll, which exist now and will continue to exist.

The general point however is that I want make the framework “leaner.”  Right now it has too many specific features (mostly from early development when things weren’t very modular) and it should really be a rather bare but flexible MVC framework.  Those features belong in plug-ins and extensions. Even the utility stand-alone functions belong elsewhere (lxcore.lib). The end goal is a smaller framework is much better: frameworks are useful – right up until the point they become bloated and hard to understand (and thus defect prone and with steep learning curves).

GLGeom Error Handling

Long story short: all this time, I’ve been using “assert(0)” as an error handling mechanism in GLGeom to keep from tying in any dependencies.  That’s not a very valid approach…

So I’m added a simple, but flexible error handling mechanism instead: docs here.

GLGeom Compute Primitive Buffer Adjacency Info

Still a work-in-progress, I’m trying to port over some old code that is pretty fast at computing adjacency from a polygon soup.  This is also stressing GLGeom from a new angle, which is helping me fill in the blanks on some of the functionality in this currently-version-0.0.5-library.

Better get back to working on it…

 

Written by arthur

April 12th, 2012 at 10:13 am

GLGeom UV generators

with 2 comments

Per Dave’s request, I’ve recently added a new function to generate UV coordinates on a glgeom::primitive_buffer. The function name is glgeom::compute_uv_mapping().

The principle is simple: it’s a callback-based function that iterates over all the vertices and calls the callback to generate a UV coordinate. The existing glgeom_extension_mappers module already provides worker functions to use in the callback argument (e.g. mapper_cube, mapper_spherical).

Images

Above is a spherical mapper with a 10x scale applied to the terrain geometry.

Above is a cube mapper with a 10x scale applied to the terrain geometry.

Code

The syntax for generating a planar XY mapping is as follows:

glgeom::compute_uv_mapping(primitive, 0, [](const glgeom::point3f& p, const glgeom::vector3f& n) -> glgeom::point2f {
     return glgeom::scale( glgeom::mapper_planar_xy(p), glgeom::vector2f(10, 10));
});

Using namespace glgeom, it looks like this:

compute_uv_mapping(primitive, 0, [](const point3f& p, const vector3f& n) -> point2f {
     return scale( mapper_planar_xy(p), vector2f(10, 10));
});

For anyone living in the dark ages of pre-C++11, the above code reads as follows:

  • Compute a UV mapping for “primitive”
  • Store the computed UVs in channel 0
  • Generate a lambda function as callback…
  • …which takes in a 3d position and a normal and returns a 2d point (i.e. the UV coordinate)
  • …which uses the GLGeom built-in “mapper_planar_xy” function to generate the UV
  • …and lastly applies a scale factor of 10 to both the u and v coordinates

API Design Commentary

I have to admit, I’ve not thoroughly satisfied with the resulting code above. It’s a bit verbose and has a very high syntactical-boilerplate-to-content ratio. However, this is the best compromise I’ve come up with yet.

What I don’t like about this design

  • The lamdba notation is heavy-weight: there’s almost as much code to define the lambda signature as there is in the lambda body
  • It’s possibly too general: in an ideal design, everything should have an immediately obvious place. Mappers transformations (scaling and rotation) as quite common so I’d be nice to have a “built-in” argument for these rather than relying on the user adding them manually into the lambda (and possibly introducing a typo into the multiplication order)
  • Is a UV coordinate a “point”? In theory yes, in practice UVs are often treated as generic tuples, making the glgeom::point2t type occasionally cumbersome

Why not allow function pointers to be passed in directly?

I’d like it better if syntax like this worked:

  glgeom::compute_uv_mapping(primitive, glgeom::mapper_cube);

But this doesn’t work well. I want to support mapper functions that require positions and normals (e.g. mapper_cube) as well as those that depend only on position (e.g. mapper_spherical). I also want to support lambda functions for inlined custom mappers. Overloading a compute_uv_mapping template method to automatically choose the right variation did not seem to work (VS2010, at least, doesn’t seem to handle overloading well with lambdas of varying type). The compiler doesn’t seem to automatically resolve to the right template overload in a way that provides the syntax I’d like.

With this approach, I ended up with compiler complaints about ambiguous type resolution.

Why not provide an explicit set of compute_uv_* methods?

The ugly boilerplate syntax would go away if a series of functions where provided:

  glgeom::compute_uv_cube_mapping(primitive, uv_transform);
  glgeom::compute_uv_spherical_mapping(primitive, uv_transform);
  glgeom::compute_uv_planar_xy_mapping(primitive, uv_transform);
  ...

I like this approach that (a) syntax doesn’t get in the way and (b) it leads to about as self-documenting code as is possible.

What I don’t like is (a) it requires a mirror function for every mapper defined in the glgeom_extension_mappers and (b) creates a dependency between the glgeom_extension_mappers module and the glgeom_extension_primitive_buffer module.

So…?

I much prefer the principle that a generic function to apply an mapper exists alongside and independent of the set of mappers that can be applied (i.e. something a bit more along the lines of functional programming, thank you Javascript and JQuery for teaching me how nice this approach can be!). With that principle in mind, I’ve ended up with the syntactically verbose lambda based approach.

What’s Next?

Hopefully, generating tangents and bi-tangents. I wrote a bit before about bump mapping and generating those values in the GLSL shader, but it would be nice to compute such data easily on the CPU side as well.

In any case, this will require me to add some functions to compute mesh adjacency information for a primitive buffer – a feature I’ve been meaning to add anyway.

Written by arthur

April 11th, 2012 at 11:42 am

glgeom::create_sphere()

with 3 comments

Per the first ever user request (thanks Dave), GLGeom has a new feature:

glgeom::primitive_buffer glgeom::create_sphere();

Implementation

The code, located here, works as follows:

  1. Creates a unit cube
  2. Moves vertices onto the surface of a unit sphere
  3. Split each quad into four quads via introducing a quad midpoint
  4. Move the new vertex onto the surface of the unit sphere
  5. Repeat steps 3 & 4 for several iterations

Why add this?

While LxEngine does already support loading meshes from Blender files, I do like the idea of providing some basic shapes for the GLGeom library. It does have practical application: especially when throwing together a quick test or maybe implementing a research project, it can be nice to create a zero-dependencies executable that creates rather than loads the geometry it needs. I see this as a feature useful for the small samples and tests use cases.

Image

The result is a (fairly) evenly divided sphere:

…and yes, the “snow” from the previous post is still in the image – I lazily hacked the new functionality into Tutorial 5 for testing :)

And also, since the rasterizer is OpenGL 3.2 based, it renders using triangles rather than (the now deprecated) quads. Thus, I mention “quads” above, yet the wireframe image displays a sphere composed of triangles. The conversion takes place at the LxEngine rasterization level so I’ve ceased to think too much about such conversions!

Details

The create_sphere() function creates a glgeom::primitive_buffer with the following properties:

primitive.type = "quads";
primitive.vertex.positions = /*vector filled with the unit sphere positions*/;
primitive.vertex.normals = /*vector filled with normals for each vertex*/;
primitive.indices = /*four 16-bit indices per quad in the sphere*/;
primitive.bbox = /*unit bounding box*/;
primitive.bsphere = /*unit bounding sphere*/;

Written by arthur

April 9th, 2012 at 8:26 pm

GLGeom v0.0.5 Released!

without comments

GLGeom v0.0.5 has been released!

GLGeom is the C++ template math library developed in conjunction with LxEngine, modeled after and extending the GLM mathematics library. It provides strongly typed point, vector, and color classes, primitives classes (spheres, cylinders, etc.), bounding objects, intersection calculations, and more.

This release is most notable for the time that’s passed since the last release! :) Almost four months has seen a hodgepodge of changes and improvements to the extent that it’s hard to coherently, yet briefly summarize them. A more orderly development and release schedule would certainly be preferable, but so it goes with pre-v1.0 releases of hobby projects.

The full release notes which includes download links, API documentation, and code diffs are located here:

GLGeom v0.0.5

.

As it will be for some time, it’s still a very early release but feedback is always welcome!

Example Code

Swizzle and vec operator

glgeom::vector3f v (1, 2, 3), u(4, 5, 6);
glgeom::color3f c;
glgeom::point3f p;
glm::vec3 q;
 
// Supports swizzle operators 
v.zxy = u.xyz;      // v now contains (6, 5, 4)
c.rgb = 1;          // set c to white (1, 1, 1)
 
 
// Strict types
// v = c;   Compiler error! No implicit conversion from color to vector
// p = v;   Compiler error! No implicit conversion from vector to point
 
// Use "vec" operator to treat the type as a generic GLM vec2/3/4
q = v.vec;
p.vec = q;

Written by arthur

September 9th, 2011 at 7:37 pm

Posted in glgeom

Tagged with , ,