• Advertisement
Sign in to follow this  

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

It seems, and I could be wrong here, but that you don't fully understand matrices and the related math.  You can also look at math libraries like GLM as it is open source if you learn better from code.

Looked like a good link for a 3D related primer on the subject:

https://www.3dgep.com/3d-math-primer-for-game-programmers-matrices/

Share this post


Link to post
Share on other sites
On 11/26/2017 at 11:43 PM, noodleBowl said:

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;

 

Why the [3]? Did you intend to scale the shear/skew factor as well?

Share this post


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

Looked like a good link for a 3D related primer on the subject

Thanks, I'll check it out!

6 hours ago, frob said:

Why the [3]? Did you intend to scale the shear/skew factor as well?

I don't think really every intended to scale the shear/skew factor, but its just how the math ended up working out when I multiplied my data matrix vs the scale matrix

 

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
  • Advertisement
  • Popular Tags

  • Advertisement
  • Popular Now

  • Similar Content

    • By Hawkblood
      I've been away for a VERY long time, so if this topic has already been discussed, I couldn't find it.
      I started using VS2017 recently and I keep getting warnings like this:
      1>c:\program files (x86)\microsoft directx sdk (june 2010)\include\d3d10.h(609): warning C4005: 'D3D10_ERROR_FILE_NOT_FOUND': macro redefinition (compiling source file test.cpp) 1>C:\Program Files (x86)\Windows Kits\10\Include\10.0.16299.0\shared\winerror.h(54103): note: see previous definition of 'D3D10_ERROR_FILE_NOT_FOUND' (compiling source file test.cpp) It pops up for various things, but the reasons are all the same. Something is already defined.....
      I have DXSDK June2010 and referencing the .lib and .h set correctly (otherwise I wouldn't get this, I'd get errors)
      Is there a way to correct this issue or do I just have to live with it?
       
      Also (a little off-topic) the compiler doesn't like to compile my code if I make very small changes.... What's up with that? Can I change it? Google is no help.
    • By lonewolff
      Hi guys,
      I am having problems with trying to perform a basic 'shift left' on a char.
      char temp[1]; temp[0] = buffer[0] << 1; // buffer[0] is 0xff After this I have temp[0] writing to a file. Instead of being the expected 0x7F it is written as 0xF8.
      Any guidance on what I am doing wrong would be awesome.
      Thanks in advance
    • By sergio2k18
      Hi all
      this is my first post on this forum.
      First of all i want to say you that i've searched many posts on this forum about this specific argument, without success, so i write another one....
      Im a beginner.
      I want use GPU geometry clipmaps algorithm to visualize virtual inifinte terrains. 
      I already tried to use vertex texture fetch with a single sampler2D with success.
       
      Readed many papers about the argument and all speak about the fact that EVERY level of a geometry clipmap, has its own texture. What means this exactly? i have to 
      upload on graphic card a sampler2DArray?
      With a single sampler2D is conceptually simple. Creating a vbo and ibo on cpu (the vbo contains only the positions on X-Z plane, not the heights)
      and upload on GPU the texture containing the elevations. In vertex shader i sample, for every vertex, the relative height to te uv coordinate.
      But i can't imagine how can i reproduce various 2d footprint for every level of the clipmap. The only way i can imagine is follow:
      Upload the finer texture on GPU (entire heightmap). Create on CPU, and for each level of clipmap, the 2D footprints of entire clipmap.
      So in CPU i create all clipmap levels in terms of X-Z plane. In vertex shader sampling these values is simple using vertex texture fetch.
      So, how can i to sample a sampler2DArray in vertex shader, instead of upload a sampler2D of entire clipmap?
       
       
      Sorry for my VERY bad english, i hope i have been clear.
       
    • By mangine
      Hello. I am developing a civ 6 clone set in space and I have a few issues. I am using Lua for the logic and UI of the game and c++ directx 12 for the graphics. I need a way to send information between Lua and c++ occasionally and was wondering what is the best and most flexible (and hopefully fast) way to do this. Don't forget that I also need to send things from c++ back to Lua. I know of a lua extension called "LuaBridge" on github but it is a little old and I am worried that it will not work with directx 12. Has anybody done something similar and knows a good method of sending data back and forth? I am aware that Lua is used more and more in the industry and surely plenty of AAA game programmers know the answer to this. I want a good solution that will hopefully still be viable code in a couple of years...
    • By owenjr
      Hi there.
      I'm pretty new to this and I don't know if it has been asked before, but here I go.
      I'm developing a game using SFML and C++.
      I would like to use the "Tiled" tool to load maps into my game but I don't actually find any tutorial or guide on how to exaclty use it (I know that I have to read an XML file and stuff). I just step into diverse projects that make all a mess. 
      Anyone knows where can I find good information to make my map loader by myself?
      Thanks in advantage!!
  • Advertisement