블로그 이미지
Every unexpected event is a path to learning for you. blueasa

카테고리

분류 전체보기 (2861)
Unity3D (899)
Programming (479)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (192)
협업 (65)
3DS Max (3)
Game (12)
Utility (142)
Etc (99)
Link (34)
Portfolio (19)
Subject (90)
iOS,OSX (53)
Android (16)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (19)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday
옵션 재정리 작업중. 

convert : 카메라와 라이트를 익스포트 시킬 것인가 결정. 
체크를 꺼 놔도 3개의 라이트는 기본적으로 넘어가는데, 나머지는 프로그래머 몫.
디폴트 라이트 2 개는 없앨 수 없고, Ambient 라이트만 없앨 수 있다. 이것은 렌더링/ 인바이론먼트 에서 색상만 없애주면 된다. 

차이는 이렇다는 것이다. 눌러서 보셈. 

Texture
- 메인 NIF에 맵이 포함된다. 
- 맵으로 따로 NIF 를 생성한다.  
- 맵이 따로 링크로만 유지된다. 단 관리는 겜브리오에서 관리된다. 중간 관리가 실행되므로 약간 느려진다.
- 맵이 따로 링크로만 유지된다. 관리도 겜브리오에서 하지 않는다. 직접 연결해서. 지원되지 않는 포맷도 쓸 수 있게 해준다.

NPOT Texture
- 2의 배수가 아닌 텍스쳐도 넘길 수 있다. 옵션이 꺼지면 엔진에서 알아서 가까운 2의 배수로 텍스쳐 크기를 조정해 준다. 
그렇게 되면 밉맵이 생기지 않는다고 한다. (이것은 확인 불가)

Animation
APP 타임 - 어플리케이션의 타임을 이용할 것이냐의 문제 타이밍을 엔진에서 컨트롤 할 것이냐 맥스에서 컨트롤 할 것이냐를 결정하는 것으로, 인터페이스 등에서 사용될때 다르게 쓰일 수 있다. 프로그래머에게 의존할 것. 

Use existing Biped keyframes instead of sampled keyframes
바이패드 키의 익스포트 옵션. 키가 있을때만 넘길꺼냐 전부 셈플링 할거냐의 옵션 . 꺼놓으면 전부 셈플링 한다. 이것은 TCB 컨트롤러를 엔진에서 이용하지 않기 때문이다. 그러므로 옵션을 켜면 성능은 증가하는데 동작은 허접해질 수 있음.

Skin Weight Threshold %
기본으로 놔둬도 좋음. 5% 미만의 웨이트 값을 가진 버텍스는 웨이트가 삭제됨 


Export Selected
기본 인스포트에서 문제가 될 수 있는게, 카메라 옵션을 제거해도 카메라 타겟은 넘어간다는것.
그러므로 셀렉티드를 이용하면, 카메라 타겟도 넘어가지 않게 할 수 있다.

Use Original Script Templates If Available
맥스 파일에 있는 스크립트와 컴퓨터에 있는 익스포트 스크립트가 다를 때 , 맥스 파일에 저장된 것을 무시하고 원래 것으로 스크립트를 돌립니다.

익스포트 스크립트
3ds Max Art Pipeline 

Process Scripts:

  • Default Process Script – 이 스크립트는 Create ABV, Optimization, Stripification plug-in들을 디폴트 파라미터로 실행시킵니다.
  • Scene Graph Optimizations Only – 이 스크립트는 SceneGraph Optimization plug-in을 디폴트 설정으로 실행시킵니다.

Viewer Scripts:

  • Default DX Viewer Script – 이 스크립트는 Gamebryo UtilityViewer Selection 롤아웃의 DX Viewer 버튼에 의해 사용됩니다.
  • Default KFM Viewer Script - 이 스크립트는 Gamebryo UtilityViewer Selection 롤아웃의 KFM Viewer 버튼에 의해 사용됩니다.
  • Default SceneImmerse Viewer Script - 이 스크립트는 Gamebryo UtilityViewer Selection 롤아웃의 Scene Viewer 버튼에 의해 사용됩니다. 


