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
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.

You Can 
But vertex editing just makes some things much easier to do, esp. if it doesn't create invalid brushes like WorldCraft does. 
This Icon Has Actually Valid Chinese Symbols In It 是的 
I just find it pretty harsh to label it _useless_ for making level geometry. I've already produced a lot of geometry with it just fine. 
Apologies. I used hyperbole to make a point. 
Just released a new version, with the "drag facing planes" mode finally implemented (key F):

And SleepwalkR made a case about proper undo/redo to me, so I'm now pondering about how I could implement proper undo/redo. 
I've always wondered, what IS a good way to implement undo/redo?

Maya, for example, has a class for every action you can perform, instantiated and stacked every time you perform one, and each one contains full information for reversing itself and maintaining references/indices in the process.

Effective, but kind of overkill? You're essentially writing all your functionality twice (backwards and forwards), wrapped in a shitload of cpp glue. 
That's The Textbook Solution 
Aka the command pattern. Even though it is a pest to implement, it has a number of advantages. Mostly because you can easily extend it to support macros in your app. And with command collation you can keep memory requirements low. 
Yeah, that's the really, really nice thing about Maya - a python window that'll let you do damn near anything (like write a .mdl exporter!)

That's for a very complex environment, though. Quake maps only contain two fairly simple kinds of data, one a pile of keyvalues and the other a pile of planes. 
a dumb way is to just make a copy of the document after every action, and store that in a stack. 
metl - Which for some apps, is great. It's brain dead but it's 100% perfect and failsafe. :) 
The only trouble is, of course, memory. If ZBrush did that it would be problematic... 
Taking Snapshots After Every Action 
would consume way too much memory and also be quite slow on large maps. The command pattern uses the minimal amount of memory. For easily invertible operations such as transformations, you don't need to store anything but the transform matrix. For other operations such as vertex edits, you do have to store a snapshot, but only of the brushes you were editing.

Also, taking snapshots is far from being 100% perfect and failsafe. There are plenty of opportunities for bugs in that scenario, too. 
Data Sharing Is Magic 
People seem to assume you need to copy the whole data structure if you want to make a copy of it. This isn't true if the data structure is designed in a particular way.

If the data structure is immutable and has a tree-like structure, you can easily share parts of it between multiple versions. Updating such a data structure requires only modifying the branch of the tree that contains the updated data.

These kinds of data structures that you can update while sharing data are called persistent data structures in the literature, as opposed to the ephemeral kind with which all slightly experienced programmers are familiar. Persistence here means simply that if you modify the data structure in state s_n to state s_n+1, you continue to have access to both states in the future. Persistent data structures can of course be implemented in multiple ways, with immutability and sharing being just one of them.

Don't confuse this use of persistent with that in persistent data, which means saving the data between program invocations in another place.

I don't know if anyone has made a non-trivial 3D modeler using immutable persistent data structures. It would certainly be an interesting experiment.

For more information, I refer you to the literature. If you want a brief intro, this might work.

It uses C++ to work through a simple example of a persistent list. 
Long Post Which I Will Certainly Want To Edit After Pressing Submit 
Functional stuff! I've done a lot of stuff in Haskell and sometimes I wonder if I should remake it all in Haskell. :X

So far I've sketched out working on creating and destroying brushes as a whole all the time, with extra memory only required for otherwise deleted versions. I think I already got the undo steps done cleanly on paper, but the redo I still have to ponder about a bit.
Since I basically create everything from my plugin scripts, I'll make it so that you can define the borders of the undo steps in those.
One interesting realization I had so far is that if _within_ the borders of an undo step I create and then destroy a brush, it doesn't need to be saved, because duh, after the undo step is used, there's no brush either.

Microbrush uses a spatial data structure to store all of its geometry in clusters. If you edit neighboring brushes, only those will be rerendered. I've done it this way with good performance when editing 100k brushes per scene in mind.
Now when I want to do a brush transformation, for instance, I first remove the brush from that data structure, edit its data, and add it back in. While removing and re-adding stuff, the spatial data structure rebalances itself, merging or splitting nodes as necessary. It has lower and upper thresholds for inner nodes per inner node and objects per leaf node.

