[ PRELIMINARY DRAFT ]Opedo FrameworkThe opedo framework is a complete high performance C++11 template library. It includes classes and functions for list and memory operations, heap and stack allocators, sort and search algorithms, vector math, quaternion and dual quaternion math, spinor math, geometry, integrals, spherical harmonics, fast fourier transformations, image and signal filtering, BRDF and radiance equations, and more. Classes are compact and aligned efficiently. Functions and classes are templated and constexpr as much as possible, and are all inlined and designed for SFINAE to work easily. Math FrameworkVector, matrix, interval, quaternion, dual quaternion, and spinor classes are full templated to support advanced features that no other library has. The classes are in standard layout with sub element addressing, swizzling, and replicating, and can be used with any function with no performance hit, just like in GLSL: .xy, .zyx .xxyy. Transposes can be addressed with the ._T() member function, and can also be used with any function with no performance hit. Column vectors of matrices can be addressed and used like any other vector.
vector3_f32 v;
matrix3x3_f32 A; // initialize v and A ... v.yz = v.zxy * A.zy._T().yzx; v.x = dot(v.xzy, A._T().y); quaternion_f32 q0, q1; // initialize q0 and q1 ... q0 *= q1._T(); The above are calculated with no performance hit from using the transposes and swizzles. Base functions and operators are easily overloadable in the opedo namespace to add support for SIMD operations for any architecture. General FrameworkThere are type traits to find out if a class is a list and if it is contiguous. A list is a class that supports the [] operator and the count_of() function. The default count_of() function tries to return a count member with SFINAE considerations. A contiguous list is a class that is a list and also supports the + and - operators with a size_t parameter. Lists can be transformed into other lists with these typical functions: to a list of a member of the value_type: list_of_member()
so it is acessesed by an index list: list_by_index() to a list of value_type cast to another type: cast_list<>() to a list of value_type derefenced: dereference_list() Sorting and searching a list can be done easily by a member of its value_type, or by dereferencing its value_type with these operator transformations: by_member() and by_dereference().
dynamic_list_<int32> list0(3);//
count of list is 3
// initialize list0 ... heap_sort(list0);// default less than heap_sort(list0, gt_t());// greater than struct foo_t { int32 a, b; }; array_<foo_t, 8> list1;// count of list is 8 // initialize list1 ... heap_sort(list1, by_member(foo_t, b));// default less than bool b = bin_exists(list1, 15, by_member(foo_t, b));// default less than size_t i = inc_search(cast_list<float32>(list_by_index(list_of_member(list1, a), list0)), 23.0f);// default equal to The general list classes, like array_<> and dynamic_list_<>, have all debug time asserts for out of bound operations. Creating new types of list classes is greatly simplified with standard macros placed in the definition. struct foo_t
{ static constexpr size_t count = 3; uint32 data[count]; DEFAULT_LIST(count, data, uint32);// defines the operators [], (), +, -, and T* and size_t casts }; There is an extremely fast dynamic best-fit allocator available that allocates cache aligned memory, and allows sub-list data moves during reallocs for efficient buffering algorithms and mid-list insertions. Geometry Framework
There are type traits to find the appropriate vector space of a geometric object, and if it is a vector or a transformation, or neither. Transformations are templated to support rotations, translations, and scales. Transposes have again no performance hit. Geometric objects can be arbitrarily transformed and maximally projected onto a vector, and distances can be calculated using GJK. The GJK implementation is high performance and robust with no termination tolerance needed (no other known implementation exists that is so robust). Transforms can also be attached to objects so they can be related to other objects with the same interface efficiently, without having to transform the object completely.
aabox3_f32 a;
dynamic_list_<vector3_f32> b; // initialize a and b ... float32 d0 = distance(a, b); rotation3_f32 r; translation3_f32 t; // initialize r and t ... float32 d1 = distance(a * r._T(), b * t); a = aabox3_f32(a * t._T() * r); b *= r * t; Geometric classes need only to implement one of two functions, and declare its vector space, to be used in various relations.
template<class T, uint32 N>
struct local_sphere_ { typedef T scalar_type; static constexpr uint32 dimension = N; T r; template<class R, class O> INLINE R projection(vector_<R, N> const& v, R len, O&& op) const { if (len <= epsilon_of(len) * R(r)) { return R(0); } return op.sign(R(r)) / len; } }; |