Symmetrize and dyntopo

Don’t have much spare time right now, but still slowly hacking away on integrating symmetrize and dyntopo. The existing work is in the dyntopo-symmetrize branch. It works except for undo, which is what I’m working on now.

Actually, symmetrize itself already works fine with undo, but re-triangulating the mesh after symmetrizing relies on the SFME (split face, make edge) BMesh euler operator, which is not supported in BMLog. I added that support in, but discovered that the inverse operator JFKE (join faces, kill edge) does not always act as a true inverse. Thanks to the Suzanne mesh for showing me that case.

Currently altering SFME and JFKE to behave as I think they should, then BMLog can be updated, and finally dyntopo-symmetrize can be completed. Once all that is done, all the work will be moved into the dyntopo branch and dyntopo-symmetrize & co. will go away.

Symmetrize improved

Suzanne symmetrized twice in different directions, then subsurf’d to demonstrate that the geometry remains connected.

I’ve pushed some fresh updates to symmetrize. It should in general behave much better:

  • Normals are recalculated correctly.
  • Fixed cracks appearing along the axis of some meshes.
  • Fixed crash when operator is run from sculpt mode.
  • Axis and direction are now selectable when running the operator.
  • Improved memory management.
  • General code cleanups, main symmetrize code is now in blenkernel.

Note that this is still Mesh-only (not BMesh), so doesn’t work for dynamic topology sculpting or edit mode yet.


Since the dawn of time (i.e. since SharpConstruct) sculpt symmetry essentially works as though multiple brushes are operating on the mesh simultaneously. This is not necessarily the most efficient method, but it is easy to implement and is generally fairly robust. It is even serviceable with dynamic topology, which is somewhat surprising considering that no attempt is made to keep the topology symmetric. That said, imperfections do begin to pop up with dynamic topology, so a workaround would be nice.

Symmetric Suzannes
Naturally the first thing I had to do was go all Photo Booth on Suzanne.

While there are certainly fancy options such as dynamically mirroring the mesh while sculpting and constantly re-stitching the center, a simpler alternative is to add an operator that the user can manually invoke to symmetrize the mesh. (I was inordinately happy to discover that symmetrize is an actual word.)

I’ve just gotten a basic implementation working, code available as usual from my Blender Github repository, symmetrize branch.

To test it, just select a mesh and spacebar-search for the symmetrize operator. Only works in object mode for now. Once the algorithm is solid for meshes I’ll add a BMesh version. Note that right now it’s hardcoded to symmetrize across the YZ plane from X- to X+.

It’s actually a bit harder to symmetrize than you might expect; there are a significant number of cases to think through. A few examples follow:

A mesh consisting of a hexagon, pentagon, and three quads being symmetrized.
  • Any polygon that is already symmetric across the axis will end up just as it started. The pentagon and square demonstrate this.
  • In general, a polygon that is not symmetric across the axis gets chopped in half — everything on one side of the axis gets thrown away, and the rest is copied over and mirrored. The hexagon at left demonstrates this.
  • An exception is made for asymmetric polygons that have some symmetric edges. For example, the two quads adjacent to the square do not get split down the middle, as that would require the nice square to become a hexagon. Instead, a triangle is added to separate the asymmetric polygon from the symmetric one, and then a mirrored copy is added.

There are actually more cases — I’m still working on dealing with polygons that cross the axis multiple times. Loose edges should also be mirrored. It may be helpful to add additional cleanups too, such as optional merging of thin polygons that are sometimes generated near the axis.

As noted, this is just a regular mesh operator for now, not yet part of the dynamic topology branch. I’ll merge it in once the tool is nicely stabilized, but I should mention that I don’t currently have a lot of time to work on Blender.

Optimizing the remesh modifier

