Skip to content

Instantly share code, notes, and snippets.

@Wolvereness
Created January 26, 2014 10:38
Show Gist options
  • Save Wolvereness/8631025 to your computer and use it in GitHub Desktop.
Save Wolvereness/8631025 to your computer and use it in GitHub Desktop.
[09:09:14] <@Wolvereness> TomyLobo: you there?
[09:09:19] <TomyLobo> yep
[09:09:26] <@Wolvereness> is English your second language?
[09:09:51] <TomyLobo> no, it's the first foreign language i took
[09:10:07] <TomyLobo> i'm not bilingual
[09:10:16] <@Wolvereness> What's your native language?
[09:10:20] <TomyLobo> german
[09:10:36] <@Wolvereness> Okay, FFR, you're bilingual
[09:10:42] <@Wolvereness> unless you use a translator
[09:10:54] <@Wolvereness> (unless you're trilingual or more)
[09:11:11] <@Wolvereness> And, "first foreign language" => Second language
[09:11:23] <TomyLobo> well, i also took a few basic courses in linguistics that allow me to call bullshit on that :)
[09:11:36] <@Wolvereness> Do you speak English?
[09:11:43] <TomyLobo> yes
[09:11:44] <@Wolvereness> Do you speak German?
[09:11:47] <TomyLobo> yes
[09:11:55] <@Wolvereness> Those are both 'languages', right?
[09:11:57] <Faithcaio> is there an event for setting bed spawn?
[09:12:08] <TomyLobo> did i grow up with 2 parents that speak these languages? no
[09:12:34] <@Wolvereness> If you can 'speak' two languages, you are 'bilingual' by definition
[09:13:15] <@Wolvereness> And, "first language" with no qualifier means "native language"
[09:13:49] <@Wolvereness> therefor, "second language" with no qualifier means "the first language after the native one"
[09:13:50] <TomyLobo> colloquially speaking, yes
[09:14:44] <TomyLobo> hmmm irony: the german and english terms differ
[09:14:46] <@Wolvereness> Alright, so I've gotten that far. I was about to write a scathing response to !B1012, but I'd like to talk to you over IRC about it instead
[09:14:46] <+WatBot> Bukkit PR #1012: http://cbukk.it/ghp/B/1012 - @TomyLobo "[B] Added Location.to{World,Local}{Axis,}(Vector). Adds BUKKIT-5338", 18 hours ago, 14 comments - Opened 18 hours ago, updated 6 minutes ago, mergable - Addresses BUKKIT-5338
[09:14:47] <+WatBot> BUKKIT-5338: http://cbukk.it/j/BUKKIT-5338 - "Add utility methods to do world<->local reference frame transformation " - Bug (18 hours ago), Open (15 hours ago)
[09:14:52] <TomyLobo> you're also right in linguistic terms
[09:15:49] <@Wolvereness> TomyLobo: the methods as they are lack severely in documentation
[09:16:15] <@Wolvereness> I'd like to ask you to link to a wikipedia concept describing what your functions do
[09:16:19] <TomyLobo> should i link the wikipedia page on reference frames?
[09:16:20] <@Wolvereness> (an English one)
[09:16:56] <TomyLobo> sure, lemme find an appropriate page
[09:20:14] <TomyLobo> hmm all the wikipedia articles i can find dont really make it easier
[09:20:19] <TomyLobo> they'll just put off people
[09:20:28] <@Wolvereness> I'm a math-guy
[09:20:36] <@Wolvereness> Find the one for the concept and I'm good
[09:20:45] <TomyLobo> http://en.wikipedia.org/wiki/Affine_transformation
[09:20:54] <@Wolvereness> (this isn't for everyone else, this is so I can eprsonally help you get this PR up-to-snuff)
[09:21:33] <TomyLobo> affine transformation minus the scaling and flipping and with only a limited set of rotations
[09:21:54] <@Wolvereness> Why do you want this?
[09:22:20] <TomyLobo> Location represents that kind of transformation
[09:22:53] <@Wolvereness> Location is a point + direction with no magnitude
[09:23:04] <TomyLobo> not quite
[09:23:24] <@Wolvereness> It's a point in a 6-dimensional system - literally
[09:23:31] <TomyLobo> it's a point+2 of the euler angles
[09:23:45] <@Wolvereness> those two angles represent all-possible-directions
[09:23:52] <TomyLobo> directions, yes
[09:24:05] <TomyLobo> but look up and turn around
[09:24:08] <@Wolvereness> Point + direction in 3-D space, but no magnitude
[09:24:10] <TomyLobo> your direction stays the same
[09:24:15] <TomyLobo> your yaw changes
[09:24:39] <@Wolvereness> Direction is derived from yaw+pitch - according to our definition
[09:24:44] <TomyLobo> yup
[09:24:50] <TomyLobo> that's a lossy transformation
[09:24:53] <@Wolvereness> Direction does not "stay the same"
[09:24:53] <TomyLobo> it's not a bijection
[09:25:23] <TomyLobo> (I'm assuming you mean Location.getDirection() here)
[09:25:39] <@Wolvereness> yeah
[09:25:51] <TomyLobo> well you wrote setDirection
[09:26:14] <TomyLobo> and i'm sure there's a cross product with the up axis somewhere in there
[09:26:18] <@Wolvereness> (I take back the 6-Dimensional point comment, because it's not)
[09:26:50] <@Wolvereness> it uses the pitch
[09:27:22] <TomyLobo> ok, that makes the implied up axis a bit less apparent
[09:27:28] <TomyLobo> let me dig through it a bit
[09:27:51] <@Wolvereness> TomyLobo: Read the getPitch setPitch documentation - it defined the values of pitch relating to y-axis
[09:27:56] <TomyLobo> oh yeah, line 277, x==0 z==0
[09:28:41] <TomyLobo> if (x == 0 && z == 0) { pitch = vector.getY() > 0 ? -90 : 90;
[09:28:46] <TomyLobo> you forgot to set yaw, btw
[09:28:59] <@Wolvereness> that's actually intentional to not set yaw
[09:29:15] <@Wolvereness> the yaw is NaN - I left it as-is
[09:29:27] <TomyLobo> it's not nan
[09:29:33] <TomyLobo> it's whatever it was before the function invocation
[09:30:02] <@Wolvereness> Truely, Vector(0, ~0, 0) has a yaw of NaN
[09:30:17] <TomyLobo> would you look at your source please?
[09:31:01] <TomyLobo> https://github.com/Bukkit/Bukkit/blob/master/src/main/java/org/bukkit/Location.java#L277
[09:31:02] <@Wolvereness> TomyLobo: you're mixing up two contexts. The VECTOR has a yaw of NaN, the LOCATION leaves yaw as-is in that situation
[09:32:29] <TomyLobo> wasnt aware that you're speaking figuratively
[09:33:26] <@Wolvereness> So, do you have an example of why MC needs an Affine transformation?
[09:33:45] <TomyLobo> i provided 2 in the PR description, let me copypaste them here
[09:33:55] <@Wolvereness> or rather, which kind of transformation?
[09:34:03] <TomyLobo> "This can be used to render effects adjacent to the player or creature and to spawn projectiles in a consistent pattern relative to the player's view."
[09:34:24] <@Wolvereness> I have code that does consistent patterns relative to player's view already
[09:34:33] <@Wolvereness> getDirection sufficed for that
[09:34:34] <TomyLobo> cosines in it?
[09:34:45] <TomyLobo> how did you go sideways?
[09:34:47] <@Wolvereness> Let me go look
[09:36:04] <@Wolvereness> private Vector setDirection(final Vector vector, final double yaw) { final double offsetYaw = yaw + rotation; return vector.setX(- Math.sin(offsetYaw) * distance).setZ(Math.cos(offsetYaw) * distance).setY(height); }
[09:36:36] <TomyLobo> that's polar coordinates
[09:36:43] <@Wolvereness> That's atually already defined in our API...
[09:36:53] <@Wolvereness> I needed it to be cached vectors though...
[09:38:07] <@Wolvereness> That rotates a vector to ' distance ' hypotinus the X-Z plane; I take that vector and just do Location.add(vector)
[09:38:32] <@Wolvereness> I have a point in 3-D space of some distance away
[09:38:38] <@Wolvereness> at an angle
[09:38:57] <TomyLobo> i dont understand "That rotates a vector to ' distance ' hypotinus the X-Z plane"
[09:39:48] <@Wolvereness> TomyLobo: it sets a vector to point in a direction, derived from a radian-yaw, at some 'distance' away
[09:40:19] <TomyLobo> ok then you have the sideways direction
[09:40:23] <@Wolvereness> A vector is a direction + magnitude, from zero
[09:40:29] <TomyLobo> now the up direction for a nonzero pitch
[09:41:20] <@Wolvereness> Okay, do you want me to write a function that rotates a vector around the "axis" defined by some "pitch & yaw"?
[09:41:33] <TomyLobo> no, because i already did that
[09:41:45] <TomyLobo> toWorldAxis
[09:42:01] <@Wolvereness> Or, perhaps, rotates it around a plane defined by the normal pitch with x,y,z point?
[09:42:22] <TomyLobo> how do you rotate around a plane?
[09:42:47] <@Wolvereness> Do you know how to define a plane based on a point + normal vector?
[09:42:54] <TomyLobo> yes
[09:43:03] <TomyLobo> but the point is arbitrary
[09:43:09] <TomyLobo> it can be any point on the plane
[09:43:18] <TomyLobo> so rotating around a plane still isnt well-defined
[09:43:19] <@Wolvereness> Rotate around that plane, with the original x, y, z being the 0, 0, 0
[09:43:51] <TomyLobo> not all planes go through 0,0,0
[09:44:14] <@Wolvereness> Rotate around the plane as defined by the X->0, Y->0, Z->0, with a normal of some pitch
[09:44:22] <TomyLobo> you can rotate around vectors, given an anchor point, sure
[09:44:44] <TomyLobo> which, together with the vector, becomes an anchor axis
[09:44:46] <@Wolvereness> Okay, rotate about the y-axis as defined by that plane
[09:44:54] <TomyLobo> or rotational axis
[09:44:54] <@Wolvereness> easier to understand that way?
[09:45:17] <TomyLobo> yaw is rotation around the y axis in minecraft, yes
[09:45:29] <TomyLobo> x axis rotation is pitch
[09:45:45] <@Wolvereness> Okay, I'm gonna explain it like this
[09:45:48] <TomyLobo> z axis rotation would be roll, but that's not used on the server side
[09:46:04] <@Wolvereness> Consider some Location l as defined by Player p (with pitch and yaw)
[09:46:21] <@Wolvereness> According to p, "up" changes depending on pitch
[09:47:13] <TomyLobo> correct
[09:47:21] <@Wolvereness> Define some plane, normal to the "up" vector. Then rotate about the "up" vector, originating from point l
[09:47:55] <@Wolvereness> such that, for some yaw, a point will travel "left" or "right" in relation to p
[09:48:24] <TomyLobo> that's not yaw
[09:48:29] <@Wolvereness> it is
[09:48:49] <@Wolvereness> http://upload.wikimedia.org/wikipedia/commons/7/7e/Rollpitchyawplain.png
[09:48:51] <TomyLobo> that's some funky local coordinate rotation, but not yaw
[09:49:03] <@Wolvereness> The plane has a yaw as defined by its facing
[09:49:11] <TomyLobo> yaw's rotation axis is always perpendicular to the ground
[09:49:28] <TomyLobo> that axis does not change with pitch
[09:49:42] <@Wolvereness> That's not useful though, we already have some yaw perpendicular to the ground-normal
[09:49:55] <TomyLobo> so let's call it extrayaw
[09:49:57] <@Wolvereness> I'm talking about your function, and what I think you want
[09:50:08] <TomyLobo> toWorldAxis(new Vector(cos(extrayaw), 0, sin(extrayaw)))
[09:50:12] <@Wolvereness> it's also why I said "for some yaw"
[09:50:26] <TomyLobo> that would be the vector you wanted
[09:50:59] <@Wolvereness> I want to rename the functions to "rotate about forward" and "rotate about up"
[09:51:22] <@Wolvereness> "rotate about forward" does a "spin" (the axis according to plane)
[09:51:32] <TomyLobo> rotations are not commutative
[09:51:49] <@Wolvereness> "rotate about forward" does a "spin" (the roll* axis according to plane)
[09:52:03] <@Wolvereness> "rotate about up" does a "turn" (the yaw* axis according to plane)
[09:52:33] <@Wolvereness> and perhaps "rotate about right" does a "left" (the pitch axis according to plane)
[09:52:41] <TomyLobo> and if you just want to spin relative to the current orientation and around some arbitary axis, you might want to look into quaternions
[09:53:08] <TomyLobo> rotation matrices are equally powerful, but are slower and suffer more from precision degradation
[09:53:13] <@Wolvereness> are these roations what you're trying to add?
[09:54:16] <TomyLobo> Wolvereness i'm just translating to the player's screen coordinate system, basically
[09:54:26] <TomyLobo> or to a pig's screen coordinate system if it had one
[09:54:34] <@Wolvereness> "translating" to screen coordinates...
[09:54:40] <TomyLobo> transforming
[09:54:41] <@Wolvereness> Okay, that's a bit different
[09:54:44] <TomyLobo> sorry for the lapse in language
[09:55:00] <@Wolvereness> Translating makes more sense
[09:55:19] <TomyLobo> translating is moving
[09:55:23] <TomyLobo> transforming is more general
[09:55:40] <@Wolvereness> eh, mixing up programming and math terms...
[09:55:41] <TomyLobo> http://en.wikipedia.org/wiki/Translation_%28geometry%29
[09:55:52] <@Wolvereness> I know what a "translation" is
[09:56:33] <TomyLobo> hmm i have an idea
[09:56:36] <@Wolvereness> You want a two-rotation system though
[09:56:46] <@Wolvereness> It can be expressed with those rotations I just defined
[09:56:47] <TomyLobo> how about a generic affine matrix class
[09:57:01] <TomyLobo> and a way to convert locations to these
[09:57:48] <@Wolvereness> TomyLobo: What you want to do is basically a "hardcoded" version of the rotations I defined
[09:57:52] <TomyLobo> that would be more efficient if you need to use toWorld more than once
[09:58:11] <TomyLobo> hardcoded according to minecraft conventions, yes
[09:58:32] <@Wolvereness> I'd much rather have arbitrary "orientation", as it doesn't change the math at all
[09:58:49] <TomyLobo> what is orientation?
[09:58:50] <@Wolvereness> Do you think the three "rotation" methods would suffice for your use-case?
[09:59:03] <@Wolvereness> Orientation is the definition of axes
[09:59:28] <TomyLobo> well the axes have to fulfill certain criteria in order to be an orthonormal system
[09:59:56] <@Wolvereness> The axes, as defined by the plane I linked earlier, assuming that a player-looking-forward is the plane
[10:00:24] <TomyLobo> plane (aviation) i assume
[10:00:27] <@Wolvereness> yes
[10:00:54] <TomyLobo> i.e. a plane we can rotate about :)
[10:01:24] <TomyLobo> plane angles are basically what minecraft's convention isderived from
[10:01:38] <@Wolvereness> Agreed, with no useful roll
[10:02:04] <TomyLobo> i can *adjust* roll by sending them damage packets *cough*
[10:02:28] <TomyLobo> but that's rather imprecise
[10:02:35] <TomyLobo> i.e. not useful
[10:02:48] <@Wolvereness> Hmm, I just thought of something
[10:02:54] <@Wolvereness> We can boil this down into 1 method
[10:03:16] <@Wolvereness> Vector.rotate(Vector, degrees)
[10:03:36] <@Wolvereness> Rotate one vector around another vector that defines the axis, by some degrees
[10:04:02] <TomyLobo> yep
[10:04:10] <@Wolvereness> Such that, to rotate about "roll", you can do vector.rotate(location.getDirection(), theta)
[10:04:39] <@Wolvereness> Such that, to rotate about "pitch", you can do vector.rotate(location.setYaw(location.getYaw(+90)).getDirection(), theta)
[10:04:40] <TomyLobo> new Matrix(axis, degrees).rotate(vector)
[10:05:00] <@Wolvereness> Such that, to rotate about "yaw", you can do vector.rotate(location.setPitch(location.getPitch(-90)).getDirection(), theta)
[10:05:19] <@Wolvereness> Pretty much
[10:05:58] <Frostalf> Be a neat method
[10:06:24] <@Wolvereness> TomyLobo: does some vector + degrees define a complete matrix?
[10:06:32] <TomyLobo> yes
[10:06:43] <@Wolvereness> So, yeah, I can add that math.
[10:06:50] <@Wolvereness> Would that solve your issue?
[10:06:59] <TomyLobo> it would solve all kinds of issues
[10:07:09] <Frostalf> Sure you probably don't get to hear this much. But thats for your hard work Wolvereness and same to the rest of BukkitTeam! :D
[10:07:11] <@Wolvereness> Would that solve your* issue? Which I care more about atm
[10:07:22] <Frostalf> thanks*
[10:07:25] <Frostalf> not thats lol
[10:07:29] <Frostalf> so tired XD
[10:07:42] <@Wolvereness> it's appreciated Frostalf
[10:08:01] <TomyLobo> right, i just volunteered to make a complete matrix class and he gets the thanks
[10:08:15] <@Wolvereness> You didn't volunteer yet
[10:08:25] <@Wolvereness> I was actually gonna do it :P
[10:08:49] <@Wolvereness> I really can't stand your PR atm because of it's documentation and hard-coded complexities
[10:09:05] <TomyLobo> how about i write the code, you write the documentation? :)
[10:09:13] <@Wolvereness> So, if I could write the matrix system instead, I'd be much happier
[10:09:44] <@Wolvereness> TomyLobo: Can we not add a new class? I don't see a problem using double[9]
[10:10:18] <TomyLobo> Matrix.rotate(Vector|Location|whatever) is so much more readable
[10:10:37] <TomyLobo> it'd also be double[12], because it's affine
[10:10:56] <TomyLobo> or maybe 16 to make it even more general
[10:11:01] <TomyLobo> to support projections and such
[10:12:00] <@Wolvereness> Wait... what?
[10:12:25] <@Wolvereness> A 3-D matrix should only be [9]
[10:12:47] <@Wolvereness> it only has 3 inputs and 3 outputs
[10:13:13] <TomyLobo> it's 3d affine
[10:13:38] <@Wolvereness> I still don't understand where you get anything other than 9
[10:13:43] <Ribesg> such maths
[10:13:57] <@Wolvereness> A vector only has 3 coordinates, so a matrix of columns > 3 doesn't make sense
[10:14:15] <@Wolvereness> the output only has 3 coordinates, soa matrix of rows > 3 doesn't make sense
[10:14:33] <TomyLobo> Wolvereness http://en.wikipedia.org/wiki/Translation_%28geometry%29#Matrix_representation
[10:15:27] <@Wolvereness> implicit 1?
[10:15:48] <Ribesg> Oh I did that at some point at school
[10:16:17] <@Wolvereness> Ribesg: the maths are fun - no really, they are
[10:16:28] <@Wolvereness> the hard part is learning, but when you use it, it's really fun
[10:16:32] <Ribesg> Yeah we used 4x4 matrices for all our Homothetic transformation stuff
[10:16:39] <Ribesg> Not 3x3
[10:16:53] <TomyLobo> homoerotic transformation
[10:16:57] <Ribesg> (I just joined and didn't read all the logs)
[10:17:40] <Ribesg> I agree with you Wolvereness, the hard part is learning :p Especially with bad teachers
[10:17:42] <@Wolvereness> TomyLobo: the affine_transformation wiki is only using NxN matrixes
[10:17:54] <TomyLobo> i dont know what that is
[10:18:12] <@Wolvereness> what what is?
[10:18:14] <Ribesg> So what is this about?
[10:18:16] <TomyLobo> but if you cite authority, i'll cite the opengl api :P
[10:18:36] <@Wolvereness> TomyLobo: those higher-order matrixes are using larger functions than rotation
[10:18:46] <TomyLobo> http://www.talisman.org/opengl-1.1/Reference/glLoadMatrix.html
[10:18:52] <Ribesg> Sure homothetic transformations are more than rotations
[10:19:02] <TomyLobo> Wolvereness Location has a position offset
[10:19:04] <@Wolvereness> we're only discussion rotations
[10:19:04] <Ribesg> You don't need 4x4 for only rotation iirc
[10:19:21] <TomyLobo> yeah
[10:19:21] <Ribesg> But I only learned rotation with 4x4 matrices :p
[10:19:28] <@Wolvereness> TomyLobo: we don't give a shit about position offsets when rotating vectors around each other - you just do location.add(vector)
[10:19:28] <TomyLobo> but rotation alone isnt fun :)
[10:19:32] <Ribesg> (Because they taught us the general concept)
[10:19:57] <@Wolvereness> besides, that's only 1 extra column, which makes it 3x4
[10:20:17] <TomyLobo> 4x4 allows projection
[10:20:29] <TomyLobo> and makes multiplication easier
[10:20:32] <@Wolvereness> Hmm...
[10:20:49] <@Wolvereness> Is the last row some form of 'scale'?
[10:21:03] <@Wolvereness> that still doens't make sense
[10:21:12] <TomyLobo> the 4th component? kind of...
[10:21:13] <@Wolvereness> I don't understand why there's a fourth-row
[10:23:57] <Ribesg> Wolvereness> Maybe you should try to determine which way has faster computation
[10:24:07] <Ribesg> That'll choose for you
[10:24:13] <@Wolvereness> Ribesg: speed isn't an argument atm
[10:24:43] <TomyLobo> multiplying 2 3x4 matrices is a headache
[10:25:15] <TomyLobo> you have to reinterpret the columns, it's not just a simple mathematical operation
[10:25:24] <@Wolvereness> usefulness of multiplying two matrices?
[10:25:42] <TomyLobo> rotating twice
[10:25:43] <@Wolvereness> in our* case
[10:25:45] <TomyLobo> in one go
[10:25:49] <@Wolvereness> Oh, rotation compression
[10:26:07] * @Wolvereness feels dumb for not remembering that
[10:26:20] * TomyLobo converts a 4x4 matrix class from C++
[10:26:30] <@Wolvereness> I still don't see a purpose for the fourth row, or even fourth column
[10:26:54] <@Wolvereness> The fourth column can be for translations, but that means the fourth row is pointless?
[10:28:33] <TomyLobo> hmmm problem:
[10:28:44] <TomyLobo> affine matrices cant be efficiently inverted
[10:29:21] <TomyLobo> i'll stick to 3x3 and wrap a transformation class around it that ensures that the matrix can still be efficiently transformed
[10:29:43] <@Wolvereness> so, 3x3 makes sense?
[10:30:05] <@Wolvereness> Also, remember, we can always do vector.transform().add(translationVector)
[10:30:12] <Ribesg> iirc with the 4x4 matrix you have some "dumb" data that is only used for the calculation. Only the upper-left 3x3 part is coherent at the start and at the end
[10:30:16] <TomyLobo> yes, because for all our use cases, they'll be orthonormal
[10:30:30] <TomyLobo> whereas in the affine case, they're not
[10:31:17] <@Wolvereness> give an example of the affine case without orthonormality
[10:31:44] * TomyLobo converts 3x3 matrix class from c++
[10:32:03] <@Wolvereness> Rephrase the ticket, close the PR, and open a new one?
[10:32:08] <TomyLobo> Wolvereness identity matrix with 1 0 0 as the offsets
[10:32:18] <TomyLobo> well it's still the same goal
[10:32:20] <TomyLobo> just broader
[10:32:41] <@Wolvereness> Rephrase the ticket, close the PR, open when you are ready to rewrite description+push?
[10:32:47] <TomyLobo> just a broader solution*
[10:32:49] <TomyLobo> sure
[10:32:54] <@Wolvereness> Awesome
[10:33:01] <@Wolvereness> Are you gonna need help documenting this?
[10:33:14] <@Wolvereness> or, writing unit tests?
[10:33:21] <TomyLobo> [11:09:02] <TomyLobo> how about i write the code, you write the documentation? :)
[10:33:29] <@Wolvereness> Sounds good, let me know
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment