Jump to content
  • Advertisement
Sign in to follow this  
MARS_999

How to calculate a new position on a line?

This topic is 2273 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am not sure if this is the best way, but I would like to take my object after it collides with another object and back it up say 2 units, 180 degrees from the vector it's moving...

My initial thoughts are, take the objects position and the object that was hit and use their positions to get a slope value? and some how back up the player 2 units using a line equation? or can this be done with vector math easier?

Thanks

Share this post


Link to post
Share on other sites
Advertisement
Computing line slopes and (2D) line equations of form y=kx+c is probably not a good way here. Instead it is better to use direction vectors.

Here is how I would achieve that kind of collision response using MathGeoLib, if the objects were spheres. The code is for 3D primitives, but works equally with 2D:


Sphere objectA, objectB;
if (objectA.Intersects(objectB))
{
float backUpDistance = objectA.r + objectB.r; // Push A away from B so that the sphere surfaces just touch.
float3 backUpFromBDirection = objectA.pos - objectB.pos; // The direction is to go from B's position towards A's position.
float3 backUpDirectionScaled = backUpFromBDirection.ScaleToLength(backUpDistance); // Make the offset direction proper length.
objectA.pos = objectB.pos + backUpDirectionScaled; // Set the new position of object A.
}

Share this post


Link to post
Share on other sites
You have the direction vector and position of your object? Reverse the direction, normalize it and then multiply it by two units. Conclude by adding the result to the position. Should work.

Share this post


Link to post
Share on other sites
Thanks to both of you!!! O-san that worked great and clb I will take a look at the lib LOOKS very very nice and actually something that I was looking for to supplement my CML lib.

Happy coding!!!

Share this post


Link to post
Share on other sites
Oh wow CLB I didn't know that was your lib!!!

I have a quick question on that lib, are the matrices setup for OpenGL or DX by default? Hopefully OpenGL.. :)

Also I am looking to switch my AABB and ray testing code over to your lib, so do you have a quick a dirty example of creating the ray? I am assuming this ray will be made by using the screen width, height and mouse x,y....

Thanks!

Share this post


Link to post
Share on other sites
The library is intended to be agnostic of whether OpenGL or Direct3D is used. That said, the functions that generate transformation matrices all generate them in the order that you'll use 'Matrix * vector' notation to apply the transformations. (To use the other notation, one would transpose the matrices) Internally, column-major storage is used, which is what OpenGL data layout is.

To generate a ray through a 2D viewport coordinate, I use the Frustum class and its method LookAt (in latest trunk this is now called Unproject to not confuse with the function float3x4::LookAt). The mouse (x,y) pixel coordinate must be manually scaled with the screen pixel sizes beforehand and mapped to [-1,1] range.



// Setup camera frustum.
Frustum camera;
camera.type = PerspectiveFrustum;
camera.nearPlaneDistance = 1.f;
camera.farPlaneDistance = 1000.f;
camera.horizontalFov = pi/2.f;
camera.verticalFov = camera.horizontalFov / screen_pixel_aspect_ratio;
camera.pos = cameraPos;
camera.front = cameraLookatDirection;
camera.up = float3(0,1,0);
float3::Orthonormalize(camera.front, camera.up); // Make sure camera 'front' and 'up' are orthonormal.

// Produce mouse viewport lookat ray.
Ray MouseRay(int mouseScreenX, int mouseScreenY, int screenWidth, int screenHeight)
{
float x = (float)mouseScreenX / screenWidth;
float y = (float)mouseScreenY / screenHeight;
x = x * 2.f - 1.f;
y = -(y * 2.f - 1.f); // Windows screen pixel coordinates go top->down. Normalized screen coordinates go bottom-up.
Ray lookAtRay = cameraFrustum.UnProject(x, y);
return lookAtRay;
}



Then use Ray::Intersects to test against collisions.

Alternatively, you can use whatever method you previously used to create the mouse ray, and then construct a MathGeoLib Ray object using those parameters, and go from there.

Share this post


Link to post
Share on other sites

I have a quick question on that lib, are the matrices setup for OpenGL or DX by default? Hopefully OpenGL.. smile.png

OpenGL uses column vectors and column major order by default, and D3D uses row vectors and row major order. In the end the memory layout of both is the same. According to this page, clib's matrices use column vectors and row major order which does match neither OpenGL nor D3D matrix layout.

On the other hand, the transformation specific parts of the matrices are specified to work using column vectors, which is consistent with OpenGL's default convention.

