Jump to content

rmgen library.js changes


Recommended Posts

I just committed some changes to this file, GetAngle() and GetDirection() have both been changed so I thought it would be good to announce it here so people don't get caught by surprise since the changes will break stuff using the functions (nothing in svn uses them currently).

GetAngle() now returns the angle anticlockwise for the positive x axis in the range [-pi, pi]. This is a standard convention for mathematics and all programming libraries that I have come across (the Math.atan2 javascript function is especially relevant). Before it returned the clockwise angle from the positive z axis.

GetDirection() has been renamed to GetGradient() because this is more explicit. Also I changed the functionality so that it correctly returns Infinity for vertical lines. For 0 width and zero height it returns 0 but I am unsure about this. Returning NaN makes most sense but from your previous implementation I was guess you probably don't want to worry about NaN checks so I did it this way.

Link to comment
Share on other sites

GetAngle() now returns the angle anticlockwise for the positive x axis in the range [-pi, pi]. This is a standard convention for mathematics and all programming libraries that I have come across (the Math.atan2 javascript function is especially relevant). Before it returned the clockwise angle from the positive z axis.

You are right if the coordinated are x (horizontal, right positive) and y (vertical, top positive), but they are x (horizontal, right positive) and z (vertical, top positive).

Since [x, y, z] are circular it's the same as if you'd use [z, x, y] or [y, z, x] (for rotation direction).

So for the plane you could use [x, y], [z, x] or [y, z] and where still right.

But fore some reason [x, z] was chosen, which is not part of any of the 3 possibilities above.

That means we look at the back of one of the planes. That leads to a different direction of rotation.

So indeed the old behavior was mathematically correct. [0, 0, 1] (x=0, z=1) has an angle of 0, [1, 0, 0] (x=1, z=0) has an angle of PI and so on...

It's the same with buildings: Placing it with a given angle of 0 let them face towards positive z, angle of PI face positive x.

In the (strange) chosen coordinate system it's correct.

IMO the best thing would be to choose [x, y] for the plane so that a point on a circle at the angle phi with radius 1 could be get by:

x = cos(phi), y = sin(phi).

But right now it is z = cos(phi), x = sin(phi).

That's at least confusing. Same with the rotation direction. It's clockwise which is unusual for a mathematician. too.

However, I strongly recommend to stay consistent whatever you choose!

Edited by FeXoR
Link to comment
Share on other sites

You are right if the coordinated are x (horizontal, right positive) and y (vertical, top positive), but they are x (horizontal, right positive) and z (vertical, top positive).

Since [x, y, z] are circular it's the same as if you'd use [z, x, y] or [y, z, x].

So for the plane you could use [x, y], [z, x] or [y, z] and where still right.

But fore some reason [x, z] was chosen, which is not part of any of the 3 possibilities above.

That means we look at the back of one of the planes. That leads to a different direction of rotation.

So indeed the old behavior was mathematically correct. [0, 0, 1] (x=0, z=1) has an angle of 0, [1, 0, 0] (x=1, z=0) hs an angle of PI and so on...

It's the same with buildings: Placing it with a given angle of 0 let them face towards positive z, angle of PI face positive x.

In the (strange) chosen coordinate system it's correct.

IMO the best thing would be to choose [x, y] for the plane so that a point on a circle at the angle phi with radius 1 could be get by:

x = cos(phi), y = sin(phi)

But right now it is z = cos(phi), y = sin(phi).

That's at least confusing. Same with the rotation direction. It's clockwise which is unusual for a mathematics too.

However, I strongly recommend to stay consistent whatever you choose!

My logic was to look at what is being represented by the coordinates rather than the variable names. Basically we have the map which is the x-z plane. In the default orientation on the minimap x positive is right and z positive is up, so we are using the standard x-y plane with y labeled as z. This is the way people creating maps should be thinking about it since they are working in 2d (or 2.5d). The labeling is an unfortunate consequence of the coordinates being chosen in the 3D engine and then being directly transferred into the 2D system used for the games simulation. Changing at this point would be far too much hassle for what is gained.

Link to comment
Share on other sites

