3D Vector Math

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

3D Vector Math

Post by Vectrotek »

This should be a useful topic in Advanced Help.
Anyone with questions or opinions on the subject could post here..
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Re: 3D Vector Math

Post by Vectrotek »

To kick it off, I thought this would be a good example of what I'd like to have found here:

Common Game Vector Math Tricks..

If you ever looked for ways to find
"The Closest Distance to a Given Finite Line Segment from a Given Point"
or "The Closest Distance from a Given Point to a Given Plane" and found nothing but
insane looking sets of formulae or useless C++ snippets, then this should lay your
questions to rest.

I had almost exhausted what Google offered on the subject and finally decided to come up with my own recipe.
(partly based on those very Google results off-course)

These functions should be quite useful not only in C++ but also in GLSL or HLSL.
(with minor variable type renaming like vec3 or Float3)

Here is a picture of a "Mockup" done In Blender (see the actual C++ functions further down)
Image
Last edited by Vectrotek on Sat Dec 05, 2015 9:21 pm, edited 1 time in total.
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Re: 3D Vector Math

Post by Vectrotek »

Here are FOUR VERY USEFULL FUNCTIONS..

Code: Select all

 
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 
// 001..
vector3df GetClosestPointOnLineSegment (vector3df TestPoint , vector3df LineStart, vector3df LineEnd)
 {f32 TheLineModule = 0.0f;
  f32 TheDotProduct = 0.0f;
  vector3df VectorPrimary;
  vector3df VectorSecondary;
  vector3df VectorTertiary;
  vector3df ClosestCheckPoint;
  vector3df Deltas;
  // -------------------------------- ---- --- -- -
  VectorPrimary = TestPoint - LineStart; 
  Deltas = LineEnd - LineStart;
  TheLineModule = sqrt(( Deltas.X * Deltas.X) + ( Deltas.Y * Deltas.Y ) + ( Deltas.Z * Deltas.Z));
  VectorSecondary = Deltas / TheLineModule; // Like Multiplication, Division of vector3df by a float is also legal..
  TheDotProduct = ((VectorPrimary.X * VectorSecondary.X)
                  +(VectorPrimary.Y * VectorSecondary.Y)
                  +(VectorPrimary.Z * VectorSecondary.Z));
  // SEGMENT EDGES ARE CLOSER THAN ANY OTHER POSITION ON THE LINE..
  if (TheDotProduct <= 0)              return LineStart;
  if (TheDotProduct >= TheLineModule)  return LineEnd;
  // Segment edges tested and failed so continue with calculation..
  VectorTertiary = VectorSecondary * TheDotProduct; // See how this statement is legal..
  ClosestCheckPoint = LineStart + VectorTertiary;
  return ClosestCheckPoint;
 }
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 
// 002..
f32 GetClosestDistanceToLineSegment (vector3df TestPoint , vector3df LineStart, vector3df LineEnd)
 {f32 TheLineModule = 0.0f;
  f32 TheDotProduct = 0.0f;
  vector3df VectorPrimary;
  vector3df VectorSecondary;
  vector3df VectorTertiary;
  vector3df ClosestCheckPoint;
  vector3df Deltas;
  f32 TheClosestDistance;
 
  // -------------------------------- ---- --- -- -
  VectorPrimary = TestPoint - LineStart; 
  Deltas = LineEnd - LineStart;
  TheLineModule = sqrt(( Deltas.X * Deltas.X)
                     + ( Deltas.Y * Deltas.Y )
                     + ( Deltas.Z * Deltas.Z));
  VectorSecondary = Deltas / TheLineModule; // Like Multiplication, Division of vector3df by a float is also legal..
  TheDotProduct = ((VectorPrimary.X * VectorSecondary.X)
                 + (VectorPrimary.Y * VectorSecondary.Y)
                 + (VectorPrimary.Z * VectorSecondary.Z));
  // SEGMENT EDGES (either Start OR End) ARE CLOSER THAN ANY OTHER POSITION (Perpendicular) ON THE LINE..
  if (TheDotProduct <= 0)   
   {vector3df DeltasStartTest =  LineStart - TestPoint;
    return sqrt((DeltasStartTest.X * DeltasStartTest.X)
              + ( DeltasStartTest.Y * DeltasStartTest.Y )
              + ( DeltasStartTest.Z * DeltasStartTest.Z));
   }
  if (TheDotProduct >= TheLineModule)
   {vector3df DeltasEndTest =  LineEnd - TestPoint;
    return sqrt(( DeltasEndTest.X * DeltasEndTest.X)
              + ( DeltasEndTest.Y * DeltasEndTest.Y )
              + ( DeltasEndTest.Z * DeltasEndTest.Z));
   } // And skip all else..
  // Segment edges tested and failed so continue with calculation..
  VectorTertiary = VectorSecondary * TheDotProduct; // See how this statement is legal..
  ClosestCheckPoint = LineStart + VectorTertiary;
  vector3df DeltasClosestTest = ClosestCheckPoint - TestPoint;
  return sqrt((DeltasClosestTest.X * DeltasClosestTest.X)
            + (DeltasClosestTest.Y * DeltasClosestTest.Y)
            + (DeltasClosestTest.Z * DeltasClosestTest.Z));
 }
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 
// 003..   Aquiring the NORMAL & POSITION for a PLANE is as simple as
//         GERATING a NORMAL from a SELECTED TRIANGLE and
//         using ANY ONE of its POINTS as the PLANE POSITION..
vector3df GetClosestPointOnPlaneFromPoint (vector3df TestPoint ,
                                           vector3df PlanePos,
                                           vector3df PlaneNormal) // NORMAL MUST BE NORMALISED!!
  {f32 TheLineModule = 0.0f;
   f32 TheDotProduct = 0.0f;
   vector3df VectorPrimary;
   vector3df VectorTertiary;
   vector3df ClosestCheckPoint;
   vector3df PlaneDeltas;
   // vector3df ToPlaneDeltas;
   vector3df ClosestPointOnPlane;
   f32       DistanceToPlane;
   // -------------------------------- ---- --- -- -
   VectorPrimary = TestPoint - PlanePos;  // See how the Plane Pos is also the start of the Normal for the Plane..
   TheDotProduct = ((VectorPrimary.X * PlaneNormal.X)
                  + (VectorPrimary.Y * PlaneNormal.Y)
                  + (VectorPrimary.Z * PlaneNormal.Z));
   VectorTertiary = PlaneNormal * TheDotProduct; // See how this statement is legal.
   ClosestCheckPoint = PlanePos + VectorTertiary;
   PlaneDeltas = ClosestCheckPoint - PlanePos;
   ClosestPointOnPlane = TestPoint - PlaneDeltas; // By a simple geometric analysis.. (Blender Mockups)
   return ClosestPointOnPlane;
 }
 
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 
// 004..
 f32 GetDistanceToPlaneFromPoint (vector3df TestPoint ,
                                  vector3df PlanePos,
                                  vector3df PlaneNormal) // NORMAL MUST BE NORMALISED!!
  {f32 TheLineModule = 0.0f;
   f32 TheDotProduct = 0.0f;
   vector3df VectorPrimary;
   vector3df VectorTertiary;
   vector3df ClosestCheckPoint;
   vector3df PlaneDeltas;
   vector3df ToPlaneDeltas;
   vector3df ClosestPointOnPlane;
   f32       DistanceToPlane;
   // -------------------------------- ---- --- -- -
   VectorPrimary = TestPoint - PlanePos;  // See how the Plane Pos is also the start of the Normal for the Plane..
   TheDotProduct = ((VectorPrimary.X * PlaneNormal.X)
                  + (VectorPrimary.Y * PlaneNormal.Y)
                  + (VectorPrimary.Z * PlaneNormal.Z));
   VectorTertiary = PlaneNormal * TheDotProduct;
   ClosestCheckPoint = PlanePos + VectorTertiary;
   PlaneDeltas = ClosestCheckPoint - PlanePos;
   ClosestPointOnPlane = TestPoint - PlaneDeltas;
   ToPlaneDeltas = ClosestPointOnPlane - TestPoint;
   DistanceToPlane = sqrt((ToPlaneDeltas.X * ToPlaneDeltas.X)
                        + (ToPlaneDeltas.Y * ToPlaneDeltas.Y)
                        + (ToPlaneDeltas.Z * ToPlaneDeltas.Z));
   return DistanceToPlane;
  }
  
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 
// These Functions can be greatly optimised so that'll be a nice exercise for you! They DO WORK THOUGH..
Jacques Pretorius 2015..
 
Last edited by Vectrotek on Sat Dec 05, 2015 9:24 pm, edited 2 times in total.
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Re: 3D Vector Math

Post by Vectrotek »

Here is a screenshot of experiments in normal Math Notation before converting it to C++..
Image
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Re: 3D Vector Math

Post by Vectrotek »

This started with with me trying to find a way to do "Plane Based Fog" i.e. Fog effect based on the distance of a fragment from a given plane for spooky effects..
kormoran
Posts: 47
Joined: Mon Dec 28, 2015 4:50 pm
Location: Tolentino

Re: 3D Vector Math

Post by kormoran »

Thank you Vectrotek, that will come handy :D
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Re: 3D Vector Math

Post by Mel »

Awesome work! Maybe you can extend the functionality of the lines and planes with all those operations, or optimize the current implementations :)
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Post Reply