HelloUpdate Tutorial

I am trying to do the excersice where you try to make a pulsating block, but when I scale the box it no longer appears. I created a second block that inherited from box in the tutorial. In the simpleupdate section I tried to put:



boxTwo.scale(2tpf, 2tpf, 2*tpf);



Not thinking at the time that why this works for a rotation is because a rotation goes in a circle anyways. However, a item can scale indefinatly which makes it where when I try to scale in this manner it gives no block because I am thinking that it is continuasly making it scale and so is causing it to get culled once it is to large.



I tried adding a second update loop with a string of:



boxTwo.scale(0.5f * tpf, 0.5f * tpf, 0.5f *tpf);



If I do not include the *tpf then the box appears scaled to one of the two .scale but does not change.



So that it would cause the cube to then go to the larger scale and then back to its original state, but the box is still not appearing.



I also tried putting both statements inside of the same update loop and box is no longer there again. I have tried making the numbers larger or smaller and still have no box appearing. I typed out boxTwo. and then searched through the options it gives for that set up but I could not find anything that was used for reseting something back to its original vector3f locations.



I tried to use an if statement but it states that I have to use a boolean value only. Thus, I was not able to construct an correct if statement to check if once the box got to a certain size then run the descaling statement which would cause it to grow and shrink.



Any pointers would appreciated.

scale() is cumulative but not in the way rotation is cumulative.



If you rotate() it’s adding the rotation to the current rotation. If you scale() then it’s scaling the current scale but the supplied scale.



Since tpf tends to be small, every frame you will be shrinking the box a little more.



Better to get the current scale and add to it by some amount or to track your own scale and add to that, setting it each frame with setLocalScale() instead of scale().

I am having trouble with the *tpf, if I try to use this in a scale or setlocalscale then the model no longer appears. However if I use them without tpf I can see the model scaled to what the new scale is, but it does not change.

Did you read my post at all?



Let’s say your scale starts at something large like 100.



Now, scale( 0.1 ) and it’s 10.0

Now, scale( 0.1 ) and it’s 1.0

Now, scale( 0.1 ) and it’s 0.1

…and so on.

In four or five frames it’s too small to see.



Read my other post again until it makes sense. Coding a 3D game may be too hard for you at this stage of learning.

I understand the concept you speak of, but the only way I can think of that being done is through a loop, but even an if loop gives me an error when I try to get the lines to work. I tried setting the scale to a set scale with setlocalscale( 2, 2, 2) and then put the scale() with tpf above and below that. Without a loop statement the model either appears slightly scaled or does not appear.



Based off the tutorial I do not need a actual loop staement like with the rotation but if I include extra lines it only runs the last line.

I will be as PLAIN as I can.



simpleUpdate() is called once per frame.



If your frame rate is 60 FPS then your tpf will be approximately 0.016



If your box starts at as size 1 then every time JME calls your simpleUpdate() method if you use scale( 2 * tpf, 2 * tpf, 2 * tpf ) then on the first frame your size will be 0.032

On the second frame: 0.001024

and so on. Every time the engine calls simpleUpdate (once per frame) then your box will get smaller and smaller but in 2 frames it is already too small to see.



Your code is broken.



But I will take a step back and give you a strategy for debugging code since you are clearly very new to programming.



When your program does not do what you expect then you need to take apart every one of your assumptions and test it. In this case, the most obvious assumption is that you think the box is supposed to be a certain size and/or growing.



So… either set a debug point and run it in the debugger or add a System.out.println( boxTwo.getLocalScale() ) and see what it says. It will not be what you are expecting and then you can figure out the math of why and why scale() is messing you up.



You want to do the equivalent of scale += someValue and instead you are doing scale *= someValue.



And I’m kind of serious when I say this: if you cannot use the above information to solve your problem then you are in WAY over your head. You should spend some months doing regular Java tutorials before tackling 3D game development… which is one of the single most complicated things to do. Trying to learn to code while also learning one of the single most complicated programming tasks is going to be next to impossible.

I may be getting confused by your statement of:



If you rotate() it’s adding the rotation to the current rotation. If you scale() then it’s scaling the current scale but the supplied scale.



Are you meaning that its not scaling what the box is currently scaled to but what the original box’s scale was?



Now you say that I could keep track of the current scale and then add to that instead of allowing the engine to add onto the origial scale?





Thank you for explaining that tpf is roughly .16 and the idea of using the prinln to see how it worked. I figured out that by if I made it 2+tpf it was only making it size to 2.016-2.018 which was not enough to see it pulsating so then the model appeared but was not moving. I then realised that I need to make the numbers larger so that then it scales the item to the correct proportion. So by using:



boxTwo.setLocalScale(100f * tpf, 100f * tpf, 100f * tpf);



