
On 6/15/06, Janek Kozicki <janek_listy@wp.pl> wrote:
Michael Fawcett said: (by the date of Wed, 14 Jun 2006 13:16:12 -0400)
Hi Michael,
I currently use enable_if and is_same from boost to determine what functions should be exposed. There are convenience functions like:
as_array() to be used like glVertex3fv(my_vec.as_array());
that only make sense if the vector contained all of the same type. Otherwise, in cases like vec3<float, short, float>, as_array() would be disabled. I suspect that we could do the same for the rest of the operations (dot_product, cross_product, etc).
in current design (see parent post) it is decided that all components of vector/matrix/quaternion have the same underlying type (specified as second template argument). IMO this is a good decision, because the main goal here is to work with units (then math). And this most of the time involves math, physics or engineering. With such target usage it makes no sense to use different underlying types.
I was really just agreeing with the current sentiment that we should allow some operations and disallow others, depending on the template parameters. I was under the impression that the vector<3, free_quantity> syntax was just one alternative to the lengthier one, in fact, I got the impression that Leland Brown currently uses mixed type vectors and matrices with success. I was also unable to find the post where it was agreed to drop mixed types. Could you quote next time?
Examples that you have provided below are not from math, physics or engineering field, so they do not apply here. It is possible that this library will work in such scenarios, but this is not the design target.
Possible solutions are given below.
Although I'm ambivalent about the implementation, I can't see why you wouldn't either support mixed types (act like a tuple), or support operations on tuples. See below.
it is more like a tuple with four components. Of course storing them as vector is handy, but there is not math inside, it's just a container for data.
Sure, but often dot products are used on that data if the author knows it makes sense. Why do you care what is stored in there as the library author? The vector<4, float> (or whatever we are calling it now) may be the color component, but it may store a normal vector in the first 3 components with a texture lookup id in the last component. Who cares if the author wants to say normalize(myvec4.as_vec3()); as long as the types in myvec4 allow normalize to function correctly.
There are often times where the 'w' component is used to signal that the vertex is at infinity, but should otherwise still be treated as a classic vector<3>.
so it would be a vector<3> with a bool flag. Makes sense, because there is no cross_product defined for vector<4> in which the last component is some bool flag.
No, but again, why do you care? The cross product IS defined for a vec<3> of all the same type, so the user will be able to use that if it makes sense. In actuality it would probably be a vec<4, float> so that I could pass it directly on to the video card without an intermediate copy being made.
For lights, the 'w' component is used to signal the type of light, directional or point (omni-directional). That type specifies how the x,y,z components should be interpreted. If the light is directional, then the x,y,z is a direction vector. If the type is a point light, the x,y,z components are a position in space.
so it's a vector<3> with an enum flag.
I agree about the only allowing certain operations using template specialization for the vector/quaternion classes, but I disagree that quaternion can simply be vector<4> with the provided quaternion specializations. I think it should be a separate class following the same principles.
Your arguments did not convince me at all, because they are out of place.
In practice, 99% of the time, my vectors and matrices are of the same type. A few other posters (John Philips and Leland Brown notably) have mentioned successful use of mixed type vectors and matrices which are convincing to me. I fail to see the problem with allowing mixed types implementation-wise, which is my only real argument against disallowing them. If the operation supports the types, allow it, if it doesn't, fail to compile.
So still I think that quaternion can be a template specialization for unitless (dimensionless) vector<4>. Also we can add a typedef quaternion<double> vector<4,double>; // etc...
I think not. vector<4> * vector<4> better be component-wise, at least, that's how it worked on the PlayStation2. I think I can agree that vectors and matrices can store the same type if we allow operations to accept tuple types, if that is suitable for others. Perhaps dot_product could be implemented as: template <typename LHS, typename RHS> BOOST_TYPEOF_TPL( something here ) dot_product(const LHS &lhs, const RHS &rhs) { return lhs.get<0>() * rhs.get<0>() + lhs.get<1>() * rhs.get<1>() + lhs.get<2>() * rhs.get<2>(); } but then our vectors have to act like tuples, and then I guess you have to ask, why isn't a tuple adequate with a bunch of free functions implemented like above? PQS would still kick in at the individual operation level (i.e. all of those multiplications and additions). Regards, --Michael Fawcett