Легко разыгрывается между математическими библиотеками - PullRequest
2 голосов
/ 23 февраля 2012

Я использую две математические библиотеки в игровом проекте.Одна - это библиотека GLM , а другая - математическая часть Box2D .Иногда необходимо преобразование между ними, например:

b2Vec2 vec1(1.0f, 1.0f);
glm::vec2 vec2(vec1.x, vec1.y);

Мне интересно, есть ли лучший способ сделать это более плавно, без редактирования какой-либо библиотеки?

Ответы [ 3 ]

3 голосов
/ 23 февраля 2012

Я думаю, что преобразование не может быть сделано неявным образом без изменения библиотек.

Однако, чтобы упростить ваш код преобразования, вы можете реализовать простые функции преобразования, например:

inline glm::vec2 make_glmVec2(const b2Vec2 &v) {
    return glm::vec2(v.x, v.y);
}
inline glm::vec3 make_glmVec3(const b2Vec3 &v) {
    return glm::vec3(v.x, v.y, v.z);
}

Если существует (почти) прямое соответствие между типами этих двух библиотек, вы можете даже использовать более простое имя для всех ваших функций преобразования, например toGlm, и просто перегрузить его для всех необходимых вам типов:

inline glm::vec2 toGlm(const b2Vec2 &v) {
    return glm::vec2(v.x, v.y);
}
inline glm::vec3 toGlm(const b2Vec3 &v) {
    return glm::vec3(v.x, v.y, v.z);
}

Редактировать

Я попытался реализовать прокси-класс, который мог бы работать в качестве моста между вашими двумя классами из двух библиотек. Прокси-класс содержит конструкторы и операторы приведения, которые позволяют создавать в и из этих классов. К сожалению, вам нужно явно вызвать конструктор, иначе компилятор даже не подумает об использовании этого класса:

//Library 1:
class Vec1 {
public:
  int x;
  int y;
  Vec1(int _x, int _y) : x(_x), y(_y) {}
};

//Library 2:   
class Vec2 {
public:
  int e1;
  int e2;
  Vec2(int _x, int _y) : e1(_x), e2(_y) {}
};

//Your code

class VecProxy {
public:
  int pxX;
  int pxY;

  VecProxy(const Vec1& v1) : pxX(v1.x), pxY(v1.y) {}
  VecProxy(const Vec2& v2) : pxX(v2.e1), pxY(v2.e2) {}

  operator Vec1() {return Vec1(pxX, pxY); }
  operator Vec2() {return Vec2(pxX, pxY); }

};

int main() {
  Vec1 v1(2,3);
  Vec2 v2=VecProxy(v1);
  Vec1 v3=VecProxy(v2);
}

Обратите внимание, что вы можете использовать одно и то же имя, независимо от того, в каком направлении вы читаете, что может быть немного лучше, чем мое предыдущее предложение выше. Я не думаю, что вы можете заставить конструктор вызываться неявно.

2 голосов
/ 23 февраля 2012

Теоретически вы можете добавить операторы неявного преобразования в одну или обе библиотеки (хотя неявные преобразования не всегда являются хорошей идеей).Но вы сказали, что не можете редактировать ни одну из библиотек, так что это исключено.

Таким образом, одной из альтернатив будет введение вашего собственного векторного класса и предоставление ему необходимых операторов преобразования.Затем, когда вам нужен вектор в вашем коде, вы всегда сохраняете его как объект вашего пользовательского класса и (неявно) конвертируете, когда вам нужно использовать библиотеки.

Но, опять же, проблема в том, что неявное преобразование можетпричина может перевесить поверхностные выгоды (подробнее см. пункт 5 Более эффективный C ++ ).

1 голос
/ 15 октября 2013

Я знаю, что это немного устарело, но недавно я столкнулся с той же ситуацией с моим текущим проектом.Я хотел поделиться своим решением, которое хорошо работает для меня.Это только те типы, которые я использую чаще всего (я определил типы для более простой (читай: ленивее) печати в моем проекте)Это может быть расширено / изменено более вероятно, но, надеюсь, это даст другой вариант любому, кто использует эти две библиотеки вместе.

...