Hence using clib's float4x4::ptr() to push a matrix to OpenGL requires a transpose.


EDIT:

The library is intended to be agnostic of whether OpenGL or Direct3D is used. That said, the functions that generate transformation matrices all generate them in the order that you'll use 'Matrix * vector' notation to apply the transformations. (To use the other notation, one would transpose the matrices) Internally, column-major storage is used, which is what OpenGL data layout is.

Err, well, I read something other from the docs. Have I misread something or are the docs deprecated? Edited by haegarr

Share this post


Link to post
Share on other sites
EDIT:


The library is intended to be agnostic of whether OpenGL or Direct3D is used. That said, the functions that generate transformation matrices all generate them in the order that you'll use 'Matrix * vector' notation to apply the transformations. (To use the other notation, one would transpose the matrices) Internally, column-major storage is used, which is what OpenGL data layout is.

Err, well, I read something other from the docs. Have I misread something or are the docs deprecated?
[/quote]

Actually, I stand corrected, and you are right. I've been going on this from old memory, but now double-checked it and yes, in OpenGL, the matrices are expected to be passed in column-major. In any case, in MathGeoLib, matrices are stored row-major, and the transform generation functions produce matrices which are intended to be applied with 'M*v' notation.

However, implementing SSE optimizations lead to realizing that Matrix*vector multiplications could be implemented somewhat faster if column-major order was used, see https://github.com/j...GeoLib/issues/3 , so in the future, column-major order may be present. Note however that this will not change the public API, i.e. the functions matrix[row][col] and matrix.At(int row, int col) will always have their parameters presented in that order, i.e. y first, then x. Edited by clb

Share this post


Link to post
Share on other sites
clb, so am I reading this correct, that you are using SSE or AVX to accelerate your math lib? Have you looked at using OpenCL to do some tests to see if it would speed up your lib?

I am currently using CML, and would like to use your lib to take over the geometry portion of my missing math lib, and so far looks promising. Do you have any ideas when you may have a more stable or complete build? From the looks of it you have quite a bit of work done, but more to do, and I am not math savvy enough to know how much of the work you have left I may need or not....

BTW if someone could please check over this AABB to Ray intersect code I have, before I move onto MathGeoLib....


inline bool Intersect(const AABB<T>& box, T& dist)
{
T temp;
T min = -std::numeric_limits<T>::max();
T max = std::numeric_limits<T>::max();

if(fabs(dir[0]) < EPSILON_E5)
if((origin[0] < box.min[0]) || (origin[0] > box.max[0]))
return false;

T t0 = (box.min[0] - origin[0]) / dir[0];
T t1 = (box.max[0] - origin[0]) / dir[0];

if(t0 > t1) {temp = t0; t0 = t1; t1 = temp;}
if(t0 > min) min = t0;
if(t1 < max) max = t1;
if(min > max) return false;
if(max < 0) return false;

if(fabs(dir[1]) < EPSILON_E5)
if((origin[1] < box.min[1]) || (origin[1] > box.max[1]))
return false;

t0 = (box.min[1] - origin[1]) / dir[1];
t1 = (box.max[1] - origin[1]) / dir[1];

if(t0 > t1) {temp = t0; t0 = t1; t1 = temp;}
if(t0 > min) min = t0;
if(t1 < max) max = t1;
if(min > max) return false;
if(max < 0) return false;

if(fabs(dir[2]) < EPSILON_E5)
if((origin[2] < box.min[2]) || (origin[2] > box.max[2]))
return false;

t0 = (box.min[2] - origin[2]) / dir[2];
t1 = (box.max[2] - origin[2]) / dir[2];

if(t0 > t1) {temp = t0; t0 = t1; t1 = temp;}
if(t0 > min) min = t0;
if(t1 < max) max = t1;
if(min > max) return false;
if(max < 0) return false;

if(min > 0)
dist = min;
else
dist = max;
return true;
}
Edited by MARS_999

Share this post


Link to post
Share on other sites
I don't much expect MathGeoLib to ever "finish". Probably the best way to use it is to take it as a repository of code snippets and documentation and reference source for further information (the original source webpages/books/articles should be quite thoroughly cited), since I do not maintain build scripts for any platform.

I haven't looked much into OpenCL, perhaps that might help in some cases, but I haven't had that much of a stress in my applications to need to squeeze out maximal performance in the low-level math ops.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!