2011-12-31 10 views
2

RGB/RGBA色情報の格納に使用するクラス構造を決定する際に問題があります。色のクラス階層

私は非常に楽しいと私のオブジェクト指向プログラミング能力を磨くための単純な3Dゲームエンジンを作っています。

私のエンジンは、RGBとRGBAの両方の色をサポートしたいと思います。その上に、RGBとRGBAの値を[0、1]にクランプされた浮動小数点数または符号なしの文字として指定できるようにしたいと思います。私は記憶目的のために、浮動小数点数の4分の1のメモリを使用するので、符号なしの文字を使用するほうがよいと考えました。

ここでは、Color、Color3、Color3f、Color3c、Color4、Color4f、Color4cの各クラスを使用するために、次のクラスを考案しました。 ColorはColor3とColor4のスーパークラスですが、Color3はColor3fとColor3cのスーパークラスです.Color4はColor4fとColor4cです。

これは、必要以上に複雑なアプローチのようです。私はジェネリックの使用についてもしばらく考えていたので、Color3fとColor3cの代わりに、Color3 <float>とColor3 <の符号なしの文字列>を使用します。しかし、このアプローチは正しいとは思わなかった。

理想的には、私はのようなコードを書くことができるようにしたいと思います:

Color3 red1(255, 0, 0); 
Color3 red2(1.0f, 0.0f, 0.0f); 
Color* someColor = new Color3(1.0f, 0.0f, 0.5f); 
Color4 anotherColor = *someColor; 
Color4 thisColor = anotherColor.toChar(); 
//thisColor.r = 255, thisColor.g = 0, thisColor.b = 127 
thisColor = thisColor.toFloat(); 
//thisColor.r = 1.0f, thisColor.g = 0.0f, thisColor.b = 0.5f 

今これはC++で(少なくとも私の知る限り)に実装することはできませんが、どのように私は同じ機能を奮い起こすことができ7つの別々のクラスを作成せずに?無駄な情報を保存することなく?たとえば、メモリに1024x1024イメージを描画します。これは100万を超える配列を持つ配列なので、どのようにして柔軟で再利用可能なColorクラス階層を作ることができますか?すなわち、RGBおよびRGBA値を符号なしの文字を介して異なる構造に格納するが、浮動小数点値を取り出す機能を提供するか?

申し訳ありませんが、これが十分に具体的でない場合や、これが私の最初の質問です。他に何が助けになるのか教えてください。あなたが好きならこれまでに試したことのコードを投稿できますが、うまくいけば私が達成しようとしていることを理解できます。

+5

OOver-engineering多く、ええ? :)ちょうど注記のために、あなたが例として書いたことは、C++では完全に可能であり、少しのpimplイディオムとインターフェースがあります。そうでないといいとは思いません。 – Xeo

答えて

3

あなたが唯一のクラスの色(またはprefferably色)が必要

内部的にあなたが、しかし、あなたが好きな32ビットのunsigned int型RGBA(またはBGRA)の値を格納することができますが一般的であり、そしてちょうどマスクを使用し、ビットが抽出に移行各コンポーネント。

あなたはColor(unsigned char red,unsigned char green,unsigned char blue, unsigned char alpha=0xff)を取るか、または浮かぶ

を、同様に各フォーム内の各コンポーネントのための/セッターをゲッタリングコンストラクタを持つことができます。

編集:高性能を計画している場合、各ピクセルの色オブジェクトの配列からなる画像は、おそらく行く方法ではありません。各コンポーネントを設定/取得する静的関数のセットを見ると、画像フォーマットのフォーマット(つまり、BGRAまたはRGBの符号なしint)でピクセルを取得するコンストラクタを見ることができます。

+0

スペース効率が必要な場合は、ビットパッキングが必要です。 – Xeo

+1

4文字しか含まれていない構造体も同じ効率でパックする必要があります。 –

+0

Err、right、nvm me。私は私の頭の中で詰め物に関するいくつかの奇妙な考えを持っていた。 – Xeo

1

オーバーエンジニアリングについてのXeoのポイントは良いもの、そしてover-engineeringを避けて私の答えを読んでみたいかもしれません。しかし、オブジェクト指向の全体的な点は、の複雑さを隠して、それを奨励していません。

