Archive

Posts Tagged ‘CS’

GSoC YouTube channel video

I recently made a video for the GSoC YouTube channel.

I included all the main features the fur plugin support:

  • Colliders
  • Enabling / Disabling physics
  • LOD
  • Geometric properties
  • Materials
  • Diffuse Type
  • Alpha / Color

Here is the video (hopefully you will be able to see it on the GSoC YouTube channel in no time):

LOD

As you have probably seen from my previous YouTube videos, the FPS in the fur plugin isn’t quite real-time, but about ~10 FPS.

After doing some manual profiling (i.e. not using any profiling tool, but just commenting code and analyzing the average FPS in various situations), I came out with the following findings regarding the fur mesh plugin:

  • Hair simulation
Number of Guide Hairs 0 50 100 200 367
Average FPS 46.07 37.70 32.63 24.76 18.76

Because I used Bullet ropes in order to simulate the physical model for guide hairs, I couldn’t really optimize the code to get better performance, so the only option was to generate as few Bullet ropes as possible, for the lowest LOD and also, not to many for the highest LOD setting.

This is why I made two types of guide hairs: pure guide hairs and LOD guide hairs. The pure guide hairs always have a Bullet rope attached, they represent the lowest LOD setting and grow on each vertex of the base mesh. On the other hand, LOD guide hairs are only synchronized with ropes at higher LOD, otherwise their position is updated just like for normal hair strands, using interpolation and barycentric coefficients.

So in order to have really good results, having a low poly mesh on which to grow fur is essential, and this can be done either by having a fake low poly mesh specified in the model file, or better yet, by obtaining a low poly mesh using the LOD system from another CS GSoC 2010 project, by Eduardo Poyart.

  • Hair modeling
Number of Hair Strands 0 500 1000 2000 3670
Average FPS 49.34 31.56 23.12 15.41 10.53

When I collected this data for hair modeling I was using a genmesh to represent the fur geometry. The problem was that when I called functions to compute normals, tangents or binormals followed by a call to Invalidate() the FPS was really low for thousands of hair strands. However, I realized that I can easily compute all this data having in mind that the hair strands are created so they always face the camera. Furthermore, doing some C/C++ optimizations by increasing pointers, instead of iterating through vectors, gave some performance boost as well.

And of course, when the camera is situated further away from the fur mesh, having a low LOD setting, which draws fewer, thicker hair strands seemed a good idea. The only trick was to generate the hair strands in such a way that they always cover the base mesh (skull) and as they grow in number they give the impression of more dense hair.

  • Hair rendering
Number of Hair Strands 0 500 1000 2000 3670
Average FPS 49.12 47.34 45.82 44.06 40.26

After testing the hair rendering data with both the Marschner implementation and a simple default CS Phong shader, I realized that the hair rendering didn’t need any more optimizations nor various LOD versions. The optimizations done by using lookup textures, as described in the Marschner Shader Part III post, provide good results by themselves.

  • Overall
Number of Guide Hairs 0 50 100 200 367
Number of Hair Strands 0 500 1000 2000 3670
Average FPS (1024×768) 47.62 26.07 17.96 11.15 7.56
Average FPS (1440×900) 49.12 26.82 18.62 11.24 7.66

So, by making all of these optimizations and various LOD settings I managed to run the hairtest demo at a constant ~28 FPS at the lowest LOD and at ~15 FPS at the highest LOD setting.

Also, I realized that although sometimes a hair simulation will not be needed, animating the hair would still be a good idea, so I wrote an implementation of the iFurPhysicsControl that only updates guide hairs based on the base mesh movement, and also added the possibility to switch between various iFurPhysicsControl implementations on the fly. Not having Bullet ropes at all made the application run at ~37 FPS for the lowest LOD setting.

Categories: Crystal Space Tags: , ,

Physics reloaded

A couple of days ago I managed to find some bullet ropes parameters that tend to make ropes act more like hair strands:

body->m_cfg.kDP = 0.08f; // no elasticity
body->m_cfg.piterations = 16; // no white zone
body->m_cfg.timescale = 2;

This is what each one of them does:

  • kDP is the Damping coefficient [0, 1], zero means no damping and one full damping. This is a damping spring:

  • piterations are the number of iterations for position solvers (if any). It goes from 1 to infinity.
  • timescale is a factor of time step, that can be used to speed up, or slow down simulation, default=1.

There are a lot more settings that can be altered with from bullet’s soft bodies. More on bullet online documentation.

Next you can see how these settings look on Krystal, having 367 control points and 3670 hair strands. I guess I will have to further modify them, to get rid of some elasticity, but I find the overall simulation quite plausible:

Generating geometry

In this post I will present how I implemented the GenerateGeometry function from the iFurMaterial interface. This function can be split in two big parts: guide hair and hair strands generation.

  • Generating guide hairs

These guide hairs will be used only for physics simulation and as reference for the hair strands. So they will not be rendered, except maybe for debug purpose.

In order to generate guide hairs the base mesh, the mesh on which fur will grow, will be used. If there are enough vertices, guide hairs will be attach to each point of every vertex. If not, the mesh will either be tessellated using a CS function, or by implementing the same technique used to generate hair strands from guide hairs. The only important thing here is to also have a vertex buffer (triangle buffer actually) for these guide hairs, and not just an index buffer (a vector to store them).

Unless any physics model is specify (ropes or so), guide hairs will grow having the direction of the vertex normal and a length specify via a heightmap.

  • Generating hair strands

