-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Calculate texture scale and offset for brushes. #80
Conversation
Nieblist
commented
Apr 23, 2022
•
edited
Loading
edited
- Map face vertex UVs to VMF UV axes with shift and scale for brushes. Shift and scale are based on texture image size, so use a material with only one image texture to get the right mapping.
- Add an "Allow Skewed Textures" option in the map export panel to keep non-perpendicular UV axes intact, otherwise it will modify the V axis to make them orthogonal.
Hi reviewers. Please note that the Allow Skewed Textures option is not working for all cases right now. It seems to be flipping some textures or otherwise having some issues. I decided to keep it because it can be useful (I'm using it for my map), but if you prefer I can remove it for now and create another PR in case I find a way to fix it. |
Hi @bonjorno7, please let me know if there is any reason not to merge this. It has been pretty useful for my map. Do you prefer me to remove the "Allow Skewed Textures" option and keep only orthogonal mappings? (This is for issue #79) |
Hi @Nieblist sorry for the wait, I've been |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you've done an amazing job, and I only have a few small nitpicks and questions.
addon/ops/export_vmf.py
Outdated
settings = Settings( | ||
brush_objects, disp_objects, | ||
geometry_scale, texture_scale, lightmap_scale, | ||
allow_skewed_textures, align_to_grid | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kind of a nitpick, but I'd prefer a trailing comma here, so each item gets its own line.
@@ -31,7 +31,7 @@ class SOURCEOPS_MapProps(bpy.types.PropertyGroup): | |||
texture_scale: bpy.props.FloatProperty( | |||
name='Texture Scale', | |||
description='Size of one texel in hammer units', | |||
default=0.5, | |||
default=1.0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems slightly out of scope, but I'm fine with it.
addon/types/map_export/brush.py
Outdated
if face_material and face_material.use_nodes: | ||
for mat_node in face_material.node_tree.nodes: | ||
if mat_node.type == 'TEX_IMAGE': | ||
texture_side_length = mat_node.image.size[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious why the width and not the height, but you don't have to explain if you don't feel like it.
addon/types/map_export/brush.py
Outdated
break | ||
|
||
return texture_side_length |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps it makes sense to do an early return instead of a break, then return the default value at the bottom; saves you 2 lines of code (44 & 52).
@@ -52,7 +66,7 @@ def calc_uv_axes(settings: typing.Any, bm: bmesh.types.BMesh, face: bmesh.types. | |||
for loop in face.loops[0:3]: | |||
uv = loop[uv_layer].uv | |||
u_vals.append(uv[0]) | |||
v_vals.append(uv[1]) | |||
v_vals.append(1 - uv[1]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this have been necessary with my old code too, or is it required because of something in your math?
Just curious; doesn't really matter.
addon/types/map_export/brush.py
Outdated
uv_side_a = mathutils.Vector((u2 - u1, v2 - v1)) | ||
uv_side_b = mathutils.Vector((u3 - u1, v3 - v1)) | ||
tangent = (p2 - p1) * uv_side_b.y - (p3 - p1) * uv_side_a.y | ||
side_v = (p3 - p1) * uv_side_a.x - (p2 - p1) * uv_side_b.x | ||
determinant = uv_side_a.x * uv_side_b.y - uv_side_b.x * uv_side_a.y | ||
|
||
epsilon = 0.0000001 | ||
|
||
# TODO: Calculate scale and offset | ||
if abs(determinant) > epsilon: | ||
tangent = tangent / determinant | ||
side_v = side_v / determinant | ||
|
||
if not settings.allow_skewed_textures: | ||
bitangent = mathutils.Quaternion(face.normal, math.radians(90)) @ tangent | ||
bitangent.normalize() | ||
bitangent = bitangent * side_v.dot(bitangent) | ||
else: | ||
bitangent = side_v | ||
|
||
# Scale | ||
texture_side_length = get_texture_size(obj, face) | ||
if texture_side_length > 0: | ||
u_scale = tangent.magnitude / texture_side_length | ||
v_scale = bitangent.magnitude / texture_side_length | ||
else: | ||
u_scale = 1 | ||
v_scale = 1 | ||
|
||
# Offset | ||
tangent_space_transform = mathutils.Matrix(( | ||
[tangent.x, bitangent.x, face.normal.x], | ||
[tangent.y, bitangent.y, face.normal.y], | ||
[tangent.z, bitangent.z, face.normal.z] | ||
)) | ||
if texture_side_length > 0 and abs(tangent_space_transform.determinant()) > epsilon: | ||
tangent_space_transform.invert() | ||
t1 = tangent_space_transform @ p1 | ||
u_offset = (1 - (t1.x - u1) * texture_side_length) % texture_side_length | ||
v_offset = (1 - (t1.y - v1) * texture_side_length) % texture_side_length | ||
else: | ||
u_offset = 0 | ||
v_offset = 0 | ||
|
||
tangent.normalize() | ||
bitangent.normalize() | ||
|
||
u_axis = f'[{tangent[0]} {tangent[1]} {tangent[2]} 0] {settings.texture_scale}' | ||
v_axis = f'[{bitangent[0]} {bitangent[1]} {bitangent[2]} 0] {settings.texture_scale}' | ||
u_axis = f'[{tangent[0]} {tangent[1]} {tangent[2]} {u_offset}] {u_scale * settings.texture_scale}' | ||
v_axis = f'[{bitangent[0]} {bitangent[1]} {bitangent[2]} {v_offset}] {v_scale * settings.texture_scale}' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not even going to pretend to understand any of this fancy math stuff, but good job!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right yeah this isn't an issue so I'll resolve it.
addon/types/map_export/vmf.py
Outdated
def __init__( | ||
self, brush_objects, disp_objects, | ||
geometry_scale, texture_scale, lightmap_scale, | ||
allow_skewed_textures, align_to_grid | ||
): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like a trailing comma here as well.
Oh and I'm fine with keeping the skewed textures option, even if it isn't perfect (the rest of the addon isn't either). |
Cool! I'll keep it as it is for now then and come back at it if I have time. Please let me know if you find anything else. |
Hi @bonjorno7! Sorry to bug you, I'm just pinging you again in case we can merge this :) |
Oh sorry I forgot, will take a look and maybe merge tomorrow. |
Nice, ok! |
Sorry for being so unavailable, I should be better. |
For adding [brush UV export](#80).
Happy to help, thank you for the plugin! |