2007年7月8日 星期日

Lost Horizon



我最喜歡的一段歌詞.. 

What about the life...
that shined so bright once in your eyes?
What about the death... faith you lost...
so that was your quest?
What about the dreams...
there where no visions in your grief?
What about the fight...
that graced your life?


Water, fire, wind and soil
My soul came to be reborn
As the lightning thrashes black skies
The spirit fills my mind

Welcome back, to the days of thunder!
Welcome back, to the days where you were born!
Welcome back, to break the spell you're under!
Welcome back, to the days of thunder!
Welcome back, to the days where you were born!
Welcome back, to raise again your honour!

What about the life...
It shines so bright now in my eyes!
What about the death...
Faith I found, now life's my quest!
What about the dreams...
There're new visions in my grief!
What about the fight...
It graces my life!

Scene Tree

很久沒貼程式碼了,據說blog 要注重單一話題做定時更新才會有人氣,這對我來說還蠻難的~

 

Scene Tree,很多人討厭這東西。但是對我而言, 大型 3D 程式沒有 tree 根本活不下去。

 

在這邊貼出我的 Scene Tree,感覺上還有些 bug,如果有誰發現就請告知一下。

 

主體可使用 map 或 hash_map,blog 上沒辦法縮排,有興趣看的人請自便吧。

 

順便一提,用 hash_map 是 47 號同學的主意。

 

#ifndef SceneTreeNode_H
#define SceneTreeNode_H

#pragma once

#ifndef _XBOX
#include <windows.h>
#endif

#ifdef _XBOX
#include <xtl.h>
#endif


#include <d3dx9math.h>
#include <string>


#include "safemacro.h"
//#include "SceneTreeNode.h"
/*
use std::map for now,
we can change it into hash_map later
*/
#include <map>

class CSceneTreeNode;

typedef std::map<std::string, CSceneTreeNode*> SceneTreeMap;
typedef std::map<std::string, CSceneTreeNode*>::iterator SceneTreeMapIterator;
typedef std::pair<std::string, CSceneTreeNode*> SceneTreePair;
typedef std::pair<SceneTreeMapIterator,bool> SceneTreeOperationReturnValue;

class CSceneTreeNode
{
public:
 CSceneTreeNode();
 virtual ~CSceneTreeNode();
 ///////////////////////////////////////////////////////////////////////////
 //scene tree operation
 ///////////////////////////////////////////////////////////////////////////

 //And new node, return new node pointer, return NULL if fail
 CSceneTreeNode* AddNewChildNode(std::string* pName);
 //And kill all it's child node
 HRESULT DeleteChildNode(std::string* pName);
 // If this node's parent isn't NULL, call DisAttachThisNodeFromParent() automatically
 HRESULT AttachThisNodeToNewParent(CSceneTreeNode* pNewParent);
 // split node from parent , this node will be new tree root
 HRESULT DisAttachThisNodeFromParent();
 void DeleteAllChild();

 CSceneTreeNode* FindChildNodeByName(std::string* pName);
 CSceneTreeNode* GetParentNode();
 ///////////////////////////////////////////////////////////////////////////
 //node matrix operation
 ///////////////////////////////////////////////////////////////////////////

 HRESULT SetLocalMatrix(D3DXMATRIX* pMatrix);
 HRESULT SetGlobalMatrix(D3DXMATRIX* pMatrix);
 const D3DXMATRIX* GetLocalMatrix();
 const D3DXMATRIX* GetGlobalMatrix();

 // flag == true 才 update
 HRESULT UpdateChildNode();
 // flag == false 就 recursive , flag == true 就呼叫 UpdateChildNode();
 HRESULT UpdateChildNodeFromSceneRoot();

protected:
 //flag operation  (self dirty)
 HRESULT SetAllChildNeedUpdateFlag(bool bFlag);
 //flag operation  (some child dirty)
 HRESULT SetAllParentSomeChildNeedUpdate(bool bFlag);

 std::string m_Name;
 SceneTreeMap m_ChildNodeMap;
 D3DXMATRIX m_LocalMatrix;
 D3DXMATRIX m_GlobalMatrix;