Export Scripts

  • Default Export Script – 이 스크립트는 한 개의 NIF 파일을 익스포트 합니다.
  • Multiple KF Export With NIF Script – 이 스크립트는 한 개의 NIF 파일과, Controller Extractor plug-in이 찾은 애니메이션에 따라 여러 개의 KF 파일을 익스포트 합니다.
  • Multiple KF Export Without NIF Script – 이 스크립트는 Controller Extractor plug-in이 찾은 애니메이션에 따라 여러 개의 KF 파일을 익스포트 하고, NIF 파일은 익스포트 하지 않습니다.
  • Single KF Export With NIF Script – 이 스크립트는 NIF 파일 한 개와, Controller Extractor plug-in이 찾은 애니메이션의 합성 KF 파일 한 개를 익스포트 합니다.
  • Single KF Export Without NIF Script – 이 스크립트는 Controller Extractor plug-in이 찾은 애니메이션의 합성 KF 파일 한 개를 익스포트 하고, NIF 파일은 익스포트 하지 않습니다.


일단 이건 몰라도 큰일 없음. 
게임에 따라 변할 것이기 땜에. 

Platform:

게임의 플렛폼을 정할 수 있음. Generic은 모든 게임에 공용될 수 있으나 느리다. 
되도록이면 타겟에 맞추도록 하자. 

Image File Subdirectory
텍스쳐가 따로 NIF 로 저장될 때, 폴더를 정할 수 있음. 

Default Content Quality
텍스쳐 퀄리티를 바꿀 수 있음. 

Override Per-Texture Settings: default content quality 옵션을 사용할 때, Gamebryo Shader에서 텍스처 포맷 타입에 대해 설정된 옵션은 디폴트로 오버라이드 되지 않을 것입니다따라서 이런 설정을 오버라이드 하고 싶은 경우엔 이 박스를 체크해야 합니다.: 아마도 맥스내에서 셋팅한 무엇이 제대로 넘어가지 않을때 사용하면 되지 않을까나. 


반응형
Posted by blueasa
, |

짜증나는 워닝과 에러 중에헤더파일 순서에 따라 발생하는 워닝/에러가 있습니다특히 링크타임에 나는 에러는 네이밍 모양새가 재밌게 생겨먹지 않은 스타일로 생기는 데다가 링커가 별로 힌트를 주지 않아서 짜증이 나기도 합니다예를 들면 아래와 같은 겁니다.

 

1>Generating Code...

1>Compiling resources...

1>Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1

1>Copyright (C) Microsoft Corporation.  All rights reserved.

1>Compiling manifest to resources...

1>Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1

1>Copyright (C) Microsoft Corporation.  All rights reserved.

1>Linking...

1>uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)" (??2@YAPAXI@Z) already defined in LIBCMTD.lib(new.obj)

1>uafxcwd.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete(void *)" (??3@YAXPAX@Z) already defined in LIBCMTD.lib(dbgdel.obj)

 

위 예는 MFC프로젝트에서 모든 파일에서 MFC 헤더를 다른 헤더 보다 먼저 선언해야 하는데(대부분 stdafx.h를 가장 상위에 선언합니다.),  MFC 프로젝트에서 사용하던 파일을 Import 하고 컴파일 하는 순간 발생했습니다.

 

이런 에러의 경우 대처법은 의외로 간단 합니다일단 똑똑고 기억력 좋으신 분들은 자기가 했던 행위들의 콜스택을 하나하나 거슬러 올라가시면서 대처 하는법이 있고이게 가장 비용대비 시간단축 효가가 가장 좋습니다.

 

순간 욱해서 콜스택 거슬러 올라가기 힘드신 (저 같은;;)분들은 아래처럼 대처 하시면 됩니다먼저 링커 옵션에 아래 옵션을 추가 합니다.

 

/verbose:lib

 

 

 

그리고 다시 빌드 하면 링킹타임에 library를 스캔하는 리스트가 아래와 같이 output창에 나오게 됩니다.

 

1>Generating Code...

1>Compiling resources...

1>Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1

1>Copyright (C) Microsoft Corporation.  All rights reserved.

1>Compiling manifest to resources...

1>Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1

1>Copyright (C) Microsoft Corporation.  All rights reserved.

1>Linking...

1>Searching libraries

1>    Searching C:\Program Files\Microsoft Visual Studio 9.0\VC\lib\DelayImp.lib:

1>    Searching C:\Program Files\Microsoft SDKs\Windows\v6.0A\\lib\uuid.lib:

1>    Searching C:\Program Files\Microsoft Visual Studio 9.0\VC\lib\LIBCMTD.lib:

1>    Searching C:\Program Files\Microsoft Visual Studio 9.0\VC\lib\OLDNAMES.lib:

1>    Searching C:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\lib\uafxcwd.lib:

1>uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)" (??2@YAPAXI@Z) already defined in LIBCMTD.lib(new.obj)

1>uafxcwd.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete(void *)" (??3@YAXPAX@Z) already defined in LIBCMTD.lib(dbgdel.obj)

1>    Searching C:\Program Files\Microsoft SDKs\Windows\v6.0A\\lib\kernel32.lib:

1>    Searching C:\Program Files\Microsoft SDKs\Windows\v6.0A\\lib\user32.lib:

1>    Searching C:\Program Files\Microsoft SDKs\Windows\v6.0A\\lib\gdi32.lib:

1>    Searching C:\Program Files\Microsoft SDKs\Windows\v6.0A\\lib\uuid.lib:

 

윗 예에서 uafxcwd.lib를 링크 할 때링크에러가 났고에러를 유발한 유력한 용의자는 uuid.lib입니다왜냐면계속 다른 애들은 디폴트 경로에서 링크되는데 uuid.lib만 sdk 에서 링크 되었고, MFC에서 new를 재정의 하기 때문에이전에 new가 정의되어 있는 파일이 링크되면 안됩니다여기서 “stdafx.h”파일을 추가 하는 것을 잊었구나 하는 생각이 듭니다.

 

/verbose 옵션을 써보지 않으신 분들은 한번 넣고 컴파일을 해보시면 쓰잘떼기 없는 정보까지 주르륵 나와서 놀라실 껍니다. 여러가지 링킹 타임에 하는 작업 정보를 자세히 알려주는 것을 알 수 있습니다. 윗예의 :lib처럼 뒷부분에 세부 옵션을 붙여 보기 좋게 정보를 추출하는 작업이 익숙해 지면 일반적인 컴파일시 정보를 잘 제공해주지 않는 링킹 타임시 발생하는 에러에 정보를 얻어 디버깅 작업 시간을 단축 시킬 수 있습니다.


출처 : http://blog.naver.com/drvoss/20064150564

반응형
Posted by blueasa
, |

/VERBOSE:LIB

 

이 옵션을 걸어주면 어떤 lib에서 라이브러리 충돌이 생기는지 알 수 있다

 

라이브러리 충돌은 라이브러리를 만들때 crt lib를 포함해서 (mtd,mt) 컴파일 하였다면

라이브러리를 사용하는 응용프로그램 또한 crt lib를 포함해서 컴파일 해야한다.

 

반대로 lib를 만들때 (mdd,md) 공유 라이브러리를 이용해 컴파일 했다면 응용프로그램에서도

그렇게 해야한다.



출처 : http://blog.naver.com/herok3/100047421303

반응형
Posted by blueasa
, |

1. API에서 참조하는 library의 순서를 확일 할수 있는 명령

 

.net -> 속성 -> linker -> 명령줄 -> 추가 옵션

/verbose:lib


반응형
Posted by blueasa
, |

예외 처리 ~~ tip

Tip & Tech / 2011. 2. 8. 17:11

예외 처리라 하면.. try{} catch(...){} 등을 사용하여 코딩을 하는게

보통이다.

 

하지만.. release 컴파일시 error로 프로그램이 죽어버리게 되면 catch등을 통하지 않고

종료되어. 버그 리포팅을 하기가 힘든데

 

이럴때를 지원해주기 위한 window API 함수를 알아본다.

 

step1 : 프로그램이 죽어버를 경우 무조건 호출될 callback함수를 하나 만든다.

LONG WINAPI  ExceptionCallStack (struct _EXCEPTION_POINTERS *exceptionInfo);

 

step 2 : 예외 처리 핸들러 생성

LPTOP_LEVEL_EXCEPTION_FILTER PrevExceptionFilter = NULL;

 

 

int APIENTRY _tWinMain(..... )

{

 

 // 콜스택 기록용 예외 콜백 함수 등록
 PrevExceptionFilter = SetUnhandledExceptionFilter(ExceptionCallStack);

Run();

 

// 콜스택 기록용 예외 콜백 함수 등록 해제
 SetUnhandledExceptionFilter(PrevExceptionFilter);

 

}

 

