NiSkinInstance는 NiGeometry객체에서 얻어올 수 있다.
추가적으로 NiGeometry객체는 NiOvject객체를 캐스팅하여 사용할 수 있다.
아래는 NiGeometry의 GetSkinInstance()와 SetSkinInstance()를 통해서 접근할 수 있다.


: NiSkinInstance* GetSkinInstance() const
: void SetSkinInstance(NiSkinInstance* pkSkinInstance)
- Skinning is achieved in Gamebryo by attaching an NiSkinInstance object to an NiGeometry object. These functions provide access to the NiSkinInstance object associated with an NiGeometry object. Unskinned NiGeometry objects have their NiSkinInstance pointer set to NULL. NiGeometry stores its NiSkinInstance reference as a smart pointer. In the current release of Gamebryo, the only classes derived from NiGeometry that support skinning are NiTriShape and NiTriStrips.



겜브리오에서 스키닝 정보는 NiGeometry오브젝트에 NiSkinInstance에 attach되어 있다. 이 함수는 NiGeometry와 연관된 NiSkinInstance오브젝트에 접근할 수 있도록 제공한다.NiSkinInstance정보가 없는 NiGeometry는 NULL포인터로 초기화되어있다. 오로지 NiGeometry의 베이스 클래스를 상속받은 NiTriShape와 NiTriStrips가 스키닝 될 수 있도록 도와준다.

Trackback Address :: http://daylogs.tistory.com/trackback/12

댓글을 달아 주세요

nif파일로 만든 이펙트가 나오지 않았더랬다.
어떤건 나오고, 또 어떤건 안나오고, 또 어떤건 애니메이트 되지 않고,
죽을라면 아얘 죽지 이런 상황이 발생하니깐 참 난감 했더랬다.
그런데 부장님께서 훑어보시더니 이펙트 노드의 타임컨트롤러 리셋애니메이션하지 안아서 않되는 거였단다.
않되서 겜브리오 코어 쪽 역시 살펴봤는데 하위 버젼에서 익스포트 했더라도 상위 버젼에서는 보이게끔 다양한 철를 해주고 있었다. 애니메이션 처리를 해보지 않아서 타임 컨트롤러에 익숙치 않는데 타임컨트롤러 쓰는건 잘 살펴봅시다.

Trackback Address :: http://daylogs.tistory.com/trackback/11

댓글을 달아 주세요

more..



이런식으로는 짜보지 않아서 기발하다는 생각이 들었다.
역시 하하의 공백은 너무 커-_-;

Trackback Address :: http://daylogs.tistory.com/trackback/10

댓글을 달아 주세요

패킷 분석 방법론? 말은 거창하나 유지보수팀이나 개발 중간에 투입이 되게 된다면 온라인상에서 게임을 플레이하면서 어떤 패킷이 오고가나를 로그로 남겨보고 이를 바탕으로 코드를 분석할 수 있는 방법도 있는것 같다. 새로오신 서버프로그래머 분께서 찍으신 로그 정보를 간단히 살펴보면 아래와 같다.

08/04/22 11:41:11> packet send = 517 PTC_GAME_NEWENTITY_MONSTER_BRD
08/04/22 11:41:11> packet recv = 514 PTC_GAME_ENTER_MAP


궂이 이 정도만을 로그로 찍어보고 패킷의 종류를 살펴보면 되겠다. 해당 프로토콜에 어떠한 정보가 담겨있는지는 패킷 분석이 완료되면 해도 될 것 같다고 생각한다.

Trackback Address :: http://daylogs.tistory.com/trackback/9

댓글을 달아 주세요

  1. 홍길동 2008/05/16 08:27 Address Modify/Delete Reply

    ..

비쥬얼어시스트 최신

2008/04/17 17:30

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

환경변수

엔비트/개발팁 2008/04/08 22:12 |
환경변수라는 것 때문에 오후 내내 삽질을 했다.
배치파일을 통해서 빌드를 수행하는데 자꾸 이 녀석이 빌드에 실패하는거다.
결국 팀장님께 여쭌 결과 환경변수에 비쥬얼스튜디오의 경로를 설정해주지 않아서 그렇다고 한다.
배치파일이 환경변수에 있는 경로를 가져와서 해당 솔루션과 연결 시켜주는데 환경변수에 비쥬얼스튜디오의 환경변수값이 없어서 그렇게 된거라고 한다.
환경변수라는 놈에 대해서 알아 볼 필요가 있겠다.