I was able to get the box to scale between 1.6-1.8 which caused the box to appear as pulsating. I am sure this is not the method you were thinking of but it works for now. I would still like to understand the concept you are speaking of with using the current scale and then adding to it if you wish to ellaborate more on the subject.



From experimenting with the setlocalscale(), scale, and prntln it looks as if setlocalscale() takes the original size of the box and sizes it to the setlocalscale() so then you have your current scale, then if you use scale with tpf it then takes the current scale and uses that to scale up or down based off of the calculations that are placed such as 10 * tpf, etc…

Playing around with it more I see now that if you use just .scale() then the model has a huge range of different x, y, and z coords. Thus, the model may end up with things like .05, 10, 25 which makes the model not appear. However, if you implemented .setLocalScale() then it now makes it to where it resets the calculation to be based off of the original models scale so that the numbers stay in the same range. So now instead of:



boxTwo.scale(10tpf, 10tpf. 10tpf) storing the scale number so say you end up with .15, .25, .35 which then gets put back in to scale which causes it to be .15 * (10tpf)



Whereas using:



boxTwo.setLocalScale((10tpf, 10tpf. 10tpf) using the .15, .25, and .35 again it goes back to the original scale of the model and reuses those numbers, say the original scale was 2.5, 2.5, 2.5 now instead of it being .15 * (10 * tpf) you end up with each loop being 2.5 (10* tpf)



Please correct me if this is not correct.

scale(x,x,x) is doing the equivalent of setLocalScale( getLocalScale().multLocal(x) );



So if your scale was 1 before you call scale() and you call scale(0.1,0.1,0.1) then your scale will then be 0.1. If you call scale(0.1, 0.1, 0.1) AGAIN (like in the next simpleUpdate() then your scale will be 0.01.



This is such a simple concept and I’m running out of different ways to explain it.



rotate() adds a rotation to an existing rotation.

scale() scales the existing scale.



So, rotate(5, 5, 5) will keep increasing the rotation every frame. If rotation starts at 5 then the next frame it’s 10, then 15, then 20, etc…



tpf is a way of making sure your stuff doesn’t move/scale/rotate faster when frame rates go faster since tpf is different as frame rate changes. That’s all. If the math is right then tpf is easy to inject but if the math is wrong then no amount of random fiddling with strange values is going to make it work.



Figure out how you want your scale to change and then change some “scale” variable and THEN set that to the spatial using setLocalScale().

Scale is multiplicative. Rotation is additive.



If you take 222 you get 8. 2 again you get 16

If you take 2+2+2 you get 6. +2 again you get 8…and the difference keeps growing



Rotation is circular. It “wraps around” when you get beyond 2
PI. Scale is linear… you can keep getting bigger or smaller indefinitely.



The two things are very different so you can’t expect the same thing to work for both.







You are also completely misunderstanding and misapplying tpf here.



tpf is time per frame - it tells you how much time has passed since the last frame. In order to get constant speed movement you need to move by whatever your speed is (say 1m/s) multiplied by tpf (0.016) to get a movement that frame of 1.6cm. If a frame takes twice as long for some reason to draw then tpf will be bigger (0.032) and so you will move 3.2cm instead - giving constant movement in real time even as the frame rate fluctuates.







Now, to make your example work you need to pick a minimum (say 0.5) and maximum (say 2.5) scale.



You need to define something that gives a nice curve between them…how about a sin wave which curves you a nice curve between +1 and -1.



so setLocalScale(1.5+sin(totalTime))



But how do you get total time?



You either keep a float and add tpf to it each frame (because sin() is giving you the circular properties you need out of an ever increasing number) or in fact there is a way to query an incrementing counter from the system that does that for you. Have a look, you’ll find it :wink:

2 Likes

Ok so I ended up adding:



private float time = 1000.0f;



and



@Override

public void simpleUpdate(float tpf)

{

time += (tpf + .05f);

player.setLocalScale(1.5f + FastMath.sin(time));



}



Is this more along the lines of what you are talking of?



Where I have time set to a constant timed rate added to tpf + a small amount so that I end up with a constant time range going from roughly 1.21 seconds ± some depending on the time between frames.



Then I take 1.5f + sin(time) to make the model scale up and down gradually along the sin wave



So this then takes 1.5f + (y*1.21); and applies it to each vertex?



So if we have a vertex of (1, 2, 1)



We then end up with 1.5f + (2 *1.21) = 1.5F + (2.42) = .setlocalscale(3.42) which then multiplies by all three coords to to make the new coords 3.42, 6.84, 3.42.



Now if the tpf changes to 1.12 we end up with coords of 3.74, 7.48, 3.74. Thus, causing the model to appear to pulsate as it does this rapidly.



If my math with sin is incorrect feel free to correct me or point something out. I start my trig/precalc class this semester and am trying to study early so the pointers are useful and guide me to learn new things.



Now if I am understanding correctly the difference between .scale and .setlocalscale is that .scale effects only one coord of the vertex at a time. So with this same equation but using scale we would end up only effecting the x axis unless we added one for the y and z as well.



.setlocalscale instead sets the scale of the entire vertex instead effecting each axis by the supplied number such.,



I think much of my confussion comes from .setlocalscale. I am unsure as to how this is different then .scale. I navigated to the source of .setlocalscale, but it brings me to a class of .setlocalscale and has:



localtransform.setscale(localscale);



but when I try to travel to the source of localtransform it pings but stays on that page. I tried looking in the help files but nothing appears for .setlocalscale just .scale.

@danvath said:
I think much of my confussion comes from .setlocalscale. I am unsure as to how this is different then .scale. I navigated to the source of .setlocalscale, but it brings me to a class of .setlocalscale and has:


Good grief... I'm not sure how to explain it any different but I will try again. Though the source code is 100% available if you want to see the real thing.

Here it is in pseudo code again:

setLocalScale( somceScale ) {
scale = someScale;
}

scale( someScale ) {
scale = scale * someScale;
}

Hopefully that clears it up.

So based off your pseudo code I am getting that if we use setlocalscale then it sets the scale = to whatever the equation gives. If we use scale then it takes the models scale and then multiplies that to the numbers that are inputed into scale?

@danvath said:
So based off your pseudo code I am getting that if we use setlocalscale then it sets the scale = to whatever the equation gives. If we use scale then it takes the models scale and then multiplies that to the numbers that are inputed into scale?


Yes. You are playing with us now, aren't you? :)
@danvath said:
Ok so I ended up adding:

private float time = 1000.0f;

and

@Override
public void simpleUpdate(float tpf)
{
time += (tpf + .05f);
player.setLocalScale(1.5f + FastMath.sin(time));

}

Is this more along the lines of what you are talking of?


Almost. Why are you doing tpf+.05f? That's making every frame longer by a fixed amount. Why?
Also there is no need to start from 1000f although it won't do any damage.

@danvath said:

Where I have time set to a constant timed rate added to tpf + a small amount so that I end up with a constant time range going from roughly 1.21 seconds +- some depending on the time between frames.


It should be constant. Adding 0.05f is making it non constant.

Every second time will increase by 1.0f. Sin repeats itself every 2*PI. So if you want the cycle to happen every second (for example) then do FastMath.sin(time/FastMath.TWO_PI);

To happen every 2 seconds do FastMath.sin(time/FastMath.PI);

@danvath said:

Then I take 1.5f + sin(time) to make the model scale up and down gradually along the sin wave

So this then takes 1.5f + (y*1.21); and applies it to each vertex?

So if we have a vertex of (1, 2, 1)

We then end up with 1.5f + (2 *1.21) = 1.5F + (2.42) = .setlocalscale(3.42) which then multiplies by all three coords to to make the new coords 3.42, 6.84, 3.42.

Now if the tpf changes to 1.12 we end up with coords of 3.74, 7.48, 3.74. Thus, causing the model to appear to pulsate as it does this rapidly.


Assuming your scene isn't changing and nothing else is running on your computer your tpf will be roughly constant. What is changing is the total time as it's growing by tpf each frame.

You are using sine to produce a nice curve, not actually for trigonometry. Go look at a sine wave to see why it's useful.

sin(time) gives a number from -1 to +1. so 1.5f+sin(time) gives you a number from 0.5f to 2.5f.

When you do setLocalScale(X) then you are saying "take the original size of this object and change it to be the original size scaled by the given number". That gives you the object at a size varying between half (0.5f) its original size and two and a half times (2.5f).

@danvath said:

If my math with sin is incorrect feel free to correct me or point something out. I start my trig/precalc class this semester and am trying to study early so the pointers are useful and guide me to learn new things.

Now if I am understanding correctly the difference between .scale and .setlocalscale is that .scale effects only one coord of the vertex at a time. So with this same equation but using scale we would end up only effecting the x axis unless we added one for the y and z as well.

.setlocalscale instead sets the scale of the entire vertex instead effecting each axis by the supplied number such.,

I think much of my confussion comes from .setlocalscale. I am unsure as to how this is different then .scale. I navigated to the source of .setlocalscale, but it brings me to a class of .setlocalscale and has:

localtransform.setscale(localscale);

but when I try to travel to the source of localtransform it pings but stays on that page. I tried looking in the help files but nothing appears for .setlocalscale just .scale.


Wow...just wow...

@pspeed already covered this so I'm just going to leave it but this is absolutely and fundamentally wrong.