=> Thingking

........... ExceptionCallStack 함수에 miniDump나 콜스택 과련 debug코드를 내포하여 release를 배포하면

차후 생각지 못한 버그가 발생했을경우 리포팅이 가능해진다.

[출처] 예외 처리 ~~ tip|작성자 모냐

반응형
Posted by blueasa
, |

무기잔상효과

Gamebryo/Lecture / 2011. 2. 8. 17:05

무기의 잔상효과를 구현하기위해서는 실시간으로 무기가 움직이는 월드상에

폴리곤을 만들어주고 텍스쳐 uv또한 실시간으로 할당해 주어야한다.

또한, 낮은 프레임에서도 부드러운 형태로 폴리곤을 만드려면 셈플링하는 무기의

위치에 대하여 보간처리를 해야한다.


여기서는 동적으로 폴리곤을 생성하고 사용될 텍스쳐의 uv를 결정해주는 방법을 살펴보도록 한다.
스플라인 보간처리부분은 직접 해보세요.
 

무기에 필요한 정보

무기의 잔상효과가 적용될 시작지점과 끝점에 더미를 추가하도록한다.

더미이름은 *point1,*point2라고 칭한다.

 

※ 구현 순서

1. 더미이름으로 각 더미노드 포인터를 찾아 저장해놓는다.

2. 매 프레임마다 더미노드의 변경된 좌표에 대하여 폴리곤을 생성한다.

3. 정해진 출력시간을 초과하면 해당 정보를 리스트에서 제거한다.
4. 일정 비율로 시간이 지남에따라 폴리곤 크기를 줄여준다.
5. 생성된 폴리곤에 대하여 텍스쳐 uv를 할당한다.
 

struct AIPoint

    {

        float       m_fStartTime; // 폴리곤을 생성할 때 현재 시간을 저장한다.

        NiPoint3    m_kPoint[2];  // 생성될때 더미노드 월드좌표를 저장한다.

};

 

    typedef std::vector<AIPoint>    VAIPOINT;

    typedef VAIPOINT::iterator      VAIPOINT_ITER;

VAIPOINT        m_vAIPointList;        // 더미노드 리스트                                  

NiTriShapePtr   m_spAIGeometry;        // 동적으로 만들어진 지오메트리

    NiAVObject*     m_pkPointNode[2];      // 잔상이 적용될 노드포인터

    float           m_fLifeTime;           // 폴리곤이 출력되는 시간

 

매 프레임마다 더미의 월드좌표와 시간정보를 리스트에 추가한다.
   실제 제작시에는 변화가있을때만 추가해야할 것이다. 또는 특정 애니메이션에서만 추가되도록 작성해야한다.
    AIPoint r_kAIPoint;

    r_kAIPoint.m_fStartTime = p_fTime;

    r_kAIPoint.m_kPoint[0]  = m_pkPointNode[0]->GetWorldTranslate();

    r_kAIPoint.m_kPoint[1]  = m_pkPointNode[1]->GetWorldTranslate();

    m_vAIPointList.push_back( r_kAIPoint );

 

※ 매프레임마다 *point2더미 위치를 *point1 더미위치방향으로 줄어들게 한다.

또한 출력시간이 지났다면 해당 AIPoint 객체를 리스트에서 제거하도록 한다.

if( m_vAIPointList.empty() )
        return;
    VAIPOINT_ITER r_iter;

    for( r_iter = m_vAIPointList.begin(); r_iter != m_vAIPointList.end(); )

    {

        float r_fElapsedTime = p_fTime - r_iter->m_fStartTime;

        if( r_fElapsedTime > m_fLifeTime )

        {

            r_iter = m_vAIPointList.erase( r_iter );

        }

        else

        {

            NiPoint3 r_kDirVec =
                     ( r_iter->m_kPoint[0] - r_iter->m_kPoint[1] );

            float r_fLength = r_kDirVec.Length();

            if ( r_fLength > 0.0f )

            {

                NiPoint3::UnitizeVector( r_kDirVec );

                float fAmount = r_fLength / ( m_fLifeTime * 10.0f );

r_kDirVec *= fAmount;

                r_iter->m_kPoint[1] += r_kDirVec;

            }

            ++r_iter;

        }

    }

 

