News | Forum | People | FAQ | Links | Search | Register | Log in
Microbrush 3 3D Modeler
Hello! :)

One of my hobby projects is a little 3D modeler/level editor for brush-based engines such as Quake or Source. I originally started working on it because I was really annoyed by how long it took to make basic brushwork in Valve's Hammer. Some inspiration for it stems from the Radiant series of level editors.

It requires Win7 or higher to run and renders its stuff with OpenGL 3.3. If your graphics driver is up to date, it should work. It's portable, so it just needs to be unzipped and can then be used from the target folder.

Project page:
After unzipping, run "First start and tasty fresh cookies!.bat" and follow the instructions. For a reference of the configured shortcuts, have a look at the config.cfg file.

Here I've recorded myself building some random stuff with it:

This is a Twitter account to go with it:

At the moment, the focus is almost exclusively on brush work. The editor can't process texture or entity information yet, so please don't resave an existing world with it unless you want to get rid of all textures and entities. :)

It supports loading and saving
- its own textual or binary formats
- Half-Life 1 .map files
- Half-Life 2 .vmf files
- Quake 3 .map files

Additionally, you can run an export in its textual format with computed data (such as polygons) included, or export the same data as a Wavefront .obj file.

Pretty much all the business logic in the editor is written down in plugin code that's compiled in the setup stage. To look under the hood, check out datasourcesplugins.
The grid supports being skewed/rotated or configured to display ellipses instead of parallel lines. The respective shader and also the shader used to color the brushes can be seen in datashaders.

Hope this is useful to some. :)

Edit: updated URL
First | Previous | Next | Last
Oops. The board ate my backslashes and I can't edit the post to correct that. x_x 
I love the moving grid ... reminds me of MODOs workplane. Looks fast and efficient, nice work! 
I really wish there was a readme or a keyboard shortcut thing I could look at... 
I admit that I lifted some of your ideas for TrenchBroom ;-). I have considered the moving grid, but my reasoning was that as soon as you have some brushwork, there's always a brush to use as reference. But for blocking out, the moving grid might be great, esp. if you don't have 2D views at all. 
Very nice, playing around with it for 5 minutes felt good.

Rostock represent! I was born in G�strow and studied in HRO for a while. I still miss the coast and the Schillerlocken.

Die Montagsbar in nem verlassen Haus in der Gerhart-Hauptmann Strasse war so geil. 
FifthElephant: Have a look at this post for starters. :)

SleepwalkR: I'm honored! :D
I've linked to your project and other such editors from my project page.

mfx: Aw nice. I've majored in computer science here.
I personally wouldn't eat those, and it's a shame they're so popular. :/ The reason they're getting smaller and more expensive over time is that they're based on another shark species that's slowly dying because of over-fishing. Predators don't reproduce as quickly as normal fish (think of a decade instead of a year), but with product names disconnected from the fish species and fishing conditions under veils, the regular customer doesn't have the information at hand to make responsible choices.

I digress. 
Hey Shrinker 
I'm a linux user, this works neither in wine (windows "emulator"), nor oracle virtualbox (running win 7).

Can you give me some insight to what 3d libs this app uses so I can diagnose and maybe get it working?

It says in the first thread message that the program uses OpenGL 3.3. In Virtualbox you have Virtualbox's own Chromium GL driver, which only supports OpenGL up to version 2.1 AFAIK. Unless you can somehow get it support 3.3, I think this prevents the program from running in any OS under VBox at all.

I hope wine will turn out to be able to run the program. 
Future Plans? 
I was just wondering what your plans for Microbrush are. I have followed your project on and off for a while (mostly to steal ideas, as I said, hehe), and it looks like you're doing this mostly for the fun of learning things and for exploring how to make editing in 3D as painless as possible.

As you say, Microbrush is only useful for editing brushes right now. Do you plan to extend it to support texturing and entity placement in the future?

Also I'd be interested how you deal with the eternal problem of having to keep the two representations of brushes in sync. In TB I have both the vertex representation (as a doubly linked edge list) and the half space intersection representation (list of planes) in memory at all times, and have to keep syncing between them. For example, when the user moves a vertex, I first compute how that affects the vertex representation, and then recompute the planes of those faces that have changed. After that I recompute all vertex information from the plane representation again to ensure that the editor actually displays what the Quake compilers will see (they only see the planes and recompute the vertices, too).

This syncing has proven to be a major pain in the ass. For example, sometimes recomputing the vertex representation from the planes after a vertex move will drop vertices due to floating point imprecisions (esp. in TB1 which uses 32bit floats). And of course sometimes you cannot compute accurate planes from the vertices, at least not if your planes only use integer coordinates (which is best for the Quake compilers). Inaccurate planes then lead to microleaks, which are supper annoying for the mappers because they can't really see those leaks in the editor...