For an undo step, I'll store the old version of a brush (before a transformation, before deleting it, etc.), and the new version will be linked with the step so it can be tracked down and deleted again. It all comes down to a bit of fiddly bookkeeping of pointers forth and back and then a bunch of testing to make sure it doesn't explode. So far, I am a bit proud about how stable Microbrush runs. If you manage to make one of its plugins crash (e.g. the grid or the camera), the plugin is unloaded and you can usually still save your work. :D 
One interesting realization I had so far is that if _within_ the borders of an undo step I create and then destroy a brush, it doesn't need to be saved, because duh, after the undo step is used, there's no brush either.

Why would that happen though? I make something I like, accidentally delete it, hit undo, and instead of getting it back I undo whatever I last did before I made it. That's a table flip.

Snapshots of the entire document might be wasteful, but that seems easy to pare down. If the interface is requesting changes from the data, the interface already has (theoretically) perfect knowledge about what bits of the document have changed and therefore belong in or out of a snapshot.

Looks like this morning's coffee reading will be the command pattern. 
Re Copy-on-write 
It's not as easy as it sounds though. Assume that your data structure is a tree, and you modify a node. If you modify a node, you basically add a new view to that data structure that sees all the other nodes, plus the new (modified) copy instead of the old node before it was modified. So what you really have is a new view onto the structure of the tree. To implement this, you also need to copy the parent of the modified node so that the new node can replace the old node in the children of the (new) parent node. And so on until you reach the root node.

So what's really happening is that you keep making new views on part of the structural information in your data structure. For trees, this might be easy to track. For graphs, it sounds like a nightmare and I'll wager that quite often you'll run into situations where you change one node, but have to copy a lot of structural information.

There's another problem though. Let's assume you have mastered this problem and you have a nice data structure that internally handles all this very well. What about references to nodes from the outside? Let's say your editor keeps a list of selected nodes and one of these nodes is changed and thereby copied. You have to update the node reference in the list of selected nodes too because now it points to the old version of the node. Okay, so maybe you can manage this too. But then you realize that keeping references to nodes is kinda handy (and also kinda the point of OO design), and so you are kind of designing against the core features of your language of choice (given that it is an OO language).

Anyways - I suppose that it is possible to write a data structure this way, and if you avoid references from the outside into the data structure, then this approach will work. But I don't think it's better than using the command pattern for undo. In fact, since it forbids a key feature of OO, I think it's quite a bit worse.

Or maybe I'm missing some things? 
I Hadn't Thought About Pointers Hard Enough 
Haskell mostly works with immutable data structures conceptually. Some of those have an operation to "refresh" the data, e.g. to chop off data that's not referenced from a view anymore.
This system is very awesome in practice, but it comes at a cost: They had to put a lot of brain into bookkeeping it all properly behind the scenes. If you just store updates upon updates all the time, there ultimately comes a point where you must start consolidating the data at the bottom. I think that's difficult.

Lunaran: You are talking about the tools the editor offers. I am talking about the functions used to create those tools. If I give the plugin programmer the ability to determine when a new undo step starts, what I said is a consequence. In practice, my tools will behave as expected: A deletion will be undoable, and I will look into making a plugin to support table-flipping so the editor is even more useful. :3 
Making A Tool Is Setting Up A Good User<->tool Feedback Loop 
Data types and implementation is important but maybe the way a tool shapes and interacts with the user should be the most important question?

Is undo/redo of every operation beneficial or does it slow down the creative process to have a huge amount of discrete steps that can optionally be back-tracked or not? Of course it's easier for the developer to just implement the standard features instead of pondering the philosophical implications of every feature.

Sometimes you do want to be able to flip back and forth between your latest action(s), sometimes deliberate snapshots(or commits � la git) might be better and sometimes it could be best to just move forward and never look back! 
Even if a plugin does create a brush and deletes it all within the same transaction, is that really a problem? That sounds like something you could live with, and if it does become a problem, it should be easily fixable. Since the only operation you allow on your tree is adding and removing nodes, it should be easy to identify such sequences.

One problem that you might have to prepare for is that there may be nested transactions. It will happen if you allow operations to be composed of other operations that might also be used in isolation. It's easy to solve though, the simplest solution is just to track the number of active transactions, and ignore the start / end of any nested transaction altogether. 
bear - Good undo/redo support that's well thought out is pretty important for the user.