 /*
  m_bSomeChildNeedUpdateFlag => reduce recursive pass
  m_bNeedUpdateFlag => reduce matrix multiplication
 */
 bool m_bNeedUpdateFlag;
 bool m_bSomeChildNeedUpdateFlag;
 CSceneTreeNode* m_pParent;

 

};

#endif

 

// 上面是 h , 下面是 cpp

 

 

#include "SceneTreeNode.h"

CSceneTreeNode::CSceneTreeNode()
{
 m_Name = "";
 m_pParent = NULL;
 m_bNeedUpdateFlag = false;
 m_bSomeChildNeedUpdateFlag = false;
 D3DXMatrixIdentity(&m_LocalMatrix);
 D3DXMatrixIdentity(&m_GlobalMatrix);
}

CSceneTreeNode::~CSceneTreeNode()
{
 if(m_ChildNodeMap.empty() == false)
 {
  DeleteAllChild();
 }
 m_pParent = NULL;
}
///////////////////////////////////////////////////////////////////////////
//scene tree operation
///////////////////////////////////////////////////////////////////////////

CSceneTreeNode* CSceneTreeNode::AddNewChildNode(std::string* pName)
{
 SceneTreeMapIterator pos;
 pos = m_ChildNodeMap.find(*pName);
 if( pos == m_ChildNodeMap.end() )
 {
  CSceneTreeNode* pNewSceneTreeNode = new CSceneTreeNode;
  m_ChildNodeMap.insert(SceneTreePair(*pName, pNewSceneTreeNode));
  pNewSceneTreeNode->SetGlobalMatrix(&m_GlobalMatrix);
  pNewSceneTreeNode->m_pParent = this;

  return pNewSceneTreeNode;
 }
 return NULL;
}
HRESULT CSceneTreeNode::DeleteChildNode(std::string* pName)
{
 SceneTreeMapIterator pos;
 pos = m_ChildNodeMap.find(*pName);
 if( pos != m_ChildNodeMap.end() )
 {
  SAFE_DELETE(pos->second);
  return S_OK;
 }
 return E_FAIL;

}
HRESULT CSceneTreeNode::AttachThisNodeToNewParent(CSceneTreeNode* pNewParent)
{
 if(m_pParent != NULL)
  DisAttachThisNodeFromParent();
 
 SceneTreeOperationReturnValue result;
 result = (pNewParent->m_ChildNodeMap).insert(SceneTreePair(m_Name, this));
 if(result.second ==false)
  return E_FAIL;
 m_pParent = pNewParent;
 return S_OK;
}
HRESULT CSceneTreeNode::DisAttachThisNodeFromParent()
{
 if(!m_pParent)
  return E_FAIL;

 SceneTreeMapIterator pos;
 pos = (m_pParent->m_ChildNodeMap).find(m_Name);
 if(pos == (m_pParent->m_ChildNodeMap).end())
  return E_FAIL;

 pos->second = NULL;
 (m_pParent->m_ChildNodeMap).erase(pos);
 m_pParent = NULL;

 return S_OK;
}
void CSceneTreeNode::DeleteAllChild()
{
 SceneTreeMapIterator pos;
 //DeleteAllChild recursive
 for(pos = m_ChildNodeMap.begin(); pos!=m_ChildNodeMap.end(); ++pos)
 {
  pos->second->DeleteAllChild();
  SAFE_DELETE(pos->second);
  //m_ChildNodeMap.~map();
 }
 //clean the Node Map
 if(m_ChildNodeMap.begin() != m_ChildNodeMap.end())
  m_ChildNodeMap.erase(m_ChildNodeMap.begin(),m_ChildNodeMap.end());
  
}

CSceneTreeNode* CSceneTreeNode::FindChildNodeByName(std::string* pName)
{
 SceneTreeMapIterator pos;
 pos = m_ChildNodeMap.find(*pName);
 if(pos != m_ChildNodeMap.end())
 {
  return pos->second;
 }
 else
  return NULL;

}
CSceneTreeNode* CSceneTreeNode::GetParentNode()
{
 return m_pParent;
}

///////////////////////////////////////////////////////////////////////////
//node matrix operation
///////////////////////////////////////////////////////////////////////////