Yeah, so this became a bit long. Anyway, would love to hear how you approach these problems in Microbrush. 
I Wish There Was A Post Edit Button 
@Shamblernaut @primal
Yeah, I guess OpenGL is the requirement in question here. The editor uses the basic Visual Studio runtime libraries and accesses the Win32 and OpenGL APIs directly. There's nothing like QT or so involved. Maybe things get better with Vulkan in a few years? I doubt it... my graphics development problems all stemmed from graphics drivers not implementing little technical details correctly according to the OpenGL specification. :( The best I could do was document my workarounds in the readme.

I'm not sure where the road is going. So far the threads where I've posted about it died pretty quickly. I have the impression that people are already comfortable with the tools they're using all the time and prefer browsing funny memes on facebook over creative work any day. Also, I was really put off by people on facepunch basically saying that the program is entirely unusable just because they don't like my font. I could not get my point across that this is not a word processor and there might be other priorities, such as making the application capable of actually editing geometry. Motivation is difficult.

My todo list says that next comes facedrag, which is still sorely missing, and then a way to make quick backups to compensate for the lack of an undo journal. I would also like to support textures in some way, and the math for bezier patch meshes is already done and implemented. I think they are a powerful graphical primitive and would really like to edit really complex bezier mesh geometry easily in Microbrush. Looking back, I figured managing point entities would have been a lot easier than implementing that stuff so far.

