Inertia's picture

Prodecural Geometry API

One thing that would not hurt OpenTK.Utilities are a couple of classes that allow straightforward creation of geometry such as cube, sphere, plane, etc. When experimenting with GL Extensions you often need *something* to draw, it does not really matter so much what is drawn exactly, and it is often desireable to experiment in a contained and simple to debug situation, rather than doing that experimentation in large applications.

To give some concrete example: The API should be dead-simple so it's most convenient to write examples or prototypes - e.g. shaders - without having to worry about the geometry and it's attributes. Also for debugging a physics binding it will be helpful to have this option.

The usage should be as simple as:

Shape MyGeom = new SierpinskiTetrahedron( scale, eSubdivisions.Four, false ); // create object, immutable
MyGeom.Draw(); // draw object
MyGeom.Dispose(); // properly clean up object

The boolean paramater controls whether upon first call of MyGeom.Draw() a Display List should be compiled and executed, or simply GL.Begin() Immediate Mode calls are done. Making the use of Display Lists optional allows the programmer to group multiple objects into a single Display List, at the programmers discretion i.e. the API itself does only deal with DL for a single object. If the geometry instance's Draw method is ever called with using Display Lists, MyGeom.Dispose() must be called prior to context destruction.

The only way to use the object with VBO is calling MyGeom.GetVBO() and handle it from there on your own.

The objects I've been working on so far are:
-Sierpinski Tetrahedron
-Menger Sponge (sometimes called Sierpinski Carpet)
-PQ Torusknot
-WIP: Capsule and Chamfercube.
-A Koch subdivision applied to a Tetrahedron, I don't think there's a name for this yet (if you know, please tell!) so I'll simply show what it looks like untextured to give an idea. (Yes, it has TexCoords, but it increases difficulty to make sense of the object ^10)

The API is easily extensible for more objects, all that new objects must be able to supply are:

Graphics.BeginMode PrimitiveMode
Vertex[] VertexArray
uint[] IndexArray

Let me try sum it up:

Guidelines for writing additional objects

  • Shapes may have multiple contructors, but once leaving the constructor an instance is immutable, i.e. can only call .Draw() .GetVBO() and .Dispose(). Deriving classes may not add any new public methods or fields.
  • No compromises must be made that would favor easy editing of the generated geometry over the simplicity to generate or draw it. I.e. if someone wishes to add the procedural objects to an 3D Editor, they must either clean up the generated arrays or implement it on their own.
  • Shapes should be marked sealed, if you intend to create a compound shape like a cylinder (2x disc, 1x tube) the correct way to do this is instantiating the 2 discs and tube, GetVBO() their arrays and merge it into a single VBO.
  • The amount of CPU cycles and memory used during shape creation is irrelevant, the user may call GetVBO() and dump to disk or serialize the instance to avoid repeated calculation of the geometry and memory allocations.
  • The Vertex and optionally Index Array must be set in the constructor. No additional methods to alter level of detail are permitted, the user should instantiate a new shape for that.
  • Explicit parameter description including default and few recommended values in the summary.
  • Vertex Attributes must be no more and no less than T2N3V3 at double-precision floating-point per Vertex.
  • Texture Coordinates should assume a tilable texture and keep their coordinates within [0..1]. Do not attempt to implement a dozen ways to map UV coordinates, a user must resort to modelling applications if more control is required.
  • It does not matter whether the output is for GL.DrawElements() or GL.DrawArrays(), the later simply has no Index Array. It is assumed that the Vertex Array is intended for DrawArrays in that case. Shapes that are intended to be part of compound shapes must use the Index Array, since they can have arbitrary high tesselation.
  • One may chose to query BeginMode from the user in the constructor, but not doing so is fine aswell.
  • The object center is ideally at (0,0,0) to allow easy rotation around itself, e.g. the Sierpinski Tetrehedron is fit into a Sphere of radius 1.0. None of it's vertices are further away from 0,0,0 than 1.0, that results in a great rotation center, as opposed to using one of the 4 corners as origin.
Koch Curve Tetrahedron.png226.82 KB


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Inertia's picture

I'd really appreciate some feedback on the matter whether the used Vertex struct should be double- or single-precision floating-point. Right now it's double-precision, but it already gave good results with single-precision because the limiting factor of the subdivisions is often related to overflows and not floating-point precision.

What should be the maximum primitive count allowed? So far I've made sure that ~1mil triangles works for every object, but at that triangle count there's already notable aliasing and depth fighting (even if near&far planes are tightly wrapping the object) when the whole object is visible within the camera. I'm not sure if increasing subdivisions beyond that would make much sense, because the objects repeat themselves and you could for example subdivide the Sierpinski Tetrahedron further by simply drawing it 4x with offsets to form the Tetrahedron at max. subdivision+1.

Any funky ideas what other volume fractals to add to the API?

flopoloco's picture

I think we should define the roadmap of OpenTK Utilities, what would be the responsibilities of the library? Provide secondary functionality extensions to OpenTK (reducing stress from the core project... e.g. font rendering), or provide shortcuts to developers (e.g. geometry drawing), or both of it?

Out of the box geometry drawing functions like those found in glut library are very useful.

Inertia's picture

Regarding the roadmap it's too early to make a statement. We've been discussing it, but without conclusion yet.

OpenTK.Utilities idea is simple: provide commonly required functionality such as printing text and interpreting file formats. The procedural geometry classes are an addition for users without any knowledge of - or interest in - 3D Modeling applications.

Mhmm the Teapot. It has been used to death and beyond, will add it to the might-do list.

Inertia's picture

This is not dead, I just put it on hold to figure out how to generate somewhat useful texture coordinates for the compound objects like capsule and chamfercube. My conclusion is: there is none. The only way to get meaningful texcoords for these objects is a) use a model editor or b) use a cube texture.

Here's an image showing the topology of the chamfercube, a capsule and the same chamfercube behind it. (fixed-func lighting)

The list of supported objects is now, each has at least 5 levels of subdivisions available:

  • Sierpinski Tetrahedron
  • Menger Sponge (sometimes called Sierpinski Carpet)
  • PQ Torusknot
  • Capsule
  • Chamfercube
  • Koch subdivision applied to a Tetrahedron

The Koch subdivision could be applied to any of those, I'll experiment a bit and see what gives somewhat useful results.

There are also some internal shapes (Sliced Hose and Sliced Sphere) which were used to create the capsule and chamfercube. The sliced sphere might be the more interesting one, since it creates the sphere without sin/cos functions and the triangle distribution on the surface is much better like this (see image for proof).

chamfercube.jpg56.87 KB
Inertia's picture

We finally figured out how to handle this, and the code is now part of svn trunk. It can be found in the examples directory where it will remain. There is no good reason to make this a part of the library itself, because we only need this for examples and demonstrations.

Please note that patches and bug reports are welcome, but there are currently no plans to add more objects or make any changes about efficiency of the current code. The objects are intended for quick prototyping and to have "something to show" in OpenTK's examples besides cubes and spheres, but they are not intended for production use or a replacement for a 3D modelling package.

It's primary purpose is to keep OpenTK's examples free from pages of constants to define VBO data.

Pygmy's picture

First of all, great stuff - it's really handy to have some good test-objects!
But... is there any chance of porting this to OpenGL >= 3.2 core ?
(So not using deprecated functionality like displaylists / glBegin / glEnd etc. ?)