Иерархия классов для цветов - PullRequest
2 голосов
/ 31 декабря 2011

У меня проблемы с определением структуры класса, которая будет использоваться для хранения информации о цветах RGB / RGBA.

Я создаю очень простой движок для 3D-игр для развлечения и оттачивания моего OO-способности программирования.

Я бы хотел, чтобы мой движок поддерживал цвета RGB и RGBA.Кроме того, мне бы хотелось, чтобы значения RGB и RGBA можно было указывать как плавающие числа с ограничением на [0, 1] или беззнаковые символы.Я подумал, что для целей хранения было бы лучше использовать неподписанные символы, поскольку они используют в четыре раза больше памяти, чем числа с плавающей запятой.

Итак, теперь я разработал следующие классы, чтобы использовать для этого: Color, Color3,Color3f, Color3c, Color4, Color4f и Color4c.Color является суперклассом Color3 и Color4, в то время как Color3 является суперклассом Color3f и Color3c, так как Color4 с Color4f и Color4c.

Этот подход выглядит гораздо более сложным, чем необходимо.Я также немного подумал об использовании дженериков, поэтому вместо Color3f и Color3c можно было бы использовать Color3 и 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 в памяти.Это был бы массив с более чем миллионом этих цветов, так как я могу сделать иерархию классов Color гибкой и многократно используемой?то есть хранить значения RGB и RGBA в разных структурах с помощью неподписанных символов, но предоставлять функции для получения значений с плавающей запятой?

Извините, если это недостаточно конкретно, или что, это мой первый вопрос!Дайте мне знать, что еще будет полезно.Я могу опубликовать код того, что я пробовал до сих пор, если вы, ребята, предпочли бы, но, надеюсь, вы понимаете, чего я пытаюсь достичь.

Ответы [ 4 ]

3 голосов
/ 31 декабря 2011

Вам нужен только один класс Color (или предпочтительно Color)

Внутренне вы можете хранить значение как хотите, 32-битный беззнаковый int RGBA (или BGRA) является обычным, а затем просто использовать маски и битовые сдвиги для извлечения каждого компонента.

У вас могут быть конструкторы, которые берут Color(unsigned char red,unsigned char green,unsigned char blue, unsigned char alpha=0xff) или плавают

И аналогично методы получения / установки для каждого компонента в каждой форме.

edit: но если вы планируете какую-либо высокую производительность, изображение, состоящее из массива цветных объектов для каждого пикселя, вероятно, не подходит. Возможно, вы захотите взглянуть на набор статических функций для установки / получения каждого компонента и конструктор, который принимает пиксель в формате формата вашего изображения (то есть BGRA или RGB без знака int)

2 голосов
/ 01 января 2012

Вы хотите сделать класс для всех возможностей.Это просто неправильно.Один класс может справиться со всеми из них просто отлично.

Во-первых, ваш графический процессор будет ожидать 4x [0, 1] с плавающей запятой для цветных данных, а два с плавающей запятой [0, 1] гораздо точнее, чем [0, 255] RGB цвет.Это означает, что переход от числа с плавающей точкой 0,1 к символу 0, 255. потерян. Эти два факта означают, что у вас нет другого выбора, кроме как использовать 4x [0, 1] в качестве реализации.Независимо от того, предлагаете ли вы методы доступа и конструкторы для [0, 255], зависит только от вас.

Во-вторых, вы можете тривиально поддерживать RGB и RGBA в одном классе, просто установив значение по умолчанию A равным 1 - таким образом, любойкто не хочет иметь дело с А, не должен будет.

1 голос
/ 31 декабря 2011

Это просто кодирование того, что говорили другие, потому что это выглядит весело. Это не ответ.

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);}
};
1 голос
/ 31 декабря 2011

Замечание Xeo по поводу чрезмерной инженерии, и вы можете прочитать мой ответ о том, как избежать чрезмерной инженерии .Но весь смысл OO состоит в том, чтобы скрыть сложность, а не поощрять ее.

Начните с класса Color с некоторым эффективным внутренним представлением и перегрузите ctors для типов данных, которые вы хотите использовать в качестве аргументов.до тех пор, пока у вас нет необходимости для предоставления реализации, не беспокойтесь обо всех подклассах.Возьмите самый простой подход, который мог бы сработать.

...