Jump to content
  • Advertisement
Sign in to follow this  
noodleBowl

Questions about a scaling up, down, and resetting using a scale matrix

Recommended Posts

Hey I have a quick question about a scale matrices

I have my matrices in column major order and I know a scale matrix looks like:

// Column order matrix. Data arragned in an array:
0 4 8  12
1 5 9  13
2 6 10 14
3 7 11 15

//Scale Matrix
x 0 0 0
0 y 0 0
0 0 z 0
0 0 0 1

And I know I need to multiple my matrix by the scale matrix in order to scale by the x, y, z values. But how am I supposed to actually scale my matrix back down/set it to a scale factor?

I have this code that is to scale my matrix the along the X access

//Scale the current matrix by X amount
void Matrix4::scaleX(float x)
{
	data[0] *= x;
	data[1] *= x;
	data[2] *= x;
	data[3] *= x;
}

And if I were to do something like this I could scale my matrix along the X axis by 2

//Scale the matrix along the x axis by 2
myMatrix.scaleX(2.0f);

But I'm honestly not sure how I'm supposed to scale back down from this point. I was hoping for something like:

//Scale the matrix along the x axis by 2
myMatrix.scaleX(2.0f);

//Scale the matrix down along the x axis by 2
myMatrix.scaleX(-2.0f);

But based on the current math that is not how it works

Also how should I go about "resetting/setting" a scale matrix to a certain value? Say I have a matrix that is at scale factor 1. Then over time I want to scale it up until it hits a scale factor of 5. Then later after some other conditions are met I want to reset/set the scale factor to 2
 

Edited by noodleBowl

Share this post


Link to post
Share on other sites
Advertisement
2 hours ago, alvaro said:

The inverse of multiplying by 2 is multiplying by 1/2, not -2.

I don't think I explained myself very well here. If I scale up by 2 then yes if I want to get back to my original number I would multiple by 0.5

I guess I'm really looking for a way to scale up / down easily using matrices. Easily in the sense that I have a single value that controls the scale factor I need to use. Example, something like:

//Declares somewhere, global or class memeber
float scaleFactor = 1.0f;

//Somewhere else in code
if(keyDown(W_KEY))
  scaleFactor += 0.5f

if(keyDown(S_KEY))
  scaleFactor -= 0.5f

//Scale the matrix up or down along the X axis based on the scaleFactor value
//See above post for implementation details
myMatrix.scaleX(scaleFactor); 

I'm not sure if adding / subtracting to a scale factor is possible using a scale matrix since it is multiplicative. Kind of throws me off since multiplying by a translation or rotation matrix seems to be additive

Share this post


Link to post
Share on other sites

I am having a hard time understanding what your problem is. But perhaps we can get to the bottom of it if by looking at your last line: "[...] multiplying by a translation or rotation matrix seems to be additive".

I can see how translations might seem additive: There is a very natural way to describe the translation using a vector, and composition of translations corresponds to addition of vectors.

In the case of rotations, they seem additive if you are thinking about them in terms of angles. Now, anything multiplicative can be made to look additive if you use logarithms, because log(a*b) = log(a) + log(b). In some sense, angles are logarithms of the transformations they represent.

Now, scaling things is the prototypical example of multiplication, and you generally want to use multiplicative updates. In the bit of code you posted, if you hit "S" twice the object will collapse to a point because you made the scaling factor zero. Also, if you have made the object very big already, hitting "W" again will have an almost imperceptible effect. My guess is that that is not what you wanted. An alternative would be to multiply the scale factor by some constant (say, 1.2) when you hit "W" and divide by the same constant when you hit "S". Try that and see if that's closer to the behavior you want.

As a side note, you could keep track of the logarithm of the scaling factor instead. To get the same effect, you would be adding log(1.2) [about 0.1823] or subtracting log(1.2) to a variable named "log_scale", and then the scaling factor would be computed as "exp(log_scale)". That's rather awkward and I don't recommend it, but it would make scaling seem additive. It gives me a similar feeling to code that uses angles. :)

 

Edited by alvaro

Share this post


Link to post
Share on other sites
11 hours ago, alvaro said:

Now, scaling things is the prototypical example of multiplication, and you generally want to use multiplicative updates. In the bit of code you posted, if you hit "S" twice the object will collapse to a point because you made the scaling factor zero. Also, if you have made the object very big already, hitting "W" again will have an almost imperceptible effect. My guess is that that is not what you wanted. An alternative would be to multiply the scale factor by some constant (say, 1.2) when you hit "W" and divide by the same constant when you hit "S". Try that and see if that's closer to the behavior you want.