- 환경변수란?

Trackback Address :: http://daylogs.tistory.com/trackback/7

댓글을 달아 주세요

 여러가지 다양한 게임 엔진을 사용하기 위해서는 각 버젼의 솔루션을 빌드해줘야 한다. 이때 배치파일을 이용하면 이걸 손쉽게 해결 할 수 있다. 먼저, 배치 파일을 사용하기 위해서는 환경변수를 추가해준다. 비쥬얼스튜디오가 설치되어 있는 폴더에 devenv가 위치한 경로를 내컴퓨터의 환경변수에 추가해준다. 이때 "경로어쩌고저쩌고" 이 처럼 콤마를 통해서 경로를 작성한다. 배치파일을 통해서는 해당옵션을 주면 된다. 최근에는 vsvars32.bat파일을 포함해주지 않아도 된다고 한다. 그 밖에도 파이썬을 통한 배치파일의 작성, C의 문자열 처리를 통한 작성 등 다양한 방법으로 배치파일을 만들 수 있겠다. CEGUI의 make파일도 자동화된 빌드 시스템의 한 예가 되겠다.

배치파일을 만드는 법에 대해 공부해두자. 쓰레드는 아래의 URL을 참고하자.
http://www.gpgstudy.com/forum/search.php?mode=results

Trackback Address :: http://daylogs.tistory.com/trackback/6

댓글을 달아 주세요

덤프?

엔비트/개발팁 2008/04/04 18:28 |
덤프에 대해서는 자세히 알아보고 일단은 사용법 부터 올려 놓겠다.

- 사용법
프로그램이 죽으면 덤프를 생성하게끔 만들어놨다면 덤프가 특정 상황에 생길 것이다.
이때 덤프파일과 실행파일을 같은 폴더에 넣어놓고 덤프파일을 비쥬얼스튜디오에서 열어준다.
play를 시키면 죽었을 때와 같은 상황이 발생하게 되며 특정 영역에서 호출스택을 확인할 수가 있게 되겠다.
메모리는 디스어셈블러에서 메모리영역을 확인할 수가 있다.
서비스시에 유저의 덤프파일 생성시 해당 덤프를 서버로 날려주는 방식으로 처리를 할 수가 있겠다.
덤프파일을 사용하기 위한 디펜던시는 비쥬얼스튜디오2005에서는 dbghelp.dll을 함께 배포해줘야 하겠다.
+ 추가적으로 덤프파일을 확인할 때는 실행파일의 빌드버젼과 동일한 덤프파일로 테스트를 해줘야한다.
이에 대한 관리 역시 해줘야 겠다.

- 덤프란?

Trackback Address :: http://daylogs.tistory.com/trackback/5

댓글을 달아 주세요

 HP게이지와 SP게이지를 만들어 주고 업데이트 하는 부분의 함수 이름이 CreateHpGauge(full.., current..)
처럼 되있다. Crete라기 보다는 Update라는 이름이 더 어울린다. 해당 매서드 내에서는 버퍼를 지우고, 캐릭터의 정보를 얻어와 offset을 계산해준 후 버퍼에 sp, hp게이지를 그려준다. 또한 이러한 매서드가 작동하는 곳의 클래스명이 Nui_NamePlateText객체 인데 이 이름 역시 잘못 됐다고 본다. 텍스트 뿐만이 아니라 hp, sp에 대한 렌더링 작업 까지 담당하며 빌보드 노드에 붙어 작동하는 3D오브젝트와 연관이 있는 클래스인ㄷ UI라는 이름 역시 잘 못됐다. 이 부분을 내일 중에 수정하기로 하겠다.

Trackback Address :: http://daylogs.tistory.com/trackback/4

댓글을 달아 주세요

- 작동원리
 리스트박스 컨트롤은 텍스트 갱신에 따라 업데이트가 자주 호출이 되므로 컨트롤 내 윈도우를 포함한다.
