<% axis_count = ENV["axis_count"].to_i real_numeric_types = { "float" => "float", "double" => "double", "fixed16_16" => "fixed16_16", "int" => "int", "uint" => "unsigned int" } scalar_type = real_numeric_types[ENV["numeric_type"]] axis_names = ["x", "y", "z", "w"] const_zero = { "float" => "0.0f", "double" => "0.0", "fixed16_16" => "0x0", "int" => "0", "unsigned int" => "0" } const_one = { "float" => "1.0f", "double" => "1.0", "fixed16_16" => "0x10000", "int" => "1", "unsigned int" => "1" } const_two = { "float" => "2.0f", "double" => "2.0", "fixed16_16" => "0x20000", "int" => "2", "unsigned int" => "2" } small_values = { "float" => "0.00001f", "double" => "0.0000001", "fixed16_16" => "0x00010" } scalar_type_suffixes = { "float" => "f", "double" => "d", "fixed16_16" => "x", "int" => "i", "unsigned int" => "u" } sqrt_functions = { "float" => "sqrtf", "double" => "sqrt", "fixed16_16" => "xsqrt" } sin_functions = { "float" => "sinf", "double" => "sin", "fixed16_16" => "xsin" } cos_functions = { "float" => "cosf", "double" => "cos", "fixed16_16" => "xcos" } abs_functions = { "float" => "fabsf", "double" => "fabs", "fixed16_16" => "xabs" } vector_type = "Vector#{axis_count}#{scalar_type_suffixes[scalar_type]}" vector_type_upper = "VECTOR#{axis_count}#{scalar_type_suffixes[scalar_type]}" vector3_type = "Vector3#{scalar_type_suffixes[scalar_type]}" c0 = const_zero[scalar_type] c1 = const_one[scalar_type] c2 = const_two[scalar_type] if scalar_type == "fixed16_16" def multiply(lhs, rhs) return "xmul(#{lhs}, #{rhs})" end def divide(lhs, rhs) return "xdiv(#{lhs}, #{rhs})" end else def multiply(lhs, rhs) return "#{lhs} * #{rhs}" end def divide(lhs, rhs) return "#{lhs} / #{rhs}" end end -%> /* Copyright (c) 2015 Alex Diener This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Alex Diener alex@ludobloom.com */ #ifndef __<%=vector_type%>_H__ #define __<%=vector_type%>_H__ #ifdef __cplusplus extern "C" { #endif #include #include <% if scalar_type != "int" && scalar_type != "unsigned int" -%> #include <% if scalar_type == "fixed16_16" -%> #include "gamemath/FixedPoint.h" <% end -%> <% if axis_count != 3 -%> #include "gamemath/Vector3<%=scalar_type_suffixes[scalar_type]%>.h" <% end -%> <% end -%> typedef struct <%=vector_type%> <%=vector_type%>; struct <%=vector_type%> { <% 0.upto(axis_count - 1) do |axis| -%> <%=scalar_type%> <%= axis_names[axis] %>; <% end -%> }; #define <%= vector_type_upper %>_ZERO ((<%=vector_type%>) {<%= c0 %><% (axis_count - 1).times do %>, <%= c0 %><% end %>}) <% if scalar_type != "unsigned int" -%> #define <%= vector_type_upper %>_LEFT ((<%=vector_type%>) {-<%= c1 %>, <%= c0 %><% (axis_count - 2).times do %>, <%= c0 %><% end %>}) #define <%= vector_type_upper %>_RIGHT ((<%=vector_type%>) { <%= c1 %>, <%= c0 %><% (axis_count - 2).times do %>, <%= c0 %><% end %>}) #define <%= vector_type_upper %>_DOWN ((<%=vector_type%>) { <%= c0 %>, -<%= c1 %><% (axis_count - 2).times do %>, <%= c0 %><% end %>}) #define <%= vector_type_upper %>_UP ((<%=vector_type%>) { <%= c0 %>, <%= c1 %><% (axis_count - 2).times do %>, <%= c0 %><% end %>}) <% if axis_count >= 3 -%> #define <%= vector_type_upper %>_BACK ((<%=vector_type%>) { <%= c0 %>, <%= c0 %>, -<%= c1 %><% (axis_count - 3).times do %>, <%= c0 %><% end %>}) #define <%= vector_type_upper %>_FRONT ((<%=vector_type%>) { <%= c0 %>, <%= c0 %>, <%= c1 %><% (axis_count - 3).times do %>, <%= c0 %><% end %>}) <% end -%> <% if axis_count >= 4 -%> #define <%= vector_type_upper %>_KATA ((<%=vector_type%>) { <%= c0 %>, <%= c0 %>, <%= c0 %>, -<%= c1 %>}) #define <%= vector_type_upper %>_ANA ((<%=vector_type%>) { <%= c0 %>, <%= c0 %>, <%= c0 %>, <%= c1 %>}) <% end -%> <% end -%> #define <%=vector_type_upper%>(x<% 1.upto(axis_count - 1) do |axis| %>, <%= axis_names[axis] %><% end %>) ((<%=vector_type%>) {x<% 1.upto(axis_count - 1) do |axis| %>, <%= axis_names[axis] %><% end %>}) #define V<%=axis_count%><%=scalar_type_suffixes[scalar_type]%>(x<% 1.upto(axis_count - 1) do |axis| %>, <%= axis_names[axis] %><% end %>) ((<%=vector_type%>) {x<% 1.upto(axis_count - 1) do |axis| %>, <%= axis_names[axis] %><% end %>}) <% if axis_count > 2 -%> <% 2.upto(axis_count - 1) do |axis| -%> #define <%=vector_type_upper%>_EXTEND<%=axis%>(vector<%=axis%><% axis.upto(axis_count - 1) do |axis2| %>, <%= axis_names[axis2] %><% end %>) ((<%=vector_type%>) {vector<%=axis%>.x<% 1.upto(axis - 1) do |axis3| %>, vector<%=axis%>.<%=axis_names[axis3]%><% end %><% axis.upto(axis_count - 1) do |axis2| %>, <%= axis_names[axis2] %><% end %>}) <% end -%> <% end -%> <% if axis_count < 4 -%> #define <%=vector_type_upper%>_TRUNCATE(vector) ((<%=vector_type%>) {vector.x<% 1.upto(axis_count - 1) do |axis| %>, vector.<%= axis_names[axis] %><% end %>}) <% end -%> #define <%=vector_type_upper%>_REPEAT(value) ((<%=vector_type%>) {value<% 1.upto(axis_count - 1) do %>, value<% end %>}) <% if scalar_type != "int" && scalar_type != "unsigned int" -%> // Returns false if magnitude is zero static inline bool <%=vector_type%>_normalize(<%=vector_type%> * vector) { <%=scalar_type%> magnitude = <%= sqrt_functions[scalar_type] %>(<%= multiply("vector->x", "vector->x") %><% 1.upto(axis_count - 1) do |axis| %> + <%= multiply("vector->#{axis_names[axis]}", "vector->#{axis_names[axis]}") %><% end %>); if (magnitude > <%= c0 %>) { <% 0.upto(axis_count - 1) do |axis| -%> vector-><%= axis_names[axis] %> = <%= divide("vector->#{axis_names[axis]}", "magnitude") %>; <% end -%> return true; } return false; } static inline <%=vector_type%> <%=vector_type%>_normalized(<%=vector_type%> vector) { <%=vector_type%>_normalize(&vector); return vector; } <% if axis_count == 4 -%> // Returns false if w is zero static inline bool <%=vector_type%>_normalizeW(<%=vector_type%> * vector) { if (vector->w != <%= c0 %>) { <% 0.upto(2) do |axis| -%> vector-><%= axis_names[axis] %> = <%= divide("vector->#{axis_names[axis]}", "vector->w") %>; <% end -%> vector->w = <%= c1 %>; return true; } return false; } // Returns vector unchanged if w is zero static inline <%=vector_type%> <%=vector_type%>_normalizedW(<%=vector_type%> vector) { <%=vector_type%>_normalizeW(&vector); return vector; } <% end -%> // Normalizes to specified magnitude bool <%=vector_type%>_scaleTo(<%=vector_type%> * vector, <%=scalar_type%> magnitude); <%=vector_type%> <%=vector_type%>_scaledTo(<%=vector_type%> vector, <%=scalar_type%> magnitude); <% end -%> <% if scalar_type != "unsigned int" -%> // Negates all components static inline void <%=vector_type%>_invert(<%=vector_type%> * vector) { <% 0.upto(axis_count - 1) do |axis| -%> vector-><%= axis_names[axis] %> = -vector-><%= axis_names[axis] %>; <% end -%> } static inline <%=vector_type%> <%=vector_type%>_inverted(<%=vector_type%> vector) { <%=vector_type%>_invert(&vector); return vector; } <% if scalar_type != "int" -%> static inline <%=scalar_type%> <%=vector_type%>_magnitude(<%=vector_type%> vector) { return <%= sqrt_functions[scalar_type] %>(<%= multiply("vector.x", "vector.x") %><% 1.upto(axis_count - 1) do |axis| %> + <%= multiply("vector.#{axis_names[axis]}", "vector.#{axis_names[axis]}") %><% end %>); } <% end -%> static inline <%=scalar_type%> <%=vector_type%>_magnitudeSquared(<%=vector_type%> vector) { return <%= multiply("vector.x", "vector.x") %><% 1.upto(axis_count - 1) do |axis| %> + <%= multiply("vector.#{axis_names[axis]}", "vector.#{axis_names[axis]}") %><% end %>; } <% end -%> static inline <%=vector_type%> <%=vector_type%>_add(<%=vector_type%> vector1, <%=vector_type%> vector2) { return <%= vector_type_upper %>(vector1.x + vector2.x<% 1.upto(axis_count - 1) do |axis| %>, vector1.<%= axis_names[axis] %> + vector2.<%= axis_names[axis] %><% end %>); } static inline <%=vector_type%> <%=vector_type%>_subtract(<%=vector_type%> vector1, <%=vector_type%> vector2) { return <%= vector_type_upper %>(vector1.x - vector2.x<% 1.upto(axis_count - 1) do |axis| %>, vector1.<%= axis_names[axis] %> - vector2.<%= axis_names[axis] %><% end %>); } static inline <%=vector_type%> <%=vector_type%>_multiplyScalar(<%=vector_type%> vector, <%=scalar_type%> scalar) { return <%= vector_type_upper %>(<%= multiply("vector.x", "scalar") %><% 1.upto(axis_count - 1) do |axis| %>, <%= multiply("vector.#{axis_names[axis]}", "scalar") %><% end %>); } static inline <%=vector_type%> <%=vector_type%>_divideScalar(<%=vector_type%> vector, <%=scalar_type%> scalar) { return <%= vector_type_upper %>(<%= divide("vector.x", "scalar") %><% 1.upto(axis_count - 1) do |axis| %>, <%= divide("vector.#{axis_names[axis]}", "scalar") %><% end %>); } static inline <%=vector_type%> <%=vector_type%>_multiplyComponents(<%=vector_type%> vector1, <%=vector_type%> vector2) { return <%= vector_type_upper %>(<%= multiply("vector1.x", "vector2.x") %><% 1.upto(axis_count - 1) do |axis| %>, <%= multiply("vector1.#{axis_names[axis]}", "vector2.#{axis_names[axis]}") %><% end %>); } static inline <%=vector_type%> <%=vector_type%>_divideComponents(<%=vector_type%> vector1, <%=vector_type%> vector2) { return <%= vector_type_upper %>(<%= divide("vector1.x", "vector2.x") %><% 1.upto(axis_count - 1) do |axis| %>, <%= divide("vector1.#{axis_names[axis]}", "vector2.#{axis_names[axis]}") %><% end %>); } static inline bool <%=vector_type%>_isZero(<%=vector_type%> vector) { return vector.x == <%= c0 %><% 1.upto(axis_count - 1) do |axis| %> && vector.<%= axis_names[axis] %> == <%= c0 %><% end %>; } static inline bool <%=vector_type%>_isEqual(<%=vector_type%> lhs, <%=vector_type%> rhs) { return lhs.x == rhs.x<% 1.upto(axis_count - 1) do |axis| %> && lhs.<%= axis_names[axis] %> == rhs.<%= axis_names[axis] %><% end %>; } <% if scalar_type != "unsigned int" -%> <% if scalar_type != "int" -%> static inline <%=scalar_type%> <%=vector_type%>_distance(<%=vector_type%> vector1, <%=vector_type%> vector2) { return <%=vector_type%>_magnitude(<%=vector_type%>_subtract(vector1, vector2)); } <% end -%> static inline <%=scalar_type%> <%=vector_type%>_distanceSquared(<%=vector_type%> vector1, <%=vector_type%> vector2) { return <%=vector_type%>_magnitudeSquared(<%=vector_type%>_subtract(vector1, vector2)); } <% if axis_count == 2 -%> static inline <%=vector_type%> <%=vector_type%>_rotate90CW(<%=vector_type%> vector) { return <%= vector_type_upper %>(vector.y, -vector.x); } static inline <%=vector_type%> <%=vector_type%>_rotate90CCW(<%=vector_type%> vector) { return <%= vector_type_upper %>(-vector.y, vector.x); } <% elsif axis_count == 3 -%> static inline <%=vector_type%> <%=vector_type%>_rotate90XCW(<%=vector_type%> vector) { return <%= vector_type_upper %>(vector.x, vector.z, -vector.y); } static inline <%=vector_type%> <%=vector_type%>_rotate90XCCW(<%=vector_type%> vector) { return <%= vector_type_upper %>(vector.x, -vector.z, vector.y); } static inline <%=vector_type%> <%=vector_type%>_rotate180X(<%=vector_type%> vector) { return <%= vector_type_upper %>(vector.x, -vector.y, -vector.z); } static inline <%=vector_type%> <%=vector_type%>_rotate90YCW(<%=vector_type%> vector) { return <%= vector_type_upper %>(-vector.z, vector.y, vector.x); } static inline <%=vector_type%> <%=vector_type%>_rotate90YCCW(<%=vector_type%> vector) { return <%= vector_type_upper %>(vector.z, vector.y, -vector.x); } static inline <%=vector_type%> <%=vector_type%>_rotate180Y(<%=vector_type%> vector) { return <%= vector_type_upper %>(-vector.x, vector.y, -vector.z); } static inline <%=vector_type%> <%=vector_type%>_rotate90ZCW(<%=vector_type%> vector) { return <%= vector_type_upper %>(vector.y, -vector.x, vector.z); } static inline <%=vector_type%> <%=vector_type%>_rotate90ZCCW(<%=vector_type%> vector) { return <%= vector_type_upper %>(-vector.y, vector.x, vector.z); } static inline <%=vector_type%> <%=vector_type%>_rotate180Z(<%=vector_type%> vector) { return <%= vector_type_upper %>(-vector.x, -vector.y, vector.z); } <% end -%> <% end -%> <% if scalar_type != "int" && scalar_type != "unsigned int" -%> <%=vector_type%> <%=vector_type%>_interpolate(<%=vector_type%> left, <%=vector_type%> right, <%=scalar_type%> value); <%=vector_type%> <%=vector_type%>_round(<%=vector_type%> vector); // Returns the vector that would result from a perfect elastic bounce of vector against a plane at the origin with the specified normal <%=vector_type%> <%=vector_type%>_reflect(<%=vector_type%> vector, <%=vector_type%> normal); // Maps vector along the specified normal onto a plane at the origin <%=vector_type%> <%=vector_type%>_project(<%=vector_type%> vector, <%=vector_type%> normal); // Returns the closest position on the specified infinite line to the input vector <%=vector_type%> <%=vector_type%>_positionOnLine(<%=vector_type%> vector, <%=vector_type%> lineOrigin, <%=vector_type%> lineNormal); <% if axis_count > 2 -%> // Returns the closest position on the specified infinite plane to the input vector <%=vector_type%> <%=vector_type%>_positionOnPlane(<%=vector_type%> vector, <%=vector_type%> planeOrigin, <%=vector_type%> planeNormal); <% end -%> <% if axis_count == 2 -%> // radians runs counter-clockwise if y is up <%=vector_type%> <%=vector_type%>_rotate(<%=vector_type%> vector, <%=scalar_type%> radians); // Calculates the intersection point between a line specified by vector and direction, with an infinite line at the // origin running perpendicular to normal. If the two lines are parallel, false is returned and outIntersectionPoint // is not modified. If an intersection point can be found, true is returned, and if outIntersectionPoint is non-NULL, // the intersecting location is written to it. // If outDistance is non-NULL, the distance between vector and the intersection will be written to it on success. // Note: The magnitude of direction will not affect the returned intersection point, but will affect the scale of // the returned distance value. Pass a normalized direction vector to get an accurate measurement. bool <%=vector_type%>_intersectLine(<%=vector_type%> vector, <%=vector_type%> direction, <%=vector_type%> normal, <%=vector_type%> * outIntersectionPoint, <%=scalar_type%> * outDistance); static inline bool <%=vector_type%>_intersectLineSegments(<%=vector_type%> point0, <%=vector_type%> point1, <%=vector_type%> point2, <%=vector_type%> point3, <%=vector_type%> * outIntersection) { <%=vector_type%> vector0_1 = <%=vector_type%>_subtract(point1, point0); <%=vector_type%> vector2_3 = <%=vector_type%>_subtract(point3, point2); <%=scalar_type%> divisor = <%= multiply("-vector2_3.x", "vector0_1.y") %> + <%= multiply("vector0_1.x", "vector2_3.y") %>; float value0 = <%= multiply("-vector0_1.y", "(point0.x - point2.x)") %> + <%= multiply("vector0_1.x", "(point0.y - point2.y)") %>; value0 = <%= divide("value0", "divisor") %>; float value1 = <%= multiply("vector2_3.x", "(point0.y - point2.y)") %> - <%= multiply("vector2_3.y", "(point0.x - point2.x)") %>; value1 = <%= divide("value1", "divisor") %>; if (value0 >= <%=c0%> && value0 <= <%=c1%> && value1 >= <%=c0%> && value1 <= <%=c1%>) { if (outIntersection != NULL) { outIntersection->x = point0.x + <%= multiply("value1", "vector0_1.x") %>; outIntersection->y = point0.y + <%= multiply("value1", "vector0_1.y") %>; } return true; } return false; } <% elsif axis_count == 3 -%> // Returns the closest point along the infinite line defined by position1/normal1 to any point along the infinite // line defined by position0/normal0. If the lines are parallel, returns position1. <%=vector_type%> <%=vector_type%>_closestLinePointToLine(<%=vector_type%> position0, <%=vector_type%> normal0, <%=vector_type%> position1, <%=vector_type%> normal1); // Returns a normalized vector somewhere on the plane perpendicular to the input <%=vector_type%> <%=vector_type%>_perpendicular(<%=vector_type%> vector); // Calculates the intersection point between a line specified by vector and direction, with an infinite plane at the // origin with the specified normal. If the line is parallel to the plane, false is returned and outIntersectionPoint // is not modified. If an intersection point can be found, true is returned, and if outIntersectionPoint is non-NULL, // the intersecting location is written to it. // If outDistance is non-NULL, the distance between vector and the intersection will be written to it on success. // Note: The magnitude of direction will not affect the returned intersection point, but will affect the scale of // the returned distance value. Pass a normalized direction vector to get an accurate measurement. bool <%=vector_type%>_intersectPlane(<%=vector_type%> vector, <%=vector_type%> direction, <%=vector_type%> normal, <%=vector_type%> * outIntersectionPoint, <%=scalar_type%> * outDistance); <% end -%> static inline <%=vector_type%> <%=vector_type%>_transpose(<%=vector_type%> vector) { <%=vector_type%> result; result.x = vector.y; result.y = vector.x; return result; } static inline <%=scalar_type%> <%=vector_type%>_dot(<%=vector_type%> vector1, <%=vector_type%> vector2) { return <%= multiply("vector1.x", "vector2.x") %><% 1.upto(axis_count - 1) do |axis| %> + <%= multiply("vector1.#{axis_names[axis]}", "vector2.#{axis_names[axis]}") %><% end %>; } <% if axis_count == 2 -%> static inline <%=scalar_type%> <%=vector_type%>_cross(<%=vector_type%> vector1, <%=vector_type%> vector2) { return <%= multiply("vector1.x", "vector2.y") %> - <%= multiply("vector1.y", "vector2.x") %>; } <% elsif axis_count == 3 -%> static inline <%=vector_type%> <%=vector_type%>_cross(<%=vector_type%> vector1, <%=vector_type%> vector2) { <%=vector_type%> result; result.x = <%= multiply("vector1.y", "vector2.z") %> - <%= multiply("vector1.z", "vector2.y") %>; result.y = <%= multiply("vector1.z", "vector2.x") %> - <%= multiply("vector1.x", "vector2.z") %>; result.z = <%= multiply("vector1.x", "vector2.y") %> - <%= multiply("vector1.y", "vector2.x") %>; return result; } <% end -%> <%=vector3_type%> <%=vector_type%>_toBarycenter(<%=vector_type%> position, <%=vector_type%> vertex0, <%=vector_type%> vertex1, <%=vector_type%> vertex2); <%=vector_type%> <%=vector_type%>_fromBarycenter(<%=vector3_type%> barycenter, <%=vector_type%> vertex0, <%=vector_type%> vertex1, <%=vector_type%> vertex2); <% end -%> #ifdef __cplusplus } #endif #endif