I went back and tried this, but I don't think it will work :(

//Declares somewhere, global or class memeber
float scaleFactor = 1.0f;

//Somewhere else in code
if(keyDown(W_KEY))
  scaleFactor *= 1.2f

if(keyDown(S_KEY))
  scaleFactor /= 1.2f

//Scale the matrix up or down along the X axis based on the scaleFactor value
//See above post for implementation details
myMatrix.scaleX(scaleFactor); 

The scenario goes like this:
1. Press the W key. scaleFactor now has a value of 1.2f. The matrix is scaled up by 1.2f just like we wanted
2. Press the W key again. scaleFactor now has a value of 1.44f. The matrix is scaled up by 1.44f. This is a issue because we will now scale by double the amount we wanted
3. Press the S key. scaleFactor is now 1.2f. The matrix is scaled up by 1.2f. This is definitely an issue. We intended to scale down by 1.2f, but because the value for scaleFactor is 1.2f we will actually scale up our matrix by 1.2f

 

Share this post


Link to post
Share on other sites

Oh, you have a more basic problem. I imagined you were building your matrix from scratch every time. You should make the scaleFactor equal to 1.2 when `W' is pressed, and 1/1.2 when 'S' is pressed, 1 otherwise. Either that, or build the matrix from scratch every time.

Share this post


Link to post
Share on other sites
6 hours ago, alvaro said:

Oh, you have a more basic problem. I imagined you were building your matrix from scratch every time. You should make the scaleFactor equal to 1.2 when `W' is pressed, and 1/1.2 when 'S' is pressed, 1 otherwise. Either that, or build the matrix from scratch every time.

This will totally work! I think I will have to rebuild the matrix from scratch if I need to keep track of how much I scaled my matrix by. That or have another variable

5 hours ago, Hodgman said:

Normalize the x vector, and then multiply it with the scale factor.

Can you explain this? I'm curious, but I don't know what you really mean by normalize the X vector since I'm just using a single value and I don't know how you are supposed to normalize a single value

Also just a side question for confirmation, I didn't mess up the scale matrix math did I? The whole not adding or subtracting to an accumulator value and then passing that value to my functions makes me feel like I did it wrong

void Matrix4::scale(float x, float y, float z)
{
	data[0] *= x;
	data[1] *= x;
	data[2] *= x;
	data[3] *= x;

	data[4] *= y;
	data[5] *= y;
	data[6] *= y;
	data[7] *= y;

	data[8]  *= z;
	data[9]  *= z;
	data[10] *= z;
	data[11] *= z;
}

 

Edited by noodleBowl

Share this post


Link to post
Share on other sites
21 minutes ago, noodleBowl said:

Can you explain this? I'm curious, but I don't know what you really mean by normalize the X vector since I'm just using a single value and I don't know how you are supposed to normalize a single value

In your matrix, elements 0, 1, 2 and 3 are the X basis vector. If you want to scale that vector, you can multiply it with a single (scalar) value. If you want to set the scale of the X axis to some new value, you can first normalize the x basis vector (which sets the scale / length to 1.0), and then multiply it by your scalar.

Share this post


Link to post
Share on other sites
54 minutes ago, Hodgman said:

In your matrix, elements 0, 1, 2 and 3 are the X basis vector. If you want to scale that vector, you can multiply it with a single (scalar) value

Isnt this what I'm already doing?

55 minutes ago, Hodgman said:

If you want to set the scale of the X axis to some new value, you can first normalize the x basis vector (which sets the scale / length to 1.0), and then multiply it by your scalar.

So then I'm looking at something like this then?:

float length = sqrt(data[0] * data[0] + data[1] * data[1] + data[2] * data[2] + data[3] * data[3]);
data[0] = (data[0]/length) * newScaleValue;
data[1] = (data[1]/length) * newScaleValue;
data[2] = (data[2]/length) * newScaleValue;
data[3] = (data[3]/length) * newScaleValue;

Does just computing the length on the first 3 columns give me back the current scale values for x, y, z?
Can I just extract everything from the matrix then? Not just scale but rotation and transform too. Is it worth it (accurate)?

Assuming the answer to my first question is yes, you wouldn't be able to get an accurate scale value back if the scale was negative. Which in my mind is "wrong" since we are missing the sign information. Only makes me wonder what I wouldn't / couldn't get back trying to extract the rotation and transform values. Mainly just the rotation values since I'm pretty sure the last column of the matrix is everything needed for the transform values

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!