Aller au contenu

Photo

How to edit a vector variable ?


  • Veuillez vous connecter pour répondre
18 réponses à ce sujet

#1
anakin5

anakin5
  • Members
  • 258 messages
Does anyone know how to change the x, y or z coord of a vector variable ? It seems we cannot extract single coords from a vector object.

EDIT: can we use arithmetical operation on vector ? are they defined ?

Modifié par anakin5, 07 janvier 2010 - 09:14 .


#2
Craig Graff

Craig Graff
  • Members
  • 608 messages
Vectors use dot notation similar to structs:
[dascript]
float fX = vPosition.x;
float fY = vPosition.y;
float fZ = vPosition.z;
[/dascript]

You can also just multiply the whole vector by a float value, which has the effect of multiplying each of the component vectors (x, y, and z) by that value.

Modifié par Craig Graff, 07 janvier 2010 - 09:47 .


#3
anakin5

anakin5
  • Members
  • 258 messages
Thank you :)

#4
Sunjammer

Sunjammer
  • Members
  • 925 messages
You can (or at least could in NWN):
  • multiply a float by a vector
  • multiply a vector by a float
  • divide a vector by a float
  • add two vectors
  • subtract two vectors
In addition you can create a vector using any of the following:

// literal
vector v = [1.0, 2.0, 3.0];

// constuctor
vector v = Vector(1.0, 2.0, 3.0);

// memberwise
vector v; 
v.x = 1.0; 
v.y = 2.0; 
v.z = 3.0;

Modifié par Sunjammer, 07 janvier 2010 - 11:24 .


#5
anakin5

anakin5
  • Members
  • 258 messages
Do you have any info about the origin of coords and axis ?

Where is the point 0, 0, 0 on a map ?



And how are angle measured ? (with GetFacingFromLocation for example)

#6
Sunjammer

Sunjammer
  • Members
  • 925 messages
In NWN [0,0,0] was the bottom left corner (or south west corner) of your area. In Dragon Age this appears to still be true for exteriors so often [0,0,0] will be in the borders and outside the playable area. However interiors can be built around the origin so [0,0,0] could potentially be anywhere: I just placed a waypoint at [0,0,0] in one of our interior areas and it appeared in the middle of the floor.

The angle doesn't get much easier I'm afraid. In NWN angle was from two different places: if memory serves in the toolset the angle was an anti-clockwise rotation from north while in the game it was an anti-clockwise rotation from east. In Dragon Age it appears in the toolset it appears the angle is still and anti-clockwise rotation from north however, going by the Direction Constants, in the game the angle is a clockwise rotation from south!

I think much testing in will be required to confirm or deny these possibilities.

#7
Sunjammer

Sunjammer
  • Members
  • 925 messages
Unfortunately according to the GetFacing function my fears have been realised! In game rotations are from south and clockwise!

#8
anakin5

anakin5
  • Members
  • 258 messages
Thanks for all these information, it is going to help me a lot.

#9
Sunjammer

Sunjammer
  • Members
  • 925 messages
Some output from GetFacing and GetPosition

Script    squirel_origin valid: 1
Script    squirel_origin facing:     -180.000152588
Script    squirel_origin position: 0.000000 0.000000 0.000000
Script    squirel_north valid: 1
Script    squirel_north facing:     -180.000152588
Script    squirel_north position: -6.000000 -4.000000 0.000000
Script    squirel_west valid: 1
Script    squirel_west facing:       90.000068665
Script    squirel_west position: -8.000000 -5.000000 0.000000
Script    squirel_south valid: 1
Script    squirel_south facing:       -0.000022312
Script    squirel_south position: -6.000000 -6.000000 0.000000
Script    squirel_east valid: 1
Script    squirel_east facing:      -90.000068665
Script    squirel_east position: -4.000000 -5.000000 0.000000
It is interesting that EAST is not in fact 270.0 but rather -90.0 which means you would have to normalise before doing a comparison with DIRECTION_EAST constant.  Similarly unlike the positions the facings are not an exact number of degrees so you may have to something like:

if(fabs(NormaliseAngle(GetFacing(oTarget)) - DIRECTION_EAST) < 0.001)

Where NormaliseAngle would be a custom function to ensure
0.0 <= angle  < 360.0
.

Modifié par Sunjammer, 08 janvier 2010 - 01:57 .


#10
FalloutBoy

FalloutBoy
  • Members
  • 580 messages
Looking at the output it looks like the valid range is actually +/- 180

float NormalizeAngle( float angle )
{
   float result = angle;
   while( result > 180 ) result -= 360;
   while( result < -180 ) result += 360;
   return result;
}


Modifié par FalloutBoy, 08 janvier 2010 - 05:48 .


#11
Craig Graff

Craig Graff
  • Members
  • 608 messages