Jackhammer, for example, doesn't do undo/redo of selections. That's really a pain when you're selecting a bunch of stuff, make a slip, and by habit try to undo it. Well, none of your selections change BUT the last edit you did before you started selecting things goes away.

That way lies madness... 
I Agree 
Undoing selection and other, similar actions that don't modify the map is a bit counter intuitive at first, because well, it doesn't modify the map! Also, other programs such as a word processor don't undo selection either. But in those programs, selection is a simple operation, whereas in a 3D tool, selection is not so simple. Sometimes you have to click a lot of times to select a number of objects, or you have to move the camera around a bit to select everything you wanted. So it can be a costly operation in terms of user effort, and that's why I think that it has to be undoable.

On top of that, I find it coherent that modifications only happen to selected things in all situations. In TB, the rule is that nothing changes unless it is selected. This is not only beneficial for optimizing the renderer (you only need to take care of updating the selected things in the renderer), but it also gives a simple, consistent rule for the user. 
^1red Title! 
@SleepwalkR: Creating and deleting a brush in the same transaction is not necessarily a problem, it's just a thing I have to consider. You know, when I sit there and sketch out all the implications of all the things that can happen. :)
Nested transactions... that sounds scary. I don't have that yet, but your heads up on that is quite correct.

@WarrenM: I don't plan on making selections undoable at the moment. 
I don't know how you sleep at night. 
You should reconsider that for the reasons outlined above. And as I said, it's easy to detect and dismiss nested transactions. Only the topmost transaction must be undoable anyway. 
bear - Good undo/redo support that's well thought out is pretty important for the user.

Yes, but what is good undo/redo support? And what other meaningful ways of navigating the command/action history of a document could there be? It's all application specific work flow design, you mentioned you want undo/redo of selection actions.

What about giving the user the ability to define important moments in history and have "Undo up to latest historic event"? What about branching document history? Or should that just be handled by source control since it's starting to sound a lot like it.

For a brushed based level editor it seems to me it would be useful to have both fine grained and coarser ways of going back and forth the building process.

Still I think Undo can sometimes be harmful since you always get the choice to take back your action and question your every move. 
Bob Ross didn't need an undo. Happy little brushes! 
"Still I think Undo can sometimes be harmful since you always get the choice to take back your action and question your every move."

The hell? 
i would even say there should be a separate undo stack for the camera................. at least when moved from mouse interactions as it wouldn't make sense for fly mode.

many times while orbiting, i've accidentally clicked a point miles away and sent my view careening off into the grey void of despair. 
^^ Err 
that's a TB complaint, btw. I haven't tried microbrush. sorry, i really need to pay more attention when i post. :P 
Good news! My first experiments are going well so far. It is very fiddly code under the hood, but I think this will succeed.
It Does Run In Wine After Initial Setup On Windows. 
I have my son's PC next to me in our home office running Windows 10 with an older Nvidia video card. I have found if I run the initial, "First start and tasty fresh cookies!.bat" on his PC and then copy the folder back over to my Linux desktop also running an Nvidia card Microbrush 3 does indeed run under my default wine-1.7.55.

Not ideal if you don't have access to a windows PC, but it seems to work OK. I'm not familiar enough with the program to say how it normally works, but it seems to operate the same in wine as it does in windows 10. 
This Cake Is For You 
That sounds rather good!

Now I'm interested in a few more details: Does this .bat file not work in WINE? It compiles the editor plugins and models using a Microsoft.Net application and also displays instructions. The file loading and saving from the editor uses such a .Net application, too.

Maybe these insights could also help Shamblernaut...

I certainly welcome your experience because not only does it tell me that this works on Windows 10 (I have really not tested that yet), and using WINE. It's also something I can point at when that question comes up in the future. :) 
Well I Have More Good News, But... 
I need more time to look into it, but shortly after I made the previous comment I figured out it was dependant on .Net and was successful in compiling the editor plugins, models and configuring via your setup batch file all in one of my WINE prefixes.

Yes WINE does batch files. With WINE installed you can run them from the Linux terminal with, "wine cmd.exe /c FILENAME.bat" for example.

