ODE Internals

From ODE Wiki

Jump to: navigation, search

Contents

ODE Internals

(only notes for now)

  • Internally, all 6x1 spatial velocities and accelerations are split into 3x1 position and angular components, which are stored as contiguous 4x1 vectors.
  • Lagrange multiplier velocity based model due to Trinkle and Stewart.
  • Friction due to Baraff.
  • Stability over accuracy.
  • Talk about the different methods possible. Say how realtime constraints make the problem much more difficult.
  • Factorizer.
  • LCP solver.
  • Equations of motion.
  • Friction model and approximations.

Why don't I implement a proper friction pyramid or friction cone (e.g. Baraff's version) ? Because I have to factor non-symmetric (and possibly indefinite) matrices, for either static or dynamic friction. Speed was considered more important - the current friction approximation only needs a symmetric factorization, which is twice as fast.

Matrix storage conventions

Matrix operations like factorization are expensive, so we must store the data in a way that is most useful to the matrix code. I want to do 4-way SIMD optimizations later, so the format is this: store the matrix by rows, and each row is rounded up to a multiple of 4 elements. The extra "padding" elements at the end of each row/column must be set to 0. This is called the "standard format". Hopefully this decision will remain good in the future, as more and more processors have 4-way SIMD (especially for fast 3D graphics).

The exception: matrices that have only one column or row (vectors), are always stored as consecutive elements in standard row format, i.e. there is no interior padding, only padding at the end.

Thus: all 3x1 floating point vectors are stored as 4x1 vectors: (x,x,x,0).

Internals FAQ

Why do some structures have a dx prefix and some have a d prefix?

The dx prefix is used for internal structures that should never be visible externally. The d prefix is used for structures that are part of the public interface.

Returned Vectors

There seem to be 2 ways of returning vectors in ODE, e.g.: const dReal* dBodyGetPosition (dxBodyID); void dWorldGetGravity (dxWorldID, dVector3); Why? The second way is the 'official' way. The first way returns pointers to volatile internal data structures and is less clean API-wise. For a stable API I feel that filling in vectors is cleaner than returning pointers to vectors, for two reasons:

  • The returned vector values may have to be calculated somehow, so there is no internal "cache" to return a pointer to.
  • The internal data structures may be moved, which is a problem if the user keeps the returned pointer and uses it later.

As it happens these two cases don't currently happen in ODE - most returned vector data is cached and always at the same address. But having the freedom to change things in the future is useful. The current API shouldn't slow you down because the cases where you need to be fast (i.e. getting body transforms) return pointers anyway - breaking my own rule.

[[Category:Development

Personal tools
Navigation