如何使用irrlicht在C ++中创建原子模型

时间:2019-06-02 19:31:28

标签: c++ math irrlicht

我正在一个项目中,我展示了一个带有质子,中子和电子的原子模型。我想像原子模型那样展示中子和质子,所以我需要一些点来说明我的观点。所以我需要这样的功能

<list of points> getPoints(int numberOfProtonsAndNeutrons)

我尝试遍历纬度和经度,但无法获得间隔时间。这也不是原子模型的直观显示。

所以我需要一个想法,如何创造点来放置我的中子和质子。

1 个答案:

答案 0 :(得分:0)

好吧,假设您想要在中心有一些中子和质子,并且在各个轨道(玻尔模型)中有一些电子在外面,那么您需要一些东西。我们可以将所有质子和中子放在半径小的半径(r = 1)的球体表面上,然后将电子放置在半径根据球体所在的轨道壳而增加的球体上。

无需完成所有工作,您将需要一个atom类。

它将具有一个用索引表示轨道壳的成员: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构造函数中添加参数来更改其轨道起点来实现。