Physics Interaction and Update Code

The source code for the physics interaction (Example 11-54 and Example 11-55) and update (Example 11-56) are presented here for you to study. You can download the complete source code from http://www.threadingbuildingblocks.org/book. Look for errata and notes at this web site as well.

For more in-depth reading on this topic, Intel engineers wrote several articles covering the topic of threading games, which you can download at the web site as well.

Example 11-54. Physics interaction code: InteractTask

class InteractTask : public tbb::task
{
  SceneNode* m_node;
  size_t m_i;
  D3DBlackHole* m_bh;
    float m_universeRadius;
size_t m_DummyCount;

public:      // Interact all stars in task
InteractTask(SceneNode* node,
             size_t i,
             D3DBlackHole* bh,
             float universeRadius,
             size_t DummyCount)
    : m_node(node), m_i(i),
      m_bh(bh), m_universeRadius(universeRadius),
      m_DummyCount(DummyCount)
  {}
    tbb::task* execute()
  {
    if (m_node->getChildCount()) {
// High in scene graph, Create parallel domain tasks for the children
      size_t i;
      tbb::task_list list;
      tbb::task& c = *new(allocate_continuation()) tbb::empty_task();
      for (i = 0; i < m_node->getChildCount(); ++i) {
        list.push_back(*new(c.allocate_child())
          InteractTask(m_node->getChild(i),
                       i, m_bh, m_universeRadius, m_DummyCount));
      }
      c.set_ref_count((int)i);
      c.spawn(list);
    }
    if (m_node->getUserID() > 0) {
      // Low-level object tasks, interact each star serially
      D3DStar* pStar = (D3DStar*)m_node;
      float elapsedTime = g_elapsedTime - pStar->getTimeStamp();
      // TODO: check accuracy of interaction and decide:
      // 1. Skip interaction for this short period of time
      // 2. Split this long period of time to parts and
      //    interact for each
      pStar->setTimeStamp(g_elapsedTime);
      pStar->setElapsedTime(elapsedTime);
      if (!pStar->isAlive() && !pStar->isDying()) {
        pStar->Reset(m_bh, m_universeRadius);
        pStar->NextState();
      } else {
        // apply attraction to black hole
        pStar->Interact(elapsedTime, m_bh,
                           m_universeRadius, m_DummyCount);
        // apply attraction to every other star
        SceneNode* node = m_node->getParent();
        for (size_t j = (m_i + 1); j < node->getChildCount(); ++j) {
          pStar->Interact(elapsedTime,
                             (D3DStar*)node->getChild(j),
                             m_DummyCount);
        }
      }
    }
    return NULL;
    }
};

Example 11-55. Physics interaction code: UpdateTask

class UpdateTask : public tbb::task
{
  SceneNode* m_node;

public: // Update all star positions based on
        // interactions in this frame
  UpdateTask(SceneNode* node)
    : m_node(node)
  {}
    tbb::task* execute()
  {
    if (m_node->getChildCount()) {
      // High in scene graph, Create parallel
      // domain tasks for the children
      size_t i;
      tbb::task_list list;
      tbb::task& c = *new(allocate_continuation()) tbb::empty_task();
      for (i = 0; i < m_node->getChildCount(); ++i) {
        list.push_back(*new(c.allocate_child())
          UpdateTask(m_node->getChild(i)));
      }
      c.set_ref_count((int)i);
      c.spawn(list);
    }
    if (m_node->getUserID() > 0) {
// Low-level object tasks, update each star serially
      D3DStar* pStar = (D3DStar*)m_node;
      // Matrix transformation
      pStar->Update(pStar->getElapsedTime());
   }
   return NULL;
   }
};

Example 11-56. Update Code

void World::Update(void)
{
  static __itt_event ev = __itt_event_create("update", 6);
// Lock out changing k-d tree until interactions
// and updates are done.
Lock();
  __itt_event_start(ev);
  tbb::tick_count t0 = tbb::tick_count::now();
  if (isParallel() && !isChanged()) {
    InteractTask& task = *new(tbb::task::allocate_root())
                                  InteractTask(m_bh, 0, m_bh,
                                               m_universeRadius,
                                               m_DummyCount);
    tbb::task::spawn_root_and_wait(task);
  } else {
// Sequential equivalent to threaded version in InteractTask
    for (size_t i = 0; i < m_bh->getChildCount(); ++i) {
      GroupNode* grp = (GroupNode*)m_bh->getChild(i);
      for (size_t j = 0; j < grp->getChildCount(); ++j) {
        D3DStar* pStar = (D3DStar*)grp->getChild(j);
        float elapsedTime = g_elapsedTime - pStar->getTimeStamp();
        pStar->setTimeStamp(g_elapsedTime);
        pStar->setElapsedTime(elapsedTime);
        if (!pStar->isAlive() && !pStar->isDying()) {
          pStar->Reset(m_bh, m_universeRadius);
          pStar->NextState();
          continue;
        }
        // apply attraction to black hole
        pStar->Interact(elapsedTime, m_bh,
                        m_universeRadius, m_DummyCount);
        // apply attraction to every other star in group
        for (size_t k = (j + 1); k < grp->getChildCount(); ++k) {
          pStar->Interact(elapsedTime,
                          (D3DStar*)grp->getChild(k),
                          m_DummyCount);
        }
      }
    }
  }
  tbb::tick_count t1 = tbb::tick_count::now();
  m_UpdateTime = (t1-t0).seconds();
  __itt_event_end(ev);

  t0 = tbb::tick_count::now();
  if (isParallel() && !isChanged()) {
    UpdateTask& task = *new(tbb::task::allocate_root())
                              UpdateTask(m_bh);
    tbb::task::spawn_root_and_wait(task);
  } else {
// Sequential equivalent to threaded version in UpdateTask
    for (size_t i = 0; i < m_bh->getChildCount(); ++i) {
      GroupNode* grp = (GroupNode*)m_bh->getChild(i);
      for (size_t j = 0; j < grp->getChildCount(); ++j) {
        D3DStar* pStar = (D3DStar*)grp->getChild(j);
        // Matrix transformation
        pStar->Update(pStar->getElapsedTime());
      }
    }
  }
  float elapsedTime = g_elapsedTime - m_bh->getTimeStamp();
  m_bh->setTimeStamp(g_elapsedTime);
  m_bh->setElapsedTime(elapsedTime);
  // update Black Hole
  m_bh->Update(elapsedTime);
  t1 = tbb::tick_count::now();
  m_TransformTime = (t1-t0).seconds();

  // Balance groups here (every 10 frame)
  static int balance_counter = 0;
  if (!(balance_counter % 10)) {
    for (size_t i = 0; i < m_bh->getChildCount(); ++i) {
      GroupNode* grp = (GroupNode*)m_bh->getChild(i);
      for (size_t j = 0; j < grp->getChildCount(); ++j) {
        D3DStar* pStar = (D3DStar*)grp->getChild(j);
        if (pStar->isAlive() &&
            !grp->isInGroup(pStar->getLocation(0),
                            pStar->getLocation(1),
                            pStar->getLocation(2))) {
          for (size_t k = 0; k < m_bh->getChildCount(); ++k) {
            GroupNode* ngrp = (GroupNode*)m_bh->getChild(k);
            if (ngrp != grp &&
                ngrp->isInGroup(pStar->getLocation(0),
                                pStar->getLocation(1),
                                pStar->getLocation(2))) {
              grp->removeChild(pStar);
              ngrp->addChild(pStar);
            }
          }
        }
      }
    }
  }
  Unlock(); // Ok, now permit changing the k-d tree.
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.103.5