로그 메씨지 & 메씨지박스출력
NiMessageBox::DisplayMessage("MOUT::CreateScene --
W../res/data/script/model.xm Loading script Failed","script error");
본 & 스키닝 구조정리
- NiSkiningInstance
NiAVObject *const* GetBones() : 본의 포인터배열 얻기
본도 오브잭트로 여긴다. 위치정보를가진 일종에 더미로 여긴다.노드와 비슷하나 자식을가지지는 못하는..
그러나 여기서 본의 갯수는알수가없다.
그래서...
이런식으로 스킨데이터를얻어온다.
NiSkinData* pkOldSkinData = spOldSkinInstance->GetSkinData();
- NiSkinData
스킨데이터에서 본의 갯수를알수있다.
pkOldSkinData->GetBoneCount()
본의 정점 링크정보를 얻기
NiSkinData::BoneData* pkOldBoneData = pkOldSkinData->GetBoneData();
for(i=0;i<pkOldSkinData->GetBoneCount();i++)
{
ppkNewBones[i]
= spOldSkinInstance->GetBones()[i];
pkNewBoneData[i].m_kBound = pkOldBoneData[i].m_kBound;
//본의위치정보계산용
pkNewBoneData[i].m_kSkinToBone =
pkOldBoneData[i].m_kSkinToBone; //???
pkNewBoneData[i].m_usVerts =
pkOldBoneData[i].m_usVerts; //본에의해 영향을받는
버텍스갯수
pkNewBoneData[i].m_pkBoneVertData = NiNew
NiSkinData::BoneVertData[pkNewBoneData[i].m_usVerts]; //본에의해 영향을받는
버텍스링크정보
for (unsigned short us = 0; us < pkNewBoneData[i].m_usVerts;
us++)
{
//본에의해 얼마나
영향받을지 가중치
pkNewBoneData[i].m_pkBoneVertData[us].m_fWeight =
pkOldBoneData[i].m_pkBoneVertData[us].m_fWeight;
//영향받는 버텍스인덱스
pkNewBoneData[i].m_pkBoneVertData[us].m_usVert
= pkOldBoneData[i].m_pkBoneVertData[us].m_usVert;
}
}
//새로운 스키닝 정보만들기
// Create the new NiSkinData and NiSkinInstance objects.
NiSkinData*
pkNewSkinData = NiNew NiSkinData(uiNumNewBones,
pkNewBoneData,
pkOldSkinData->GetRootParentToSkin(),
spNewPartClone->GetVertices());
pkNewSkinData->SortAndMergeBoneData();
NiSkinInstance* pkNewSkinInst = NiNew
NiSkinInstance(pkNewSkinData,
spOldSkinInstance->GetRootParent(),
ppkNewBones);
// 새로운 스킹닝정보 붙이기
spNewPartClone->SetSkinInstance(pkNewSkinInst);
벡토를각도로
irr::core::vector3df
v3Angle;
irr::core::vector3df v3Temp =
irr::core::vector3df(Heading.x,Heading.z,Heading.y);
v3Angle =
v3Temp.getHorizontalAngle();
SadowGeomerty 분석
UpdateShadowGeometryBound : 컬링되지 않도록 타겟오브잭트와 같은 범위를
지정한다.
아래소스와같이 데칼을 붙이기위한지형에대한 지오메트리(삼각형들)를 얻기위해서 카메라노드(m_spCamera)의 절두체를 조작해서
얻는다. 이동할때마다 회전을 보정하지않는이유는 태양광이기 때문에 방향변화가 거의없기때문이다.
void ShadowGeometry::UpdateShadowCamera(float fTime)
{
// this
function moves the shadow camera so that it appears to view the
// target
(caster) from infinity, facing a fixed direction. This is done
// by
moving the camera so the the desired fixed direction vector is
// always
coincident with the line through the caster's bounding volume
// center
and the camera location
if (!m_spCamera)
return;
// get the "look at" point
NiPoint3 kTarget =
m_spCaster->GetWorldBound().GetCenter();
// translate the camera to a distant point such that the camera is
looking
// directly at the target point
m_spCamera->SetTranslate(kTarget - (m_kLightDir * 500.0f));//카메라는 이미빛으 방향과
일치되있다.
// set the field of view of the camera to enclose the bounding sphere
of
// the caster object.
float fRadius =
m_spCaster->GetWorldBound().GetRadius();
float fFOV = fRadius /
(kTarget -
m_spCamera->GetWorldLocation()).Length() * 0.95f;
NiFrustum kFrust = m_spCamera->GetViewFrustum();
kFrust.m_fLeft = -fFOV;
kFrust.m_fRight = fFOV;
kFrust.m_fTop =
fFOV;
kFrust.m_fBottom = -fFOV;
m_spCamera->SetViewFrustum(kFrust);
m_spCamera->Update(fTime);
}
특정방향쳐다보기(유도탄공식)
NiPoint3 kYVec =
-m_kLightDir.Perpendicular();
NiPoint3 kZVec = m_kLightDir.UnitCross(kYVec);
// Rotate the camera based on the orthonormal frame
NiMatrix3
kRotation(m_kLightDir, kYVec, kZVec);
m_spCamera->SetRotate(kRotation);
m_spCamera->Update(0.0f);
광원과 같은방향으로 바라보기 예..
camera 설정하기
pkRenderer->SetCameraData(m_spCamera);
타입캐스팅
-일반포인터 타입캐스팅
NiNode* pkCamOri;
pkCamOri = NiDynamicCast(NiNode,
m_spCharacterRoot->GetObjectByName("camOrient"));
타입이맞지않으면 NULL이된다.
-스마트포인터 타입 캐스팅
NiGeometry* pkGeom =
NiSmartPointerCast(NiGeometry,m_kCastingObjects.GetAt(i));
겜브리오엔진 회전
기초
카메라는 기본적으로 시 점벡터가 (1,0,0), 업벡터는 0,0,1 이므로
pitch->roll ->yaw
- 쿼터니온
//쿼터니온 변환
{
NiQuaternion kQua,q1,q2,q3;
q3.FromAngleAxisZ(m_fPitch);// 피치 ..이부분중요 90도 롤하기이전에는 요 이후에 피치가된다.
q1.FromAngleAxisX(NI_PI/2);
//롤
q2.FromAngleAxisZ(-m_fHeading); //요
kQua = q2*q1*q3;
m_spCamera->SetRotate(kQua);
}
- 오일러회전
FromEulerAnglesYZX(..)
오일러 회전행렬 만들기 , 접미사의 순서가 거꾸로임 즉 위의 경우 x으로 돌리고,z축돌리고 y축돌리라는뜻
짐벌락 주의...
NiNode의역활
이름그대로그밑으로자식을달수있는노드를말한다.
재귀적으로노드를 순회할때...
재귀호출함수(..)
{
들어가면서처리해야될꺼.....
if (NiIsKindOf(NiNode, pkObject))
{
NiNode* pkNode = (NiNode*) pkObject;
for (unsigned int ui = 0; ui
< pkNode->GetArrayCount(); ui++)
{
재귀호출함수()
}
}
트리 끝까지 들어 간 다음 처리 해야될꺼 .....
}
식으로 코드구성할수있다.
즉 NiNode가이닌것은(상속개체포함) 밑으로 자식을가질수없다.
예제>
static void DisableZBuffer(NiAVObject* pkObject)
{
NiProperty*
pkProp = pkObject->GetProperty(NiZBufferProperty::GetType());
if
(pkProp)
{
((NiZBufferProperty*)pkProp)->SetZBufferTest(false);
((NiZBufferProperty*)pkProp)->SetZBufferWrite(false);
}
if (NiIsKindOf(NiNode, pkObject))
{
NiNode* pkNode =
(NiNode*)pkObject;
for (unsigned int i = 0; i <
pkNode->GetArrayCount(); i++)
{
NiAVObject* pkChild
= pkNode->GetAt(i);
if (pkChild)
DisableZBuffer(pkChild);
}
}
}
static void DisableZBuffer(NiAVObject* pkObject)
{
NiProperty*
pkProp = pkObject->GetProperty(NiZBufferProperty::GetType());
if
(pkProp)static void DisableZBuffer(NiAVObject* pkObject)
{
NiProperty*
pkProp = pkObject->GetProperty(NiZBufferProperty::GetType());
if
(pkProp)
{
((NiZBufferProperty*)pkProp)->SetZBufferTest(false);
((NiZBufferProperty*)pkProp)->SetZBufferWrite(false);
}
if (NiIsKindOf(NiNode, pkObject))
{
NiNode* pkNode =
(NiNode*)pkObject;
for (unsigned int i = 0; i <
pkNode->GetArrayCount(); i++)
{
NiAVObject* pkChild
= pkNode->GetAt(i);
if (pkChild)
DisableZBuffer(pkChild);
}
}
}
디파인 2개 검사해보기
#if defined(MYDEBUG) ||
defined(_DEBUG)
#endif
정적라이브러리링크시유의사항
-정적인 데이터 모듈관리(NiStaticDataManager)
기능별로 로더를따로등록한다.
int NiStream::RegisterLoader(const char* pcName,
CreateFunction pfnFunc)
라이브러리별로 로더를 묶어서 올리는 함수지정
static void AddLibrary(InitFunction pfnInit,
ShutdownFunction pfnShutdown);
기본외예 Animation,Collision 관련 로더를 활성시키려면 관련헤더파일을
인크루드시켜야한다.
예>
#include <collision.h>
#include
<animation.h>
Nif파일로드시 이점에 주의하지않으면 로더가 없는부분은 데이터를
읽어들이지않는다.
2 D텍스춰 기능정리
-스크린텍스춰 만들기 & 사용하기 기본
//소스텍스춰 생성
NiSourceTexture* pkTexture =
NiSourceTexture::Create(NiApplication::ConvertMediaFilename("emergentlogo.tga"));
NiScreenTexture* pkScreenTexture = NiNew
NiScreenTexture(pkTexture);
pkScreenTexture->AddNewScreenRect(32, 32,pkTexture->GetWidth(),
pkTexture->GetHeight(), 0, 0);
-NiScreenTexture 주요기능
AddNewScreenRect(찍을위치x,찍을위치y,끈어올크기가로,세로,끈어올위치x,y) ;
SetTexture(pkTexture) //소스 텍스춰지정
-스크린텍스춰 변경하기
먼저
변경공지를때려준다.
m_spScreenTexture->MarkAsChanged(NiScreenTexture::EVERYTHING_MASK);
AddNewScreenRect,또는
RemoveScreenRect 를 써서 추가삭제를한다.
-화면에출력
NiScreenTextureArray m_kScreenTextures;
를 화면 랜더링큰난후 한번씩찍어준다.
예>
void NiApplication::RenderScreenItems()
{
m_spRenderer->SetScreenSpaceCameraData();
const unsigned int uiSESize
= m_kScreenElements.GetSize();
unsigned int i;
for (i = 0; i <
uiSESize; i++)
{
NiScreenElements* pkElements =
m_kScreenElements.GetAt(i);
if (pkElements)
pkElements->Draw(m_spRenderer);
}
const unsigned int uiSTSize = m_kScreenTextures.GetSize();
for (i = 0; i < uiSTSize; i++)
{
NiScreenTexture* pkTexture
= m_kScreenTextures.GetAt(i);
if (pkTexture)
pkTexture->Draw(m_spRenderer);
}
}
|