Saturday, March 27, 2010

Marschner Scheme

My attempt to sort out what the heck is going on in this paper. Click to enlarge.

I tried to write it all up in C++ first, but I got so mixed up and didn't know where the variables for each section were coming from. Maybe this will help me. Or...maybe someone who's really good at decoding math lingo can help me...? I'd much rather be working with more Bullet instead of this. You may be wondering, "what's this paper...what happened to Zinke?" Zinke's local component of the dual scattering calculation uses Marschner's BRDF, which is "explained" in this paper.

Goals Running in the Background:
  • Fix Bullet hair oscillations by projecting hair roots onto the head collider
  • Try OpenMesh decimation (and scaling?) as a pre-step to convex hull decomposition
  • Global multiple scattering (even though my love for opacity shadow maps has faded...)

Monday, March 22, 2010

Idea for Fixing Oscillations

After a good deal of playing around with parameters, I found that I was able to calm the oscillating hairs (mostly) whenever their anchors were above the surface of the collider.
In this situation, the hairs are grown from inside the collider; Bullet gets mad and the hairs oscillate around wildly.

But in this situation, the hairs are grown from outside the collider; aside from a few oscillations (unnoticeable from far away), Bullet is happy and the hairs stay still.

So, growing the key hairs from the vertices of the original input scalp is a good starting point, but perhaps projecting each scalp vertex onto the collider and growing from these projected positions is a better idea. This would ensure that the key hairs are anchored to the surface of the collider and not somewhere above or below it.

Sunday, March 21, 2010

Interpolation (and memory leaks)

Am I graduating with a degree in computer science? Are you serious? Because...I just found out I could look at the Task Manager to check for memory leaks in my program. And you know what? It was leaky. And here I thought I was managing memory quite well all this time. I really don't know how I ever got by all those programming classes with good grades...(though being a temp grader has given me a hint). Well, anyway...the point is, this project has taught me a lot about programming practice in general, especially w.r.t. passing by reference, memory management, and getting different open source libraries to play nicely with each other.