My logic was to look at what is being represented by the coordinates rather than the variable names. Basically we have the map which is the x-z plane. In the default orientation on the minimap x positive is right and z positive is up, so we are using the standard x-y plane with y labeled as z. This is the way people creating maps should be thinking about it since they are working in 2d (or 2.5d). The labeling is an unfortunate consequence of the coordinates being chosen in the 3D engine and then being directly transferred into the 2D system used for the games simulation. Changing at this point would be far too much hassle for what is gained.

Well, then you have to change the unit angle for placement too to stay consistent.

Angle of 0 then should mean facing positive x, PI/2 facing bottom (on the minimap) and so on.

The BUILDING_ANGlE then should be -PI/4 instead of 3*PI/4 (Edited, got it wrong 1st)

By the way, I use it and it crashes with:

ERROR: JavaScript error: maps/random/rmgen/library.js line 620 ReferenceError: assignment to undeclared variable output getAngle(98,86,103,55)@maps/random/rmgen/library.js:620 @maps/random/fexor.js:119ERROR: CMapGeneratorWorker::Run: Failed to load RMS 'maps/random/fexor.js'

Checking my map and the libs...

Edit: Just remove the 'output =' after the 'return' Edit: Thx for the fix, now it works as x/y plain

Edit: And it has to read:

function getAngle(x1, z1, x2, z2)
{
return Math.atan2(z1 - z2, x1 - x2);
}

Otherwise it's the angle towards negative x axis...

Edited by FeXoR
Link to comment
Share on other sites

Well, then you have to change the unit angle for placement too to stay consistent.

Angle of 0 then should mean facing positive x, PI/2 facing top (on the minimap) and so on.

The BUILDING_ANGlE then should be -PI/4 instead of 3*PI/4 (Edited, got it wrong 1st)

By the way, I use it and it crashes with:

ERROR: JavaScript error: maps/random/rmgen/library.js line 620 ReferenceError: assignment to undeclared variable output getAngle(98,86,103,55)@maps/random/rmgen/library.js:620 @maps/random/fexor.js:119ERROR: CMapGeneratorWorker::Run: Failed to load RMS 'maps/random/fexor.js'

Checking my map and the libs...

Edit: Just remove the 'output =' after the 'return'

Edit: And it has to read:

function getAngle(x1, z1, x2, z2)
{
return Math.atan2(z1 - z2, x1 - x2);
}

Otherwise it's the angle towards negative x axis...

I fixed the error, sorry about that. I am not sure why you think it should be changed to z1-z2, I have attached a diagram and my testing matches with the diagram.

I also did a quick check of how the current random maps use angles and the x = cos(theta), y = sin(theta) is the current convention so the GetAngle function matches that.

The building angle is also messed up as you say, looking at the createStartingPlayerEntities() function I see this code:

var uAngle = -BUILDING_ANGlE + PI * (j - 1) / 2;

Which transforms it into the coordinates which I have been calling standard. Perhaps we should change this.

post-13166-0-99040400-1332150914_thumb.p

Link to comment
Share on other sites

Thanks for the fix.

I am not sure why you think it should be changed to z1-z2, I have attached a diagram and my testing matches with the diagram.

You are right, kept x/y2 = 0 which was wrong. Need to keep x/y1 = 0 to see against which axis it turns.

Fixed the values for BUILDING_ANGlE in my post that I got wrong 1st.

Edit: There's still something strange (from mainlog.html):

getAngle(1, 0, 0, 0) = 3.141592653589793 <- Should be 0 or?

getAngle(1, 1, 0, 0) = -2.356194490192345

getAngle(0, 1, 0, 0) = -1.5707963267948966

getAngle(-1, 1, 0, 0) = -0.7853981633974483

getAngle(-1, 0, 0, 0) = 0

getAngle(-1, -1, 0, 0) = 0.7853981633974483

getAngle(0, -1, 0, 0) = 1.5707963267948966

getAngle(1, -1, 0, 0) = 2.356194490192345

(Everything's right from this point on though)

getAngle(0, 0, 1, 0) = 0

getAngle(0, 0, 1, 1) = 0.7853981633974483

getAngle(0, 0, 0, 1) = 1.5707963267948966

getAngle(0, 0, -1, 1) = 2.356194490192345

getAngle(0, 0, -1, 0) = 3.141592653589793

getAngle(0, 0, -1, -1) = -2.356194490192345

getAngle(0, 0, 0, -1) = -1.5707963267948966

getAngle(0, 0, 1, -1) = -0.7853981633974483

By the way, generally I agree with you the map surface plane should act like x/y plane. I just guess that when making the engine the clockwise rotation on the plane to design was exactly the idea that made them choose x/z (or more accurate z/x rotated by -PI/4).

I think rotation direction is less of an issue for designers to get used to counter clockwise rotation then for people using trigonometric functions and has to figure out where sin/cos belongs and which sign they should have to act as they like.

So, yes, it should act like x/y, I agree.

OT: Did I mention that I hate the edit function of this forum? x)

