Jump to content
  • Advertisement
Sign in to follow this  
The C modest god

Physics data classes?

This topic is 4582 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I was thinking if the following would be a good or bad idea: Let's say we have a physics engine, and lets say this engine uses physical dimentions such as distance, time and velocity. What if for each dimention you would create a class. So if you have:
time a;
distance b;

a = b; // <= compilation error
The assigment operation will produce a compilation error. However, you could define in the class operations between different dimentions. For example:
time a;
distance b;
velocity c;

b = a*c; // <= Ok!
So a*c will return a value of class distance. Another bonus, is that you wont be able to use functions such as sin on a dimention class, unless you explictly cast the variable. What will be the speed cost for this? However, will it improove the developement productivity and prevent bugs? What do you think? Thanks in advance.

Share this post


Link to post
Share on other sites
Advertisement
Generally speaking, operator overloading (like what you suggest) is one of C++'s most useful features. I absolutely think that what you suggest is a good idea.

Share this post


Link to post
Share on other sites
I decided to have some fun with this problem. Here is a template-based solution based on the fact that units behave exactly like vectors:


#include<iostream>
#include<sstream>

// Argument order: KG M S

template<int KG, int M, int S>
class TUnit {
public:
static std::string Describe( ) {
std::stringstream str;

if( KG != 0 ) {
str << " kg";
if( KG != 1 ) {
str << "^" << KG;
}
}

if( M != 0 ) {
str << " m";
if( M != 1 ) {
str << "^" << M;
}
}

if( S != 0 ) {
str << " s";
if( S != 1 ) {
str << "^" << S;
}
}

return str.str( );
}
};

template<int KG, int M, int S>
class TValue {

float value;

public:

typedef TUnit<KG,M,S> Unit;
typedef TValue<KG,M,S> Self;

TValue( float value ) : value(value) { }

float Value( ) const { return value; }

// Same-unit operations

Self operator+( const Self & other ) const { return Self( value + other.value ); }
Self operator-( const Self & other ) const { return Self( value - other.value ); }

Self & operator+=( const Self & other ) {
value += other.value;
return *this;
}

Self & operator-=( const Self & other ) {
value -= other.value;
return *this;
}

// Different-unit operations

template<int KG2, int M2, int S2>
TValue<KG+KG2,M+M2,S+S2> operator*( const TValue<KG2,M2,S2> & other ) const {
return TValue<KG+KG2,M+M2,S+S2>( value * other.Value( ) );
}

template<int KG2, int M2, int S2>
TValue<KG-KG2,M-M2,S-S2> operator/( const TValue<KG2,M2,S2> & other ) const {
return TValue<KG-KG2,M-M2,S-S2>( value / other.Value( ) );
}

Self & operator*=( const TValue<0,0,0> & other ) {
value *= other.Value( );
return *this;
}

Self & operator/=( const TValue<0,0,0> & other ) {
value /= other.Value( );
return *this;
}
};

template<int KG,int M,int S>
std::ostream & operator<<( std::ostream & os, const TValue<KG,M,S> & val ) {

typedef typename TValue<KG,M,S>::Unit SelfUnit;

os << val.Value( ) << SelfUnit::Describe( );
return os;
}

typedef TValue<0,0,0> Scalar;
typedef TValue<0,1,0> Distance;
typedef TValue<0,0,1> Time;
typedef TValue<0,1,-1> Speed;
typedef TValue<0,1,-2> Acceleration;
typedef TValue<1,0,0> Weight;
typedef TValue<1,1,-2> Force;

int main( ) {

Distance d( 10000.0f );
Time t( 3600.0f );

Speed s = d / t;

std::cout << d << std::endl;
std::cout << t << std::endl;
std::cout << s << std::endl;
std::cout << t * d / Force( 10.0 ) << std::endl;
std::cout << sizeof(d) << std::endl;
}






You can't compile things like s+t.

Improvement to add: make an implicit float -> TValue<0,0,0> constructor, and make the other constructors explicit. And maybe make a better formatting for unit display, and for unit creation syntax.

EDIT: made the operator<< rhs argument a const reference, to display the result of a computation directly.

Share this post


Link to post
Share on other sites
From the link I posted:
Quote:

* Low speed overhead. All units management is enforced by the C++ compiler. Mathematical equations using units should be just as fast as those without. In fact, this can be tested, by turning off the units management using a compile-time definition.

Share this post


Link to post
Share on other sites
Quote:
What will be the speed cost for this?


As dalleboy's quote said the cost can be nothing, you just have to write things correctly so that the compiler will do all the unit checking at compile time and inline all the operations. This shouldn't be that hard to do (I'm pretty sure ToohrVyk's solution will have no overhead when you turn on compiler optimizations).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!