Regarding the brush math:
I do all manipulations on the level of half-spaces/planes. I don't edit vertices or regenerate plane info from triangles anywhere. If I did allow for vertex editing, it would only apply to individual vertices at a time, and the plane info would be recomputed from a best-fitting triangle per face where the vertex is involved.
Back when working on Microbrush 1 (see, you'll eventually have a Trenchbroom _3_, too :P), I figured a way to get stable brushes: Instead of saving a normal and a d = p0*n, I save a p0 and two spanning vectors u and v for each plane. This allows me to move sloped planes around without worrying about degrading precision at all. The plane normal is just a derived value in this scenario.
And then, along the long way to what's in Microbrush 3 now, there was a lot of fine-tuning the algorithms for computing the mesh representations from intersecting planes, and also for merging brushes and stuff. Small mistakes in deciding when to drop which point as being outside of a brush lead to clipping brushes making them grow wildly in various directions, or computed brush meshes being full of holes.
I have to order intersection points within a plane to generate an actual face, of course. One key insight there was that when using atan2/acos, etc. for determining the angles, computed can exceed the valid input range of [-1, 1] for the inverse trigonometric functions even though the math is sound. Limited precision is the reason for that, so when I've started clamping there, things suddenly worked out well.
Microbrush 3 does all of its computation with 32 bit floats. You have to move things a long way from the origin for them to become noticeably imprecise. 
Small mistakes in deciding when to drop which point as being outside of a brush lead to clipping brushes making them grow wildly in various directions

Sounds familiar. Radiant used to (maybe still does?) have exactly that problem. 
For me I find the way the selection/de-selection system works to be very unintuitive. Especially when you consider having to press escape all the time.
I looked at the tool thinking it might be a nice way to create interesting brush shapes, like .obj files, so I could make slightly more complex geometry to use in conjunction with trenchbroom for my quake maps. So far this doesn't seem like a good fit. I was thinking along the lines of starting with a box, extruding and manipulating shapes perhaps and vertex editing (like a simplistic modelling tool).

Not quite sure what this tool is for to be honest. 
If I did allow for vertex editing, it would only apply to individual vertices at a time, and the plane info would be recomputed from a best-fitting triangle per face where the vertex is involved.

Yes, but since that plane is just an approximation, you'll end up with vertices that have "wrong" positions in that they are different to what they would be if you were to recompute them from your now changed planes.

But I see that you have chosen (wisely) to avoid this problem altogether. It's pretty bad.

Instead of saving a normal and a d = p0*n, I save a p0 and two spanning vectors u and v for each plane. This allows me to move sloped planes around without worrying about degrading precision at all. The plane normal is just a derived value in this scenario.

But that is just a three point representation, isn't it? It doesn't really contain any more information than the normal + distance representation that QBSP uses. Of course, the information is distributed over more values (9 instead of 4), so maybe it gets you a bit more numerical precision due to the redundancy? It would be interesting to do a proper analysis of how much this actually improves anything (because I think going to 64bit floats gives a better improvement at a smaller cost).

One key insight there was that when using atan2/acos, etc. for determining the angles

What angles? You seem to be using a very different methods to enumerate the vertices of the half plane representation than QBSP does. The problem is that, even if your method is better, it will lead to problems down the road because your editor shows the mappers something that isn't there according to QBSP. It is my experience that the best thing you can do is to do exactly the same thing as the compilers so that the mapper sees what the compiler sees.

Microbrush 3 does all of its computation with 32 bit floats. You have to move things a long way from the origin for them to become noticeably imprecise.

That is not my experience, unfortunately. Moving from 32 bit to 64 bit floats has done away with quite a number of problems in TB1, but this may be due to my algorithms not being numerically stable enough. 
I Like This Pie Icon 
Ah yes, I still need Hammer-style camera controls. Esc is more intuitive for someone who used the Serious Editor series of level editors.

Suppose you have a sloped plane with a normal vector n = vec3(1, 2, 4) going through the origin, so d = 0.
All is fine. But now you want to move the plane a bit, say 10 units in the x direction. Your d suddenly becomes a problem. And of course n isn't filled with such neat values. And it might be normalized, too. I don't have this problem of d degenerating because d and n are just derived values for me. I always manipulate the defined sample point p0 that the plane goes through, and the numerically stable spanning vectors U and V. I can translate a sloped plane forth and back a million times, and the end result is just the same as the plane I've started with, while in the form d = n*p0, d becomes more and more imprecise over time. For a translation, I just add to p0. For rotating something by 90�, I swap out coordinates in the spanning vectors. But other than that, those spanning vectors aren't touched. That's why I'm fine with 32 bit floats. The d = n*p0 form is unambiguous, there's always just one representation per plane. I do have redundant information here, with an infinite amount of combinations of p0 and spanning vectors representing the same plane. In all this time I've been fiddling with computing brushes, I never had a case where a brush face was slightly off so that it would cause a leak.

QBSP: I have so far never seen a difference between a final brush in-game and a brush in the editor. The goal of what the computed brushes had to look like was clear, so I've derived it all from scratch. Do note that I've originally done this years ago when I was still green and stupid. I never looked at QBSP or anything like that for reference because I plainly wouldn't have understood that back then. :D
Likewise, I've tried to validate a bit of my bezier math with GtkRadiant this year, but failed to understand the computations there altogether. So I just fiddled with my stuff until it yielded the exact same coordinates for all test cases I could think of.

Yes, I probably do things differently than in QBSP and Radiant, but it seems that both ways work. 
Note: The d = n*p0 representation is always unambiguous if n is normalized. If not, then there's an infinite combination of {n, d} per plane. too. 
Yeah I see your point about the plane representation. And now that I think of it, the n*d representation is a derived value for me too, because I actually store the plane in a three point format, which exhibits the same properties you describe. The advantage of the three point representation is that it maps directly to the face points in the .map file.

I don't understand how you map your plane representation to the three points in the map files. How do you compute these three points so that they are integer? Or do you use floats in the map file? If so, that's a source of infinite trouble for mappers as the slightest deviations produce microleaks. These things become even more difficult once you have vertex manipulation and arbitrary rotation.

If you have a smart solution for these problems, I'd love to hear it because I have been struggling with these issues for a long time in TB. As long as you limit yourself to simple things like 90 deg rotation and clipping (with integer clip points), everything is good. But more complex tools that rely on the vertex representation fuck everything up. 
I use floats and write them into the files as they are. I discourage arbitrary rotation for brushes, but if that's needed, it becomes the problem of the next tool in the pipeline. At the moment I'm not rounding any values, and if you use only the regular tools and align your work normally, you don't get such odd values at all. 
That's the beauty of the limited toolset. When I started I wanted the exact same thing - just do everything with the 3 point clipper. But then everyone moaned how much they need vertex editing, etc. 
"But then everyone moaned how much they need vertex editing, etc."

Well, yeah. A level editor without vertex editing is basically useless... 
I never moaned about it. TB was already pretty much feature complete when it came out and it basically stopped me using WC 1.6 
Excuse My Ignorance, But 
"there was a lot of fine-tuning the algorithms for computing... for merging brushes and stuff."

is that not what QBSP does? 
Qbsp merges faces. It hardly cares about brushes at all. 
@WarrenM: I'm sorry then. :(

@Shamblernaut: QBSP might be able to do all of those calculations, but I can't just harness them out of the box for my own realtime rendering of stuff. That's why both I and SleepwalkR had to implement our own versions of the respective algorithms. This was needed to turn a list of plane representations into polygons that you can see. :) 
Ha! I meant useless for Quake editing ... your project is cool in it's own right. 
If I Pick The Pie Icon Often Enough, Do I Get Actual Pie? 
I could edit Quake and Doom 3 levels in Radiant just fine without needing its vertex edit mode.

First | Previous | Next | Last
You must be logged in to post in this thread.
Website copyright © 2002-2024 John Fitzgibbons. All posts are copyright their respective authors.