Can anyone help optimise this code?

Started by
8 comments, last by MENTAL 24 years ago
After a complete lack of responce from my vectors post, I managed to work out the routing myself. however, it seems over complicated and slow. I was wondering if anyone has any ideas about how to speed it up? the code concerns moving one vertex to another, but making sure that destination is reached at the same time on all 3 axis. there is a maximum speed that the vertex can move, but it can move slower if needed. the code is below. CVector __VECTOR; CVector __TMPVECTOR; CVector CreateVector(CVertex Current, CVertex Destination, int Speed) { __VECTOR.X = Current.X - Destination.X; __VECTOR.Y = Current.Y - Destination.Y; __VECTOR.Z = Current.Z - Destination.Z; if(__VECTOR.X < 0) __TMPVECTOR.X = VECTOR.X * -1; if(__VECTOR.Y < 0) __TMPVECTOR.Y = VECTOR.Y * -1; if(__VECTOR.Z < 0) __TMPVECTOR.Z = VECTOR.Z * -1; float LargeVec; if(__TMPVECTOR.X >= __TMPVECTOR.Y) { if(__TMPVECTOR.X >= __TMPVECTOR.Z) { LargeVec = __TMPVECTOR.X; } else { LargeVec = __TMPVECTOR.Z; } } else { if(__TMPVECTOR.Y >= __TMPVECTOR.Z) { LargeVec = __TMPVECTOR.Y; } else { LargeVec = __TMPVECTOR.Z; } } int Frames; Frames = RoundUpFloatToInt(LargeVec) / Speed; // gives the number of frames __VECTOR.X = __VECTOR.X / Frames; __VECTOR.Y = __VECTOR.Y / Frames; __VECTOR.Z = __VECTOR.Z / Frames; __VECTOR.Life = Frames; return __VECTOR; } i know the board is gonna make a complete hash of the code, but i think the idea is clear. i also need to know how to rount up a float to the next integer, e.g. 4.2 goes to 5, 1.00000000000000000000000001 goes to 2. any help appriciated MENTAL
Advertisement
Hi,

You're not initializing __TMPVECTOR.? for positive VECTOR.? values.

I *think* the following will work (and fix the above bug I mentioned), but I'm not sure if it's a good idea, nor what it will do for performance.

You might try changing:

if(__VECTOR.X < 0)
__TMPVECTOR.X = VECTOR.X * -1;

if(__VECTOR.Y < 0)
__TMPVECTOR.Y = VECTOR.Y * -1;

if(__VECTOR.Z < 0)
__TMPVECTOR.Z = VECTOR.Z * -1;

to (assuming you're working with floats):

__TMPVECTOR.X = VECTOR.X & 0x7fffffff; // force signbits positive
__TMPVECTOR.Y = VECTOR.Y & 0x7fffffff;
__TMPVECTOR.Z = VECTOR.Z & 0x7fffffff;

You can replace all that code that finds the largest of the three by:

float LargeVec = MAX(MAX(__TMPVECTOR.X, __TMPVECTOR.Y), __TMPVECTOR.Z); // but this is probably essentially the same as what you're doing already

I'm not sure the best way to round up a float the way you want. Simply adding 1.0 will usually work, except when the value is an whole number.

Hope this helps a bit. BTW, your code looks like it wouldn't be that slow already. Have you tried timing it or anything yet?

aig




Edited by - An Irritable Gent on 4/16/00 12:22:16 PM
aig
//RoundAFloatUpToNearestInt:
float f = someValue;
int i = static_cast< int > (f + 1.0f);
// or using C casts;
int i = (float) (f + 1.0f);

Jaap Suter
____________________________Mmmm, I''ll have to think of one.
quote:Original post by s9801758

//RoundAFloatUpToNearestInt:
float f = someValue;
int i = static_cast< int > (f + 1.0f);
// or using C casts;
int i = (float) (f + 1.0f);

Jaap Suter


Actually, it should be:

int i = static_cast(f + 0.5f);

As for the original code, you''re making things WAY to complicated. First, you only need to calculate the difference vector, scaled by speed, from the current position to the destination position. You can calculate the frames by taking any non-zero component of the difference vector and dividing that by the scaled vector. The code is trivial, and if you can''t figure out how to do it yourself, learn some linear algebra.

MSN
The easiest way to optimize this would be to take out the multiplication and division so here is what I would do...

if(__VECTOR.X < 0)
__TMPVECTOR.X = -VECTOR.X;

if(__VECTOR.Y < 0)
__TMPVECTOR.Y = -VECTOR.Y;

if(__VECTOR.Z < 0)
__TMPVECTOR.Z = -VECTOR.Z;

As for the division, I''d probably do some bitshifting.

Now onto the rounding:

float f,f2;
int final;

f2= (f-(int)f);
if(f2>=0.5)
final=(int)f+1;
else
final=(int)f;


Joseph FernaldSoftware EngineerRed Storm Entertainment.------------------------The opinions expressed are that of the person postingand not that of Red Storm Entertainment.
The "rounding" question the original poster had was not about true rounding, but about bumping up to the next whole number, ie. 1.00001 would bump up to 2.

aig
aig
Try this code (available for free from Nvidia''s website, along with some other fast floating point code)

__forceinline void FloatToInt(int *int_pointer, float f)
{
__asm fld f
__asm mov edx,int_pointer
__asm FRNDINT
__asm fistp dword ptr [edx];

}

Also, if you want to see if code can be optimized, may I suggest making a post like "I''ve optimized this code, I don''t think it can get any more than 50% faster, I challenge anyone here to try to beat that." You''ll probably get a lot more replies.
quote:Original post by mhkrause
Also, if you want to see if code can be optimized, may I suggest making a post like "I''ve optimized this code, I don''t think it can get any more than 50% faster, I challenge anyone here to try to beat that." You''ll probably get a lot more replies.


Alright, a challenge it is then!

Renaming everything to be a little more semantically accurate, as well as removing the frames member, since it''s just ceil( length( vel )/speed ). Note: This is not optimized for any sort of SIMD instructions.


CVector GetVelocityVector( const CVector& pos, const CVector& dest, int Speed )
{
CVector vel;

vel.x = dest.x-pos.x;
vel.y = dest.y-pos.y;
vel.z = dest.z-pos.z;

float invspd = 1.0f/Speed;

vel.x*=invspd; vel.y*=invspd; vel.z*=invspd;

return vel;
}

MENTAL: What exactly do you want this function to do? Do you want the velocity to move the position to destination in a set number of frames, or at a specific speed? Because otherwise this problem is deceptively easy, with a proper background in numerical methods.

MSN
Thanks for heling out everyone!

msn12b: i want it to move using the required velocity or less. The number of frames is in so i know when to stop the vector. however, the vertex MUST meet at the destination at the same time on all 3 axis or else it will look funny.

the frame number is included because it is decresed on each cycle of the game loop, and when it''s zero, the vector is no longer applied. it is much simpler (and probably faster) to calculate it once, instead of calculating "ceil( length( vel )/speed )" every frame.

could you please tell me how your code works, as i''m finding it slightly confusing

aig: thanks for the signbit code. i never knew it could be done this way!

mhkrause: wooo, optimizations a go-go! does this code work on any PC, or only one with a NVidia graphics card (i''m useless when it comes to complicated assembler).


as for the competition, i''m gonna try out all of these improvements, and then post it with the "I can get the code working 50% faster...". good idea

MENTAL
quote:Original post by MENTAL
msn12b: i want it to move using the required velocity or less. The number of frames is in so i know when to stop the vector. however, the vertex MUST meet at the destination at the same time on all 3 axis or else it will look funny.


The code takes the displacement vector, divides by the speed, and stores the resultant vector as the velocity vector.

if( vel.x!= 0 )
{
vel.Frames = ceil( (dest.x-pos.x)/vel.x );
}
else if( vel.y!= 0 )
{
vel.Frames = ceil( (dest.y-pos.y)/vel.y );
}
else if( vel.z!= 0 )
{
vel.Frames = ceil( (dest.z-pos.z)/vel.z );
}
else
{
vel.Frames = 0;
}

MSN

This topic is closed to new replies.

Advertisement