HRESULT CSceneTreeNode::SetLocalMatrix(D3DXMATRIX* pMatrix)
{
 if(pMatrix)
 {
  m_LocalMatrix = *pMatrix;
  SetAllChildNeedUpdateFlag(true);
  SetAllParentSomeChildNeedUpdate(true);
  return S_OK;
 }

 return E_FAIL;
}
HRESULT CSceneTreeNode::SetGlobalMatrix(D3DXMATRIX* pMatrix)
{
 //注意矩陣乘法順序
 //[L] * [Par_G] = [G]
 //[L] = [G] * [Par_G]^-1
 if(pMatrix)
 {
  m_GlobalMatrix = *pMatrix;
  SetAllChildNeedUpdateFlag(true);
  SetAllParentSomeChildNeedUpdate(true);
  if(m_pParent != NULL)
  {
   D3DXMATRIX ParentGlobalMatrixInverse;
   D3DXMatrixInverse( &ParentGlobalMatrixInverse, NULL, &(m_pParent->m_GlobalMatrix));
   D3DXMatrixMultiply( &m_LocalMatrix, &m_GlobalMatrix, &ParentGlobalMatrixInverse);
  }
  else
  {
   m_LocalMatrix = m_GlobalMatrix;
  }

  m_bNeedUpdateFlag = false;
  return S_OK;
 }
 return E_FAIL;
}
const D3DXMATRIX* CSceneTreeNode::GetLocalMatrix()
{
 return &m_LocalMatrix;
}
const D3DXMATRIX* CSceneTreeNode::GetGlobalMatrix()
{
 return &m_GlobalMatrix;
}

HRESULT CSceneTreeNode::UpdateChildNode()
{
 //注意矩陣乘法順序
 //[L] * [Par_G] = [G]
 if(m_bNeedUpdateFlag == true)
 {
  if(m_pParent != NULL)
  {
   D3DXMatrixMultiply( &m_GlobalMatrix, &m_LocalMatrix, &(m_pParent->m_GlobalMatrix));
  }
  else
  {
   m_GlobalMatrix = m_LocalMatrix;
  }
  
  m_bNeedUpdateFlag = false;
  m_bSomeChildNeedUpdateFlag = false;
  SceneTreeMapIterator pos;
  for(pos = m_ChildNodeMap.begin(); pos!=m_ChildNodeMap.end(); ++pos)
  {
   pos->second->UpdateChildNode();
  }
  return S_OK;
 }

 return E_FAIL;

}
HRESULT CSceneTreeNode::UpdateChildNodeFromSceneRoot()
{
 // keep on looking, while some child dirty
 if(m_bSomeChildNeedUpdateFlag == false)
 {
  return S_OK;
 }

 if(m_bNeedUpdateFlag == true)
 {
  UpdateChildNode();
  return S_OK;
 }

 SceneTreeMapIterator pos;
 for(pos = m_ChildNodeMap.begin(); pos!=m_ChildNodeMap.end(); ++pos)
 {
  pos->second->UpdateChildNodeFromSceneRoot();
  m_bSomeChildNeedUpdateFlag = false;
 }
 return S_OK;
}

// protected functions
HRESULT CSceneTreeNode::SetAllChildNeedUpdateFlag(bool bFlag)
{
 if( bFlag == m_bNeedUpdateFlag)
 {
  return E_FAIL;
 }

 m_bNeedUpdateFlag = bFlag;
 SceneTreeMapIterator pos;
 for(pos = m_ChildNodeMap.begin(); pos!=m_ChildNodeMap.end(); ++pos)
 {
  pos->second->SetAllChildNeedUpdateFlag(bFlag);
 }
 return S_OK;
}

HRESULT CSceneTreeNode::SetAllParentSomeChildNeedUpdate(bool bFlag)
{
 if(bFlag == m_bSomeChildNeedUpdateFlag)
 {
  return E_FAIL;
 }
 m_bSomeChildNeedUpdateFlag = bFlag;
 if(m_pParent != NULL)
  m_pParent->SetAllParentSomeChildNeedUpdate(bFlag);
 return S_OK;
}

 

2007年7月1日 星期日

Interview 的感覺就像?

去 Interview 的感覺就像路不熟的宅急便,鈴響三聲內本人服務。

 

而且我們可以發現,公司越大一棟,門牌號碼越不知道寫在哪裡。