効率的な内部表現でColorクラスを開始し、引数として必要なデータ型をオーバーロードします。実装が公開されるまで、にはが必要な場合を除き、すべてのサブクラスを気にする必要はありません。おそらく動作する可能性が最も簡単なアプローチを取る。

+0

非常に有益なポストをありがとう。私はいつもあらゆる細部を突き詰める傾向がありましたが、本当に必要なことだけを行い、必要に応じて他の機能を追加するというあなたのアプローチが本当に好きです。 – berserkguard

1

これは楽しいように見えるので、他の人の言うとおりにコーディングしています。これは答えではありません。

class color { 
    unsigned char red_, green_, blue_, alpha_; 
public: 
    color() 
    :red_(0), green_(0), blue_(0), alpha_(0xFF) {} 
    color(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha=0xFF) 
    :red_(red), green_(green), blue_(blue), alpha_(alpha) {} 
    color(float red, float green, float blue, float alpha=1.0) 
    :red_(red*255.0+.5), green_(green*255.0+.5), blue_(blue*255.0+.5), alpha_(alpha*255.0+.5) {} 
    color(const color& rhs) 
    :red_(rhs.red_), green_(rhs.green_), blue_(rhs.blue_), alpha_(rhs.alpha_) {} 
    //operator= and dtor automatically generated 
    unsigned char& c_red() {return red_;} 
    unsigned char& c_green() {return green_;} 
    unsigned char& c_blue() {return blue_;} 
    unsigned char& c_alpha() {return alpha_;} 
    const unsigned char& c_red() const {return red_;} 
    const unsigned char& c_green() const {return green_;} 
    const unsigned char& c_blue() const {return blue_;} 
    const unsigned char& c_alpha() const {return alpha_;} 
    void set_f_red(float val) {red_=val*255.0+.5;} 
    void set_f_green(float val) {green_=val*255.0+.5;} 
    void set_f_blue(float val) {blue_=val*255.0+.5;} 
    void set_f_alpha(float val) {alpha_=val*255.0+.5;} 
    float get_f_red() const {return red_/255.0;} 
    float get_f_green() const {return green_/255.0;} 
    float get_f_blue() const {return blue_/255.0;} 
    float get_f_alpha() const {return alpha_/255.0;} 

    unsigned int rgba() {return (red_<<24)|(green_<<16)|(blue_<<8)|(alpha_<<0);} 
}; 
+0

興味深い...私は符号なし整数として格納していたと思います。なぜなら、rgbaメソッドはctorsとgetters/setterに比べてもっと多く呼び出されると期待しているからです。その好みの理由は何ですか? –

+0

基本的には、移植性。いくつかのアプリケーションではargb、rgba、ある種のrbgが必要です...また、エンディアンの問題の恐れはありません...あなたはそうですが、ほとんどの場合、unsigned int rgbaが高速になるでしょう。 –

2

すべての可能性についてクラスを作成したいと考えています。これは間違っています。 1つのクラスですべての問題を処理できます。

まず、GPUでカラーデータの4倍[0,1]浮動小数点数が予測され、浮動小数点[0、1]は[0、255] RGBカラーよりも正確です。つまり、float 0,1からchar 0,255に行くのは損失です。これらの2つの事実は、現実的には4x [0、1]を実装として使用する以外に選択肢がないことを意味します。 [0、255]のアクセサとコンストラクタを提供するかどうかは、あなた次第です。

第2に、同じクラスのRGBとRGBAを簡単にサポートするには、Aをこのように1にするだけで、Aを扱いたくない人はいなくてもかまいません。

+0

4x [0,1]浮動小数点数の使用には4倍のメモリが必要です。これは、2Kビデオフレームなどの非常に大きな画像を操作する一部のアプリケーションでは受け入れられません。 –

+0

私の考えはちょうどAndré - 素晴らしい点DeadMGを作っている間に、1024x1024テクスチャのRGBカラーを表現するのに16バイトを使うのは妥当でしょうか?私はそれよりはるかに高いだろうと思う。おそらく2048x2048?それは3バイトで合理的にうまく表現できるとき、無駄なメモリのように思えるでしょう... – berserkguard

+0

@Andre:私が知る限り、GPUは独自の圧縮アルゴリズムを使用しており、独自に実装する必要はありません。第二に、最新のハイエンドGPUにはVRAMの*ロット*が付属しています。 – Puppy