Many of the facing functions were messed up when we made a low-level change to allow for the rotation of placeables around all axes. Unfortunately this was not caught in time to fix before lockdown. If you are going to use SetFacing and GetFacing, set the optional bMirrorAxis parameter to FALSE. GetOrientation and SetOrientation work correctly, and can be used in combination VectorToAngle and AngleToVector to translate from a facing float.



Unfortunately the problems extend to the facing in Location functions as well, so pairing CreateObject with SetOrientation is sometimes necessary.



Another note on SetFacing is that it will rotate placeables smoothly, which is nice, but not always the desired functionality. If you want to snap a placeable to face something, use SetOrientation.

#12
Innodil Ath Nathosh

Innodil Ath Nathosh
  • Members
  • 28 messages
yeah, orientation vectors get screwed up in location constructors

I wrote my own "correction" function for orientation vectors that basically calculates the "mirrored" angle and passing that to Location correcting this issue...

That way if you guys decide to fix this massively annoying bug :-p I only need to change my function to do nothing....

It would be nice though to DOCUMENT stuff like this on the wiki



And to confirm, the valid range IS -180.0 to 180.0 depending which "way" you want to rotate.



if you print the orientation vector with GetOrientation(...) and your want to use that same orientation with Location(....) you need to:



float angle = VectorToAngle(orientationVector);

float sign = angle < 0.0?-1.0:1.0;

float correctLocationAngle = sign * ( 180 - (sign * angle) );



This will return a usable angle for Location() which actually points the correct way...




#13
Sunjammer

Sunjammer
  • Members
  • 925 messages

FalloutBoy wrote...

Looking at the output it looks like the valid range is actually +/- 180

That is what the function returns however whether or not someone considers that to be the "valid" range depends on their needs. In my example I'm comparing it with constants that are in the range 0.0 to 270.0 so, as stated, I would normalise to
0.0 <= angle < 360.0
as the range -180.0 <= angle < 0.0 isn't appropriate.

You of course could realign the constants using your version of the function and compare them with the raw output but that feel's a little that is counterintuitive as we tend to think in terms of 0 to 360 degrees.

Incidentally you've omitted a minus operator from your second
while
condition. It should be:

while(result < -180.0) result += 360.0;

Also your function will produce values in the range
-180.0 <= angle <= 180.0
which could cause you problems as you would have two equivalent values. I would suggest using
-180.0 < angle <= 180.0
or
-180.0 <= angle < 180.0
.

Modifié par Sunjammer, 08 janvier 2010 - 12:28 .


#14
Sunjammer

Sunjammer
  • Members
  • 925 messages

Innodil Ath Nathosh wrote...

It would be nice though to DOCUMENT stuff like this on the wiki

Rest assured it will be going into the Lexicon as soon as I've done some more testing on these functions.

#15
Craig Graff

Craig Graff
  • Members
  • 608 messages
Whatever is input into any SetFacing will work fine - 720.0 is the same as 360.0 and there is no need to create recursive functions to "normalize" them unless you are looking to print out the values - as long as you remember to always et the bMirrorAxis parameter to false.

Does the normalized input actually help for Location constructors (as in will the facing be consistently what you expect it to be)? Even if it is, make sure you aren't using a recursive function based on input that can grow arbitrarily large, like calling a GetFacing on an object. It is likely still better to SetOrientation in most cases.

If you decide you want to use the normalization function, at least preface your while loops with angle %= 360.0; so you don't run into TMI (too many instructions) errors.

Modifié par Craig Graff, 08 janvier 2010 - 04:45 .


#16
FalloutBoy

FalloutBoy
  • Members
  • 580 messages

Sunjammer wrote...
Incidentally you've omitted a minus operator from your second

while
condition. It should be:


Heh, fixed it. Thanks. I had to rewrite it several times because the forum software had trouble with my less-than operator.

Does your modulus operator work with floats? Pretty sure you would have to change them to ints to use %.

Modifié par FalloutBoy, 08 janvier 2010 - 05:53 .


#17
fluffyamoeba

fluffyamoeba
  • Members
  • 264 messages
You'd have to have a huge angle to TMI on that. :o You could just assume any value outside the range -/+360 is an error ( check, then complain). This is reasonable if the angle you are trying to normalise is one returned from a native script function.

#18
Craig Graff

Craig Graff
  • Members
  • 608 messages
Yeah, a working version would be more like

[dascript]

float fAngle = 1770.0;

int nAngle = FloatToInt(fAngle);

fAngle -= nAngle;

nAngle %= 360;

fAngle += nAngle;

[/dascript]

Still better than even the possibility of TMI errors, I think.



@ fluffyamoeba Huge angle, true - but it is quite possible depending on your usage.


#19
anakin5

anakin5
  • Members
  • 258 messages
Just to add that GetVectorNormalize(vDir) seems to always return [0, 0, 0] for me.

While the equivalent : vDir / GetVectorMagnitude(vDir) is working and return a non nul vector.