JoakimNordstrandStien 114 Report post Posted August 8, 2011 Greetings, GameDev community! I'm currently working with Box2D, and I'm implementing an explosion-effect. Therefore, I'm in need of a direction vector to be multiplied by the force (which is based on distance). In order to make it appear as seamless as possile, I need to first transform the vector so that the highest value of the vector is 1. Let me show you; A vector of (15, 10) would be (1, 6.67). As would a vector (30,15) be (1, 0.5). Has anyone done this before and have a code snippet to share? The general theory / principle behind it would be sufficient as well. Thanks in advance //pimms 0 Share this post Link to post Share on other sites
alvaro 21270 Report post Posted August 9, 2011 Compute the maximum of the absolute values of the coordinates and divide every coordinate by it. Is that what you wanted? 0 Share this post Link to post Share on other sites
Hassanbasil 195 Report post Posted August 9, 2011 i think you're looking for [url="http://www.fundza.com/vectors/normalize/index.html"]vector normalization[/url] to have a unit vector that is the direction? (the link is 3d, just remove any z from calculation and it's fine) 0 Share this post Link to post Share on other sites
JoakimNordstrandStien 114 Report post Posted August 9, 2011 Thanks for the quick replies, guys. Appreciate it a lot [b]@alvaro[/b] I'm not 100% sure of what you mean - what I've tried (without much success) is to first find the ratio between X and Y, based on the highest value. If the highest value is > 1.0, I divide X and Y by the highest value. This produces some funny results, though. If the highest value is < 1.0, I find the ratio by dividing 1 by the highest. Then X and Y is divided by ratio. The current (faulty) code: [source] if ( vector.x > vector.y ) { for (;;) { if ( high < 1.0f ) { ratio = 1.f / high; x = high * ratio; y = low * ratio; break; } if ( high > 1.0f ) { ratio = high / high; x = high / ratio; y = low / ratio; break; } } } [/source] [b]@Hassanbasil[/b] I've looked into normalizing the vector, but that would be quite the workaround for me, as I'm calculating the force to be applied as so; [source] body->ApplyForce( (hitVector*distance)*force, body->GetWorldCenter() ); [/source] Where hitVector is the vector I'm trying to calculate. 0 Share this post Link to post Share on other sites
JoakimNordstrandStien 114 Report post Posted August 9, 2011 I came up with something that works somewhat decent, thought I'd share it as it might be of help to someone out there It's messy as shit, and could use a rewrite, but I'm satisfied considering it's 2:45 AM. As mentioned, this function returns a vector scaled down to 1. [source] inline b2Vec2 scaleVecTo1( b2Vec2 vector ) { //flag for reversing them to negative before return bool invX=NO, invY=NO; float x=0.f, y=0.f; float ratio; invX = vector.x < 0.f ? YES : NO; invY = vector.y < 0.f ? YES : NO; vector.x *= vector.x < 0.f ? -1.f : 1.f; vector.y *= vector.y < 0.f ? -1.f : 1.f; if ( vector.x > vector.y ) { for (;;) { if ( vector.x < 1.0f ) { ratio = 1.f / vector.x; x = vector.x * ratio; y = vector.y * ratio; break; } if ( vector.x > 1.0f ) { ratio = vector.x / vector.x; x = vector.x / ratio; y = vector.y / ratio; break; } } } if ( vector.x <= vector.y ) { for (;;) { if ( vector.y < 1.0f ) { ratio = 1.f / vector.y; y = vector.y * ratio; x = vector.x * ratio; break; } if ( vector.y > 1.0f ) { ratio = vector.y / vector.y; y = vector.y / ratio; x = vector.x / ratio; break; } } } x *= invX ? -1.f : 1.f; y *= invY ? -1.f : 1.f; return b2Vec2(x,y); } [/source] 0 Share this post Link to post Share on other sites
alvaro 21270 Report post Posted August 9, 2011 [quote name='Admiral Pimms' timestamp='1312850112' post='4846456'] [b]@alvaro[/b] I'm not 100% sure of what you mean - what I've tried (without much success) is to first find the ratio between X and Y, based on the highest value. [/quote] I mean this: [code]inline b2Vec2 scaleVecTo1( b2Vec2 vector ) { float m = std::max(std::abs(vector.x), std::abs(vector.y)); return b2Vec(vector.x/m, vector.y/m); } [/code] [font="Consolas,"] [/font] 0 Share this post Link to post Share on other sites
Hassanbasil 195 Report post Posted August 9, 2011 alvaro's method is just what you're asking for - but what you're asking for doesn't seem to be the right way to do it, normalizing the vector and making it a unit vector is actually what looks suitable in your case, since it has the length of 1 (hence the name unit vector) let's assume you have the vector (5,10), your desired method will make it (0.5,1), now calculate the length of it: sqrt(0.5*0.5+1*1) = sqrt(1.25) != 1 now the normalization method: sqrt((5 / sqrt(5 * 5 + 10 * 10))^2 + (10 / sqrt(5 * 5 + 10 * 10))^2) = 1 0 Share this post Link to post Share on other sites
JoakimNordstrandStien 114 Report post Posted August 9, 2011 Thanks again for your replies - As it turned out, a Normalized vector is in fact what I was looking for to begin with. Thank you for putting up with my ridiculously bad math knowledge. //Pimms 0 Share this post Link to post Share on other sites