Skip to content

Commit f448150

Browse files
committed
vecmat: Fix vm_test_parallel()
Fixes a subtle problem with vm_test_parallel() wherein a relative error was accidentally converted into an absolute error. Instead of comparing the result of the cross product to the zero vector, the two calculated components of the cross product are compared against each other. This permits vectors whose cross product is a large number but whose cross product partials are within relative error of each other to be treated as parallel. For example, the following two vectors may now be considered as parallel whereas before they were not: v1 = (1000004.0, 1.0, 1.0) v2 = (1000000.0, 1.0, 1.0) The relative difference between them is sufficiently small according to vm_vec_equal() for them to be considered equal, but their cross product would have elements whose magnitudes would be near 4.0 which would otherwise indicate that they are not parallel. By comparing the partials instead, a higher degree of consistency is maintained. Signed-off-by: Peter Mitsis <peter.mitsis@gmail.com>
1 parent eb1389d commit f448150

File tree

1 file changed

+18
-6
lines changed

1 file changed

+18
-6
lines changed

code/math/vecmat.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -617,14 +617,26 @@ vec3d *vm_vec_cross(vec3d *dest, const vec3d *src0, const vec3d *src1)
617617

618618
int vm_test_parallel(const vec3d *src0, const vec3d *src1)
619619
{
620-
// This version assumes SIMD/SSE optimizations, which would essentially be only 2 operations
621-
// If SIMD/SSE is not available, you could check if the vectors are a scalar of each other. i.g. if((x1/x2) == (y1/y2) == (z1/z2)
622-
// TODO: make a compile-time check for SIMD/SSE optimizations, If we have them, then use the vecmath method, if not, then use the logical method.
620+
vec3d partial1;
621+
vec3d partial2;
623622

624-
vec3d test;
623+
/*
624+
* To test if two vectors are parallel, calculate their cross product.
625+
* If the result is zero, then the vectors are parallel. It is better
626+
* to compare the two cross product "partials" (for lack of a better
627+
* word) against each other instead of the final cross product against
628+
* zero.
629+
*/
630+
631+
partial1.xyz.x = (src0->xyz.y * src1->xyz.z);
632+
partial1.xyz.y = (src0->xyz.z * src1->xyz.x);
633+
partial1.xyz.z = (src0->xyz.x * src1->xyz.y);
634+
635+
partial2.xyz.x = (src0->xyz.z * src1->xyz.y);
636+
partial2.xyz.y = (src0->xyz.x * src1->xyz.z);
637+
partial2.xyz.z = (src0->xyz.y * src1->xyz.x);
625638

626-
vm_vec_cross(&test, src0, src1);
627-
return vm_vec_equal(test, vmd_zero_vector);
639+
return vm_vec_equal(partial1, partial2);
628640
}
629641

630642
//computes non-normalized surface normal from three points.

0 commit comments

Comments
 (0)