math: refactor Vec and Mat mixin structs #1420
No reviewers
Labels
No labels
CI
all
basisu
blog
bug
build
contributor-friendly
core
correctness
deferred
dev
direct3d-headers
docs
driver-os-issue
duplicate
dxcompiler
editor
examples
experiment
feature-idea
feedback
flac
freetype
gamemode
gkurve
glfw
gpu
gpu-dawn
harfbuzz
help welcome
in-progress
infrastructure
invalid
libmach
linux-audio-headers
long-term
mach
mach.gfx
mach.math
mach.physics
mach.testing
model3d
needs-triage
object
opengl-headers
opus
os/linux
os/macos
os/wasm
os/windows
package-manager
priority
proposal
proposal-accepted
question
roadmap
slipped
stability
sysaudio
sysgpu
sysjs
validating-fix
vulkan-zig-generated
wayland-headers
website
wontfix
wrench
www
x11-headers
xcode-frameworks
zig-update
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
hexops/mach!1420
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "spectre256/mixins"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This change refactors the vector and matrix mixin structs to instead share a single generic struct. This allows for more generalized functions and less boilerplate. It also adds a new implementation of swizzle that is more flexible, more suitable for generalized vectors, and supports different axis names.
New mixin approach
This change moves all vector and matrix functions to their respective generic structs (e.g.
Vec2.dot,Vec3.dot,Vec4.dot=>VecN.dot). Functions that are specific to certain versions of the struct (e.g.Mat4x4.projection2D) have also been moved to the generic struct. This means that the public API for these functions does not change at all; users can still callMat4x4.projection2D(.{ ... })like normal.Somewhat confusingly, this means that users can also refer to this function as
Mat2x2.projection2D, but if they attempt to use the result as aMat2x2instead of aMat4x4, there will of course be a compile error. I think this is a reasonable sacrifice compared to the benefits of this change.pub const x = Shared.xboilerplatetranspose,scale,translate, etc. can be merged into one implementationinitNew swizzle implementation
The current implementation is somewhat awkward to use and lacks the flexibility that swizzling in shaders feature. For example, using the current implementation, the input vector type must be the same as the output, e.g. you can't write
const v: Vec2 = myVec4.swizzle(.x, .y);. You are also locked into using xyz to as your axis names. This is inconvenient when working with vectors of rgba values or texture coordinates. Finally, due to the current implementation of mixin structs, swizzle can't be used on higher dimensional vectors.My implementation solves all of these problems. Instead of an array of enum values, it takes a
comptime []const u8which represents a list of the vector components to use. It accounts for returning vectors of a different size than the input, it allows you to use "xyzw", "rgba", and "stpq" depending on the application. It also has the bonus of being slightly faster to type (myVec.swizzle("yzw")instead ofmyVec.swizzle(.y, .z, .w)).P.S. I know it's probably bad to include this in the same PR, but making these changes separately would result in wasted work. If you would like me to move it into a new PR, I will do that.
Public API changes
Swizzle changes arguments from enum to string
VectorComponent enum removed
initfunctions for vector and matrix structs take slices instead of the exact number of arguments (the reexports in main remain the same, however)Vec.fromIntremoved from generic struct (the reexports in main remain the same, however)Mat.Vec changed to Mat.MinVec
By selecting this checkbox, I agree to license my contributions to this project under the license(s) described in the LICENSE file, and I have the right to do so or have received permission to do so by an employer or client I am producing work for whom has this right.
@ -286,39 +36,33 @@ pub fn Mat4x4(///Unless a Mat3x4 is constructed with MatNxN(4, 3), rather than MatNxN(3, 4), wouldn't
rowsbe 3 andcolsbe 4 in this example?This would also mean Mat3x4.ColVec == Vec3, not Vec4 like stated in a comment above, since there are 3 rows which corresponds to 3 elements per column (the logic/code is correct, the comment seems wrong).
@ -331,129 +75,230 @@ pub fn Mat4x4(/// You would write it with the same visual layout:Looks like there's been a typo here.
@ -286,39 +36,33 @@ pub fn Mat4x4(///Good catch, thanks!
@ -331,129 +75,230 @@ pub fn Mat4x4(/// You would write it with the same visual layout:Fixed 👍
Fair disclaimer, these are just my opinions as someone who isn't an active contributor to this project, so take them with a grain of salt.
@ -49,71 +49,92 @@ const ray = @import("ray.zig");/// Public namespacesnitpick: it would usually be called MxN in linear algebra since NxN may imply it's a square matrix.
@ -6,269 +6,19 @@ const math = mach.math;const vec = @import("vec.zig");In linear algebra, the convention is that
musually comes first and means rows. In this case it's flipped around;mis last and is columns. I might suggest naming themrowsandcols(then remove the other definitions of rows/cols) to simplify things.@ -286,39 +36,33 @@ pub fn Mat4x4(///Does this type make sense for matrices without equal numbers of rows and columns?
If this definition of
Vecis kept, maybe it should be renamed toMinVecto go alongsideRowVecandColVec, although this would create a breaking change sinceVecwould no longer existThis name isn't all that descriptive to me, although I'm not sure what else to call it. Maybe
MinVecMinusOne?@ -286,39 +36,33 @@ pub fn Mat4x4(///Sure, that works. I wasn't sure what to name it either
@ -6,269 +6,19 @@ const math = mach.math;const vec = @import("vec.zig");Fixed, thanks! I decided to change the names of the generic structs (VecN and MatMxN) to the same names as the reexports in main (Vec and Mat) for the sake of consistency.
@ -286,39 +36,33 @@ pub fn Mat4x4(///Since the Mat type is not necessarily square anymore, maybe it just doesn't make sense to have this type at all? Those using Vec should replace that usage with RowVec or ColVec as appropriate.
@ -49,71 +49,92 @@ const ray = @import("ray.zig");/// Public namespacesGood point, thanks. I changed the names of the reexports in main accordingly. I decided to change VecN and MatMxN to Vec and Mat, since those are the names of their reexports in main.
I noticed a minor inconsistency: Vec takes a parameter named
lengthand the resulting struct has a member namedn, but Mat takes parametersmandnbut has membersrowsandcols. Maybe one of these should be switched to match the other (e.g. change Vec to take a parameternand have a memberlength)?View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.