The WINE prefix I used is my Steam game prefix and it has many dependencies installed to run most any game I play so it already had the required stuff. Anyone with enough Linux/WINE knowledge can duplicate this themselves, but I'd be happy come up with a process for duplicating it from a fresh Winetricks/WINE or POL/WINE install when time premits if it helps anyone. 
01:15 AM 
If you do, I will gladly post that information on or link to it from the project page with due credit. :) 
Shrinker I Forgot To Ask... 
What is the Minimum .Net requirement?

4.5? 4? 3.5? 2? 
Nevermind 4.5 Does The Trick. 
The only dependencies i needed to install in a fresh WINE 32bit prefix to make your program setup and run was corefonts and dotnet4.5. :)

I'm writing it up now. 
Shrinker, It's Up On Your Steam Group. 
I tried to put it here, but this board eats backslashes. Its just as good on your Steam group page. 
It's Way Past 5 AM Now. Oops. 
Very nice, thank you a lot! :D
I'll integrate that info soon. :)

And more good news: After a lot of crashing and then a lot of fiddling, all of the tools just fully survived an undo test. This feature is quite a delicate addition on top of what was already there, with the potential for really nasty bugs, but so far it seems to work. Let's hope I won't need to reprogram it all based on new findings that I've missed bad behavior. Should be releasable soon. 
Well That's Good News. 
I saw at least one person asking about an undo feature. 
I Hope It Won't Crash Like Mad. It Doesn't For Me. 
The new version ( with undo/redo support (ctrl+z, ctrl+y) is now available at
Seems Stable ^_^ 
I gave it a quick 30 minute test installing it in WINE, making basic blocks and undo/redoing a lot.

Also updated my Steam post in your group with the updated URL, zip name and a few very basic notes for those maybe not as familiar with WINE. 
I'm on holiday at the moment. I'll try again when i get home ^_^ 
Hm, the WINE guide should be independent of the zip name. It changes on every release. :)

I've fiddled with the shortcuts a little, so F10 brings up the horizontal version of the toolbar in future, and Ctrl+O brings up the load mb3txt/mb3dat dialog then. The remaining load/save/export dialogs are now bindable, too (all in the next version).

The next thing I'm working on now is listing the shortcuts in the help texts. That'd be good for learning the shortcuts, and it's on my todo list for ages already. 
Yeah I Agree 
I won't be doing it again since I added basic notes addressing name changes. ^_^

I did get it to crash for me once in another 30 minutes session I had with it. Didn't look to hard at the crash though since it was late. 

Were you told by the editor that a plugin was unloaded, and then the editor continued to run, or was it a hard crash that made it stop entirely?

Did the crash occur during undo/redo or shortly after, or was it something entirely else?

Can you repro the crash? That'd be very valuable for me. :) 
It Was A Hard Crash 
I believe it was a Windows (WINE) program illegal operation or Unhandled exception crash followed by a memory dump. It was very late and didn't look into it further.

When I have time I'll try to make it crash again and keep the memory dump to show you. 
Oh And... 
I remember it happening after something other than undo/redo. I have some experience with Blender and Trenchbroom's GUI, but since I have little experience with your program I was trying different things along with messing with the gui trying to get a feel for it. It crashed in there somewhere. 
Hmpf. Yes, if you can, an explanation of which work steps cause that hard crash would be nice. I have no infrastructure in place to process memory dumps. :) 
No dice? 
Upcoming changes: The log becomes much more talkative. 
xaGe, you might be M.I.A., but I've just fixed a crash when closing a world or the editor that was definitely related to the new undo/redo system. And it was nicely difficult to track down. Chances are high it was your crash too. Time for a new release. 
I Feel So Alone In My Thread 
Ctrl+F5 on to see the new version (2015-12-08).
* Fixed an undo/redo-related crash when closing a world or the editor
* Added logging for the modeling tools - you now get live feedback on deltas, dimensions, counts, etc.
* Extended the help system (comes up when you press F1 while hovering over a window, then rightclick on something) to display relevant currently bound shortcuts (main menu and Mb3 tools)
* Deleting the selection set 1/2 is now properly undoable
* Help messages and error messages are now displayed in the log even if the respective plugin is deactivated in the log
* Modal tools are now canceled by nonmodal tools, too (e.g. making a box is canceled when deleting the selection)
* The main menu now has a button explaining the not so obvious window controls
* For better performance, the brush shader is now reused when a world is closed and then a new world created or opened
* Extended the FAQ a bit
* Bound opening a .mb3txt file to Ctrl+O (you can change that stuff in config.cfg)
* Bound opening the toolbar to F10 (horizontal) and Shift+F10 (vertical) 
YUP, Must Be It... 
"fixed a crash when closing a world"

