This is the code in Unreal C++
float GetT( float t, float alpha, const FVector& p0, const FVector& p1 )
{
auto d = p1 - p0;
float a = d | d; // Dot product
float b = FMath::Pow( a, alpha*.5f );
return (b + t);
}
Does this line means "float a = d | d; // Dot product" dot product of FVector d with itself
https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline
Look for documentation of FVector. Search "operators". Look for |. Find:
float
operator|
(
const FVector& V
)
Calculate the dot product between this and another vector.
Yes. d | d calculates the dot product of the vector with itself.
Related
I am using a piece of code I have found on the internet (here) to compute the distance between a point and a segment. Here is the code:
float
dist_Point_to_Segment( Point P, Segment S)
{
Vector v = S.P1 - S.P0;
Vector w = P - S.P0;
double c1 = dot(w,v);
if ( c1 <= 0 )
return d(P, S.P0);
double c2 = dot(v,v);
if ( c2 <= c1 )
return d(P, S.P1);
double b = c1 / c2;
Point Pb = S.P0 + b * v;
return d(P, Pb);
}
When computing double b = c1 / c2; c2 is dot(v, v) (so, the norm of v squared). Shouldn't we use norm(v)? Isn't that the proper definition of the projection of a vector on another one?
Thanks.
Actually the definition is with norm(v) squared. So dot(v, v) is correct.
Here's a nice and short explanation:
http://math.oregonstate.edu/home/programs/undergrad/CalculusQuestStudyGuides/vcalc/dotprod/dotprod.html
If v is normalized, the length of the projection is w.v, and the projected vector is (w.v) v.
As v appears twice, the formula for an unnormalized vector is
(w.(v/|v|)) v/|v| = (w.v/|v|²) v
This spares a square root.
Ok, so I'm making this fun little game in c++, unfortunately I'm stuck on making a "radar", I'm stuck on this part
(EDIT, i already have A & B, the only thing i do not have is C & D)
So what i need to do is calculate the two points (2d vector) of C & D, they need to be in the placement like in the lil pic i made shown above (sorry, i know it's bad).
B will rotate around A so i need to calculate the position of C & D based on the how much B has rotated around A. I am going to create a triangle (e.g. draw a line from C to D, D to B & B to A)
A could be thought of as the center of the bottom line of the triangle, this is like the base of everything, everything rotates around A, and the position of C & D need to be calculated according to how much B has rotated around A.
What would be like the best way to make a lil function for this calculation?
e.g.
inline float returnDPoint(float A, float B)
{
float dPoint;
//calculate point of D based off A & B
return dPoint;
}
inline float returnCPoint(float A, float B)
{
float cPoint;
//calculate point of C based off A & B
return cPoint;
}
Hopefully i have worded my question well enough, thanks for the read!
Here's a computation to get C:
auto angle = atan2(b.y-a.y,b.x-a.x) + pi/2.0;
auto radius = sqrt((b.y-a.y)*(b.y-a.y)+(b.x-a.x)*(b.x-a.x));
Point C {a.x + radius * cos(angle), a.y +radius * sin(angle)};
Since you are looking for rotations by 90°, you don't need to use expensive functions such as atan2, sqrt, etc. A simple alternative would be:
diffx = bx - ax;
diffy = by - ay;
cx = ax - diffy = ax - by + ay;
cy = ay + diffx = ay + bx - ax;
dx = ax + diffy = ax + by - ay;
dy = ay - diffx = ay - bx + ax;
I need to implement a tool to detect intersction between a 3D box and 3D Sphere in c++. Write now I find a way how to detect the intersection using that code.
inline float squared(float v) { return v * v; }
bool doesCubeIntersectSphere(vec3 C1, vec3 C2, vec3 S, float R)
{
float dist_squared = R * R;
/* assume C1 and C2 are element-wise sorted, if not, do that now */
if (S.X < C1.X) dist_squared -= squared(S.X - C1.X);
else if (S.X > C2.X) dist_squared -= squared(S.X - C2.X);
if (S.Y < C1.Y) dist_squared -= squared(S.Y - C1.Y);
else if (S.Y > C2.Y) dist_squared -= squared(S.Y - C2.Y);
if (S.Z < C1.Z) dist_squared -= squared(S.Z - C1.Z);
else if (S.Z > C2.Z) dist_squared -= squared(S.Z - C2.Z);
return dist_squared > 0;
}
What I need is an example of C++ code to create a 3D sphere using origin vector and a radius and
I need to create a 3D sphere using origin vector and a radius and a 3D box through its maximum and minimum corner vector.
I may be mistaken, but (assuming Axis-Aligned boxes):
The length of a vector from origin to corner C1 or C2 should be the radius r, right?
Explanation for my deriviation below: An Axis-Aligned-box with equal distance from center to all corners is a perfect cube. Translating such a cube to the origin puts two of the corners exactly at the line from the origin through the point {x=1,y=1,z=1}. Thus those two corners will have coordinates {d,d,d} and {-d, -d, -d}, where d is "distance" of the corner along the axises X,Y,Z. The distance to say the first corner is squaring and adding all components of the vector, and taking the square root, e.g:
|C1| = |{d,d,d}| = sqrt(d * d + d * d + d * d) = sqrt(3 * d * d)
Therefore solve:
r = sqrt(3 *d * d)
<=>
r * r = 3 * d * d
<=>
d = sqrt(r*r/3)
<=>
d = r/sqrt(3)
This needs to be translated back to the center of the Sphere, thus:
C1 = { S.x+d, S.y+d, S.z+d}
C2 = { S.x-d, S.y-d, S.z-d}
Your explanation is a little vague, so I made some assumptions. Perhaps I'm dead wrong. Anyway here is some non-tested code showing what I mean:
void makeCube(vec3 S, float R, vec3* C1, vec3* C2)
{
static const float sqrt_one_third = sqrtf(1.0f/3.0f);
float d = R * sqrt_one_third;
C1->X = S.X + d;
C1->Y = S.Y + d;
C1->Z = S.Z + d;
C2->X = S.X - d;
C2->Y = S.Y - d;
C2->Z = S.Z - d;
}
How do I calculate the intersection between a ray and a plane?
Code
This produces the wrong results.
float denom = normal.dot(ray.direction);
if (denom > 0)
{
float t = -((center - ray.origin).dot(normal)) / denom;
if (t >= 0)
{
rec.tHit = t;
rec.anyHit = true;
computeSurfaceHitFields(ray, rec);
return true;
}
}
Parameters
ray represents the ray object.
ray.direction is the direction vector.
ray.origin is the origin vector.
rec represents the result object.
rec.tHit is the value of the hit.
rec.anyHit is a boolean.
My function has access to the plane:
center and normal defines the plane
As wonce commented, you want to also allow the denominator to be negative, otherwise you will miss intersections with the front face of your plane. However, you still want a test to avoid a division by zero, which would indicate the ray being parallel to the plane. You also have a superfluous negation in your computation of t. Overall, it should look like this:
float denom = normal.dot(ray.direction);
if (abs(denom) > 0.0001f) // your favorite epsilon
{
float t = (center - ray.origin).dot(normal) / denom;
if (t >= 0) return true; // you might want to allow an epsilon here too
}
return false;
First consider the math of the ray-plane intersection:
In general one intersects the parametric form of the ray, with the implicit form of the geometry.
So given a ray of the form x = a * t + a0, y = b * t + b0, z = c * t + c0;
and a plane of the form: A x * B y * C z + D = 0;
now substitute the x, y and z ray equations into the plane equation and you will get a polynomial in t. you then solve that polynomial for the real values of t. With those values of t you can back substitute into the ray equation to get the real values of x, y and z.
Here it is in Maxima:
Note that the answer looks like the quotient of two dot products!
The normal to a plane is the first three coefficients of the plane equation A, B, and C.
You still need D to uniquely determine the plane.
Then you code that up in the language of your choice like so:
Point3D intersectRayPlane(Ray ray, Plane plane)
{
Point3D point3D;
// Do the dot products and find t > epsilon that provides intersection.
return (point3D);
}
Math
Define:
Let the ray be given parametrically by q = p + t*v for initial point p and direction vector v for t >= 0.
Let the plane be the set of points r satisfying the equation dot(n, r) + d = 0 for normal vector n = (a, b, c) and constant d. Fully expanded, the plane equation may also be written in the familiar form ax + by + cz + d = 0.
The ray-plane intersection occurs when q satisfies the plane equation. Substituting, we have:
d = -dot(n, q)
= -dot(n, p + t * v)
= -dot(n, p) + t * dot(n, v)
Rearranging:
t = -(dot(n, p) + d) / dot(n, v)
This value of t can be used to determine the intersection by plugging it back into p + t*v.
Example implementation
std::optional<vec3> intersectRayWithPlane(
vec3 p, vec3 v, // ray
vec3 n, float d // plane
) {
float denom = dot(n, v);
// Prevent divide by zero:
if (abs(denom) <= 1e-4f)
return std::nullopt;
// If you want to ensure the ray reflects off only
// the "top" half of the plane, use this instead:
//
// if (-denom <= 1e-4f)
// return std::nullopt;
float t = -(dot(n, p) + d) / dot(n, v);
// Use pointy end of the ray.
// It is technically correct to compare t < 0,
// but that may be undesirable in a raytracer.
if (t <= 1e-4)
return std::nullopt;
return p + t * v;
}
implementation of vwvan's answer
Vector3 Intersect(Vector3 planeP, Vector3 planeN, Vector3 rayP, Vector3 rayD)
{
var d = Vector3.Dot(planeP, -planeN);
var t = -(d + Vector3.Dot(rayP, planeN)) / Vector3.Dot(rayD, planeN);
return rayP + t * rayD;
}
Consider the following problem:
My question is the following: how to optimize the following independent functions:
// Computation of the coordinates of P
inline std::array<double, 3> P(const std::array<double, 3>& A,
const std::array<double, 3>& B,
const std::array<double, 3>& M)
{
// The most inefficient version in the world (to be verified)
std::array<double, 3> AB = {B[0]-A[0], B[1]-A[1], B[2]-A[2]};
std::array<double, 3> AM = {M[0]-A[0], M[1]-A[1], M[2]-A[2]};
double norm = std::sqrt(AB[0]*AB[0]+AB[1]*AB[1]+AB[2]*AB[2]);
double dot = AB[0]*AM[0]+AB[1]*AM[1]+AB[2]*AM[2];
double d1 = dot/norm;
std::array<double, 3> AP = {AB[0]/d1, AB[1]/d1, AB[2]/d1};
std::array<double, 3> P = {AP[0]-A[0], AP[1]-A[1], AP[2]-A[2]};
return P;
}
// Computation of the distance d0
inline double d0(const std::array<double, 3>& A,
const std::array<double, 3>& B,
const std::array<double, 3>& M)
{
// The most inefficient version in the world (to be verified)
std::array<double, 3> AB = {B[0]-A[0], B[1]-A[1], B[2]-A[2]};
std::array<double, 3> AM = {M[0]-A[0], M[1]-A[1], M[2]-A[2]};
double norm = std::sqrt(AB[0]*AB[0]+AB[1]*AB[1]+AB[2]*AB[2]);
double dot = AB[0]*AM[0]+AB[1]*AM[1]+AB[2]*AM[2];
double d1 = dot/norm;
std::array<double, 3> AP = {AB[0]/d1, AB[1]/d1, AB[2]/d1};
std::array<double, 3> P = {AP[0]-A[0], AP[1]-A[1], AP[2]-A[2]};
std::array<double, 3> MP = {P[0]-M[0], P[1]-M[1], P[2]-M[2]};
double d0 = std::sqrt(MP[0]*MP[0]+MP[1]*MP[1]+MP[2]*MP[2]);
return d0;
}
// Computation of the distance d1
inline double d1(const std::array<double, 3>& A,
const std::array<double, 3>& B,
const std::array<double, 3>& M)
{
// The most inefficient version in the world (to be verified)
std::array<double, 3> AB = {B[0]-A[0], B[1]-A[1], B[2]-A[2]};
std::array<double, 3> AM = {M[0]-A[0], M[1]-A[1], M[2]-A[2]};
double norm = std::sqrt(AB[0]*AB[0]+AB[1]*AB[1]+AB[2]*AB[2]);
double dot = AB[0]*AM[0]+AB[1]*AM[1]+AB[2]*AM[2];
double d1 = dot/norm;
}
// Computation of the distance d2
inline double d2(const std::array<double, 3>& A,
const std::array<double, 3>& B,
const std::array<double, 3>& M)
{
// The most inefficient version in the world (to be verified)
std::array<double, 3> AB = {B[0]-A[0], B[1]-A[1], B[2]-A[2]};
std::array<double, 3> AM = {M[0]-A[0], M[1]-A[1], M[2]-A[2]};
double norm = std::sqrt(AB[0]*AB[0]+AB[1]*AB[1]+AB[2]*AB[2]);
double dot = AB[0]*AM[0]+AB[1]*AM[1]+AB[2]*AM[2];
double d1 = dot/norm;
double d2 = norm-d1;
return d2;
}
So that each function will be as much optimized as possible ? (I will execute these functions billion times).
From algorithm point of view, you can calculate projection of vector to another vector not using SQRT call
the pseudocode from here
http://www.euclideanspace.com/maths/geometry/elements/line/projections/
// projection of vector v1 onto v2
inline vector3 projection( const vector3& v1, const vector3& v2 ) {
float v2_ls = v2.len_squared();
return v2 * ( dot( v2, v1 )/v2_ls );
}
where dot() is a dot product of two vectors and len_squared is the dot product of vector with self.
NOTE: Try to pre calculate inverse of v2_ls before main loop, if possible.
It is probably better to compute all requested quantities in a single go.
Let P = A + t . AB the vector equation giving the position of P. Express that MP and AB are orthogonal: MP . AB = 0 = (MA + t . AB) . AB, which yields t= - (MA . AB) / AB^2, and P.
t is the ratio AP / AB, hence d1 = t . |AB|. Similarly, d2 = (1 - t) . |AB|. d0 is obtained from Pythagoras, d0^2 = MA^2 - d1^2, or by direct computation of |MP|.
Accounting: compute MA (3 add), AB (3 add), AB^2 (2 add, 3 mul), MA.AB (2 add, 3 mul), t (1 div), P (3 add, 3 mul), |AB| (1 sqrt), d1 (1 mul), d2 (1 add, 1 mul), MA^2 (2 add, 3 mul), d0 (1 add, 1 mul, 1 sqrt).
Total 17 add, 15 mul, 1 div, 2 sqrt.
If you want portable code, so no processor specific features are used, I'd suggest the following:-
1) As I mentioned in my comment above, create a 3D vector class, it will just make it a lot easier to write the code (optimise development time)
2) Create an intersection class that uses lazy evaluation to get P, d0 and d1, like this:-
class Intersection
{
public:
Intersection (A, B, M) { store A, B, M; constants_calculated = false }
Point GetP () { CalculateConstants; Return P; }
double GetD0 () { CalculateConstants; Return D0; }
double GetD1 () { CalculateConstants; Return D1; }
private:
CalculateConstants ()
{
if (!constants_calculate)
{
calculate and store common expressions required for P, d0 and d1
constants_calculate = true
}
}
3) Don't call it a billion times. Not doing something is infinitely quicker. Why does it need to be called so often? Is there a way to do the same thing with fewer calls to find P, d0 and d1?
If you can use processor specific features, then you could look into doing things like using SIMD, but that may require dropping the precision from double to float.
The following is a C++implementation of point-to-line projection calculation
#include <iostream>
#include <cmath>
using namespace std;
int main() {
// the point
double x0 = 1.0, y0 = 1.0;
// the line equation
double A = 1.0, B = 1.0, C = 0.0;
// calc point to line distance
double dist = fabs(A * x0 + B * y0 + C) / sqrt(A * A + B * B);
// calc project point coord
double x1 = x0 - dist * A / sqrt(A * A + B * B);
double y1 = y0 - dist * B / sqrt(A * A + B * B);
// result
cout << "project point:(" << x1 << ", " << y1 << ")" << endl;
return 0;
}