This is where the guide hairs triangle buffer will be used. For each such triangle, based on a density map, hair strands will be generated. In order to get any number of points inside a triangle, as random distributed as possibly, barycentric coordinates will be used.

If we look closely at the above picture, we see that we can generate a point Y, in a triangle ABC, just by Y = bA * A + bB * B + bC * C, where bA + bB + bC = 1. And randomly choosing the barycentric coordinates is not tough at all: bA = random (0,1), bB = random (0,1) * (1 - bA), bC = 1 - bA - bB.

The interesting thing here is that these barycentric coordinates can also be used for setting the whole hair strand (not just the base point), and even the UV coordinates for the density map.

  • Updating Geometry

All hair strands need to be updated even if there is no physics model involved.

The iFurPhysicsControl interface will update guide hairs, and after this, hair strands will be regenerated every time. Even if no physics interface is specify the hair strands still need to be regenerated because they are represented as triangle strips and they need to always face the camera. This can be done be taking into account that the vertex tangent has to be perpendicular to the eye direction.


csVector3 firstPoint = furMaterial->hairStrands.Get(x).controlPoints[y];
csVector3 secondPoint = furMaterial->hairStrands.Get(x).controlPoints[y + 1];
csVector3 tangent;


csMath3::CalcNormal(
tangent, firstPoint, secondPoint, tc.GetOrigin());
tangent.Normalize();
strip = furMaterial->strandWidth *
tangent;

The reason why I used solid geometry instead of lines is that vertices support both textures and shaders.

  • The result

Here is a picture of some generated hair strands, with no physics model specified (hair grows on vertex normal direction).

The plugin

Giving the fact that this project has two main parts, the physics simulation and the rendering, it would probably be a good designing idea if the plugin implementing it will also have two CS interfaces. This is what these interface should do:

iFurMaterial

  • Attach fur to the base mesh

For this, a mesh (any type) would have to be specify along with some control points for the guide hairs.

  • Generate geometry

Using the guide hairs and a density map (maybe a heightmap too) the rest of the hair strands will be generated using interpolation.

  • Update position

This is done by synchronizing the position with iFurPhysicsControl. This interface can implement any type of physics not just ropes, and it can even be null, specifying that a particular instance of the iFurMaterial interface doesn’t have any physics simulation (might be used for static objects, or such).

  • Implementing a shader

Or specify a shader/material to be used with this interface. This is especially important because although Marschner is a good model for hair rendering, it might be too complex for fur in general. Here Kajiya and Kay shading model could be used instead, because it has pretty good results too and it’s faster.

iFurPhysicsControl

  • Initialize strand

Given a guide hair this function will create a physics object, a rope in my case, and make a connection with this strand by a unique id, or so.

  • Animate strand

This function will update a strand’s position using the physics object especially created (via the initialize method) for this strand.

  • Remove strand

Removing physics objects might be a good idea for a LOD scheme, because animating physics objects is quite computational expensive.

Categories: Crystal Space Tags: , , ,

Hair simulation types

There are various ways in which hair can be simulated using a physics engine.

Next I am going to present 3 of them. For these simulations I used CS for rendering, and for physics the Bullet plugin, that as of recently supports soft bodies, thanks to my mentor Christian Van Brussel.

  • Solid geometry

Perhaps the easiest way to simulate hair is as standard collision objects, such as spheres or cylinders. Although this representation has the best performance, it only covers some particular types of hair like the one below:

  • Soft Body Dynamics

Another approach is to use soft body dynamics, and represent the hair as a … cloth. A larger number of hair styles can be simulated using this method and it also looks more convincing. You can see in the next video both Krystal’s (that’s the model’s name BTW) hair and her skirt represented as soft bodies (drawn in green):

  • Ropes

This is probably the best and somehow the most intuitive way to simulate hair: as ropes. But, as you already know, there are way to much (i.e. millions) hair strands to be simulated individually as physics objects. So the trick here is to choose (either random or better yet using a density map) lets say a hundred hair strands to be guide hairs, represented as ropes. And for the rest of the hair strands just interpolate. You can see these guide hairs (hopefully) in black:

Building CS

If you are interested to view the progress of my project, you can do that by checking out via SVN the CS hair branch (no account needed) .

After that you have to compile the source code. Until the project is finished and integrated in CS, probably in v2.0, this will be the only way in which you can see the hair plugin.

Next, I am going to present how you can do this on Windows, using Microsoft Visual Studio C++. If you are interested in compiling CS on other platforms or operating system, you can always check the manual.

  1. Download and install CS dependencies. Luckily, there is a package for Windows users, that installs all these dependencies and sets up the environment. You can download from here the latest version either for win32 or x64 architectures (the current one is 1.9_006).
  2. Set up VC support and install windows libraries to the /CS directory (the one where you SVN checkout-ed).
  3. Open wkstypical.sln, build and run.

That’s it.

But keep in mind that although MSVC is probably the easiest way to compile and run CS, it’s not by far the best way. If you want to make a new project or plugin you have to run a script in order to do that, and you will have to set up other environments for that (MSYS or Cygwin). And when you will see that the MSVC compiler is rather poor in performance when compared with the other compilers, you might want to switch to another environment, like I did.

LE: Almost forgot, if you have problems with incremental linking when compiling, you can either disable it, compile with Release instead of Debug, or install this hotfix from Microsoft.

Categories: Crystal Space Tags: , , , ,