The past couple days I’ve been looking into the performance of the remesh modifier. Although I’m committed to getting dynamic-topology sculpting working, the remesh modifier is also a useful approach to clay-like sculpting. Ideally it should support quite high density levels at fast speeds. Below I’ll get very detailed about what I’ve found, but spoiler alert: it turns out there’s quite a lot we can do to make remesh faster.

Continue reading Optimizing the remesh modifier

Two new options and a brush for dynamic topology

I’ve pushed a few updates for dyntopo:

  • As a follow-up to yesterday’s post about better flat-shaded drawing for regular sculpt mode, you can now toggle between smooth and flat shading in dyntopo. This is just a display setting for now, doesn’t alter the actual mesh at all.
  • Edge collapse is now available again, but disabled by default. When making large alterations to the mesh (e.g. with the snake hook brush), you can enable the “Collapse Short Edges” toggle to get smoother and more regular topology. The trade-off is that, while enabled, brushes will tend to erase fine details. For example, if you use the crease brush to define a sharp indent in the mesh, you probably don’t want to collapse short edges in that area.
  • Added a “Simplify” brush that only modifies topology. It’s pretty much the same as using a regular brush with zero strength and Collapse Short Edges enabled. (Note that as this is a new brush it won’t show up in your brush list by default, you have to add a simplify brush manually.)

Flat shading in sculpt mode

Spent a little time today looking at improving one small aspect of sculpt drawing: flat-shaded faces in solid view mode with VBO enabled.

In current trunk, flat shading in sculpt mode looks quite different depending on whether VBO is enabled or not. When VBO is not enabled, and immediate mode is used to draw the mesh, each face (triangle or quad) gets drawn separately. Before drawing the face, a single averaged normal and mask value is calculated. The normal and mask values are used for each vertex of the face. In contrast, VBO drawing uses a shared vertex normal and mask value for every face that uses the vertex. This behavior is correct for smooth shading, but looks strange for flat shading.

The benefit to using a shared vertex value is lower storage requirements; the mesh’s faces can simply reference vertices with an index (and the index can usually be a short, so two bytes per index.) When flat shading is enabled, however, OpenGL uses only a single vertex’s value for the entire face. On any particular face this generally looks OK, but the problem is evident when adjacent quads appear to have the same normal despite facing different directions.

Flat shading in sculpt mode
Click to embiggen
Left: current trunk. Middle: averaged normals and interpolated mask. Right: averaged normals and averaged mask.

I’ve implemented a simple fix for this, available from the sculpt-flat-shading branch on Github. If the mesh is flat shaded, the index buffer is scrapped in favor of duplicating vertex values. The GPU storage requirements are in general slightly higher, but the output looks much more correct.

In the image above you can see two variations of the fix. Both have flat-shaded normals, but the middle uses interpolated mask values while the right uses a single average mask value. Using an averaged mask value seems to look a bit better, although it’s technically a bit inaccurate as sculpt brushes operate on vertex mask values, not the average.

One further issue which affects smooth shading is that interpolation over quads doesn’t look very good with OpenGL. Mask values and normals don’t look smooth because OpenGL tessellates quads into two triangles. The vertex values are interpolated within each triangle, without regard to the missing corner. It’s technically possible to solve this with shaders. Instead of using regular vertex attributes, the vertices just get texture coordinates and the attributes are put into a texture. A bilinear (or even bicubic) interpolation can then be coded in the shader. Such fanciness is probably of questionable usefulness though, and at the very least will have to wait on the completion of other improvements to the various drawing systems in Blender.

My current plan is to wait until 2.64 is released, then commit the flat-shading fix (with averaged mask values.)

Localized subdivision for dynamic topology

OK, time for some updates. Based in part of some useful feedback on BlenderArtists, I’ve spent the past week experimenting with various approaches to the topological update step. I think it’s now getting much closer to what people want to see; in particular the subdivision is localized to the area directly around the brush.

Localized dynamic subdivision
A sphere with varying levels of detail. The small clay stroke in the center has edge lengths a couple orders of magnitude smaller than the large edges to the right.

