Making a raycast bounce?

Author Topic: Making a raycast bounce?  (Read 3632 times)

I'm trying to add a prediction mechanism to Brickochet to allow players a chance to see approximately what combo their projectile will end up with, but I'm having a hard time understanding how to make a raycast bounce/redirect in the other direction. This vector math in a 3D plane is screwing with me.

I've tried scaling it by -1, but it's not working like I think it would.

Code: [Select]
function Player::testCast(%this) {
%eyePoint = %this.getEyePoint();
%eyeVector = %this.getEyeVector();
echo(%eyePoint SPC ":" SPC %eyeVector);
%Range = vectorAdd(%eyePoint,vectorScale(%eyeVector,10));
%raycast = containerRayCast(%eyePoint,%Range,$TypeMasks::fxBrickObjectType);

echo(vectorScale(normalFromRaycast(%raycast), %eyeVector));

%obj = getWord(%raycast, 0);
%testStart = getRealTime();
while(isObject(%obj) && getRealTime() - %testStart < 200) {
%obj.setColorFX(3);
%obj.schedule(200, setColorFX, 0);

echo("B:" SPC %eyeVector);

%pos = posFromRaycast(%raycast);
%eyeVector = vectorNormalize(VectorScale(%pos,-1));

echo("A:" SPC %eyeVector);

%Range = vectorAdd(%pos,vectorScale(%eyeVector,10));
%raycast = containerRayCast(%pos,%Range,$TypeMasks::fxBrickObjectType);

%obj = getWord(%raycast, 0);
}
}

if you scale it by -1, it will do a full 180 degree turn
basically it goes back to the shooter
you need to know the angle of the thing you're hitting in order to bounce

Are you just trying to get it to turn 180 degrees from the original vector or are you trying to make it bounce as in leaving the surface with the same angle as it hit the surface?

Are you just trying to get it to turn 180 degrees from the original vector or are you trying to make it bounce as in leaving the surface with the same angle as it hit the surface?
Like if you were to throw a ball at a wall and it would bounce off of it.

I have this old code snippet from god knows where that rotates vectors:
Code: [Select]
function VectorRotateAxis(%vector,%axis,%angle)
{
  %x = getWord(%vector,0);
  %y = getWord(%vector,1);
  %z = getWord(%vector,2);
  %u = getWord(%axis,0);
  %v = getWord(%axis,1);
  %w = getWord(%axis,2);
  %ux = %u * %x;
  %uy = %u * %y;
  %uz = %u * %z;
  %vx = %v * %x;
  %vy = %v * %y;
  %vz = %v * %z;
  %wx = %w * %x;
  %wy = %w * %y;
  %wz = %w * %z;
  %sa = mSin(%angle);
  %ca = mCos(%angle);
  %nx = %u*(%ux+%vy+%wz)+(%x*(%v*%v+%w*%w)-%u*(%vy+%wz))*%ca+(-%wy+%vz)*%sa;
  %ny = %v*(%ux+%vy+%wz)+(%y*(%u*%u+%w*%w)-%v*(%ux+%wz))*%ca+(%wx-%uz)*%sa;
  %nz = %w*(%ux+%vy+%wz)+(%z*(%u*%u+%v*%v)-%w*(%ux+%vy))*%ca+(-%vx+%uy)*%sa;
  return(%nx SPC %ny SPC %nz);
}
Rotating the raycast vector around the normal vector by 180° should give the results you want - assuming this piece of code actually works.

Nonono, you need to factor in the actual direction of the surface it hit.
Assuming that %v is the direction of the raycast and %n is the normal vector of the hit surface:

%vn = vectorAdd(vectorScale(%n, -2 * vectorDot(%v, %n)), %v);

%vn is the direction that your new raycast from the hit surface position should go in.

For reference, the words returned by a raycast are:

Hit object
Hit position X
Hit position Y
Hit position Z
Surface normal X
Surface normal Y
Surface normal Z

Use getWords to get the position and normal.

Rotating the raycast vector around the normal vector by 180° should give the results you want - assuming this piece of code actually works.
if you were just going to rotate it by 180, wouldn't scaling it by -1 do the same thing?

to make it bounce like you're chucking pinballs/pong everywhere, you need to know the angle of the plane that you're hitting and flip it over the normal of the plane

if you were just going to rotate it by 180, wouldn't scaling it by -1 do the same thing?

to make it bounce like you're chucking pinballs/pong everywhere, you need to know the angle of the plane that you're hitting and flip it over the normal of the plane

Rotating the 180 degrees around the normal (and then flipping the direction) would have the same effect, but it's probably the least efficient way you can do this.

Assuming that %v is the direction of the raycast and %n is the normal vector of the hit surface:

%vn = vectorAdd(vectorScale(%n, -2 * vectorDot(%v, %n)), %v);

%vn is the direction that your new raycast from the hit surface position should go in.

Code: [Select]
function Player::testCast(%this) {
%eyePoint = %this.getEyePoint();
%eyeVector = %this.getEyeVector();
%range = vectorAdd(%eyePoint,vectorScale(%eyeVector,100));
%raycast = containerRayCast(%eyePoint,%range,$TypeMasks::fxBrickObjectType);

%obj = getWord(%raycast, 0);
%testStart = getRealTime();

while(isObject(%obj) && getRealTime() - %testStart < 10) {
%obj.setColorFX(3);
%obj.schedule(20, setColorFX, 0);

%n = getWords(%raycast, 4, 6); // eyeVector
%v = getWords(%raycast, 1, 3); // eyePoint
%vn = vectorAdd(vectorScale(%n, -2 * vectorDot(%v, %n)), %v); // new eyeVector?

%range = vectorAdd(%v,vectorScale(%vn,100));
%raycast = containerRayCast(%v,%range,$TypeMasks::fxBrickObjectType);

%obj = getWord(%raycast, 0);
}
}

package testPackage {
function Player::activateStuff(%this) {
%this.testCast();
return parent::activateStuff(%this);
}
};
activatePackage(testPackage);

decided to fiddle with this again, still not working correctly? i hate vectors

In your while loop, the raycast is using the wrong parameter.

%raycast = containerRayCast(%v,%range,$TypeMasks::fxBrickObjectType);
should be
%raycast = containerRayCast(%nv,%range,$TypeMasks::fxBrickObjectType);


Cant see anything else wrong other than that. Your variable names could be better though. I recommend start and end for raycast points.

that doesn't fix it

i don't know if port's example works right, it seems to get things perpendicular to the normal? (e.g. i fire it at an angle, the angle is flattened and sent in reverse from the normal or something)

that doesn't fix it

i don't know if port's example works right, it seems to get things perpendicular to the normal? (e.g. i fire it at an angle, the angle is flattened and sent in reverse from the normal or something)

Port's math seems fine to me in my head.

Looking at it again, I think I was wrong thinking it should be %nv. Try changing
%vn = vectorAdd(vectorScale(%n, -2 * vectorDot(%v, %n)), %v);
to
%vn = vectorAdd(vectorScale(%n, -2 * vectorDot(%eyeVector, %n)), %eyeVector);
No guarantees though, its late.

%v is badly named, it is the hit position of the raycast, not a vector.

As stated in the post, I meant for %v to be the normalized direction of the raycast. So yes, in that case the eye vector (but only for the first bounce!).

Code: [Select]
%n = getWords(%raycast, 4, 6); // eyeVector
%v = getWords(%raycast, 1, 3); // eyePoint
You probably already know this and it probably doesn't matter, but neither of these are right. The first one is the position where the raycast stopped. The second is the normal of where it hit on the object.