주어진 리스트를 이용하여 동적으로 폴리곤과 uv좌표정보를 갱신한다.

unsigned short  r_usAIPointCount = m_vAIPointList.size();
    // 최소한 3개이상이어야 정상적인 메쉬를 만들 수 있다

    if ( r_usAIPointCount <= 2 )
        return;
   
unsigned short  r_usVertices     = r_usAIPointCount * 2;

    unsigned short  r_usTriangles    = ( r_usAIPointCount - 1 ) * 2;

    unsigned short* r_pusTriList     = NULL;

    NiPoint3*       r_pkVerts        = NiNew NiPoint3[ r_usVertices ];

    NiPoint2*       r_pkTexture      = NiNew NiPoint2[ r_usVertices ];

 

    if ( r_usTriangles )

    {

        r_pusTriList = (unsigned short*)NiMalloc(

            sizeof(unsigned short) * ( 3 * r_usTriangles ) );

    }

 

    for( int r_i = 0; r_i < r_usAIPointCount; ++r_i )

    {

        int r_nNum = r_i * 2;

 

        r_pkVerts[r_nNum]     = m_vAIPointList[r_i].m_kPoint[0];

        r_pkVerts[r_nNum + 1] = m_vAIPointList[r_i].m_kPoint[1];

 

        if( 0 == r_i )

        {

            r_pkTexture[0] = NiPoint2( 0.0f, 0.0f );

            r_pkTexture[1] = NiPoint2( 1.0f, 0.0f );

        }

        else

        {

            float r_uv = (float)( r_i ) / (float)( r_usAIPointCount - 1 );

            r_pkTexture[r_nNum]     = NiPoint2( 0.0f, r_uv );

            r_pkTexture[r_nNum + 1] = NiPoint2( 1.0f, r_uv );

 

            int r_nIndex  = ( r_i - 1 ) * 6;

            int r_nFactor = ( r_i - 1 ) * 2;

 

            r_pusTriList[r_nIndex + 0] = 0 + r_nFactor;

            r_pusTriList[r_nIndex + 1] = 1 + r_nFactor;

            r_pusTriList[r_nIndex + 2] = 2 + r_nFactor;

            r_pusTriList[r_nIndex + 3] = 2 + r_nFactor;

            r_pusTriList[r_nIndex + 4] = 1 + r_nFactor;

            r_pusTriList[r_nIndex + 5] = 3 + r_nFactor;

        }

    }

 

    NiGeometryData* r_pkGeomData = m_spAIGeometry->GetModelData();

    NiTriShapeData* r_pkTriShape = (NiTriShapeData*)r_pkGeomData;

   

    r_pkGeomData->Replace(

        r_usVertices,

        r_pkVerts,

        0,                                  // Normal

        0,                                  // Color

        r_pkTexture,

        1,                                  // TextureSets

        NiGeometryData::NBT_METHOD_NONE );  // Normal Binormal Tangent Method

 

    r_pkTriShape->Replace( r_usTriangles, r_pusTriList );

 

    r_pkGeomData->MarkAsChanged (

            NiGeometryData::VERTEX_MASK |

            NiGeometryData::TEXTURE_MASK |

            NiTriBasedGeomData::TRIANGLE_INDEX_MASK |

            NiTriBasedGeomData::TRIANGLE_COUNT_MASK );

 

    // Perform initial update.

    m_spAIGeometry->Update(0.0f);

    m_spAIGeometry->UpdateProperties();

    m_spAIGeometry->UpdateEffects();

    m_spAIGeometry->UpdateNodeBound();

 

 

-> URL : http://clodymade.tistory.com/entry/무기잔상효과

반응형

'Gamebryo > Lecture' 카테고리의 다른 글

게임브리오 2D Line관련  (0) 2011.10.30
FrameRenderSystem에서.. 커스텀알파소터프로세스..  (0) 2011.09.18
캐릭터 기울기 연산  (0) 2011.02.08
Gamebryo 셋팅  (1) 2011.01.06
게임브리오 강좌(?) 링크  (3) 2010.04.14
Posted by blueasa
, |
필요한 경우는 아래와 같다.
1. 2족 캐릭터가 지형의 경사면에서 죽는 애니메이션.
2. 4족 이상 동물의 지형 경사면 이동.


