c-d-a / io_export_qmap

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

Any plans to improve standard UVs? #3

Closed myuce closed 2 years ago

myuce commented 2 years ago

I'm working on a tool that converts Source Engine maps (which use the Valve 220 format) to Call of Duty maps (which use the standard UV format). It basically generates the geometry by intersecting planes and creating patch meshes (similar to Quake 3's bezier patches) instead of brushes. Having a lot of meshes in the map makes it very difficult to edit it though, so I decided to borrow a small part of this repo, but it doesn't yield very accurate results, so I was wondering if there were any plans to improve the part where it exports brush faces with Quake's standard texture coordinate format.

I've tried to use the part of this repo where it converts UV coordinates of three vertices to Quake's standard format in my own tool and did some tests with some brushes. Simple brushes that only have straight faces seem to work well as seen in the pictures below.

This one is from Hammer Editor. hammer And this one is from CodRadiant. radiant

When I tested it with more complex brushes, I realized it doesn't always yield accurate results.

hammer radiant

The inaccuracies become more obvious when it is tested on an actual map. mirage1 mirage2

c-d-a commented 2 years ago

I'm going to look into this over the weekend, but in the meantime could you check if your basic assumption is correct? I'm seeing shearing on your fourth screenshot - in an editor that you said doesn't support V220 (and therefore shearing). Are you sure the maps won't open as is, maybe with some slight format tweaks?

myuce commented 2 years ago

The brush in the screenshot is rotated randomly and so is the texture applied to the face, which is why it looks like it is skewed, but it is not.

A brush face in CoD's map format looks like this.

( 64 32 -8 ) ( 0 32 -8 ) ( 0 0 -8 ) me_woodplanks01 128 128 100 140 90

The first two values that come after are for the texture's size, The two values that come after those are for the texture's offset, and the last is the rotation of the texture. The only difference between Quake's format and CoD's is that the first two values are multiplied by the texture's dimensions (for example, they will be 128 128 when the texture is 512x512 in size and the scale values are set to 0.25 in Radiant) and the order of these values, so I am quite certain there is no direct way to make the editor support V220 or converting from one format to another.

I don't mind converting brush faces to patch meshes if they are sheared since I want to have accurate conversions, but having all the other brushes converted as patch meshes makes things more complicated than needed.

Thanks for replying though. I really appreciate it!

c-d-a commented 2 years ago

Changed some things:

Before/after: before-after There's some clear improvement, but still no miracles. In the end, converting from Valve to Quake format is a lossy operation. If you find that this hasn't fixed enough, you could split off the shearing component from the transformation matrix and use it to weed out the incompatible coordinates (i.e. any face sheared above some threshold gets exported as a patch).

Also, just in case, be aware that snapping to grid can be very destructive towards Quake-format UVs if you (or the editor) do it after converting the UVs.

myuce commented 2 years ago

I finally had enough time to try this out. I tested it on the latest version of Blender and it seems work really well. However, it looks like the version of mathutils available as a Python package is outdated, so I get the following error message when I try to use it in my project.

Vector.rotate(value): matrix must have minimum 3x3 dimensions

According to the error message, it's because of the following line.

v0.rotate(Matrix.Rotation(math.radians(-rotation), 2))

Is there a way to do this in an older version of mathutils, or should I try to grab the latest version of it and try to compile it as a standalone Python package. Thanks again for your help.

c-d-a commented 2 years ago

Try this:

v0 = v0.to_3d()
v0.rotate(Matrix.Rotation(math.radians(-rotation), 3, 'Z'))
myuce commented 2 years ago

That seems to fix the issue. It's not perfect as you said, but it's definitely better than nothing. Thanks again for you help.

c-d-a commented 1 year ago

I have added the Brush Primitives format in https://github.com/c-d-a/io_export_qmap/commit/fb72371c718f8b108c0e5ccacece00ec55fa080f The name is a bit misleading, as it's only really different in how it stores UVs. It seems to allow the same flexibility as Valve220, but should be supported across Radiant-derived editors and post-Q3 compilers. Can't vouch for CoD, but give it a try.