I can duplicate the crash when closing worlds in WINE & Windows 10 pretty consistently, so most likely that was it.

MIA: Yeah I've been sick last few weeks.

I still haven't used Microbrush3 too much other than getting it to install/run in WINE. I do try each update you come up with to make sure its still working in WINE for those who need it. It's interesting and reminds me a bit of Trenchbroom. 
Planning for texture support now.
This is gonna be a very complex change.
Good Luck! 
My host,, will shut down soon.

I'm moving to 
Updated Thread ^^^^ 

I've conceptualized how I could do textures from a technical point of view.

The current plan is for the editor's config to point at a texture folder filled with an index file and images. The index would map texture names to image file names. I don't intend to connect directly to pak files or wad files or anything, could think of a separate extraction process later on.

The geometry data that Microbrush "thinks" with will get named properties for the planes; Texturing will be realized using a named string property for the material name and a named UV property for the UV settings. I'm making it so that if needed, I could edit other plane properties using the same system later on, or even have different skins with different UV maps. And if it works out, I can add a named numeric property just the same to represent the lightmap of a brush face scale in Source, for instance.

I've already thought of some plugin API functions I'll need to build a surface inspector. I don't plan to introduce a concept of "selected brush faces", but rather opt to do raycasts in 3D to read and write material properties. This does not imply that any change to a texture or UV would need a manual click -- I can just repeat a raycast from plugin code, after all. But before I can really put effort into the usability of such a tool, I need to do my technology homework.

Oh, and I'm kinda leaning toward leaving what one would otherwise use caulk in Q3 and nodraw in HL2 for completely untextured. The conversion to the target map format could autotexture such "technical back faces", and maybe I could even make it possible to augment an exported .obj file with texture and UV information, and optionally discard untextured faces.
So many things that could be done... 
Playing With The Shader 
Playing With The Shader Turned Into Different Render Modes 
Figures I will need different ways of displaying things when I want to display textures, so I might as well add a few other things I thought of. I hope the black wireframe is good enough... because it's a fake wireframe mode done in the shader on the brush surfaces. 
Luckily These Icons Are Simple To Draw 
Adding a means to quickly arrange the views of a world in useful layouts. 
... of course it became yet another toolbar! 
You're doing an amazing job, it's just so sexy and looks so polished. 
A new version is available for download:
* Added a tool to switch render modes
* Added a tool to layout views
* Added a better font
* Thinned viewport borders
* Polished some things 
This Will Be A Day For Me To Remember 
I got bindless textures to work in Microbrush. o_o

This test shader accesses textures from graphic memory wildly without any extra draw calls or stitching or anything else like that. I don't know yet how well it will scale, but damn, this feels good now. :D 
Refurbished a few plugins and figured out that my neat spatial data structure for speeding up everything did not really speed up anything because I forgot to implement all the relevant prefiltering. It's in there now.

Made progress on the property stuff, can now associate string properties with brushes (no plugin yet) and worlds (plugin shown):

Trying to add a cylinder and pyramid tool now, and other little things: 
I forgot to implement all the relevant prefiltering. It's in there now.

I'm glad I'm not the only one who does something like this. Impressive that it ran with reasonable performance at all. 
One Step At A Time 
Finished the bulk of GUI stuff for new planned features, next I have to fill them with life.

This will be a cool version 1.0.0, in 2028. 
I've tried to carve out textured rooms from a voxel space and bake that into brushes. I guess this could be useful for random level generation... hm... 
That's Cool 
Any updates on your project 
Many new construction sites in the editor's plugin code (following my concepts) and leisurely slow development every now and then. The thing I've worked on the most lately are new camera controls.

My biggest concern, a crash bug that I found regarding bindless textures, is seemingly being worked on by ATI/AMD, so that's good. 
You must be logged in to post in this thread.
Website copyright © 2002-2020 John Fitzgibbons. All posts are copyright their respective authors.