일단 캐릭터가 서있는 지형에대한 노멀벡터를 알아야한다.
자신의 위치에서 바닥으로 피킹을 해서 얻으면 된다.
캐릭터의 크기가 바닥 그리드에 비해 크다면 캐릭터의 크기에 맞게 삼각형 형태의
3정점에서 피킹을하여 얻어지는 평면의 노멀값을 계산하여 사용하도록 하자.

1. 현재 캐릭터 위치에서 지형으로 피킹을 한다.
2. 피킹으로 얻어진 노멀 벡터와 Z축 벡터를 이용하여 회전행렬을 구한다.
3. 캐릭터의 회전값에 적용한다.


ex)
// 원래 벡터 srcVec, 변환후 벡터 destVec, 회전축 벡터 axisVec
// axisVec = srcVec x destVec                                               // 회전축 벡터
// angle = acos( srcVec * destVec / |srcVec| |destVec| )       // 회전각


// m_spCharRootNode 캐릭터 루트 노드
// m_kPickNormal 현재 위치에대한 노멀 벡터
NiMatrix3 r_kRot;
NiPoint3 r_kAxis = m_kPickNormal.Cross( NiPoint3(0.0f, 0.0f, 1.0f) );
float r_fDot = m_kPickNormal.Dot( NiPoint3(0.0f, 0.0f, 1.0f) );
float r_fRadian = NiACos( r_fDot );
r_kRot.MakeRotation( r_fRadian, r_kAxis );
m_spCharRootNode->SetRotate( r_kRot );


주의사항 : 루트노드를 카메라 회전및 기타 다른용도에
사용되고 있다면 위 코드는 정상적으로 구현되지 않을 수 있습니다.
이럴 경우 노멀벡터값을 루트노드회전행렬과 곱한값을 사용하면 해결 될 수 있습니다.
 
반응형

'Gamebryo > Lecture' 카테고리의 다른 글

FrameRenderSystem에서.. 커스텀알파소터프로세스..  (0) 2011.09.18
무기잔상효과  (0) 2011.02.08
Gamebryo 셋팅  (1) 2011.01.06
게임브리오 강좌(?) 링크  (3) 2010.04.14
Gamebryo 2.5  (0) 2010.04.12
Posted by blueasa
, |

이펙트 출력

Gamebryo/Effect / 2011. 2. 8. 17:03

이펙트 애니메이션이 종료되는 시점(이펙트 애니메이션 시간)을 알아야한다.
아래 함수는 이펙트 애니메이션 길이(시간)을 알아내는 함수이다.

//////////////////////////////////////////////////////////////////////////////
<이펙트 출력 순서>
1. 이펙트를 로딩한다.
2. 아래 함수를 통해 애니메이션 길이(m_fAnimLength)을 구한다.
3. 이펙트 애니메이션 시작 시간을 정한다.
    NiTimeController::StartAnimations( m_spEffect, m_fStartTime );
4. 이펙트 종료를 체크한다.
    if( fTime - m_fStartTime >= m_fAnimLength )
        m_spEffect = 0;   // 이펙트 노드 제거
    else
        m_spEffect->Update( fTime );
//////////////////////////////////////////////////////////////////////////////

void RecursiveGetAnimRange(NiAVObject* pkObject, float& rfLoKeyTime, float& rfHiKeyTime)
{
    NiTimeController* pkController = pkObject->GetControllers();
    while ( pkController )
    {
        float fLoTime = pkController->GetBeginKeyTime();
        float fHiTime = pkController->GetEndKeyTime();
        if ( fLoTime < rfLoKeyTime )
            rfLoKeyTime = fLoTime;
        if ( fHiTime > rfHiKeyTime )
            rfHiKeyTime = fHiTime;

        pkController->SetAnimType( NiTimeController::APP_INIT );
        pkController = pkController->GetNext();
    }

    // Do the same for any animation controllers attached to the rendering properties
    if ( NiIsKindOf( NiAVObject, pkObject ) )
    {
        NiAVObject* pAVObj = (NiAVObject*)pkObject;
        pAVObj->SetSelectiveUpdate(true);
        pAVObj->SetSelectiveUpdateTransforms(true);
        pAVObj->SetSelectiveUpdatePropertyControllers(true);
        pAVObj->SetSelectiveUpdateRigid(false);

        NiTListIterator kPos = pAVObj->GetPropertyList().GetHeadPos();
        while ( kPos )
        {
            NiProperty *pProp = pAVObj->GetPropertyList().GetNext( kPos );
            if ( pProp )
            {
                for ( pkController = pProp->GetControllers(); pkController; pkController = pkController->GetNext() )
                {
                    float fLoTime = pkController->GetBeginKeyTime();
                    float fHiTime = pkController->GetEndKeyTime();
                    if ( fLoTime < rfLoKeyTime )
                        rfLoKeyTime = fLoTime;
                    if ( fHiTime > rfHiKeyTime )
                        rfHiKeyTime = fHiTime;

                    pkController->SetAnimType( NiTimeController::APP_INIT );
                }
            }
        }

    }

    if ( NiIsKindOf( NiNode, pkObject ) )
    {
        NiNode* pkNode = (NiNode*)pkObject;
        for ( unsigned int i = 0; i < pkNode->GetArrayCount(); ++i )
        {
            NiAVObject* pkChild = pkNode->GetAt( i );
            if ( pkChild )
                RecursiveGetAnimRange( pkChild, rfLoKeyTime, rfHiKeyTime );
        }
    }
}


