Sign in to follow this  
SteveDeFacto

How to make my class castable to another class?

Recommended Posts

I have two matrix classes that I want to be able to cast to each other but I don't know how to do that...

Here are the two classes:


class AxMatrix33
{
public:
union
{
struct
{
float _11, _12, _13;
float _21, _22, _23;
float _31, _32, _33;
};
float m[3][3];
};

AxMatrix33 operator * ( const AxMatrix33& ) const;
};

class AxMatrix44
{
public:
union
{
struct
{
float _11, _12, _13, _14;
float _21, _22, _23, _24;
float _31, _32, _33, _34;
float _41, _42, _43, _44;
};
float m[4][4];
};

AxMatrix44 operator * ( const AxMatrix44& ) const;
};




One is a 3x3 matrix and the other is a 4x4 matrix. I simply want to drop the last row to convert the 4x4 to a 3x3 and add a row to cast the 3x3 to a 4x4. The classes that I have shown are inside a header and the actual implementation of the code will be inside the CPP file.

Share this post


Link to post
Share on other sites
Quote:
Original post by TerranceN
Try reading this.


I read it all the way through but I don't see how that is going to help me. Maybe I'm not understanding it but I don't see anywhere in that article that explains how to actually define how to cast the type... I'm thought it would work something like an operator.

Share this post


Link to post
Share on other sites
Add some constructors and assignment operators:
class AxMatrix44;
class AxMatrix33
{
public:
AxMatrix33( const AxMatrix44& );
AxMatrix33& operator=( const AxMatrix44& );
};
class AxMatrix33
{
public:
AxMatrix44( const AxMatrix33& );
AxMatrix44& operator=( const AxMatrix33& );
};

Share this post


Link to post
Share on other sites
isn't the assignment operator not unnecessary?

Since the constructor isn't explicit, the casting can be done implicitelly and hence casting can be done automatically by the compiler when assigning.

Share this post


Link to post
Share on other sites
You can't cast from a 4x4 matrix to a 3x3 because a 4x4 matrix isn't a superset in terms of memory layout. The m[4][4] is a contiguous set of floats, so regardless of where you slice the memory, you won't get 9 floating point values referring to a rectangular region of the 4x4 matrix.

It is possible however, to extract the 4 component row/column vectors from the matrix via typecasting. Either the row vectors or the column vectors will be contiguous depending on how you interpret the data in the matrix (row major vs column major)

Edit: You don't need to typecast to extract vectors, provided you define the matrix as an array of 3/4 component vectors to begin with.

Share this post


Link to post
Share on other sites
Please explain, in detail, exactly what you expect to happen when you "cast" a 3x3 matrix to a 4x4 matrix, and vice-versa. Please also explain why such behaviour is "obvious" enough to justify making it happen automatically by casting.

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
Please explain, in detail, exactly what you expect to happen when you "cast" a 3x3 matrix to a 4x4 matrix, and vice-versa.
Quote:
Original post by SteveDeFacto
I simply want to drop the last row to convert the 4x4 to a 3x3 and add a row to cast the 3x3 to a 4x4.

Quote:
Please also explain why such behaviour is "obvious" enough to justify making it happen automatically by casting.
See HLSL's usage.

Share this post


Link to post
Share on other sites
Just because nobody has brought this up and it bugs the hell out of me.


SteveDeFacto do you realise that both the definition of your union and almost certainly the usage of it is either implementation specific or undefined in current C++?

Share this post


Link to post
Share on other sites
Quote:
Original post by dmail
SteveDeFacto do you realise that both the definition of your union and almost certainly the usage of it is either implementation specific or undefined in current C++?


It's not standard, but it's pretty common. D3DMATRIX is defined the same way and if you try to compile it with gcc I believe it gives you a warning but only that it's not standard.

Share this post


Link to post
Share on other sites
Yes ender_341 I did actually make a comment in IRC blaming D3DMATRIX :)
The problem is two fold, firstly unnamed unions can not define types (nested types) and accessing data in a union which is not the active data is illegal. MSCV allows these via language extensions but this behaviour should not be relied on with other compilers or even with MS extensions disabled, if the OP was using MSCV why not just use D3DMATRIX?

Share this post


Link to post
Share on other sites
Quote:
Original post by dmail
Yes ender_341 I did actually make a comment in IRC blaming D3DMATRIX :)
The problem is two fold, firstly unnamed unions can not define types (nested types) and accessing data in a union which is not the active data is illegal. MSCV allows these via language extensions but this behaviour should not be relied on with other compilers or even with MS extensions disabled, if the OP was using MSCV why not just use D3DMATRIX?
I've seen the same non-standard union usage in game engines for PS3/360/Wii, so I assume this non-standard behavior works on MSVC, GCC and CodeWarrior... making it defacto-standard ;)

Share this post


Link to post
Share on other sites
Quote:
Original post by dmail
Just because nobody has brought this up and it bugs the hell out of me.


SteveDeFacto do you realise that both the definition of your union and almost certainly the usage of it is either implementation specific or undefined in current C++?


Is there another way to do it that would be more standard?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this