of     3   
chevron_rightchevron_rightchevron_right

stravant
Forum Moderator
#59544478Wednesday, December 14, 2011 3:22 AM GMT

Since no-one seems to know how to use CFrame:inverse, here's a quick introduction on what it does. Note that what we're dealing with here is really Matricies,every CFrame is just a rotation matrix + a position, but I'll be calling them CFrames for simplicity. You're already familiar with the fact that for every mathematical operation there is a special quantity which is "neutral with respect to" that operation. For example: For addition that number is 0, that is, every number plus zero will still be that number. For multiplication that number is 1, that is, every number times one will just be that number. Well, CFrames as you might already know, have multiplication defined on them in a very special way. However, this special form of multiplication also has a neutral element just like addition and multiplication of normal numbers. CFrame.new() happens to return that value when you give it no arguments. And that makes sense, right? You wouldn't want to get back some arbitrary CFrame from .new(), you want a CFrame that does nothing when you apply it to other CFrames. In the case of a Part's CFrame that would mean not moving the part anywhere for example. That is, we have the following identity for any CFrame "cf": cf*CFrame.new() == CFrame.new()*cf == cf Now, what about inverse operations? Most mathematical operations have some sort of inverse. For example, the inverse with respect to addition is taking the negative of a number, and the inverse with respect to multiplication is taking 1/the value. But what exactly is an inverse operation doing? What any inverse is really doing when applied to an element "x" is satisfying the following identity: x OPERATION inverse_with_respect_to_operation(x) == the neutral element That is to say, if you apply the operation to an element and it's inverse with respect to that operation, you get the neutral element with respect to that operation. For example, with addition ans multiplication: x + (-x) == 0 x * (1/x) == 1 But what if you apply this same logic to CFrames? There is a slight complication with the fact that multiplication of CFrames is "not commutative", that is to say if you take two frames "a" and "b", "a*b" won't necessarily be the same thing as "b*a", that is, it matters what order you do the CFrame multiplication in. However, aside from needing to be more careful in keeping our order constant, that doesn't change the way inverses work for CFrames: CFrame:inverse() will still give you the inverse of a CFrame. That value you get back from inverse will satisfy the same identity as before. If you take a CFrame "cf": cf * cf:inverse() == cf:inverse() * cf == CFrame.new() Note that here commutativity does hold, the multiplication of the CFrames does work both ways for CFrames and their inverses, but ONLY IN THIS CASE, normally it won't give you the same result if you switch the order of a CFrame multiplication. So, now, what if we apply that to a common situation: Finding out what C0 or C1 you need for a weld to make it work. It turns out all you need to know is a bit of basic algebra, and this understanding of CFrame multiplication to do it. The first thing you need to know is that all joints in Roblox satisfy the following identity: Part1.CFrame * C1 == Part0.CFrame * C0 * joint_effect() Where "joint_effect()" is whatever the joint needs to do, for example in the case of welds it does nothing at all, but for motors it's equal to an extra rotation CFrame around a specific axis. Now suppose we know where to parts are, and we set the C0 to something specific, but now we want to find out what C1 to use to not move the parts, how do we do it? It turns out not to be that hard. We just start with the identity (I've just called Part0/1.CFrame Part0/1 here for brevity): Part1*C1 == Part0*C0 Now, just like you would with normal algebra, we're going to multiply something to both sides of the equation. The only thing to be careful of we have to multiply the thing to the _same side_ of each half o the equation since order matters for CFrames. Remember, we're trying to isolate the "C1" variable since that's what we want to find. To do this we can use Part1:inverse(): Part1:inverse() * Part1*C1 == Part1:inverse() * Part0*C0 Now, remember what we said about inverses? If you multiply a CFrame and it's inverse then you get CFrame.new() back every time, so we can replace "Part1:inverse()*Part1" with just "CFrame.new()": CFrame.new() *C1 == Part1:inverse() * Part0*C0 But then also remember what we said about the "neutral element" with respect to any operation. CFrame.new() is the neutral element, so multiplying C1 by it should have no effect whatsoever. That means we can remove it without breaking the equality: C1 == Part1:inverse() * Part0 * C0 And we've successfully isolated the required C1 just like that. You can now plug the known values for Part1, Part0 and C0 into the multiplication to get out the C1 that you need. And it's really as simple as that. By moving values around using inverse you can easily perform whatever algebra you need in order to find CFrames. For example, rotating a bunch of parts around an origin becomes easy with this knowledge: We have an origin, we need to know how far the part is displaced from the origin, so: part.CFrame = origin * displacement so: displacement = origin:inverse()*part.CFrame and then we just need to apply the rotation to the origin before moving the part back: part.CFrame = origin * rotation * displacement
belial52
#59545927Wednesday, December 14, 2011 3:50 AM GMT

Sorry, but this is a bit long and drawn out, but it is an excellent guide.
stravant
Forum Moderator
#59546033Wednesday, December 14, 2011 3:51 AM GMT

I think the in depth description is good to actually cement the ideas of what's going on. It's important to understand that it really is just algebra that you're doing but with different operations.
belial52
#59546090Wednesday, December 14, 2011 3:52 AM GMT