Nui_WindowBase와 Nui_ListboxText를 포함하게 된다. 여기에서 문제는 Nui_ListboxText의 작동방식에 있다. 먼저 PushText()매서드를 호출하면 현재의 텍스트리스트에 추가 시키기 되는데 이때 FreeType과 연동하여 윈도우의 넓이와 비교하는데 만약 넘친다면 쪼개서 관리하게 된다. 기존 CEGUI에서는 문자열의 길이가 라인을 넘어가도 리스트 자체에서는 동일하게 관리를 했는데 여간불편하게 아니었다. 그리고 이렇게 완성된 문자열은 버퍼에 덮어 쓰게 되는데 버퍼에 쓸 때는 텍스트리스트에서 rbegin() - rend()로 돌면서 버퍼에 쓰도록 한다. currentTop은 윈도우의 높이값에서 라인 스페이싱 만큼을 뺀 값에서 출발하며 다음 문자열을 출력할 때 마다 라인스페이싱 만큼을 계속적으로 빼가며 버퍼에 써준다. 버퍼에 쓰기가 완료 되었다면 업데이트를 통해 다이나믹텍스쳐에 Lock()을 걸고 버퍼에 있는 내용을 복사해준다.

- 현재 문제점
문자열을 돌면서 버퍼에 텍스트비트맵의 내용을 기록하는데 이때 관리가 되질 않아 현재는 문자열이 겹쳐져서 한 곳에만 출력이 되고 있다. 문제점은 작동원리의 "이렇게 완성된 문자열은 버퍼에 덮어 쓰게 되는데 버퍼에 쓸 때는 텍스트리스트에서 rbegin() - rend()로 돌면서 버퍼에 쓰도록 한다. currentTop은 윈도우의 높이값에서 라인 스페이싱 만큼을 뺀 값에서 출발하며 다음 문자열을 출력할 때 마다 라인스페이싱 만큼을 계속적으로 빼가며 버퍼에 써준다." 이 부분을 처리해주지 않아서 발생하는 것이다. 내일 오전 중에 이러한 부분을 해결하고 오후 중에는 리스트박스컨트롤 작업을 끝내기로 하겠다. 물론 단위테스트도 실시하고 실행가능한 버젼으로 체크인 해논다.

- 코드샘플

 m_StringList.push_back(szText);
 DWORD** ppBuffer = m_pParentWindow->GetBuffer();
 int nCurrentLeft = 0;
 int nCurrentTop = m_pParentWindow->GetArea()->GetHeight() - m_uiLineSpacing;
 for(unsigned int i=m_StringList.size()-1; i<m_StringList.size(); i++)
 {
  std::string& currstr = m_StringList.at(i);
  WCHAR code[1024];
  int num_chars_mb = strlen(currstr.c_str());
  int num_chars = MultiByteToWideChar( CP_ACP, 0, currstr.c_str(), num_chars_mb, code, 1024);
  for ( int n = 0; n < num_chars; n++ )
  {
   FT_ULong ftcode = code[n];
   FontInfo* pFontInfo = Nui_FontManager::GetPtr()->GetGlyphMap(ftcode);
   if(!pFontInfo)
   {
    pFontInfo = Nui_FontManager::GetPtr()->CreateGlyphImage(ftcode);
    assert(pFontInfo);
   }
   if ( nCurrentLeft + pFontInfo->bitmap.width >= m_pParentWindow->GetArea()->GetWidth())
   {
    std::string& str1 = currstr.substr(0, n);
    std::string& str2 = currstr.substr(n, currstr.size());
    currstr.resize(str1.size());
    m_StringList.insert(m_StringList.begin()+m_StringList.size(), str2);
    break;
   }
   WriteToBuffer(pFontInfo, nCurrentLeft, nCurrentTop);
   nCurrentLeft += pFontInfo->bitmap.width;
  }
  nCurrentLeft = 0;
  nCurrentTop -= m_uiLineSpacing;
 }

 int nDeleteCount = m_StringList.size() - m_nMaxTextCount;
 if(nDeleteCount > 0)
 {
  m_StringList.erase(m_StringList.begin(), m_StringList.begin() + nDeleteCount);
 }
 m_pParentWindow->Update();

작동 문제가 있는 코드 중 한 부분이다.
문자열을 자르는 부분을 유심히 살펴보자.




 

Trackback Address :: http://daylogs.tistory.com/trackback/3

댓글을 달아 주세요