------------------------------------------------------------------
ex)
    float fLoTime =  NI_INFINITY;
    float fHiTime = -NI_INFINITY;
    RecursiveGetAnimRange( m_spModel, fLoTime, fHiTime );
    m_fAnimLength = fHiTime - fLoTime;    // 애니메이션 전체 시간 계산

[출처] GameBryo - 이펙트 출력|작성자 모냐

반응형

'Gamebryo > Effect' 카테고리의 다른 글

강의자료 - 파티클 예제  (0) 2011.03.22
Setup about Effect Dumy…  (0) 2011.03.21
파티클 컨트롤 해보기  (0) 2011.02.24
이펙트 작업에 필요한 기능  (0) 2011.01.27
검광, 검기 잔상 효과에 대하여...  (1) 2011.01.21
Posted by blueasa
, |
    문자열(std::string)을 키로 가지는 맵 같은 경우, 문자열 비교 자체에 걸리는 시간 때문에 검색이 느려질 수 있다. 이 경우, 키로 사용하는 문자열이 별로 중요한 내용이 아니라면 아래와 같은 클래스를 사용함으로서 성능을 약간 증가시킬 수 있다. 
    ////////////////////////////////////////////////////////////////////////////////
    /// \class cStringKey
    /// \brief STL 컨테이너를 위한 문자열 키
    ////////////////////////////////////////////////////////////////////////////////
    
    class cStringKey
    {
    private:
        enum
        {
            BYTE_SIZE = 32,
        };
    
        char m_Text[BYTE_SIZE]; ///< 문자열
    
    
    public:
        /// \brief 생성자
        cStringKey()
        {
            memset(m_Text, 0, sizeof(m_Text));
        }
    
        /// \brief 생성자
        cStringKey(const char* text)
        {
            memset(m_Text, 0, sizeof(m_Text));
            memcpy_s(m_Text, sizeof(m_Text), text, std::min(sizeof(m_Text), strlen(text)));
        }
    
        /// \brief 생성자
        cStringKey(const std::string& text)
        {
            memset(m_Text, 0, sizeof(m_Text));
            memcpy_s(m_Text, sizeof(m_Text), text.c_str(), std::min(sizeof(m_Text), text.size()));
        }
    
        /// \brief 복사 생성자
        cStringKey(const cStringKey& rhs)
        {
            memcpy_s(m_Text, sizeof(m_Text), rhs.m_Text, sizeof(m_Text));
        }
    
    
    public:
        /// \brief 대입 연산자
        inline const cStringKey& operator = (const cStringKey& rhs)
        {
            if (this != &rhs)
                memcpy_s(m_Text, sizeof(m_Text), rhs.m_Text, sizeof(m_Text));
    
            return *this;
        }
    
        /// \brief 비교 연산자
        ///
        /// 이 함수는 약간 유의해야 하는데, 속도를 위해 루프를 풀어버렸기 때문이다.
        /// 클래스의 크기가 변경되면, 이 함수도 같이 변경해줘야 한다.
        inline bool operator < (const cStringKey& rhs) const
        {
            const int* buf1 = reinterpret_cast<const int*>(this);
            const int* buf2 = reinterpret_cast<const int*>(&rhs);
    
            if (*buf1 != *buf2) return *buf1 < *buf2; // 0-3
    
            ++buf1; ++buf2;
            if (*buf1 != *buf2) return *buf1 < *buf2; // 4-7
    
            ++buf1; ++buf2;
            if (*buf1 != *buf2) return *buf1 < *buf2; // 8-11
    
            ++buf1; ++buf2;
            if (*buf1 != *buf2) return *buf1 < *buf2; // 12-15
    
            ++buf1; ++buf2;
            if (*buf1 != *buf2) return *buf1 < *buf2; // 16-19
    
            ++buf1; ++buf2;
            if (*buf1 != *buf2) return *buf1 < *buf2; // 20-23
    
            ++buf1; ++buf2;
            if (*buf1 != *buf2) return *buf1 < *buf2; // 24-27
    
            ++buf1; ++buf2;
            return *buf1 < *buf2; // 28-31
        }
    };

    대소문자 구별없이 비교를 할 수 없다는 점이 좀 아쉽다. 어셈블리도 좀 안다면 비교 연산자를 좀 더 깔끔하게 만들 수 있을 텐데. 어쨌든 테스트해보니, 릴리즈 빌드에서 약 25~33% 정도의 성능이 향상되었다. 
    typedef std::map<std::string, std::string> OLD_MAP;
    typedef std::map<cStringKey, std::string> NEW_MAP;
    
    OLD_MAP oldMap;
    NEW_MAP newMap;
    
    for (int i=0; i<1000; ++i)
    {
        std::string key = generic::to_string(rand() % 1000, 4);
        std::string value = generic::to_string(rand() % 1000, 4);
        oldMap.insert(OLD_MAP::value_type(key, value));
        newMap.insert(NEW_MAP::value_type(key, value));
    }
    
    DWORD begin = 0, oldTime = 0, newTime = 0;
    int repetition = 200000;
    
    begin = timeGetTime();
    for (int i=0; i<repetition; ++i)
    {
        oldMap.find(generic::to_string(rand() % 1000, 4));
    }
    oldTime = timeGetTime() - begin;
    
    begin = timeGetTime();
    for (int i=0; i<repetition; ++i)
    {
        newMap.find(generic::to_string(rand() % 1000, 4));
    }
    newTime = timeGetTime() - begin;
    
    std::cout << "OLD: " << oldTime << std::endl;
    std::cout << "NEW: " << newTime << std::endl;


