c-d-a / io_export_qmap

.map exporter for Blender
GNU General Public License v3.0
84 stars 18 forks source link

Export Connected Mesh as a Patch *(Pls read) #21

Open creed59 opened 5 months ago

creed59 commented 5 months ago

I think I found a way to represent pretty much every connected mesh (whatever you'd actually call that) as a patch. Use the following Blender operations on the scene with the specified settings:

  1. Limited Dissolve with Max Angle of 0.1°.
  2. Triangulate Faces: Quad Method: Longest Diagonal N-gon Method: Clip I think what was making it impossible were those t-junc verts created at bsp compile. With the current method of exporting each face as a patch I get 156,911 brushes in my map file, whereas with the proposed method I could get roughly between 700-1500 brushes.

So basically then the only problem is fixing irregular mesh / mesh with divots at what should be corners. Any part of a mesh with the 'lightning' shape is what needs fixed. I'm working on that solution I just don't have time at the moment since I have to go to work. But basically you fill where the corner should be with necessary vertices then apply the 2 steps above to the new mesh.

Something like this won't work because the faces don't all meet (left hand side cut-quad doesn't meet the right quad with its entire length): q Whereas something like this should work: g

waradm commented 5 months ago

try to fork to fix

c-d-a commented 5 months ago
  1. You've demonstrated that if you had followed my advice on preparing the mesh, none of this would have been necessary, and you could have simply exported as brushes (with the added benefit of sealing/vis/shadows/sound). For reference, Quake E1M1 has 1200 brushes.
  2. You're still treating all triangles as topological equals, ready to be merged into patch grid cells. Like I said with the icosphere, this is not the case, edges matter.
  3. Limited dissolve would at least need to be delimited by UVs. Which would then require testing to check if typical use cases (imported compiled maps) have enough precision that their continuous UVs don't count as disjointed by the dissolve op.
  4. Even if you could merge and dissolve at will, I think you're optimistic about the extent to which you're proving that a mesh is patch-compatible. Grab some random bits of Suzanne, flatten along an axis, and you'll have plenty of examples of incompatible topology, even after your dissolve+triangulate steps. Of course, the algorithm will need to be capable of processing the entire Suzanne mesh.
  5. At best, you're aiming at some kind of analytic proof that a mesh could be a patch. It's not terribly useful algorithmically. Filling in the gaps is a lot of effort. Cutting the mesh into a bunch of 1xN ribbons is much easier, can be done on the spot without pre-processing the mesh, and should work on pretty much anything. But even that is still unpredictable and of dubious use.
creed59 commented 5 months ago

I have already attempted to export as a brush, it never works quite like it should. You mean that I will get exactly 100% accuracy exporting the mesh as a brush? I would be very happy if I could get that to work the results just aren't there. With clipping setting: e With beauty setting: f Just from quickly scanning over the topology of the second one (or first) its pretty easy to discern that it at least might be patch-compatible. I'm pretty sure that's roughly 98% quad-based, only a few lone triangles.

creed59 commented 5 months ago

btw your convex decomposition tool works great except curves/patchdefs are the problem trig

c-d-a commented 5 months ago

You mean that I will get exactly 100% accuracy exporting the mesh as a brush?

In principle: yes, whatever geometry you have in Blender can be exported to brushes without any loss of detail (in 'Faces' mode). Though obviously I can't vouch for a map I've never seen, compiled with tools I've never used, for a game I've never played.

Some things could need more work, but mostly very specific stuff, and usually there's a workaround. For instance, X-shaped foliage wouldn't work as a single brush entity, wall decals wouldn't work as worldspawn brushes, etc.

is there a way to export each connected mesh as a convex hull brush?

Yes, that's what 'Brush' mode export is for. You'd have to separate the mesh by loose parts first (enter edit mode, select all, press P).

its pretty easy to discern that it at least might be patch-compatible

Unlikely. I'm seeing loops all around. There might be some specific way for grid topology to emerge from triangulation, but at that point you're not even treating all edges as equals, you're relegating actual silhouette-forming geometry to second class.

convex decomposition tool works great except curves/patchdefs are the problem

Well, wires are not convex, what do you expect? At best you'll get as many cross-sections as there are vertices length-wise.

creed59 commented 4 months ago

You can have this as a patch: view

but not this: f

or this: g There must be some way to re-mesh a mesh such that there aren't enclosed lone triangles or such that there are an even number of tris (so every triangles is paired anyways so no problem). Basically you cant have a tri that's not already 'paired' when enclosed it must be unenclosed. They only exist not being completely engulfed by other faces. If such a thing exists it should make any mesh patch compatible after limited dissolve 0.1°. Also no valence of 9 or greater can exist. Now another thing that I can't figure out is how to represent the topology in its entirety, how to specify which direction an edge is facing, 45°(/) or 135°(\)?

c-d-a commented 4 months ago

There is another (degenerate) triangle in your last image. Meaning that combined with the "enclosed" triangle it forms a quad. Meaning that by your rules, you should be able to lay it out as a grid.

c-d-a commented 4 months ago

I'll make my point about edges again, visually. Let's say you've lucked out and your mesh neatly fits into a grid, with no edge splits required. But then the engine might have other ideas about what the grid represents.

https://github.com/c-d-a/io_export_qmap/assets/55441216/d317c961-c2f7-4f80-a732-544ebe930570

You don't control how the game will triangulate patches, so you don't have the luxury of ignoring "load-bearing" edges. Each triangle has to be treated as a whole quad, there's no way around this.

All my other points still stand too. And as a side note, even the assumption that we can stack duplicate verts (to patch up missing corners and triangles) may be flawed. For all I know, lightmappers could interpret that as occlusion and fill it with shadow.

creed59 commented 4 months ago

Ok your argument stands but can you suspend your disbelief for a second about everything and assume everything (the game magically knows how to deal with edges) works the right way except for some of the topology problems, like holes, or the Suzanne samples you sent me. Does this make any sense?: The following mesh will have a minimum patch value, I can't tell from looking at it but the idea is it has N rows x M columns patch. The extra control points can be used as 'fixers' for anywhere the mesh has disconnected quads and adds tris, when possible, along the longest side of lone triangles, like in the photo: test

Proof that this is 'not' impossible: patch

cor The only way to make it a possibility is to make all holes as corners.

Can you explain visually what you meant by "treat each triangle as a quad"? and what if the engine doesn't have 'another' idea about what a patch represents? The definition of a corner is when two quads that touch share only one vertex, no sides and both segments of the shared vertex are open on one end. The maximum number of corners is of course 4; you can't have more than 4 corners to represent a patch, just as you can't have a vertex valence of a vertex to be greater than 8. All of the following pieces of the Suzanne monkey are patch-compatible, believe it or not. None of them exceed 4 corners, contain a triangle which is subdivided into 2^n subdivisions, letting n be 3,6, or 9, or has a vertex valence of 9 or greater. As far as I know the limited dissolve to 0.1° fixes all if not most of these problems. sheisse So really the only thing that's left to discern is WHAT the engine really thinks of how to represent edges of a patch.

c-d-a commented 4 months ago

So its "impossible"?

We've been over this. Not impossible, but:

Can you explain visually what you meant by "treat each triangle as a quad"?

I've shown it with the icosphere. It means you add another vertex somewhere. If you have two neighbouring triangles, subdividing the shared edge turns both tris into quads. If you have a triangle with a neighbouring quad, one of triangle's corners will have to become a duplicate. Aside from precision issues, it doesn't matter whether you place the new vert right on top of an existing vert, or in the middle of an existing edge.

All of the following pieces of the Suzanne monkey are patch-compatible, believe it or not.

I wouldn't have to believe it if you just showed them fitting on a grid. In fact, that was the point of the excercise, which you seem to have missed: the shapes at the top are taken directly from Suzanne, the shapes in the middle were processed using your proposed steps, and the shapes at the bottom are topologically identical to the shapes in the middle, just with their verts dragged about to show the overlaps. There should be no difference in the number of corners, yet you've managed to get a different result every time.

So really the only thing that's left to discern is WHAT the engine really thinks of how to represent edges of a patch.

Like I said: you don't control it. One game might be doing it one way, another might do it differently, yet another might switch its method in a patch tomorrow, and GPU drivers might also be involved at every step.

creed59 commented 4 months ago

I wouldn't have to believe it if you just showed them fitting on a grid.

Here: sheisse2

pointless (less efficient vert-wise than patch-per-face, less utility than brush-per-face, can't benefit from patch subdivision)

The whole point of all this was to have an export option so as to greatly reduce brush count while accurately representing the geometry, even if the UVs are bad. I have tried many times and in different ways of getting the brush option to get me decent results but to no avail. I tried using decomposition and separate mesh by parts and without them. I get something like this about half the time: nacht

c-d-a commented 4 months ago

Here:

First one merges triangles, but okay, let's ignore that for now. Third one has been misread. Like I said, it's identical to the second one. Second one leaves a gap it can't account for. So this shows that it isn't, in fact, patch-compatible. Not without adding extra rows. And with extra rows you don't need that yellow corner at all. Or triangulation, or valence counting.

I get something like this about half the time:

If the caulk sides are facing up/out, your Blender geometry might have flipped normals, or negative scale. The walls seem to be missing, possibly grid snapping set too high. Anyway, I'm guessing here. Could always be a bug of course, but I have no such problems with my test meshes. Try to isolate to a small part of it, or post the entire thing, I'll have a look.

creed59 commented 4 months ago

These are the steps I take when exporting:

  1. Select all mesh. Limited Dissolve 0.1°.
  2. Object - Decompose Here are my export settings for the plugin: settings and before I export I flip normals i just forgot to last time it works i just get way too many brushes
creed59 commented 4 months ago

4 powerlines mesh = 865 brushes with brush export 4 powerline mesh should equal 4 brushes with a connected mesh to patch export r

c-d-a commented 4 months ago

These are the steps I take when exporting:

'Brush' mode is for quite specific cases, I don't expect imported bsp to be one. Use 'Faces' instead.

4 powerline mesh should equal 4 brushes

Powerlines "should" be four 9x3 patches, but you won't get any better than four 9x200 patches from this input. Consider changing input.

creed59 commented 4 months ago

These are the steps I take when exporting:

'Brush' mode is for quite specific cases, I don't expect imported bsp to be one. Use 'Faces' instead.

4 powerline mesh should equal 4 brushes

Powerlines "should" be four 9x3 patches, but you won't get any better than four 9x200 patches from this input. Consider changing input.

three 9x20-30 something patches, one of them is 8 cylinders long

simple_terrain_brush simple_terrain_patchface there's my point, patch mesh export would probably decrease the brush load by 95% while also likely retaining good UVs

creed59 commented 4 months ago

pointless (less efficient vert-wise than patch-per-face, less utility than brush-per-face, can't benefit from patch subdivision)

Wouldn't the brush count be significantly less?

creed59 commented 4 months ago

So if you were to add a vertex at every edge of a triangle that is shared by a neighboring triangle / add a new corner to every triangle that neighbors a quad you'd basically have a quad-based mesh, assuming the mesh originally was made of only tris and quads? One of the first steps in the algorithm would have to be traversing each vertex and getting linked mesh’ coordinates (in Blender: Select - Select Linked - Linked) stored into a 2d array. Also each group out of the object is assumed to have already been grouped by material; patches are only assigned one material. I will post code shortly.

https://github.com/c-d-a/io_export_qmap/assets/156862058/2bd24cc8-2602-4133-b719-883a5baaa206