Until now, the topological updates were based on the paper “Freestyle: Sculpting meshes with self-adaptive topology”. This paper assumes that the entire mesh will have a consistent detail size. Note that since the algorithm collapses short edges, you can lose detail if you change your brush to a coarser detail size.

In contrast, the approach I am using now is to only do edge splits. If you create very dense topology and then set a coarse detail size, the dense topology will remain and not be collapsed. To handle situations where you want to make the topology less dense, a separate simplify brush will be added. (I haven’t done that yet, but the code is largely already written.)

In order to get a good boundary between a dense portion of the mesh and larger polygons, I used a trick that Farsthary described in his unlimited clay research: identify nearby pole vertices (in this case, defined as having nine or more adjacent edges) and split the adjacent edges. This isolates the pole vertex and prevents it from distorting the mesh. This wasn’t an issue with edge collapses, which implicitly force triangles to be relatively regular, but in a subdivision-only approach it turns out this is a really critical step. Without it the mesh quickly develops degenerate triangles that can’t be smoothed away.

Some other changes: the topology update now occurs before each sculpt step, so the result should match the brush shape a bit better. The brush also avoids the accumulation problem now, so repeatedly brushing over an area won’t continually build the surface up (unless the brush accumulate option is on, of course.)

I’m still looking into surface relaxation; I suspect a smoother result can be achieved while still maintaining detail, but haven’t found a good way to do it yet. My current short-term goal is to do some brush work: add the reduce/simplify mentioned earlier and fix the guaranteed-crash brushes like grab.

As usual, the code is available from the dyntopo branch on Github.

Emacs notes

I spent some time today cleanup up my Emacs configuration directory. The files are now up in a new repository on Github: emacs-conf.

Emacs in action, including a compilation buffer, debugging (GDB) buffer, Org buffer with the README for the emacs-conf repository, IRC for #blendercoders, and a shell.

Most of the stuff in there should be quite easy to copy and paste into your own configuration if you don’t want the whole thing. If you do want to try all of it, simply replace your .emacs.el with this:

(add-to-list 'load-path "/path/to/emacs-conf/")
(load "top")

I also append this to my .emacs.el.

(cd "/d/src/blender/git-trunk")

Of course, you will want to replace the path with something more useful on your own system.

General advice, some of it Emacs-specific:

  • Rebind your capslock key to a control key. I do this system wide. In Ubuntu it can be done easily from System Settings (Keyboard Layout > Options > Ctrl key position > Caps Lock as Ctrl. It can also be done with XModMap. In Windows you’ll need to make a small registry edit. See also this overview of various techniques.
  • Related to the control key, be careful with your hands. If you find some action is causing your hands/wrists/arms to hurt, find a different way to do it. Or take more breaks. Or buy a different keyboard. Basically, don’t let programming damage your hands!
  • Make sure your Alt (Meta) key isn’t tied up with something annoying. In Ubuntu you probably want to disable or rebind the HUD.
  • Look at how other people do things. For example, some of my configuration (like C-x C-m as a replacement for M-x) comes from Steve Yegge. Emacs has been around for a long time, so it’s quite likely that someone else has already found a solution for most problems you encounter.
  • Use a big screen, or multiple screens. I use an HP ZR30w (30 inches, IPS panel.) Especially when refactoring a large piece of source, being able to see a lot of things at once is very helpful.
  • Related to the above, if you split your Emacs window into a lot of smaller sections (in Emacs terminology that’s splitting a frame into lots of windows), it’s important to be able to switch between them rapidly. I use C-M-j and C-M-k for this (that’s Ctrl+Alt+J and Ctrl+Alt+k).
  • Keep everything inside Emacs, where possible. You don’t need to run a separate terminal for compilation, debugging, or general shell commands. These can be done inside Emacs with commands like “compile”, “gud-gdb”, and “shell”.
  • Identify patterns in your own work and automate them with a key binding. In Emacs, everything can be scripted.