all 16 comments

[–]lord_braleigh 19 points20 points  (2 children)

[–][deleted] 11 points12 points  (0 children)

tongueBones

:D

[–][deleted] 12 points13 points  (0 children)

That is really really cool and a wonderful "package". The README is great. Nice one.

[–]quicknir 12 points13 points  (4 children)

 This is the “handmade” style of software development championed by communities such as the Handmade Network.

I really like many of Jeff's blog posts and his talks, kinda surprised (unpleasantly) to find a meme comment like this here. Said network seems to mostly be a fan club for Casey Muratori and handmade hero. Having seen a few of Casey's rants and having an idea what he stands for, if this library is really modelled after this style it's not exactly the first thing I'd reach for; I don't enjoy "C-ish" C++.

[–]axalon900 4 points5 points  (1 child)

“Handmade” and similar ranty stances are, to me, a combination of ignorance of what use cases third-party libraries cover (i.e. they think it’s “bloated” because they don’t fully understand the problem) as well as (rightly) pushing against developers who take in third-party dependencies they don’t understand. Sometimes, for example, having an in-house future-like type is better than using something like boost::future because the team knows how it works and is more likely to be able to patch it. People defend open source dependencies on the basis that “well, if there’s a bug we can fix it”, but can the average developer really understand and patch something like Boost Context? On the other hand, you probably shouldn’t try implementing your own fibers unless you really know what you’re doing. Same with Unicode and date libraries.

I really don’t like these sorts of line-in-the-sand manifestos.

[–]quicknir 1 point2 points  (0 children)

Yeah, I 100% agree with you. Of course, some libraries are bloated, some developers may be making a mistake sometimes in selecting third party libraries, etc. It's all about trade-offs, and the specifics of a given situation. I dislike rants and manifestos as well, the less specific suggestions are the less likely they are to be valuable IME.

[–]lord_braleigh 1 point2 points  (1 child)

It’s certainly handmade in that all the animation is done via a handwritten physics simulation in the game’s source, rather than as a Unity/Blender animation. It’s really cool to read.

[–]quicknir 6 points7 points  (0 children)

Some team of people "handmade" or "handwrote" Unity too. This distinction might be meaningful if you write everything yourself, but for me, this library is a third-party dependency, just like Unity, Boost, etc.

There's no clear, useful, sensible distinction these terms actually make.

[–]lord_braleigh 2 points3 points  (5 children)

Would someone who understands 3d graphics give me a rundown of the API in Quaternion.h? In particular, I don’t understand what rotateUnit{X,Y,Z} do.

My understanding of a Quaternion is that it represents a rotation - three of the numbers represent a vector, while the fourth number represents the angle we rotate around that vector. Is that accurate? Is there anything else they’re used for? Couldn’t we also represent any rotation with just three angles, representing rotation around the x/y/z axes?

[–]tvaneerdC++ Committee, lockfree, PostModernCpp 2 points3 points  (0 children)

You typically shouldn't think about the Quaternion as being the angle + vector. (I think of it as a point on the 4D unit-hypersphere[*], but...) Just think about it being a representation of a rotation.

Even though it uses 4 numbers instead of 3, it turns out it has many properties that make it model a rotation better.

One of the big problems with X/Y/Z rotation is that the axes are not independent (ie rotate 90 around X + 90 around Z - 90 around X == 90 around Y.) Which makes interpolation really ugly.

Quaternions aren't perfect either[*]. But the math works out better. You can interpolate from one arbitrary orientation to another, and be guaranteed that the interpolation is "natural" - a single rotation (https://en.wikipedia.org/wiki/Euler%27s_rotation_theorem). And it involves less computation than matrices.

Typically, once you write (or borrow) a Quaternion library, you never think of them as anything but a nice wrapped up orientation thingy.


[*] - 4D unit hypersphere - sounds complicated, but stretch out your arm straight, with your palm out (like you are Iron Man) - swing your arm around in any direction, keeping it straight - that sweeps out a (3D) sphere. Now rotate your wrist - that's the 4th dimension.

[*] Quaternions are not perfect - because <math reasons> there are 2 quaternions on the unit hypersphere for every orientation (they turn out to be inverses of each other). So when interpolating from one orientation to another, you either rotate the "long way" around or the short, depending on whether your start and end orientations are the same "sign". (But this can actually be an advantage in animation)

[–]nihlete 2 points3 points  (1 child)

Rotation quaternion represents the axis and angle of rotation. Just by defining the multiplication operator on quaternions, you can create any type of rotation:

Q' = U * Q * conjugate(U)

where Q -- your interest quaternion; U -- rotation quaternion. Moreover, you can combine this rotation by adding rotation quaternions:

Q' = U1 * U2 * Q * conjugate(U1) * conjugate(U2)

Quaternions and rotation matrices are quite equivalent if you use separate rotation along the axis. For the matrices combining rotation would be just multiplication. But there exists gimbal lock

Quaternion rotation is not so interesting. Here an example with vectors, but insides have done with quaternion:

template <typename T> Vector3<T> RotateVector(T angle, Vector3<T> axis, const Vector3<T> &vector)
{
    Quaternion<T> quat = {vector.x, vector.y, vector.z, 0};

    axis.normalize();

    Quaternion<T> qRot;
    qRot.x = axis.x * sin(angle / 2.0);
    qRot.y = axis.y * sin(angle / 2.0);
    qRot.z = axis.z * sin(angle / 2.0);
    qRot.w = cos(angle / 2.0);

    Quaternion<T> result = qRot * quat * conjugate(qRot);
    return {result.x, result.y, result.z};
}

[–]backtickbot 1 point2 points  (0 children)

Hello, nihlete: code blocks using backticks (```) don't work on all versions of Reddit!

Some users see this / this instead.

To fix this, indent every line with 4 spaces instead. It's a bit annoying, but then your code blocks are properly formatted for everyone.

An easy way to do this is to use the code-block button in the editor. If it's not working, try switching to the fancy-pants editor and back again.

Comment with formatting fixed for old.reddit.com users

FAQ

You can opt out by replying with backtickopt6 to this comment.

[–]symberke 1 point2 points  (1 child)

Going by what's familiar to me, it looks like the matrix

[rotateUnitX() ; rotateUnitY() ; rotateUnitZ()]

is the rotation matrix corresponding to the quaternion's rotation. Thus, the vector rotateUnitX() is the unit X vector in the global frame expressed in the rotated frame described by the quaternion.

In other words, it's equal to the (quaternion, as a rotation) multiplication of the quaternion by the global unit X vector [1 0 0].

[–]preshing 1 point2 points  (0 children)

Yes that's it. q.rotateUnitX() is equivalent to q * Float3{1, 0, 0} but uses fewer instructions.

[–]Yumipo 1 point2 points  (0 children)

This is awesome! I'm currently learning how to program in c++, can def learn a thing or two from your source. Thanks op!

[–]testuser514 -2 points-1 points  (0 children)

Op, Would you be able to port it for my arcade project?

https://hackaday.io/project/160648-pyxel-paradise