Is there a way to AND or OR two bvec's in GLSL? - glsl

Say you want to combine multiple conditions into one bvec . . .
// None of these compile
bvec2 b = greaterThan(u, v) && notEqual(u, vec2(0.0f));
bvec2 b = greaterThan(u, v) & notEqual(u, vec2(0.0f));
bvec2 b = greaterThan(u, v) * notEqual(u, vec2(0.0f));
bvec2 b = all(greaterThan(u, v), notEqual(u, vec2(0.0f)));
// Per-component works
bvec2 b = bvec2(u.x > v.x && u.x != 0.0f, u.y > v.y && u.y != 0.0f);
// Casting to uvec works, but is gross
bvec2 b = bvec2(uvec2(greaterThan(u, v)) & uvec2(notEqual(u, vec2(0.0f))));
I would expect an overload of the any/all builtins to work per-component, or an overload of the && operator, but neither seems to be the case. Am I missing something, or does glsl not have a way to combine bvec's directly?

Related

Intersection between line and triangle in 3D

I have a line and a triangle somewhere in 3D space. In other words, I have 3 points ([x,y,z] each) for the triangle, and two points (also [x,y,z]) for the line.
I need to figure out a way, hopefully using C++, to figure out if the line ever crosses the triangle. A line parallel to the triangle, and with more than one point in common, should be counted as "does not intersect".
I already made some code, but it doesn't work, and I always get false even when a visual representation clearly shows an intersection.
ofVec3f P1, P2;
P1 = ray.s;
P2 = ray.s + ray.t;
ofVec3f p1, p2, p3;
p1 = face.getVertex(0);
p2 = face.getVertex(1);
p3 = face.getVertex(2);
ofVec3f v1 = p1 - p2;
ofVec3f v2 = p3 - p2;
float a, b, c, d;
a = v1.y * v2.z - v1.z * v2.y;
b = -(v1.x * v2.z - v1.z * v2.x);
c = v1.x * v2.y - v1.y * v2.x;
d = -(a * p1.x + b * p1.y + c * p1.z);
ofVec3f O = P1;
ofVec3f V = P2 - P1;
float t;
t = -(a * O.x + b * O.y + c * O.z + d) / (a * V.x + b * V.y + c * V.z);
ofVec3f p = O + V * t;
float xmin = std::min(P1.x, P2.x);
float ymin = std::min(P1.y, P2.y);
float zmin = std::min(P1.z, P2.z);
float xmax = std::max(P1.x, P2.x);
float ymax = std::max(P1.y, P2.y);
float zmax = std::max(P1.z, P2.z);
if (inside(p, xmin, xmax, ymin, ymax, zmin, zmax)) {
*result = p.length();
return true;
}
return false;
And here is the definition of inside()
bool primitive3d::inside(ofVec3f p, float xmin, float xmax, float ymin, float ymax, float zmin, float zmax) const {
if (p.x >= xmin && p.x <= xmax && p.y >= ymin && p.y <= ymax && p.z >= zmin && p.z <= zmax)
return true;
return false;
}
1) If you just want to know whether the line intersects the triangle (without needing the actual intersection point):
Let p1,p2,p3 denote your triangle
Pick two points q1,q2 on the line very far away in both directions.
Let SignedVolume(a,b,c,d) denote the signed volume of the tetrahedron a,b,c,d.
If SignedVolume(q1,p1,p2,p3) and SignedVolume(q2,p1,p2,p3) have different signs AND
SignedVolume(q1,q2,p1,p2), SignedVolume(q1,q2,p2,p3) and SignedVolume(q1,q2,p3,p1) have the same sign, then there is an intersection.
SignedVolume(a,b,c,d) = (1.0/6.0)*dot(cross(b-a,c-a),d-a)
2) Now if you want the intersection, when the test in 1) passes
write the equation of the line in parametric form: p(t) = q1 + t*(q2-q1)
Write the equation of the plane: dot(p-p1,N) = 0 where
N = cross(p2-p1, p3-p1)
Inject p(t) into the equation of the plane: dot(q1 + t*(q2-q1) - p1, N) = 0
Expand: dot(q1-p1,N) + t dot(q2-q1,N) = 0
Deduce t = -dot(q1-p1,N)/dot(q2-q1,N)
The intersection point is q1 + t*(q2-q1)
3) A more efficient algorithm
We now study the algorithm in:
Möller and Trumbore, "Fast, Minimum Storage Ray-Triangle Intersection", Journal of Graphics Tools, vol. 2,‎ 1997, p. 21–28
(see also: https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm)
The algorithm is in the end simpler (less instructions than what we did in 1) and 2)), but sightly more complicated to understand. Let us derive it step by step.
Notation:
O = origin of the ray,
D = direction vector of the ray,
A,B,C = vertices of the triangle
An arbitrary point P on the ray can be written as P = O + tD
An arbitrary point P on the triangle can be written as P = A + uE1 + vE2 where E1 = B-A and E2 = C-A, u>=0, v>=0 and (u+v)<=1
Writing both expressions of P gives:
O + tD = A + uE1 + vE2
or:
uE1 + vE2 -tD = O-A
in matrix form:
[u]
[E1|E2|-D] [v] = O-A
[t]
(where [E1|E2|-D] is the 3x3 matrix with E1,E2,-D as its columns)
Using Cramer's formula for the solution of:
[a11 a12 a13][x1] [b1]
[a12 a22 a23][x2] = [b2]
[a31 a32 a33][x3] [b3]
gives:
|b1 a12 a13| |a11 a12 a13|
x1 = |b2 a22 a23| / |a21 a22 a23|
|b3 a32 a33| |a31 a32 a33|
|a11 b1 a13| |a11 a12 a13|
x2 = |a21 b2 a23| / |a21 a22 a23|
|a31 b3 a33| |a31 a32 a33|
|a11 a12 b1| |a11 a12 a13|
x3 = |a21 a22 b2| / |a21 a22 a23|
|a31 a32 b3| |a31 a32 a33|
Now we get:
u = (O-A,E2,-D) / (E1,E2,-D)
v = (E1,O-A,-D) / (E1,E2,-D)
t = (E1,E2,O-A) / (E1,E2,-D)
where (A,B,C) denotes the determinant of the 3x3 matrix with A,B,C as its column vectors.
Now we use the following identities:
(A,B,C) = dot(A,cross(B,C)) (develop the determinant w.r.t. first column)
(B,A,C) = -(A,B,C) (swapping two vectors changes the sign)
(B,C,A) = (A,B,C) (circular permutation does not change the sign)
Now we get:
u = -(E2,O-A,D) / (D,E1,E2)
v = (E1,O-A,D) / (D,E1,E2)
t = -(O-A,E1,E2) / (D,E1,E2)
Using:
N=cross(E1,E2);
AO = O-A;
DAO = cross(D,AO)
We obtain finally the following code (here in GLSL, easy to translate to other languages):
bool intersect_triangle(
in Ray R, in vec3 A, in vec3 B, in vec3 C, out float t,
out float u, out float v, out vec3 N
) {
vec3 E1 = B-A;
vec3 E2 = C-A;
N = cross(E1,E2);
float det = -dot(R.Dir, N);
float invdet = 1.0/det;
vec3 AO = R.Origin - A;
vec3 DAO = cross(AO, R.Dir);
u = dot(E2,DAO) * invdet;
v = -dot(E1,DAO) * invdet;
t = dot(AO,N) * invdet;
return (det >= 1e-6 && t >= 0.0 && u >= 0.0 && v >= 0.0 && (u+v) <= 1.0);
}
When the function returns true, the intersection point is given by R.Origin + t * R.Dir. The barycentric coordinates of the intersection in the triangle are u, v, 1-u-v (useful for Gouraud shading or texture mapping). The nice thing is that you get them for free !
Note that the code is branchless.
It is used by some of my shaders on ShaderToy
https://www.shadertoy.com/view/tl3XRN
https://www.shadertoy.com/view/3ltSzM
#BrunoLevi: your algorithm does not seem to work, see the following python implementation:
def intersect_line_triangle(q1,q2,p1,p2,p3):
def signed_tetra_volume(a,b,c,d):
return np.sign(np.dot(np.cross(b-a,c-a),d-a)/6.0)
s1 = signed_tetra_volume(q1,p1,p2,p3)
s2 = signed_tetra_volume(q2,p1,p2,p3)
if s1 != s2:
s3 = signed_tetra_volume(q1,q2,p1,p2)
s4 = signed_tetra_volume(q1,q2,p2,p3)
s5 = signed_tetra_volume(q1,q2,p3,p1)
if s3 == s4 and s4 == s5:
n = np.cross(p2-p1,p3-p1)
t = -np.dot(q1,n-p1) / np.dot(q1,q2-q1)
return q1 + t * (q2-q1)
return None
My test code is:
q0 = np.array([0.0,0.0,1.0])
q1 = np.array([0.0,0.0,-1.0])
p0 = np.array([-1.0,-1.0,0.0])
p1 = np.array([1.0,-1.0,0.0])
p2 = np.array([0.0,1.0,0.0])
print(intersect_line_triangle(q0,q1,p0,p1,p2))
gives:
[ 0. 0. -3.]
instead of the expected
[ 0. 0. 0.]
looking at the line
t = np.dot(q1,n-p1) / np.dot(q1,q2-q1)
Subtracting p1 from the normal doesn't make sense to me, you want to project from q1 onto the plane of the triangle, so you need to project along the normal, with a distance that is proportional to the ratio of the distance from q1 to the plane and q1-q2 along the normal, right?
The following code fixes this:
n = np.cross(p2-p1,p3-p1)
t = np.dot(p1-q1,n) / np.dot(q2-q1,n)
return q1 + t * (q2-q1)
To find the intersection between a line and a triangle in 3D, follow this approach:
Compute the plane supporting the triangle,
Intersect the line with the plane supporting the triangle:
If there is no intersection, then there is no intersection with the triangle.
If there is an intersection, verify that the intersection point indeed lies in the triangle:
Each edge of the triangle together with the normal of the plane supporting the triangle determines a half-space bounding the inside of the triangle (the corresponding bounding plane can be derived from the normal and the edge vertices),
Verify that the intersection point lies on the inside of all the edge half-spaces.
Here is some sample code with detailed computations that should work:
// Compute the plane supporting the triangle (p1, p2, p3)
// normal: n
// offset: d
//
// A point P lies on the supporting plane iff n.dot(P) + d = 0
//
ofVec3f v21 = p2 - p1;
ofVec3f v31 = p3 - p1;
ofVec3f n = v21.getCrossed(v31);
float d = -n.dot(p1);
// A point P belongs to the line from P1 to P2 iff
// P = P1 + t * (P2 - P1)
//
// Find the intersection point P(t) between the line and
// the plane supporting the triangle:
// n.dot(P) + d = 0
// = n.dot(P1 + t (P2 - P1)) + d
// = n.dot(P1) + t n.dot(P2 - P1) + d
//
// t = -(n.dot(P1) + d) / n.dot(P2 - P1)
//
ofVec3f P21 = P2 - P1;
float nDotP21 = n.dot(P21);
// Ignore line parallel to (or lying in) the plane
if (fabs(nDotP21) < Epsilon)
return false;
float t = -(n.dot(P1) + d) / nDotP21;
ofVec3f P = P1 + t * P21;
// Plane bounding the inside half-space of edge (p1, p2):
// normal: n21 = n x (p2 - p1)
// offset: d21 = -n21.dot(p1)
//
// A point P is in the inside half-space iff n21.dot(P) + d21 > 0
//
// Edge (p1, p2)
ofVec3f n21 = n.cross(v21);
float d21 = -n21.dot(p1);
if (n21.dot(P) + d21 <= 0)
return false;
// Edge (p2, p3)
ofVec3f v32 = p3 - p2;
ofVec3f n32 = n.cross(v32);
float d32 = -n32.dot(p2);
if (n32.dot(P) + d32 <= 0)
return false;
// Edge (p3, p1)
ofVec3f n13 = n.cross(-v31);
float d13 = -n13.dot(p3);
if (n13.dot(P) + d13 <= 0)
return false;
return true;
Some comments on the code posted with the question:
Predefined operations of ofVec3f (.dot() and .cross() for geometric products, etc...) should be preferred when available (more readable, avoids implementation mistakes, etc...),
The code initially follows the approach above but then only checks that the intersection point is in the 3D axis-aligned bounding box of the line segment [P1, P2]. This combined with possible other errorscould explain why the results are incorrect.
One can verify that the intersection point is in the 3D axis-aligned bounding box of the (whole) triangle. While this is not enough to guarantee intersection, it can however be used to cull points clearly not intersecting and avoid further complex computations.
I have a different way to do it which I found in my renderer to be far faster than the first way given by BrunoLevy. (I haven't implemented the second way)
Points A, B, C are vertexes of the triangle
O is the origin of the ray
D is the direction of the ray (doesn't need to be normalised, just closer to the origin than the triangle)
Check if the direction (D+O) is inside the tetrahedron A, B, C, O
bool SameSide(vec3 A, vec3 B, vec3 C, vec3 D, vec3 p)
{
vec3 normal = cross(B - A, C - A);
float dotD = dot(normal, D - A);
float dotP = dot(normal, p - A);
return signbit(dotD) == signbit(dotP);
}
bool LineIntersectTri(vec3 A, vec3 B, vec3 C, vec3 O, vec3 D)
{
return SameSide(A, B, C, O, O+D) &&
SameSide(B, C, O, A, O+D) &&
SameSide(C, O, A, B, O+D) &&
SameSide(O, A, B, C, O+D);
}
If D varies, and everything else stays the same (for example in a raycasting renderer) then normal and dotP don't need to be recalculated; This is why I found it so much faster
The code came from this answer https://stackoverflow.com/a/25180294/18244401

How to understand this RayTracer code [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
So this RT code creates a 3D image, with blur, through raw code. How is that actually done without any modelling tools?
I am currently working to understand how RT work and different ways to implement them, so this was kind of cool to see such a small amount of code producing a pretty impressive 3D image.
#include <stdlib.h> // card > aek.ppm
#include <stdio.h>
#include <math.h>
#include <fstream>
typedef int i;
typedef float f;
struct v {
f x, y, z;
v operator+(v r) {
return v(x + r.x, y + r.y, z + r.z);
}
v operator*(f r) {
return v(x * r, y * r, z * r);
}
f operator%(v r) {
return x * r.x + y * r.y + z * r.z;
}
v() {}
v operator^(v r) {
return v(y * r.z - z * r.y, z * r.x - x * r.z, x * r.y - y * r.x);
}
v(f a, f b, f c) {x = a; y = b; z = c;}
v operator!() {
return*this * (1 / sqrt(*this % *this));
}
};
i G[] = {247570, 280596, 280600, 249748, 18578, 18577, 231184, 16, 16};
f R()
{
return(f)rand() / RAND_MAX;
}
i T(v o, v d, f&t, v&n)
{
t = 1e9; i m = 0;
f p = -o.z / d.z;
if(.01 < p)t = p, n = v(0, 0, 1), m = 1;
for(i k = 19; k--;)
for(i j = 9; j--;)if(G[j] & 1 << k) {
v p = o + v(-k, 0, -j - 4);
f b = p % d, c = p % p - 1, q = b * b - c;
if(q > 0) {
f s = -b - sqrt(q);
if(s < t && s > .01)
t = s, n = !(p + d * t), m = 2;
}
}
return m;
} v S(v o, v d)
{
f t;
v n;
i m = T(o, d, t, n);
if(!m)return v(.7, .6, 1) * pow(1 - d.z, 4);
v h = o + d * t, l = !(v(9 + R(), 9 + R(), 16) + h * -1), r = d + n * (n % d * -2);
f b = l % n; if(b < 0 || T(h, l, t, n))b = 0;
f p = pow(l % r * (b > 0), 99);
if(m & 1) {
h = h * .2;
return((i)(ceil(h.x) + ceil(h.y)) & 1 ? v(3, 1, 1) : v(3, 3, 3)) * (b * .2 + .1);
} return v(p, p, p) + S(h, r) * .5;
} i
main()
{
FILE * pFile;
pFile = fopen("d:\\myfile3.ppm", "w");
fprintf(pFile,"P6 512 512 255 ");
v g = !v(-6, -16, 0), a = !(v(0, 0, 1) ^ g) * .002, b = !(g ^ a) * .002, c = (a + b) * -256 + g;
for(i y = 512; y--;)
for(i x = 512; x--;) {
v p(13, 13, 13);
for(i r = 64; r--;) {
v t = a * (R() - .5) * 99 + b * (R() - .5) * 99;
p = S(v(17, 16, 8) + t, !(t * -1 + (a * (R() + x) + b * (y + R()) + c) * 16)) * 3.5 + p;
}
fprintf(pFile, "%c%c%c", (i)p.x, (i)p.y, (i)p.z);
}
}
My dear friend that's Paul Heckbert code's right?
You could at least mention it.
For people thinking this code is unreadable, here is why:
This guy made a code that could fit on a credit card, that was the goal :)
His website: http://www.cs.cmu.edu/~ph/
Edit: Knowing the source of this code may help you understand it. Even if it'snot your main motivation...
If you are really interested in raytracing, start with other sources.
Take a look at this website http://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-1-writing-a-simple-raytracer/source-code/ (Plus it talk about your code)
This code is not really special. It is basically a ray tracer that was obfuscated into a form that makes it fit on a business card (see https://www.cs.cmu.edu/~ph/).
How is that actually done without any modelling tools?
You don't need tools to render anything. You could even create a complete game of WoW (or what's hip at the moment) without any modelling tool. Modelling tools just make your live easier w.r.t. certain kinds of scenes (read: very complex ones).
You could always hardcode these data, or hack them manually into some external file.
You could also use parametric generators; Perlin Noise is one of the more popular examples thereof.
In a ray tracer, it happens that it is very simple to start out without modelling tools, as it is very simple to calculate geometric intersections between the rendering primitive "ray" and any finite geometric primitive. E.g., intersection a non-approximated, "perfect" sphere is just a few lines of code.
tl;dr: Data is just data. How you create and crunch it is completely up to you.

About avoiding IFs in GLSL

Somebody knows how to avoid using these IF statements?
float v = 9999.0;
if (a.x > 0.0 && a.x < v) { v = a.x; }
if (a.y > 0.0 && a.y < v) { v = a.y; }
if (a.z > 0.0 && a.z < v) { v = a.z; }
Initially I used the following lines but then I realized I only wanted the minimum iff it does not equal zero.
float v = min(a.x, min(a.y, a.z));
I also assume that a.xyz are always greater or equal than zero, being at least one of the components greater than zero.
You could use a construct like
vec3 b=a+10000.0*step(0.0, -a);
float v=min(b.x, min(b.y, b.z));
which also assumes (as your code does) that your minimal element is < 10000. Note that the step(0,0, -a) was chosen in favour of (1.0-step(0.0, a)) since step is defined to return 0.0 only if the value is below the edge (0.0 in this case), not if it is equal. In pratice it might still be a good idea to use a small epsilon value.

Optimize c++ bitmap processing algorithm [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 9 years ago.
Improve this question
I have written the next algorithm (for Android/NDK) to apply levels to a bitmap. The problem is that is really very slow, on a fast device such as the SGSIII can take up to 4 seconds for a 8MP image. And on devices with ARMv6 takes ages (over 10 seconds). Is there any way to optimize it?
void applyLevels(unsigned int *rgb, const unsigned int width, const unsigned int height, const float exposure, const float brightness, const float contrast, const float saturation)
{
float R, G, B;
unsigned int pixelIndex = 0;
float exposureFactor = powf(2.0f, exposure);
float brightnessFactor = brightness / 10.0f;
float contrastFactor = contrast > 0.0f ? contrast : 0.0f;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
const int pixelValue = buffer[pixelIndex];
R = ((pixelValue & 0xff0000) >> 16) / 255.0f;
G = ((pixelValue & 0xff00) >> 8) / 255.0f;
B = (pixelValue & 0xff) / 255.0f;
// Clamp values
R = R > 1.0f ? 1.0f : R < 0.0f ? 0.0f : R;
G = G > 1.0f ? 1.0f : G < 0.0f ? 0.0f : G;
B = B > 1.0f ? 1.0f : B < 0.0f ? 0.0f : B;
// Exposure
R *= exposureFactor;
G *= exposureFactor;
B *= exposureFactor;
// Contrast
R = (((R - 0.5f) * contrastFactor) + 0.5f);
G = (((G - 0.5f) * contrastFactor) + 0.5f);
B = (((B - 0.5f) * contrastFactor) + 0.5f);
// Saturation
float gray = (R * 0.3f) + (G * 0.59f) + (B * 0.11f);
R = gray * (1.0f - saturation) + R * saturation;
G = gray * (1.0f - saturation) + G * saturation;
B = gray * (1.0f - saturation) + B * saturation;
// Brightness
R += brightnessFactor;
G += brightnessFactor;
B += brightnessFactor;
// Clamp values
R = R > 1.0f ? 1.0f : R < 0.0f ? 0.0f : R;
G = G > 1.0f ? 1.0f : G < 0.0f ? 0.0f : G;
B = B > 1.0f ? 1.0f : B < 0.0f ? 0.0f : B;
// Store new pixel value
R *= 255.0f;
G *= 255.0f;
B *= 255.0f;
buffer[pixelIndex] = ((int)R << 16) | ((int)G << 8) | (int)B;
pixelIndex++;
}
}
}
Most of your computations can be trivially tabled... the whole processing can become
for (int i=0; i<n; i++) {
int px = buffer[i];
int r = tab1[(px >> 16) & 255];
int g = tab1[(px >> 8) & 255];
int b = tab1[px & 255];
gray = (kr*r + kg*g + kb*b) >> 16;
grayval = tsat1[gray];
r = brtab[tsat2[r] + grayval];
g = brtab[tsat2[g] + grayval];
b = brtab[tsat2[b] + grayval];
buffer[i] = (r << 16) | (g << 16) | b;
}
where
tab1 is a table of 256 bytes tabling the result of exposure and constrast processing
tsat1 and tsat2 are 256 bytes tables for saturation processing
brtab is a 512-bytes table for brightness processing
Note that without saturation processing you would need just a lookup per component in a 256 bytes table.
A huge speed problem can be because you are using floating-point computations where there is no dedicated hardware for it. Software implementation of floating point is really slow.
You're reducing your fast int based RGB values to slower floats and then using a lot of floating point multiplication for your adjustments. Better to multiply your adjustments (brightness, saturation etc...) by 256 and store them as ints, and don't use any floating point in your inner loop.
(1.0f - saturation) is the same everywhere, therefore you can just assign it to a variable.
Instead of >> 16) / 255.0f and >> 8) / 255.0f you can convert them to single multiplications. Or, you can divide them by 256 instead of 255 with >> 10 and >> 8 respectively:
R = ((pixelValue & 0xff0000) >> 10);
G = ((pixelValue & 0xff00) >> 2);
Several point to optimize that code
Favor integer computation, that mean that instead of transforming your RGB data from [0, 255] to [0, 1] do the inverse and transform all your contrast, brightness etc to be between 0 and 255
clipping operation can often be simplify with a clipping table to remove if-else statement .
R = clip[R'];
I notice a strange clipping section
// Clamp values
R = R > 255.0f ? 255.0f : R < 0.0f ? 0.0f : R;
G = G > 255.0f ? 255.0f : G < 0.0f ? 0.0f : G;
B = B > 255.0f ? 255.0f : B < 0.0f ? 0.0f : B;
here it look like your are still in [0, 1] range so it useless !
at the end review your formula because it seems that exposure and brightness can be fact prize to remove some op.
Finally that code is a good candidate for SIMD and MIMD, so look if MMX/SSE or OpenMP can solve your performance issue.

Given two points and two vectors, find point of intersection [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do you detect where two line segments intersect?
Given two points a and b plus two vectors v and u I want to find a third point c, which is the point of intersection in the following manner:
vector2 intersection(vector2 a, vector2 v, vector2 b, vector2 u)
{
float r, s;
a + r * v = b + s * u;
r * v - s * u = b - a
r * v.x - s * u.x = b.x - a.x
r * v.y - s * u.y = b.y - a.y
}
Is there any other way than using gaussian elimination to solve this system? Or is this the best (or at least an acceptable) way to handle this?
EDIT:
Definition of vector2
typedef union vector2
{
float v[2];
struct { float x, y; };
} vector2;
a and b are also of type vector2, because the only difference between a point and a vector is in the the way it is transformed by an affine transformation.
Looks like an assignment problem to me. Here is the logic that will help you write the code.
Let us call the first Ray as R0.
Locus of a point on R0 is defined as P:
P = P0 + alpha x V0
For the second ray R1:
P = P1 + beta x V1
Since they should intersect:
P0 + alpha x V0 = P1 + beta x V1
alpha and beta are unknowns and we have two equations in x any y.
Solve for the unknowns and get back the point of intersection.
i.e.,
P0.x + alpha * V0.x = P1.x + beta * V1.x
P0.y + alpha * V0.y = P1.y + beta * V1.y
solve for alpha and beta.
If there is a real positive solution for both alpha and beta, rays intersect.
If there is a real but at least one negative solution for both alpha and beta, extended rays intersect.
It's simple math.
But, first, check that you have intersection. If both vector are parallel you will fail to solve that:
// Edit this line to protect from division by 0
if (Vy == 0 && Uy == 0) || ((Vy != 0 && Uy != 0 && (Vx/Vy == Ux/Uy)) // => Fail.
Then (I won't show the calculation because they are long but the result is):
R = (AxUy - AyUx + ByUx - BxUy) / (VyUx - VxUy)
S = (Ax - Bx + RVx) / Ux
Hope that helped you.