It often eats my newlines or adds some or adds spaces at the beginning of the line I add one.  

Edited by FeXoR
Link to comment
Share on other sites

getAngle(1, 0, 0, 0) = 3.141592653589793 <- Should be 0 or?

getAngle(1, 1, 0, 0) = -2.356194490192345

getAngle(0, 1, 0, 0) = -1.5707963267948966

getAngle(-1, 1, 0, 0) = -0.7853981633974483

getAngle(-1, 0, 0, 0) = 0

getAngle(-1, -1, 0, 0) = 0.7853981633974483

getAngle(0, -1, 0, 0) = 1.5707963267948966

getAngle(1, -1, 0, 0) = 2.356194490192345

(Everything's right from this point on though)

getAngle(0, 0, 1, 0) = 0

getAngle(0, 0, 1, 1) = 0.7853981633974483

getAngle(0, 0, 0, 1) = 1.5707963267948966

getAngle(0, 0, -1, 1) = 2.356194490192345

getAngle(0, 0, -1, 0) = 3.141592653589793

getAngle(0, 0, -1, -1) = -2.356194490192345

getAngle(0, 0, 0, -1) = -1.5707963267948966

getAngle(0, 0, 1, -1) = -0.7853981633974483

Mathematically speaking, those are all correct. :mellow: But they are much different from what we expect. Anyway, we won't need the angles themselves. We need their tan/sin values which are correct.

Link to comment
Share on other sites

When the angle of unit placement is fixed, add a post, too.

It effects my wall_tool for example and that has to be fixed then.

Luckily I did all the angle stuff in one function so only 40 lines of code to watch :sweatdrop:

Though sin( getAngle(1, 0, 0, 0) ) is -1, not 1 but everything seams to be in order!

Edited by FeXoR
Link to comment
Share on other sites

This function will return the angle of the vector from point 1 to point 2. So since the vector from (1,0) to (0,0) is (-1,0) the function is behaving correctly (for what I thought it should be doing). This unfortunately doesn't seem to be what you are wanting from this function.

From what you say I think you want the acute angle between the line passing through points 1 and 2 and the x axis. Is this correct?

Link to comment
Share on other sites

This function will return the angle of the vector from point 1 to point 2. So since the vector from (1,0) to (0,0) is (-1,0) the function is behaving correctly (for what I thought it should be doing). This unfortunately doesn't seem to be what you are wanting from this function.

From what you say I think you want the acute angle between the line passing through points 1 and 2 and the x axis. Is this correct?

When I made the request to add this functions I thought of (though I didn't clearly say, sry):

With 2 given points (witch also can be interpreted as vectors from [0, 0] to this point):

point1 = [x1, y1]

point2 = [x2, y2]

getVector(point1, point2) returning the vector from point1 to point2: [x2-x1, y2-y1]

getDistance(point1, point2) returning the distance between 2 points: Math.pow(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2), 1/2)

getAngle(point1, point2) returning the angle between the vectors to point1 and point2.

getDirection(point1, point2) returning the angle between getVector(point1, point2) and and a vector directed where a unit faces to when placed with angle = 0.

Since we agreed to use z as y it would be getAngle(getVector(point1, point2), [1, 0]) with counter clockwise rotation with growing angle (as far as unit placement is done this way too).

And, yes, as I use the function now it's the angle of the line between the 2 points towards the coordinate system.

 

Edited by FeXoR
Link to comment
Share on other sites

When I made the request to add this functions I thought of (though I didn't clearly say, sry):

With 2 given points (witch also can be interpreted as vectors from [0, 0] to this point):

point1 = [x1, y1]

point2 = [x2, y2]

getVector(point1, point2) returning the vector from point1 to point2: [x2-x1, y2-y1]

getDistance(point1, point2) returning the distance between 2 points: Math.pow(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2), 1/2)

getAngle(point1, point2) returning the angle between the vectors to point1 and point2.

getDirection(point1, point2) returning the angle between getVector(point1, point2) and and a vector directed where a unit faces to when placed with angle = 0.

And, yes, as I use the function now it's the angle of the line between the 2 points towards the coordinate system.

Ah, I see. Those different from the functions which I modified which is why we have been confused. I have drawn another diagram, is this what you want? If so which of the angles do you want?

So the current function is basically getDirection but using anticlockwise from the x axis rather than clockwise from the z axis which is what buildings use?

post-13166-0-19576500-1332168316_thumb.p

Link to comment
Share on other sites

Exactly!

It should be phi but it doesn't really matter cause sin/cos will give the same values, or? Edit, yes, they do. and you get the same result when using them for building placement.

Otherwise phi%(2*PI) Edit: Makes no sense, always smaller than 2*PI and never negative.

So the current function is basically getDirection but using anticlockwise from the x axis rather than clockwise from the z axis which is what buildings use?

Yes, and both should be consistent of cause.

As we agree that z should just be taken as y counter clockwise starting from positive x would be the choice to take.

Edited by FeXoR
Link to comment
Share on other sites

Exactly!

It should be phi but it doesn't really matter cause sin/cos will give the same values, or? Edit, yes, they do. and you get the same result when using them for building placement.

Otherwise phi%(2*PI) Edit: Makes no sense, always smaller than 2*PI and never negative

They don't give the same values. sin(phi) = -sin(theta).

Also in your earlier post you put

(Everything's right from this point on though)

getAngle(0, 0, 1, 0) = 0

getAngle(0, 0, 1, 1) = 0.7853981633974483..."

But these test values don't make sense with your definition of the function since the vector (0,0) has no defined direction.

Would you be able to draw some diagrams showing what you want from the functions, trying to describe geometry can be confusing.

Link to comment
Share on other sites

theta > 0 since phi < 2*pi though.

Oh, true x)

But theta < 0 because it's the angle from vector to point1 towards vector to point2.

It just that phi - theta = 2*PI (not phi + theta = 2*PI) no matter how often you rotate them around full circle.

That make phi = 2*PI + theta, but since theta < 0 -> phi < 2*PI.

Sorry x)