반응형
Posted by blueasa
, |

define DEBUG_OUTPUT
//------------------------------------------------------------------------
// 2010/01/22 [19:56:32]
// jedikim72
// - 디버깅출력함수
//------------------------------------------------------------------------
#ifdef DEBUG_OUTPUT
 #define debugLog(...) { char acTemp[2048]; \
                                      char acTemp2[2048]; \
                                      NiSprintf(acTemp, 2048, __VA_ARGS__); \
                                      NiSprintf(acTemp2, 2048, "[L%d]:%s - %s", __LINE__, __FUNCTION__, acTemp ); \
                                      OutputDebugString( acTemp2 ); \
                                    }
#else
 #define debugLog(...) ((void)0)
#endif
//------------------------------------------------------------------------

 

빌딩모드와 상관없이 디버깅 메세지를 출력하는 메써드가 필요해서 부랴부랴 만든 매크로.

(기존 매크로는 사용하기 불편해서... - -a)

 

매크로 가변인자를 사용하여 가변인수를 받아 출력할 수 있다.

사용예) debugLog("%.2f, %.2f, %.2f\n", pos.x, pos.y, pos.z);

또한 VS IDE 출력창 뿐만 아니라, 실행파일만 독립적으로 실행해도 DebugView 유틸을 통해 디버깅 출력 메세지를 볼 수 있다는 장점이 있다.

 

 

이제까진 TraceWindow를 써서 출력했는데, 프로젝트에 매번 관련 모듈 삽입하는 것도 귀찮고 해서 아예 매크로로 빼버려 간단한 구문 삽입만으로 간편하게 작업을 완료할 수 있게 했다.

 

 

 

DebugView와 함께 구동시킨 작업중인 데모 스크린샷

그나저나,

DebugView 유틸은 첨부파일로~!



출처  : http://jedikim72.blog.me/10079110907

반응형
Posted by blueasa
, |