DirectX如何构建一个太阳系

基本上都是之前学过的知识,要运用好!总结运用的知识有:

1 物体移位选择(transformation)

2 树形数据结构管理整个场景的信息

3 根据时间控制恒星旋转

如下效果:

首先设置太阳系各恒星的数据结构

 枚举太阳,恒星和月亮三个对象类

// We classify the objects in our scene as one of three types.
enum SolarType
{
     SUN,
     PLANET,
     MOON
};

数据结构保存各个信息:

struct SolarObject
{
      void set(SolarType type, D3DXVECTOR3 p, float yRot,
               int parentIndex, float s, IDirect3DTexture9* t)
      {
           typeID = type;
           pos    = p;
           yAngle = yRot;
           parent = parentIndex;
           size   = s;
           tex    = t;
      }

      // Note: The root's "parent" frame is the world space.

      SolarType typeID;//据此确定是什么类型,好确定相对应的纹理,大小等。
      D3DXVECTOR3 pos;  // 相对父母节点的位置.
      float yAngle;     // 相对父母节点的角度.
      int parent;       // 父母索引根节点为-1
      float size;       // 大小就是相对于世界坐标的大小了.
      IDirect3DTexture9* tex;
      D3DXMATRIX toParentXForm;
      D3DXMATRIX toWorldXForm;
};

定义一个数组保存三个节点的信息(其中每个节点含三个恒星),含根节点,则需要10个节点,如下:

static const int NUM_OBJECTS = 10;
SolarObject mObject[NUM_OBJECTS];

mObject[j]的父母节点是mObject[mObject[j].parent]。

下面是设置其整个太阳系各个恒星的坐标位置及相关信息的代码:

// Create the textures.
HR(D3DXCreateTextureFromFile(gd3dDevice, "sun.dds", &mSunTex));
HR(D3DXCreateTextureFromFile(gd3dDevice, "planet1.dds", &mPlanet1Tex));
HR(D3DXCreateTextureFromFile(gd3dDevice, "planet2.dds", &mPlanet2Tex));
HR(D3DXCreateTextureFromFile(gd3dDevice, "planet3.dds", &mPlanet3Tex));
HR(D3DXCreateTextureFromFile(gd3dDevice, "moon.dds", &mMoonTex));

D3DXVECTOR3 pos[NUM_OBJECTS] =
{
      D3DXVECTOR3(0.0f, 0.0f, 0.0f),
      D3DXVECTOR3(7.0f, 0.0f, 7.0f),
      D3DXVECTOR3(-9.0f, 0.0f, 0.0f),
      D3DXVECTOR3(7.0f, 0.0f, -6.0f),
      D3DXVECTOR3(5.0f, 0.0f, 0.0f),
      D3DXVECTOR3(-5.0f, 0.0f, 0.0f),
      D3DXVECTOR3(3.0f, 0.0f, 0.0f),
      D3DXVECTOR3(2.0f, 0.0f, -2.0f),
      D3DXVECTOR3(-2.0f, 0.0f, 0.0f),
      D3DXVECTOR3(0.0f, 0.0f, 2.0f)
};

mObject[0].set(SUN, pos[0], 0.0f, -1, 2.5f, mSunTex);       // Sun
mObject[1].set(PLANET, pos[1], 0.0f, 0, 1.5f, mPlanet1Tex); // P1
mObject[2].set(PLANET, pos[2], 0.0f, 0, 1.2f, mPlanet2Tex); // P2
mObject[3].set(PLANET, pos[3], 0.0f, 0, 0.8f, mPlanet3Tex); // P3

mObject[4].set(MOON, pos[4], 0.0f, 1, 0.5f, mMoonTex); // M1P1
mObject[5].set(MOON, pos[5], 0.0f, 1, 0.5f, mMoonTex); // M2P1
mObject[6].set(MOON, pos[6], 0.0f, 2, 0.4f, mMoonTex); // M1P2
mObject[7].set(MOON, pos[7], 0.0f, 3, 0.3f, mMoonTex); // M1P3
mObject[8].set(MOON, pos[8], 0.0f, 3, 0.3f, mMoonTex); // M2P3
mObject[9].set(MOON, pos[9], 0.0f, 3, 0.3f, mMoonTex); // M3P3


然后根据这些信息构建好各个对象的转换到世界坐标的矩阵。

void SolarSysDemo::buildObjectWorldTransforms()
{
      // First, construct the transformation matrix that transforms
      // the ith bone into the coordinate system of its parent.

      D3DXMATRIX R, T;
      D3DXVECTOR3 p;
      for(int i = 0; i < NUM_OBJECTS; ++i)
      {
            p = mObject[i].pos;
            D3DXMatrixRotationY(&R, mObject[i].yAngle);
            D3DXMatrixTranslation(&T, p.x, p.y, p.z);
            mObject[i].toParentXForm = R * T;
      }//构建每个节点到父母节点的坐标
 
      // For each object...
      for(int i = 0; i < NUM_OBJECTS; ++i)
      {
            // 跟节点的矩阵.
            D3DXMatrixIdentity(&mObject[i].toWorldXForm);

            // 循环计算各个节点转换到世界坐标的矩阵.
            int k = i;
            while( k != -1 ) //-1作为一个标兵,用好标兵技术很好的.
            {
                  mObject[i].toWorldXForm *= mObject[k].toParentXForm;
                  k = mObject[k].parent; // Move up the ancestry chain.
            }
      }
}


让太阳系动起来:

void SolarSysDemo::updateScene(float dt)
{
      // dt是时间,各个恒星随时间流逝而转动.
      for(int i = 0; i < NUM_OBJECTS; ++i)
      {
            switch(mObject[i].typeID)
            {
            case SUN:
                  mObject[i].yAngle += 1.5f * dt;
                  break;
            case PLANET:
                  mObject[i].yAngle += 2.0f * dt;
                  break;
            case MOON:
                  mObject[i].yAngle += 2.5f * dt;
                  break;
            }

            // 转到360度就置零.
            if(mObject[i].yAngle >= 2.0f*D3DX_PI)
                  mObject[i].yAngle = 0.0f;
      }
}

结果如下:

        

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值