Though it's a wonderful conversation :thumbup:  but I have to go , will get back to this tomorrow... 

Edited by FeXoR
Link to comment
Share on other sites

You new getAngle function could be defined quite simply in terms of the current one as GetAngle(0,0,x1,z1) - GetAngle(0,0,x2,z2). I don't know about function names, I can't think of any that make it really clear what is being done.

I would like to replace the current unit placement angle with the anticlockwise angle from positive x. This is quite a big change though, I don't know what the other programmers think about it.

Link to comment
Share on other sites

I would like to replace the current unit placement angle with the anticlockwise angle from positive x. This is quite a big change though, I don't know what the other programmers think about it.

Well, then talk to them.

I don't really mind what comes out in the end, but I think (like stated above) the advantages of default x/y plain behavior are greater than both, the 3D mathematical consistence and the clockwise rotation.

Whatever happens one thing is important to me:

Unit placement and the functions of the rmgen libs have to be consistent!

If I can do anything just ask... I just don't know how to help ATM.

Edited by FeXoR
Link to comment
Share on other sites

We had a chat on irc and ended up with changing the engine's random map loader so it does the conversion. This means the change will only affect random maps rather than the whole engine so not too much needs changing. So this will need coding, I don't know if you are interested in doing it? Otherwise I can have a go.

Edit: Also it must be documented (or we risk histroric bruno's wrath).

Link to comment
Share on other sites

We had a chat on irc and ended up with changing the engine's random map loader so it does the conversion. This means the change will only affect random maps rather than the whole engine so not too much needs changing. So this will need coding, I don't know if you are interested in doing it? Otherwise I can have a go.

Edit: Also it must be documented (or we risk histroric bruno's wrath).

Well, I don't know if I can do it and what '...engine's random map loader so it does the conversion...' means in total, since I only read the rmgen libs yet.

However, I can of cause look into it and I would like to help documenting the results to RMS scripters.

The documentation of code change should of cause be done by the person who changes it...

I'll look deeper into the code on Monday.

Link to comment
Share on other sites

  • 2 months later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...