Okay, so...interpolation. Progress so far is displayed below. Please note that HyperCam chews up some of my CPU power, so the program runs a bit faster than what is shown (yes, it's slow...but not that slow). The memory leaks aren't as bad as they were before I discovered the Task Manager trick, but there are still some there (I think). So, I still need to track down memory leaks and do more memory clean ups (std::vector's clear() function does not free memory automatically like I thought it did...). Other remaining issues (in addition to the ones mentioned in the previous post):
  • when two key hairs are very far apart (as is the case for the two on either side of the nose), interpolation between them causes blatant hair-head intersections, so I think I should implement a distance check before interpolating adjacent (in terms of growing from the same face) key hairs
  • the convex hull decomposition step tends to yield hulls that lie just under the original head mesh surface; ideally, I would want the collider to completely encompass the original head mesh (i.e. have the red mesh completely surround the tan mesh); I think this would prevent the hair from falling below the scalp and causing bald patches; there are several ways I could go about doing this: (1) after reduction and before decomposition, scale the head mesh so that it is slightly larger than the original (I like this option), or (2) ask the user to provide a scalp that floats a little bit above the head

I should bring my focus back to the rendering side of the project, if I can. You know, those opacity shadow maps... x__x

Plugging in Bullet (Step 2)

Goal: Add the ability to render the Bullet soft body key hairs as lines
Check. Some issues that still need to be cleared up:
  • For heavy hairs, the contact jittering gets really bad (you can see it when I zoom in). I've tried messing with all sorts of soft body parameters, but no dice. The only thing that guarantees less "wigging out" is a lighter mass. I'll poke around in the Bullet forums to see what the Bullet equivalent of "skin thickness" is. Unfortunately, light hairs don't have the kind of motion I'm looking for (they look like they're moving around in water). On the other hand, since this is all still on the CPU, the simulation is moving really slow to begin with...so I think I'll leave the parameter tuning for later on when I've (hopefully) found a way to bring the simulation rate up.
  • When I rotate the collider to test the simulation, things get a little crazy. Heavy hairs pull on the collider more (i.e. influence its inertia), so unless the collider-to-hair mass ratio is very high, the collider will oscillate around wildly. I thought I had bumped this ratio up enough (see the videos of my Bullet tests) to get rid of oscillations, but perhaps I tweaking parameters messed things up. If I can somehow set the position/orientation of the collider at each frame without continuity issues, then maybe this issue would go away.
The GUI could use the following additions (though these aren't necessary, so I'll hold off on sticking them in for now):
  • an output line that gives the user feedback (error messages or status messages other than the ones associated with bad file parsing)
  • memory freeing (I'm being sloppy with it at the moment)
  • a loading bar for importing head meshes (because the convex hull decomposition step can take a while)
  • automatic scaling to accommodate input meshes of different sizes (this would include grid size, camera movement increments, light position, control node size, and key hair parameters)
  • interactive control over the control node (the ability to choose between playing KF data or entering an interactive mode that lets you move the control node with keyboard input)
Next step: draw interpolated hairs (as lines) between the key hairs. The problem with this is the fact that the key hairs could be moving at every frame. As a result, it's a waste of time/memory to store a collection of interpolated hairs, since I'd have to go through and update the collection at each simulation step. The fastest approach would be to interpolate and draw all in one pass. I'll give that idea a go and let you know how it plays out.

Saturday, March 20, 2010

Plugging in Bullet

I am so random.

Goal: Plug Bullet into the GUI and draw the head collider
I have finally accomplished this goal! The following video demonstrates the ability to load an .obj file for the head, which is then used to generate a Bullet rigid body for hair-head collisions. For high-density meshes, the compound convex hull decomposition step (mentioned several entries back) takes a very long time. So, I would have to add an additional reduction step before the decomposition one. I think OpenMesh supports mesh reduction (or there must be some open source library out there that does). The collider is semi-transparent and spinning to demonstrate that I can control the Bullet physics. Alas, the physics are not yet linked to the control node's movements yet. Soon, though...

Friday, March 19, 2010

My very first LOD!

[Wipes away a tear]. Here is a video demonstrating my polygonal cylinder LOD that has dynamic parameters including: strand radius, strand stacks (smoothness), and strand slices (the number of divisions in each cylinder segment). From far away, a thick radius and low number of stacks/slices looks fine (ignore the odd shading). At the moment, the LOD uses quads instead of tris, but triangulation would be an easy addition.
Okay! Next step, opacity shadow maps for hair rendering. The Zinke paper uses deep opacity shadow mapping to approximate the global component of the dual scattering computation, but I'm going to start off with plain opacity shadow mapping to get my feet wet.

And yes, waiting (ominously) in the background of the current progress is Bullet integration and interpolation between key hairs. I'm skipping around a bit, I know...

Thursday, March 18, 2010

Smoothing Strands

Given a set of hair control points (like the ones outputted from Bullet's soft body ropes), I can now form a Bezier spline to make a "prettier" hair strand. Recomputing the Bezier function on every frame is very costly, though (part of that is because I'm just testing things out and not really being efficient with the number of loops I use). Anyway, after I get back from class later, I want to draw a triangle-mesh tube around the smoothed strand (my first LOD, I'm so proud...).

(strand formed from the raw control points)

(smoothed strand)

Friday, March 12, 2010

Zinke's Paper and Other Ramblings

As I've mentioned before, I'm implementing Zinke's dual scattering paper in CIS660 (which means I'll be able to kill two hair renderers with one stone, so to speak). That being said, the Zinke paper is a hefty one. Very dense. I've read through it several times and watched the presentation video twice...and even after all of that, I'm still trying to wrap my head around the math involved. I'm definitely getting the main points though. For example: depth map = way to cheat global multiple scattering = can get one from the GPU. So, my plan for approaching the rendering side of things is to see if I can grab a depth map from the CPU /GPU and use it to add shading to a solid color (the hair color). Hopefully this will give me an okay starting point (though not very shiny) for hair rendering. After that, it's a matter of implementing Marschner's single scattering model (to insert reflections). My goal is to have a couple renders to show in time for the Alpha Review (Mark II) on 3/19! Alas, my other goals are still up in the air at this point...other class projects are really cutting into my time. I'm going to try to get back up to speed before the 19th, though.

In the meantime, I figured it might be worthwhile to post my CIS660 overview presentation of Zinke's paper. Dual scattering is quite a clever concept, in my opinion...