GLSL Plane Deformation

Inspired by the work of Dominik Ströhlein posted on Form Over Function I started myself to port some of the oldschool amiga plane deformation effects to GLSL. The video below shows a compilation of most of the effects.

References

GLSL Shadow Mapping

During Revision 2011 I finally found some free time to fix a small bug in my GLSL shadow mapping demo. The result can be seen in the video below.

The demo does not make use of the OpenGL texture coordinate generation facility as described by Cass Everitt in "Projective Texture Mapping". Instead it computes the needed transformations including the inverse of the camera view transformation by hand using a shortcut that makes use of view matrix specific properties. After that the resulting matrix is send down to the vertex shader where the matrix is used to transform every incoming vertex to clip coordinates of the spot light view. The bug was that I did the divide by w already in the vertex shader and send these normalized device coordinates down to the fragment shader to get interpolated. The problem here is just that interpolation needs to be done before the divide by w because otherwise you wont get properly perspective correct interpolated normalised devide coordinates. So doing the divide by w in the fragment shader solved the problem.

References

GLSL Bump Reflection Mapping

Approx. a week ago I came up with the idea to implement the OpenGL spherical reflection mapping equation per fragment based on a normal map. This effect was extensively used in the demoscene since it looks kind of fancy.

It's a modification of a bump mapping shader that does all the computations in the tangent space. Since the spherical reflection mapping equation assumes the reflection vector to be in the eye space the reflection vector is transformed back to eye space using the TBN matrix before plugging it in the sphere map equation and sampling the sphere map. This works quite well although it's probably not an optimal solution. Below is the fragment shader code:

uniform sampler2D sphereMapSampler; uniform sampler2D normalMapSampler; varying vec3 tangentSpaceEyeVector; varying mat3 tbnMatrix; void main() {   vec3 tangentSpaceNormal = normalize(texture2D(normalMapSampler,     gl_TexCoord[0].st)*2.0-1.0);   vec3 r = tbnMatrix * reflect(-normalize(tangentSpaceEyeVector)     tangentSpaceNormal);   float m = sqrt(r.x*r.x+r.y*r.y+(r.z+1.0)*(r.z+1.0));   vec2 sphereMapCoord = vec2(r.x/(2.0*m)+0.5, r.y/(2.0*m)+0.5)   gl_FragColor = texture2D(sphereMapSampler, sphereMapCoord); }

And finally by request here is the vertex shader code:

attribute vec3 tangent; varying vec3 tangentSpaceEyeVector; varying mat3 tbnMatrix; void main() {   vec3 eyeSpaceVertex = vec3(gl_ModelViewMatrix * gl_Vertex);   vec3 normal = normalize(gl_NormalMatrix * gl_Normal);   vec3 tangent = normalize(gl_NormalMatrix * tangent);   vec3 binormal = cross(normal, tangent);   tbnMatrix = mat3(tangent, binormal, normal);     tangentSpaceEyeVector = -eyeSpaceVertex * tbnMatrix;   gl_TexCoord[0= gl_MultiTexCoord0;   gl_Position = ftransform(); }

In the first four lines of code the normal and tangent are transformed into eye space. Afterwards the binormal is computed using the cross product. The TBN matrix is constructed and subsequently used to transform the eye space eye vector into tangent space. The last step is probably a bit tricky in case you are not used to matrix transformations. In fact it consists of two parts. First of all it negates the eye space vertex wich yields the eye space eye vector. The eye space eye vector is then post multiplied with the TBN matrix. Since the TBN matrix is an orthogonal matrix this is the same as pre multiplying the eye space eye vector with the inverse of the TBN matrix and thats what actually is needed to transform the eye space eye vector into the tangend space to compute everything in there. It's easy as that.

References

OpenGL Exercise Course

Here are my exercise course slides and exercises I prepared for a lecture on computer graphics with OpenGL at the University of Oldenburg. The slides do not in any sense claim to be exhaustive still they provide a lot of information needed to get started with OpenGL and in particular with JOGL 2. In case you spot any mistake make sure to contact me.
Read More...

Displaying Wavefront OBJ Files

Within the scope of my OpenGL exercise course I gave a short talk about the Wavefront OBJ File Format as well as on how to write code to load and display 3D geometry from OBJ Files. The capture below shows a rudimentary implementation of a Wavefront OBJ File Loader for demonstration purposes. The slides of the talk are available for download in the reference section.

References

Oldenburger RoboSoccer Team Technical Report

After one year of improving the Oldenburger RoboSoccer Team we finally ended our work on this project. The final result is a 317 pages technical report about our achievements. It includes all the major improvements we added to the existing soccer team to achieve a better soccer play and a more natural cooperative behavior of our autonomous agents. The technical report is available for download in the reference section below.

References

Artificial Potential Field (APF) Path Planning

Finally the first development release of the VPF Toolbox is out. The objective of the VPF Toolbox is to develop a static C++ library that provides an easy to use and extensible set of tools for artifical potential field based path planning. The following code example shows what is needed to create a simple attractive potentialfield and how to compute the gradient at a certain point in space:

#include <boost/shared_ptr.hpp> #include <VPFToolbox/VPFToolbox.h> int main(int argc, char *argv[]) {   // create a container object   boost::shared_ptr<vpf::ComplexPotentialfield>     complex(new vpf::ComplexPotentialfield());   // create an attractive potentialfield   boost::shared_ptr<vpf::ParabolicAttractivePotentialfield>     attractive(new vpf::ParabolicAttractivePotentialfield);   // create a target position for the attractive potentialfield   boost::shared_ptr<vpf::PointPrimitive>     position(new vpf::PointPrimitive(vpf::Vector(0.0f0.0f)));   // configure the attractive potentialfield   attractive->setScalingFactor(1.0f);   attractive->setPosition(position);   // add one or more potentialfields and compute the force vector   complex->add(attractive);   complex->computeGradient(vpf::Vector(10.0f5.0f));   return 0; }

The gradient can then be used in a gradient descent to navigate to a goal position. Right now there is support for several attractive and repulsive potentialfields as well as a basic set of geometric primitves that induce repulsive forces. Plans for the future are several optimizations to the basic potentialfield approach like local minima avoidance, path optimization through reverese path planning, oscillation avoidance and so forth.

Below you can see a capture showing a sample application that ultilizes the VPT Toolbox in the robot soccer 2d simulation league domain. As you can see the path adapts to the moving obstacles represented by the gray circles:

The source package of the VPF Toolbox is available for download and contains everything to built the library. Beside the source it includes full doxygen documentation of the source code. To build the library you need the boost C++ libraries since the VPF Toolbox makes heavy use of boost smart pointers.

References

Subclipse unable to load default SVN client

Today I installed Subclipse 1.6.13 on top of Eclipse CDT. After adding a new repository to the repository browser i got the following error message:

Unable to load default SVN client.

Later on while I was trying to check out the repositories' content I got another eclipse error message:

Cannot map the project with SVN provider.

In case you have the same problem even though you properly installed Subclipse, one solution might be as simple as intalling additionally the SVNKit Library as well as the SVNKit Client Adapter. This worked at least for me.

References

Delaunay Triangulation

Lately I have been working on the problem of triangulating a given set of points. We need this in our robot soccer project team since we are implementing an agent positioning mechanims that is based on human knowledge that is captured at certain points in space and lateron interpolated with the Gouroud shading algorithm using the triangles of the triangulation. For a more precise explaination of this method take a look at the "HELIOS2009 Team Description" paper in the references section. In particular I have been messing around with the Delaunay Triangulation wich has some specific properties i.e. it maximizes the minimum angle of all the angles of the triangles in the triangulation.

With the Java classes I implemented the code needed to get a Delaunay Triangulation of a given set of points reduces to:

Vector<Vector2D> pointSet; pointSet = loadPointSet("data/normal-formation.conf"); DelaunayTriangulator delaunayTriangulator;      try {   delaunayTriangulator = new DelaunayTriangulator(pointSet); catch (NotEnoughPointsException e) {   // handle exception here }    delaunayTriangulator.compute();

This is probably not yet one hundred percent robust due to the used floating point based predicate for the in-circumcircle-test. The visualization of the point set used in the example code snippet using the OpenGL API looks as follows:

The java source package including the example code and point set is available in the reference section. To compile and run the example code you need the Java Bindings for OpenGL (stable release 1.1.1). They are freely available under a BSD license at JogAmp.org.

References

Processing Flower Effect

I always liked the Assembly 2004 invitation by Moppi Productions for its lovely and unique flower effect. Actually years passed by until I started to implement this effect myself. All of a sudden I found a paper by Mikko Mononen, the lead programmer of Moppi Productions and nowadays the lead AI programmer on Crysis, where he explained his implementation of the effect. Finally I got it working. Thanks goes to Mikko Mononen for the paper. The video below shows the fifth version of my implementation of the Moppi Flower Effect in processing.

References

Boost C++ Libraries

Within the scope of the Oldenburger RoboSoccer Team 2009/2010 I gave a short talk about the Boost C++ Libraries and in particular about Smart Pointers. The slides of the talk are now available for download below.

References

Agile Project Management with Scrum

Within the scope of the Oldenburger RoboSoccer Team 2009 I gave a short talk about agile software development and in particular about Scrum, an iterative, incremental methodology for project management. The slides of the talk are now available for download below.

References

Oldenburger RoboSoccer Team 2008 Review

Since we are going to improve the Oldenburger RoboSoccer Team in the next 12 months I prepared a review report about the existing soccer team from the year 2008. The report starts off with a recapitulation of the fundamentals of autonomous agents and the RoboCup 2D Simulation Domain followed by an in-depth review of the existing architecture and performance of single components. The report cloeses with suggestions and representations concerning the existing soccer team.

References

Sphere Tracing in the Demoscene

Sphere tracing is the latest hype in the demoscene. It is everywhere. So what is it all about? To grasp the strength of this approach you should take a look at the winning 4kb intro Rudebox by the demogroup Alcatraz. The images below show two of its scenes.

In fact it is a rather old numerical method for finding the intersection of a ray with an implicit surface, first introduced by John C. Hart in 1993. Sometimes it is just called distance field rendering, but both mean the same. You can think of it as a raymarcher with a variable step size. To make it work you need to define the whole scene as a distance field. In principle a distance field is just a function that maps a position in three-dimensional space to the distance of the nearest surface. To compute an intersection you start at the viewer's eye position and evaluate its function value. The output of the distance field function is the distance you can securely walk along the view ray without intersecting a surface. You have to repeat this until your distance is below a certain epsilon which basically means that you hit a surface.

If you take a closer look at Rudebox you will notice some astonishing effects. Besides the standard lighting it features ambient occlusion and surface distortion with FBM noise while most other 4kb intros making use of sphere tracing, i.e. Sult by Loonies, only show undistorted surfaces and instead make heavy use of reflections. The best thing about sphere tracing is that you get all these effects almost for free.

Rudebox and Sult both abuse the GPU for sphere tracing to make use of the hundreds of very capable floating point processing cores that nowadays are even part of run-of-the-mill hardware like standard workstation machines. The main problem right now is that it is nearly impossible to use surface distortion and reflections at the same time while managing a decent frame rate on topical GPUs. Even though this will probably change very soon.

References

Polygonal Approximation of Torus Knots

Lately I have been playing around with space curves. My objective was to obtain a polygonal approximation of a (p,q)-torus-knot. At first glance the frenet-frame seemed to be a convincing solution since it defines an orthonormal basis gliding through the space curve that could be used to span polygons along the curve. Unfortunately the frenet-frames normal and hence its binormal do 180-degree-twists in the inflection-points of the curve. This leads to grafical artifacts while spanning polygons along the curve.

The solution is to calculate the frame not using the second derivation but using an arbitrary vector that is never parallel to the tangent. This gets around the nasty 180-degree-twist however the arbitary vector you have to choose is dependent on the particular space curve you want to display. We can approximate the tangent of the frenet-frame instead of using the expensive to calculate first derivation of our curve. Another reason for this approach beside its quite convincing results is that it works for every curve contrary to the first derivation that is different for different space curves. The pseudocode for calculating the frenet-frame-approximation using the forward difference approach is as follows:

point1 := curve(t); point2 := curve(t + delta); unitTangent := normalize(point2 - point1); unitNormal := crossProduct(unitTangent, vec3(0, 1, 0)); unitBinormal := crossProduct(unitTangent, unitNormal);

An even better way to approximate the tangent as you may have guessed is using the central difference approach as shown below:

point1 := curve(t - delta/2); point2 := curve(t + delta/2); unitTangent := normalize(point2 - point1); unitNormal := crossProduct(unitTangent, vec3(0, 1, 0)); unitBinormal := crossProduct(unitTangent, unitNormal);

A capture of the resulting procedural generated (2,3)-torus knot with a bump mapping shader applyed to a linear combination of worley's cellular texture basis function can be seen below:

References

eXtensible Procedural Texturing System

Below is a capture of me using eXtensible Procedural Texturing System (XPTS). XPTS is an operator stacking based procedural texture generator I am currently developing using the Java programming language. Operator stacking was first introduced in 2001 by Dierk Ohlerich, the project leader and progammer behind titles like Killer Loop or .kkrieger, and is in fact a variety of a dataflow graph. The operator stacking paradigm is kind of powerful for digitial content creation and is quite a lot of fun to work with.

Plans for the future are a powerful graphical user interface, a xml-based file format, a plugin mechanism for developers to extend the default set of functionality and a built-in plugin editor and compiler for rapid operator development.

References

Domain Name Allocation

Within the scope of a seminar on internet law I gave a talk about the domain name allocation with an emphasis on the legal questions that arise from the allocation through the german top level domain registrar denic. The slides are available for download in the reference section.

References

Software Product Lines

Some time ago I wrote an introductory paper and gave a talk about software product lines within the scope of a software system engineering seminar. The paper serves as a survey of a range of topics treated in the development of a software productline. The paper and the slides can be found in references section. For an in depth coverage of software product lines I recommend you to to visit the website of the SEI.

References

Theory Exploration OpenGL Assignment

Last summer I attended a lecture on computer graphics with OpenGL at the University of Oldenburg. We started out with the fundamentals and quickly moved on to more advanced topics such as normal mapping, shadow mapping, cell shading, shadow volumes, vertex and pixel shaders and all the fancy stuff one would expect. Beside the weekly excercises we had to prepare using the Java Bindings for OpenGL (JSR-231) (that are by the way freely available under a BSD license at JogAmp.org) we also had to deliver an assessed assignment by the end of the semester.

The objective of the assignment was to show some of the rendering techniques we learned during the lecture. Some techniques used in my assignment that are worth mentioning are music synchronization, a particle system, 3d mesh distortion, multi texturing, animated textures, shadow mapping and animated isosurfaces using the marching cubes algorithm. Sadly i didn't make use of the programmable pipeline. A capture of the assigment can be seen below:

References

Introduction to Minimum Spanning Trees

Within the scope of a seminar I gave an introductory talk about minimum spanning trees. In practice, often the question arises, on how to connect a given set of nodes together while keeping the costs of connections minimal. In graph theory the answer to this question is known as a minimum spanning tree (MST). See Figure 1 for an example of a graph and its corresponding (minimum) spanning tree.

Figure 1: A graph and its corresponding (minimum) spanning tree.

A spanning tree with is a subgraph of an undirected, connected graph that is a tree and connects all the vertices together. A weighted graph associates a weight with every edge. The weight of a graph is the sum of the weights of the edges of the graph :

A minimum spanning tree is a spanning tree with weight less than or equal to the weight of every other spanning tree :

The seminar paper presents two commonly used greedy algorithms to compute a minimum spanning tree, namely Prim’s algorithm and Kruskal’s algorithm. The paper and slides are available for download in the reference section.

References