Cartoon-style outlines

Blitz3D Forums/Blitz3D Programming/Cartoon-style outlines

Yasha(Posted 2009) [#1]
No inverted mesh here! I told you so - or maybe I just thought it to myself. At any rate, it can be done in real time (blazingly fast in fact, at least on my machine). The idea here is simple enough: a line is drawn against each edge where one of its two faces is facing the camera, and the other one isn't. Using a 3D line function means that detecting obstructions, and parts of the mesh in front of the line, is unnecessary. Rather than detecting which edges are suitable in real-time, the idea is to precalculate planes that define the space in which edges would be highlighted (which may take several seconds on older machines, because the function to do this at the moment is a bit awful - it's only set to do 25 frames as this bit is really quite slow) so the actual checking requires only one TFormPoint per frame (although drawing the 3D lines does also use TFormPoint) to get the camera's position in the entity's space.

There are still several obvious flaws:

- The lines don't match up perfectly at the ends. This is the fault of the 3D line function and should hopefully be easy to address.

- Some of the lines look like they're double-thickness. This is because the lines are supposed to be half-inside, half-outside the mesh. Particularly sharp edges won't conceal the other half of the line; probably the only way around this is to design the character with this in mind and not give it sharp edges.

- Lines "pop in" in funny places - again, this would best be solved by designing a character not to display edges in places you don't want outlines.

- The edge data uses absolute positions, which is obviously not compatible with render tweening or animation speeds other than 1. I think (I hope) this can be addressed by tweening between two frames of edge data according to whatever position the animation is at. This is why this demo uses SetAnimTime and suffers from terrible stuttering (the ninja's animation is very fast so it's set to 0.1 speed). Fixed this, see next post. Whoops, no I haven't.

- The lines are red (so you can see them). I will leave correcting this as an exercise for the interested reader.

In order to precalculate the edge information, a static version of each frame of the animated model needs to be made, which is what most of the code is doing. Don't examine this part too closely, because it's a real mess. It's also rather slow - this information should probably be saved to a file rather than recalculated at runtime. All this part really needs is some way of knowing animated vertex positions, so if anyone knows a better way of getting these, please suggest it.

This example was made with Psionic's ninja model. I can't find the link to download it (I'm pretty sure it's free) EDIT: OTHER MODELS MAY NOT WORK! Don't know why yet, it's to do with the getting-static-meshes-from-frames part, not the outline drawing. The Psionic models that come with PaceMaker (dwarf, robot, zombie) seem to work correctly.

Some of the code (Navigate_World_With_MouseAndKeys(), mainly) is taken from this attempt to do the same thing a while back as I just modified the example until it worked this way.



Anyway, I realise it's been four years and nobody cares any more, but there don't seem to be any other examples in this forum of any method of drawing outlines that don't involve the horrifyingly, gamebreakingly ugly inverted mesh method. So here's the beginning of one.


Ross C(Posted 2009) [#2]
Do you have to use the 3d line option? Have you tested drawing 2d lines? Anyway, i can't wait to try it, thanks for sharing this :)


Yasha(Posted 2009) [#3]
Well aside from 3D lines being about a bajillion times faster than 2D ones, if say your character has its arms crossed in front of its body, and you outline both arms with 2D lines, all the lines will be visible (ie. the outline of the arm behind will be drawn in front, which is obviously wrong). With 3D lines correcting for this, or any other circumstances when the entire length of an edge might not be visible such as curving around the side, is automatic, as obscured parts of the line are really just obscured by the geometry.

Incidentally if you have PaceMaker (or at least, Psionic's models) I'd recommend using the robot, it works better than the ninja. I think you do need to have designed the mesh with this system in mind if you want to use it for anything.

Here's a version that tweens the outlines between "keyframes":



I think it's still accurate for the sequences themselves. However, it shows definite inaccuracy if skipping between sequences - not sure why this should be. Anyway, still needs a lot of tidying up. The tweening doesn't damage performance as badly as I feared (still in the high hundreds of FPS).

EDIT2: Actually testing it with a longer sequence shows there are some accuracy problems, with some meshes and not others. Not sure why...

EDIT3: OK, worked it out - the problem is with rotations. Say you have an keyframe at a given point, and the next one rotated 180%; while the animation spins between them, simply interpolating the vertex positions has the object squish down and stretch out again. That's why simple interpolation won't work - I'll ponder more on this. Unfortunately this is probably going to mean DLLs.