14

I was looking at vec4 glm's source code implementation, and I was wondering why they represent vector values with a union, instead of primitive data types like float or int?

This is the code I found in vec4 implementation:

union { T x, r, s; };
union { T y, g, t; };
union { T z, b, p; };
union { T w, a, q; };

What is the difference if we just write T x, T y, T z, T w?

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
pureofpure
  • 1,060
  • 2
  • 12
  • 31

2 Answers2

19

Because a vec4 is commonly used for:

  • Space coordinates x, y, z, w
  • Colour components r, g, b, a
  • Texture coordinates s, t, p, q (although these are less standardised, and I've also seen r and u used in different contexts)

Using unions allows use to access the e.g. second data member as either .y or .g, depending on your preference & semantics.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • 1
    Is this usage defined behavior? I know type punning with a union isn't, but this isn't really type punning. – chbaker0 Feb 24 '17 at 19:58
  • 1
    @chbaker0 If you only use one name for a given member, undoubtedly. If you use multiple... I still think so. I'm more familiar with C, which has language specifically for unions covering it. C++ doesn't seem to, but I think that some stuff under "Object Lifetimes" (N4140 3.8.7) has the effect of making it legal, because the different names are different "objects" with the same type and the same storage location, and the storage isn't freed between using one and using another (which causes the lifetime of one to end and the other to begin, technically). – hobbs Feb 24 '17 at 20:15
  • @chbaker0: Yes, it's well defined behavior because all of the types are the same. Yes, even in C++. – Nicol Bolas Feb 24 '17 at 20:25
  • 2
    @NicolBolas the language in the C++11 standard is "In a union, at most one of the non-static data members can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time," so at face value it looks like the answer would be no. That's why I asked. However hobbs' answer is convincing. – chbaker0 Feb 24 '17 at 20:31
  • 2
    @chbaker0 The rest of that paragraph you quote explains why you can use the union the way they do. Assuming `T` is a standard-layout type (which all primitives are), then you can access data from the common portion of them (which, because they are all the same type, is the entire value) – Cort Ammon Feb 24 '17 at 23:07
16

GLM is designed to behave like GLSL as much as C++ allows. In GLSL, swizzle operations for vectors can use xyzw, rgba, or stpq, with the corresponding element names referencing the same elements of the vector. Therefore, the union is used to match this behavior.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982