Difference between revisions of "User:Cron Stardust/LLVector Spec"

From Second Life Wiki
Jump to navigation Jump to search
(→‎Modifying: added abs())
m (Text replacement - "http://lecs.opensource.secondlife.com/" to "http://lecs-opensource.secondlife.com/")
 
(15 intermediate revisions by one other user not shown)
Line 10: Line 10:
In the below please replace LLVector with the name of your specific type.  Also replace any instants of NUM with your specific class's base type; eg. F32, F64, &c.  Likewise with LLMatrix, replace with the corresponding matrix type.
In the below please replace LLVector with the name of your specific type.  Also replace any instants of NUM with your specific class's base type; eg. F32, F64, &c.  Likewise with LLMatrix, replace with the corresponding matrix type.


The exception to this specification is the advanced SIMD vector format: [http://lecs-opensource.secondlife.com/doxygen/class_l_l_vector4a.html LLVector4a].  Please use that data type wherever possible: while its API is drastically different, it's worth the effort in performance gains.
== Public Static Properties ==
== Public Static Properties ==
* <cpp>static LLVector zero;</cpp> set to NUM(0) on all axis.
* <cpp>static const LLVector zero;</cpp> set to NUM(0) on all axis.
* <cpp>static LLVector [xyzw]_axis;</cpp> set to NUM(0) on all but the relevant axis, which is set to NUM(1).
* <cpp>static const LLVector [xyzw]_axis;</cpp> set to NUM(0) on all but the relevant axis, which is set to NUM(1).
* <cpp>static LLVector [xyzw]_axis_neg;</cpp> set to NUM(0) on all but the relevant axis, which is set to NUM(-1).
* <cpp>static const LLVector [xyzw]_axis_neg;</cpp> set to NUM(0) on all but the relevant axis, which is set to NUM(-1).


Where you see [xyzw] create one property for each applicable character; e.g. a 2D type will only need X and Y:
Where you see [xyzw] create one property for each applicable character; e.g. a 2D type will only need X and Y:
<cpp>
<cpp>
static LLVector2 x_axis;
static const LLVector2 x_axis;
static LLVector2 y_axis;
static const LLVector2 y_axis;
static LLVector2 x_axis_neg;
static const LLVector2 x_axis_neg;
static LLVector2 y_axis_neg;
static const LLVector2 y_axis_neg;
</cpp>
</cpp>


Line 29: Line 30:




Conversion constructors are to be marked explicit, and are optional: they are not required by this specification, but are a good idea - it's nice to the programmers to provide that extra bit of fluff that makes things easy to use.  After all that why there's so many operators, right?
Conversion constructors are to be marked explicit, and are optional: they are not required by this specification, but are a good idea - it's nice to the programmers to provide that extra bit of fluff that makes things easy to use.  After all that is why there's so many operators, right?
Example:
Example:
<cpp>
<cpp>
Line 57: Line 58:
Methods in this category shall mimic the constructors.
Methods in this category shall mimic the constructors.


* <cpp>const LLVector& setZero()</cpp> Same as set(0, 0, ...)
* <cpp>LLVector& setZero()</cpp> Same as set(0, 0, ...)
* <cpp>const LLVector& set(NUM x, NUM y, ...)</cpp> However many axis are needed to fully define the current type.  Defaulting some values is acceptable. Be VERY sure to clarify your call by only passing floating point values - integers can cause ambiguity.
* <cpp>LLVector& set(NUM x, NUM y, ...)</cpp> However many axis are needed to fully define the current type.  Defaulting some values is acceptable. Be VERY sure to clarify your call by only passing floating point values - integers can cause ambiguity.
* <cpp>const LLVector& set(const LLVector& vec)</cpp>
* <cpp>LLVector& set(const LLVector& vec)</cpp>
* <cpp>const LLVector& set(const NUM* vec, U32 len = C)</cpp> where C is the expected count of elements in X, Y, Z, W order.
* <cpp>LLVector& set(const NUM* vec, U32 len = C)</cpp> where C is the expected count of elements in X, Y, Z, W order.


=== Reading ===
=== Reading ===
Line 73: Line 74:
* <cpp>BOOL abs()</cpp>
* <cpp>BOOL abs()</cpp>
* <cpp>NUM normalize()</cpp>
* <cpp>NUM normalize()</cpp>
* <cpp>const LLVector& scale(const LLVector& vec)</cpp>
* <cpp>LLVector& scale(const LLVector& vec)</cpp>


The following only make sense in 2 dimensional vectors:
The following only make sense in 2 dimensional vectors:
* <cpp>const LLVector& rotate(NUM angle)</cpp>
* <cpp>LLVector& rotate(NUM theta)</cpp>


The following only make sense in 3 or more dimensional vectors:
The following only make sense in 3 or more dimensional vectors:
* <cpp>const LLVector& transform(const LLMatrix)</cpp> current code does not have an LLMatrix2, therefore this is relegated to the higher order vectors.
* <cpp>LLVector& rotate(const LLMatrix3)</cpp> Breaking abstract notation: a 3x3 matrix should only be used for rotations on 3D vectors.
* <cpp>const LLVector& rotate(NUM angle, const LLVector& axis)</cpp>
* <cpp>LLVector& transform(const LLMatrix4)</cpp> Breaking abstract notation: a 4x4 matrix can be used for rotations, translations, and much more on 3D vectors.  4D vectors are assumed to be 3D vectors with an extra component that indicates whether to translate or not: in the former case the vector is a point in space aka a position, as indicated by the w component being 1.f, or a direction and magnitude, as indicated by the w component being 0.f.
* <cpp>const LLVector& rotate(NUM angle, NUM axis_x_component, NUM axis_y_component, NUM axis_z_component, ...)</cpp>
* <cpp>LLVector& rotate(NUM theta, const LLVector& axis)</cpp>
* <cpp>const LLVector& rotate(const LLQuaternion& q)</cpp>
* <cpp>LLVector& rotate(NUM theta, NUM axis_x_component, NUM axis_y_component, NUM axis_z_component, ...)</cpp>
* <cpp>LLVector& rotate(const LLQuaternion& q)</cpp>


== Operators ==
== Operators ==
Line 89: Line 91:


The following all are typically implemented as "friend" methods.
The following all are typically implemented as "friend" methods.
* <cpp>BOOL operator< (const LLVector&, const LLVector&) const</cpp> less-than
=== Algebraic ===
* <cpp>LLVector operator+ (const LLVector&, const LLVector&) cons</cpp> addition
* <cpp>LLVector operator+ (const LLVector&, const LLVector&)</cpp> addition
* <cpp>LLVector operator- (const LLVector&, const LLVector&) const</cpp> subtraction
* <cpp>LLVector operator- (const LLVector&, const LLVector&)</cpp> subtraction
* <cpp>LLVector operator- (const LLVector&) const</cpp> negation
* <cpp>LLVector operator- (const LLVector&)</cpp> negation
* <cpp>LLVector operator* (const LLVector&, const LLVector&) const</cpp> dot product
* <cpp>LLVector operator* (const LLVector&, NUM)</cpp> scaling
* <cpp>LLVector operator* (const LLVector&, NUM) const</cpp> scaling
* <cpp>LLVector operator* (NUM, const LLVector&)</cpp> scaling
* <cpp>LLVector operator* (NUM, const LLVector&) const</cpp> scaling
* <cpp>LLVector operator/ (const LLVector&, NUM)</cpp> scaling
* <cpp>LLVector operator/ (const LLVector&, NUM) const</cpp> scaling
* <cpp>NUM operator* (const LLVector&, const LLVector&)</cpp> dot product
* <cpp>BOOL operator== (const LLVector&, const LLVector&) const</cpp> equality
* <cpp>LLVector operator% (const LLVector&, const LLVector&)</cpp> cross product. Only makes sense when the number of axis is greater than or equal to 3.
* <cpp>BOOL operator!= (const LLVector&, const LLVector&) const</cpp> non-equality
* <cpp>LLVector operator* (const LLVector&, const LLQuaternion&) </cpp> quat rotation. Only makes sense when the number of axis is greater than or equal to 3.
* <cpp>const LLVector& operator+= (const LLVector&, const LLVector&)</cpp> addition-assignment
* <cpp>LLVector operator* (const LLVector&, const LLMatrix&)</cpp> matrix transformation. Only makes sense when the number of axis is greater than or equal to 3.
* <cpp>const LLVector& operator-= (const LLVector&, const LLVector&)</cpp> subtraction-assignment
* <cpp>const LLVector& operator*= (const LLVector&, NUM)</cpp> scaling-assignment
* <cpp>const LLVector& operator/= (const LLVector&, NUM)</cpp> scaling-assignment
* <cpp>std::ostream& operator<<(std::ostream&, const LLVector3 &) const</cpp>


These only make sense when the number of axis is greater than or equal to 3.
=== Comparison ===
* <cpp>LLVector operator% (const LLVector&, const LLVector&) const</cpp> cross product
* <cpp>BOOL operator== (const LLVector&, const LLVector&)</cpp> equality
* <cpp>const LLVector& operator%= (const LLVector&, const LLVector&)</cpp> cross-product-assignment
* <cpp>BOOL operator!= (const LLVector&, const LLVector&)</cpp> non-equality
* <cpp>LLVector operator* (const LLVector&, const LLQuaternion&) const </cpp> quat rotation
* <cpp>BOOL operator< (const LLVector&, const LLVector&)</cpp> less-than
* <cpp>const LLVector& operator*= (const LLVector&, const LLQuaternion&)</cpp> quat rotation
 
* <cpp>LLVector operator* (const LLVector&, const LLMatrix&) const</cpp> matrix transformation
=== Assignment ===
* <cpp>const LLVector& operator*= (const LLVector&, const LLMatrix&)</cpp> matrix transformation
* <cpp>LLVector& operator+= (const LLVector&, const LLVector&)</cpp> addition-assignment
* <cpp>LLVector& operator-= (const LLVector&, const LLVector&)</cpp> subtraction-assignment
* <cpp>LLVector& operator*= (const LLVector&, NUM)</cpp> scaling-assignment
* <cpp>LLVector& operator/= (const LLVector&, NUM)</cpp> scaling-assignment
* <cpp>LLVector& operator%= (const LLVector&, const LLVector&)</cpp> cross-product-assignment. Only makes sense when the number of axis is greater than or equal to 3.
* <cpp>LLVector& operator*= (const LLVector&, const LLQuaternion&)</cpp> quat rotation. Only makes sense when the number of axis is greater than or equal to 3.
* <cpp>LLVector& operator*= (const LLVector&, const LLMatrix&)</cpp> matrix transformation. Only makes sense when the number of axis is greater than or equal to 3.
 
=== Conversion ===
* <cpp>std::ostream& operator<<(std::ostream&, const LLVector3 &)</cpp>

Latest revision as of 14:15, 6 July 2017

This is a simple specification for all LLVector formats. This does NOT include the LLColor formats.

Everything below is to be considered a minimum compatibility specification. Specific type implementations are free to add extra items as their own use cases dictate.

Every type that is only differentiated from another type by the precision, or number of bits, in its components shall be directly compatible: all such related types are to implement the same public interface.

It is recommended that types be freely convertible between themselves, but this is not a requirement.


In the below please replace LLVector with the name of your specific type. Also replace any instants of NUM with your specific class's base type; eg. F32, F64, &c. Likewise with LLMatrix, replace with the corresponding matrix type.

The exception to this specification is the advanced SIMD vector format: LLVector4a. Please use that data type wherever possible: while its API is drastically different, it's worth the effort in performance gains.

Public Static Properties

  • <cpp>static const LLVector zero;</cpp> set to NUM(0) on all axis.
  • <cpp>static const LLVector [xyzw]_axis;</cpp> set to NUM(0) on all but the relevant axis, which is set to NUM(1).
  • <cpp>static const LLVector [xyzw]_axis_neg;</cpp> set to NUM(0) on all but the relevant axis, which is set to NUM(-1).

Where you see [xyzw] create one property for each applicable character; e.g. a 2D type will only need X and Y: <cpp> static const LLVector2 x_axis; static const LLVector2 y_axis; static const LLVector2 x_axis_neg; static const LLVector2 y_axis_neg; </cpp>

Public Constructors

  • Basic Constructor: <cpp>LLVector()</cpp>
  • Direct-value Constructor: <cpp>LLVector(NUM x, NUM y, ...)</cpp> be VERY sure to clarify your call by only passing floating point values - integers can cause ambiguity.
  • Array Constructor: <cpp>LLVector(const NUM* vec, U32 len = C)</cpp> where C is the expected count of elements in X, Y, Z, W order.


Conversion constructors are to be marked explicit, and are optional: they are not required by this specification, but are a good idea - it's nice to the programmers to provide that extra bit of fluff that makes things easy to use. After all that is why there's so many operators, right? Example: <cpp> explicit LLVector2(const LLVector3& vec); </cpp>

Public Properties

  • Array of values: <cpp>NUM mV[LENGTH_OF_VECTOR]</cpp> where LENGTH_OF_VECTOR is the count of elements in this array: e.g. a 2D vector would be 2, 3D would be 3, &c. Each element in the array represents the, if applicable, X, Y, Z, and W values of the vector.

Note that this is a significant departure from previous convention: there is to be NO differentiating the array-of-values property by its datatype. This is to make switching vector formats as painless as possible - there's already too much to watch for other than simple semantic changes.

It is highly recommended that each class expose a static constant that defines the length of each respective vector, e.g.: <cpp> static const U32 LENGTH_OF_VECTOR2 = 2; </cpp>

Public Methods

Inlining or not shall be determined on a case-by-case basis.

All methods that have a return type of LLVector& shall return a reference to the current instance.

Serialization

  • <cpp>LLSD getValue() const</cpp>
  • <cpp>const LLVector& setValue(const LLSD& sd)</cpp>

Setting

Methods in this category shall mimic the constructors.

  • <cpp>LLVector& setZero()</cpp> Same as set(0, 0, ...)
  • <cpp>LLVector& set(NUM x, NUM y, ...)</cpp> However many axis are needed to fully define the current type. Defaulting some values is acceptable. Be VERY sure to clarify your call by only passing floating point values - integers can cause ambiguity.
  • <cpp>LLVector& set(const LLVector& vec)</cpp>
  • <cpp>LLVector& set(const NUM* vec, U32 len = C)</cpp> where C is the expected count of elements in X, Y, Z, W order.

Reading

  • <cpp>BOOL isExactlyZero() const</cpp>
  • <cpp>BOOL isFinite() const</cpp>
  • <cpp>BOOL isNull() const</cpp>
  • <cpp>NUM length() const</cpp>
  • <cpp>NUM lengthSquared() const</cpp>
  • <cpp>LLVector scaled(const LLVector& vec) const</cpp>

Modifying

  • <cpp>BOOL abs()</cpp>
  • <cpp>NUM normalize()</cpp>
  • <cpp>LLVector& scale(const LLVector& vec)</cpp>

The following only make sense in 2 dimensional vectors:

  • <cpp>LLVector& rotate(NUM theta)</cpp>

The following only make sense in 3 or more dimensional vectors:

  • <cpp>LLVector& rotate(const LLMatrix3)</cpp> Breaking abstract notation: a 3x3 matrix should only be used for rotations on 3D vectors.
  • <cpp>LLVector& transform(const LLMatrix4)</cpp> Breaking abstract notation: a 4x4 matrix can be used for rotations, translations, and much more on 3D vectors. 4D vectors are assumed to be 3D vectors with an extra component that indicates whether to translate or not: in the former case the vector is a point in space aka a position, as indicated by the w component being 1.f, or a direction and magnitude, as indicated by the w component being 0.f.
  • <cpp>LLVector& rotate(NUM theta, const LLVector& axis)</cpp>
  • <cpp>LLVector& rotate(NUM theta, NUM axis_x_component, NUM axis_y_component, NUM axis_z_component, ...)</cpp>
  • <cpp>LLVector& rotate(const LLQuaternion& q)</cpp>

Operators

  • <cpp>NUM operator[] (int idx) const</cpp>
  • <cpp>NUM& operator[] (int idx)</cpp>

The following all are typically implemented as "friend" methods.

Algebraic

  • <cpp>LLVector operator+ (const LLVector&, const LLVector&)</cpp> addition
  • <cpp>LLVector operator- (const LLVector&, const LLVector&)</cpp> subtraction
  • <cpp>LLVector operator- (const LLVector&)</cpp> negation
  • <cpp>LLVector operator* (const LLVector&, NUM)</cpp> scaling
  • <cpp>LLVector operator* (NUM, const LLVector&)</cpp> scaling
  • <cpp>LLVector operator/ (const LLVector&, NUM)</cpp> scaling
  • <cpp>NUM operator* (const LLVector&, const LLVector&)</cpp> dot product
  • <cpp>LLVector operator% (const LLVector&, const LLVector&)</cpp> cross product. Only makes sense when the number of axis is greater than or equal to 3.
  • <cpp>LLVector operator* (const LLVector&, const LLQuaternion&) </cpp> quat rotation. Only makes sense when the number of axis is greater than or equal to 3.
  • <cpp>LLVector operator* (const LLVector&, const LLMatrix&)</cpp> matrix transformation. Only makes sense when the number of axis is greater than or equal to 3.

Comparison

  • <cpp>BOOL operator== (const LLVector&, const LLVector&)</cpp> equality
  • <cpp>BOOL operator!= (const LLVector&, const LLVector&)</cpp> non-equality
  • <cpp>BOOL operator< (const LLVector&, const LLVector&)</cpp> less-than

Assignment

  • <cpp>LLVector& operator+= (const LLVector&, const LLVector&)</cpp> addition-assignment
  • <cpp>LLVector& operator-= (const LLVector&, const LLVector&)</cpp> subtraction-assignment
  • <cpp>LLVector& operator*= (const LLVector&, NUM)</cpp> scaling-assignment
  • <cpp>LLVector& operator/= (const LLVector&, NUM)</cpp> scaling-assignment
  • <cpp>LLVector& operator%= (const LLVector&, const LLVector&)</cpp> cross-product-assignment. Only makes sense when the number of axis is greater than or equal to 3.
  • <cpp>LLVector& operator*= (const LLVector&, const LLQuaternion&)</cpp> quat rotation. Only makes sense when the number of axis is greater than or equal to 3.
  • <cpp>LLVector& operator*= (const LLVector&, const LLMatrix&)</cpp> matrix transformation. Only makes sense when the number of axis is greater than or equal to 3.

Conversion

  • <cpp>std::ostream& operator<<(std::ostream&, const LLVector3 &)</cpp>