Что ж, если вы хотите, чтобы в центре было несколько нейтронов и протонов, а электроны находились снаружи на разных орбитах (модель Бора), то вам нужно несколько вещей.Мы можем просто поместить все протоны и нейтроны на поверхность сферы с небольшим радиусом (r = 1), а затем разместить электроны на сфере с радиусом, увеличивающимся в зависимости от орбитальной оболочки, на которой находится электрон.
Не выполняя всю работу за вас, вам понадобится класс атома.
Он будет иметь член, представляющий орбитальную оболочку с использованием индекса: i = 0 может быть самой внутренней оболочкой, а i> 0 определяетвнешние оболочки с электронами.
Затем вы можете вычислить радиус сферы, используя индекс в качестве функции-члена.Что-то вроде
radius() { return i * ShellDist + 1; }
, где ShellDist - это расстояние между электронными оболочками.
Вы можете создать класс для общего атома, учитывая его оболочку и тип.
class Atom {
public:
static const double ShellDist = 2; // remember to include a definition for this
Atom(int shell) : shell(shell) {}
virtual void radius() { return shell * ShellDist + 1; }
private:
int shell;
};
class Electron : public Atom {
public:
Electron(int shell) : Atom(shell) {}
};
class Neutron : public Atom {
public:
Neutron() : Atom(0) {}
};
Я предполагаю, что вы хотите, чтобы все точки на сфере находились на плоскости, совпадающей со сферой, причем плоскость проходит через начало координат.Чтобы упростить это, мы просто выберем круг, который идет вдоль экватора сферы, и затем повернем его, используя матрицу вращения R.
Таким образом, уравнение круга экватора, если z - вертикальная ось
Vector3d
circle(double t, double r) { return Vector3d(cos(t) * r, sin(t) * r, 0); }
Если z - наша вертикальная ось, то здесь z всегда равно нулю.
Затем выберите матрицу вращения R с использованием библиотеки векторной математики (я не уверен, какую из них вы используете).Обычно вы можете создать представление угла Эйлера.Поверните его на произвольную фиксированную величину вокруг осей x и y.Это будет вращать круг, поэтому мы помещаем все электроны на случайную круговую орбиту вокруг начала координат.Это использует Eigen:
Transform t = AngleAxis(rand() * 2 * M_PI, Vector3d(0, 1, 0))
* AngleAxis(rand() * 2 * M_PI, Vector3d(1, 0, 0));
Собираем это вместе:
Vector3d createPoint(const Atom& atom, double t) {
auto xform = AngleAxis(rand() * 2 * M_PI, Vector3d(0, 1, 0))
* AngleAxis(rand() * 2 * M_PI, Vector3d(1, 0, 0));
Vector3d electronPoint = xform * circle(t, atom.shellRadius());
return electronPoint;
}
Наконец, вы можете сложить все точки вместе для всех атомов в вашем исходном массиве
vector<Vector3d> getPoints() {
vector<shared_ptr<Atom>> atoms;
// construct your atoms depending on the molecule
// eg.
atom.push_back(make_shared<Electron>(1)); // Create an electron on shell 1
atom.push_back(make_shared<Neutron>()); // Create a neutron, which will be shell 0
vector<Vector3d> points;
for (const auto& atom : atoms) {
// instead of rand() you could use some scaling
// of the current time to get an animation with the shells orbiting,
points.push_back(createPoint(atom, rand()));
}
}
Наконец, вы можете передать этот вектор точек в irrlicht.Возможно, вы захотите сгенерировать этот кадр каждый раз, если хотите анимацию.
Удачи!У Irrlicht, вероятно, есть встроенная матричная библиотека, которая также может помочь.Если вы действительно хотите ускорить процесс, вы можете создать собственные вершинные шейдеры, которые выполняют всю эту математику на GPU, а затем просто передают электроны.Это не будет необходимо для любых известных молекул, хотя :).Вы также можете хотеть фиксированное смещение на электрон.Все это можно сделать, добавив параметры в конструкторы Electron и Neutron, чтобы изменить начало их орбиты.