I didn't say it was bad, I just said it was a bit too drawn out for my tastes. I don't like reading, but I will type all day long. :D
[rfa#hidefromsearch]
#59547478Wednesday, December 14, 2011 4:27 AM GMT

[rfa#hidefromsearch]
Merlin11188
#59547487Wednesday, December 14, 2011 4:28 AM GMT

x * (1/x) == 1, not 0.
Merlin11188
#59547659Wednesday, December 14, 2011 4:33 AM GMT

This was very educational, thank you :D Just now I need to figure out how to multiply CFrames. That made perfect sense, and I even guessed the points you were about to make before you made them =P
stravant
Forum Moderator
#59547963Wednesday, December 14, 2011 4:42 AM GMT

"x * (1/x) == 1, not 0." Fixed. "now I need to figure out how to multiply CFrames" There's a simple enough formula for it. Just search the wiki article on Matrix multiplication. It looks intimidating but the concept is pretty simple, it's just a systematic way of multiplying a big pile of things with another big pile of things. What a CFrame really is is a 4x4 matrix, where the top 3x3 part is a rotation matrix, and all but three of the other values are 1's something like this: | R R R 0 | | R R R 0 | | R R R 0 | | x y z 1 | That or you can break a multiply up into both multiplying the rotation matrix parts and the position parts separately. Either will work.
Merlin11188
#59548941Wednesday, December 14, 2011 5:28 AM GMT

Oh fail. I knew matrix multiplication... I wasn't thinking of CFrame multiplication as matrix multiplication. I feel like this thread boosted my knowledge of CFrame tenfold (oh yeah, I used that word). Anyway, just an observation, you seem to be the one who increases my knowledge of this stuff, one way or another. First, you mentioned that lookVector was a unitVector. Now I understand lookVector. Now, you point out that CFrame:inverse() is simply the inverse of the CFrame matrix you're... inverting? Now I understand CFrame:inverse(). Then you remind me that CFrame is a matrix. Now I have a much better understanding of CFrame. Thanks mister helpful :D Oh, and editing your post is cheating =P
stravant
Forum Moderator
#59549574Wednesday, December 14, 2011 6:05 AM GMT

Bonus Material, how to get the unit vectors for a CFrame: local R = {CFrame:components()} Position = ( R[1], R[2], R[3] ) RightVector = ( R[4], R[7], R[10] ) TopVector = ( R[5], R[8], R[11] ) BackVector = ( R[6], R[9], R[12] ) And how to reflect a vector through an axis: local reflected = vector - (axis.unit*vector:Dot(axis.unit))*2
Oysi
#59550580Wednesday, December 14, 2011 8:36 AM GMT

[ Content Deleted ]
stravant
Forum Moderator
#59572800Wednesday, December 14, 2011 11:55 PM GMT

Bump
SFGiant
#59573813Thursday, December 15, 2011 12:10 AM GMT

[ Content Deleted ]
Profile
#59583786Thursday, December 15, 2011 2:42 AM GMT

now sfgiant thats no way to troll your not even spellin correctly or have your avatar resembling anything like a troll. GOBWEY!
manaphy966
#59588404Thursday, December 15, 2011 4:03 AM GMT

Might I ask something, I've been wondering this for a while now, does ROBLOX use Tensors to C-Frame? Most model programs do, and the such; and I was just wanting to know, also, very nice guide, --Official programmer of OT--
stravant
Forum Moderator
#59591172Thursday, December 15, 2011 6:16 AM GMT

@manaphy I have no idea what it would mean using tensors for CFrames. I assume Roblox uses the obvious rotation matrix/translation data, plus quaternions to do it's Physics, just like any other real-time physics engine. I guess you can call matrices 2D tensors, but I wouldn't really call that "using tensors" for the physics simulation. I know that a tensor is more of the general case of a matrix but that's about the extend of my knowledge on the topic so I can't give you a definite answer.
Waterlimon
#59595028Thursday, December 15, 2011 2:12 PM GMT

tl;dr How CFrame math works CFrameA:toObjectSpace(CFrameB) returns the offset of CFrameB from CFrameA's view CFrameA:toWorldSpace(CFrameB) returns what CFrameB (currently being an offset from CFrameA from CFrameA's view) is from the worlds view (Cframe.new()==worlds view) CFrameA:pointToWorldSpace etc. is the same but it converts Vector3s. Basically it just doesnt translate the rotation of what its converting as vector3's dont have one :3 CFrameA:vectorToWorldSpace etc. is same as above but it ignores the position of the cframe so if the vector is 1 stud from origin before, itll be 1 stud from origin after, but it might be pointing at a different direction.
ASmanX
#59598848Thursday, December 15, 2011 6:10 PM GMT

Nice i like that.
stravant
Forum Moderator
#59599544Thursday, December 15, 2011 6:50 PM GMT

"CFrameA:vectorToWorldSpace etc. is same as above but it ignores the position of the cframe so if the vector is 1 stud from origin before, itll be 1 stud from origin after, but it might be pointing at a different direction." You might want to re-read that, it doesn't make any sense: " so if the vector is 1 stud from origin before, itll be 1 stud from origin after" A vector only has one value, so if that value is staying constant, then the whole vector must be staying constant, which obviously isn't the case or the function wouldn't exist. You're acting as though the vector is a ray in your description, which has both a position and direction.
Waterlimon
#59600220Thursday, December 15, 2011 7:27 PM GMT

Nowait i mean the magnitude of it stays constant but direction can change
[rfa#hidefromsearch]
#64808847Friday, March 23, 2012 2:11 AM GMT

[rfa#hidefromsearch]
popinman322
#65719278Friday, April 06, 2012 4:46 PM GMT

*Bumps important thread*
popinman322
#66797584Sunday, April 22, 2012 2:05 PM GMT

*bump*
popinman322
#67626454Sunday, May 06, 2012 9:06 PM GMT

I wish this was pinned. :/
Ozzypig
#67633987Sunday, May 06, 2012 10:43 PM GMT

Let's say you had a CFrame called "plane" and you had a CFrame called "ray". How would you reflect "ray" off of "plane"? Assuming that "ray" intersects "plane".

    of     3   
chevron_rightchevron_rightchevron_right