void AABoundingBox::Update(const Quaternion& orientation, const Vector3D<Real>& trans) { Matrix3D<Real> rot = orientation.GetMatrix(); for(int i = 0; i < 3; ++i) { m_min[i] = m_max[i] = trans[i]; for(int j = 0; j < 3; ++j) { Real e = rot[i * 3 + j] * m_baseMin[j]; Real f = rot[i * 3 + j] * m_baseMax[j]; if(e < f) { m_min[i] += e; m_max[i] += f; } else { m_min[i] += f; m_max[i] += e; } } } }
bool cMove::ActionUpdate(const float elapseTime) { IArtificialIntelligence *obj = GetOwner(); RETV(!obj, false); const Vector3 curPos = obj->aiGetTransform().GetPosition(); // 회전 보간 계산 if (m_rotateTime < m_rotateInterval) { m_rotateTime += elapseTime; const float alpha = min(1, m_rotateTime / m_rotateInterval); const Quaternion q = m_fromDir.Interpolate(m_toDir, alpha); obj->aiGetTransform() = q.GetMatrix(); } // 캐릭터 이동. const Vector3 pos = curPos + m_dir * m_speed * elapseTime; obj->aiGetTransform().SetPosition(pos); // 목적지에 가깝다면 종료. // 프레임이 낮을 때, 통과되는 문제가 있을 수 있다. if (pos.LengthRoughly(m_dest) < 0.01f) return false; // 목적지 도착. 액션종료. return true; }
// Animation void cTrack::Move( const int curFrame, OUT Matrix44 &out ) { RET(!m_rawAni); m_curFrame = curFrame; Quaternion q; if (GetRotKey(curFrame, q)) out = q.GetMatrix(); Vector3 p(0,0,0); if (GetPosKey(curFrame, p)) { out._41 = p.x; out._42 = p.y; out._43 = p.z; } Vector3 s(1,1,1); if (GetScaleKey(curFrame, s)) { out._11 *= s.x; out._22 *= s.y; out._33 *= s.z; } }
//--------------------------- // //--------------------------- void Matrix44::SetWorld( const Vector3& vPos, const Quaternion& qRot ) { *this = qRot.GetMatrix(); _41 = vPos.x; _42 = vPos.y; _43 = vPos.z; } //Matrix44::SetWorld
void CModel::SetDirection( const Quaternion& q ) { Vector3 dir = q.GetDirection(); if( m_Dir == dir ) return; Vector3 pos( m_matWorld._41, m_matWorld._42, m_matWorld._43 ); m_matWorld.SetIdentity(); m_matWorld._11 *= m_fSize; m_matWorld._22 *= m_fSize; m_matWorld._33 *= m_fSize; m_matWorld *= q.GetMatrix(); m_matWorld._41 = pos.x; m_matWorld._42 = pos.y; m_matWorld._43 = pos.z; m_Dir = dir; if( m_pBone ) m_pBone->SetTM( &m_matWorld ); }
void cTrack::KeyRot( const int currFrame, OUT Matrix44& out ) { switch( (int)m_rawAni.rot.size() ) { case 0: out.SetIdentity(); return; case 1: out = m_rawAni.rot[0].q.GetMatrix(); return; default: break; } if( currFrame < m_rawAni.rot[m_keyIndexRot - 1].t ) return; else if( currFrame >= m_rawAni.rot[m_keyIndexRot].t ) { if( m_keyIndexRot >= (int)m_rawAni.rot.size() - 1) { //m_keyIndexPos = 0; out = m_rawAni.rot[m_keyIndexRot].q.GetMatrix(); return; } m_keyIndexRot++; } const float alpha = ( (float)currFrame - m_rawAni.rot[m_keyIndexRot - 1].t ) / ( m_rawAni.rot[m_keyIndexRot].t - m_rawAni.rot[m_keyIndexRot - 1].t ); Quaternion q = m_rawAni.rot[m_keyIndexRot - 1].q.Interpolate( m_rawAni.rot[m_keyIndexRot].q, alpha ); out = q.GetMatrix(); }
void SceneNode::Update(float32 timeElapsed) { inUpdate = true; // TODO - move node update to render because any of objects can change params of other objects if (nodeAnimations.size() != 0) { Quaternion blendedRotation; Vector3 blendedTranslation; float32 accumWeight = 0.0f; std::deque<SceneNodeAnimation*>::const_iterator end = nodeAnimations.end(); for (std::deque<SceneNodeAnimation*>::iterator it = nodeAnimations.begin(); it != end; ++it) { SceneNodeAnimation * animation = *it; SceneNodeAnimationKey & key = animation->Intepolate(animation->GetCurrentTime()); if (accumWeight == 0.0f) { blendedTranslation = key.translation; blendedRotation = key.rotation; accumWeight = animation->weight; }else { float32 factor = animation->weight / (accumWeight + animation->weight); accumWeight += accumWeight; blendedTranslation.Lerp(blendedTranslation, key.translation, factor); blendedRotation.Slerp(blendedRotation, key.rotation, factor); } //key.GetMatrix(localTransform); } Matrix4 localTransformTrans; Matrix4 localTransformRot; Matrix4 localTransformFinal; localTransformTrans.CreateTranslation(blendedTranslation); localTransformRot = blendedRotation.GetMatrix(); localTransform = localTransformRot * localTransformTrans; // if (nodeAnimations.size() != 1) // { // printf("-- blended node: %s\n", name.c_str()); // std::deque<SceneNodeAnimation*>::const_iterator end = nodeAnimations.end(); // for (std::deque<SceneNodeAnimation*>::iterator it = nodeAnimations.begin(); it != end; ++it) // { // SceneNodeAnimation * animation = *it; // printf(">>> blend: %s wei: %f inDelay: %f\n", animation->GetParent()->name.c_str(), animation->weight, animation->delayTime); // } // } } // update world transform only in case if if (!(flags & NODE_WORLD_MATRIX_ACTUAL)) { if (parent) { worldTransform = localTransform * parent->worldTransform; }else { worldTransform = localTransform; } // need propagate changes to child nodes flags |= NODE_WORLD_MATRIX_ACTUAL; uint32 size = (uint32)childs.size(); for (uint32 c = 0; c < size; ++c) { childs[c]->InvalidateLocalTransform(); childs[c]->Update(timeElapsed); } } else { uint32 size = (uint32)childs.size(); for (uint32 c = 0; c < size; ++c) { childs[c]->Update(timeElapsed); } } //printf("- node: %s tr: %f %f %f\n", name.c_str(), localTransform.data[12], localTransform.data[13], localTransform.data[14]); inUpdate = false; if (!removedCache.empty()) { for (std::deque<SceneNode*>::iterator t = removedCache.begin(); t != removedCache.end(); ++t) { RemoveNode(*t); } removedCache.clear(); } }
//------------------------------------------------------------------------------------------------------ //static function that applies passed quaternion rotation to model matrix //------------------------------------------------------------------------------------------------------ void GameObject::Rotate(Quaternion& quaternion) { s_modelMatrix.back() = s_modelMatrix.back() * quaternion.GetMatrix(); }
//랜더 void Render(int timeDelta) { //화면 청소 if (SUCCEEDED(g_pDevice->Clear( 0, //청소할 영역의 D3DRECT 배열 갯수 ( 전체 클리어 0 ) NULL, //청소할 영역의 D3DRECT 배열 포인터 ( 전체 클리어 NULL ) D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, //청소될 버퍼 플레그 ( D3DCLEAR_TARGET 컬러버퍼, D3DCLEAR_ZBUFFER 깊이버퍼, D3DCLEAR_STENCIL 스텐실버퍼 D3DCOLOR_XRGB(150, 150, 150), //컬러버퍼를 청소하고 채워질 색상( 0xAARRGGBB ) 1.0f, //깊이버퍼를 청소할값 ( 0 ~ 1 0 이 카메라에서 제일가까운 1 이 카메라에서 제일 먼 ) 0 //스텐실 버퍼를 채울값 ))) { //화면 청소가 성공적으로 이루어 졌다면... 랜더링 시작 g_pDevice->BeginScene(); //fps출력 static WORD frameCnt = 0; static DWORD ntimeDelay = 0; static float fps = 0.f; frameCnt++; ntimeDelay += timeDelta; if( ntimeDelay >= 1000 ) { fps = (float)frameCnt; frameCnt = 0; ntimeDelay -= ntimeDelay; } string outputFps = format( "%0.3f", fps ); RECT rc; SetRect( &rc, 150, 100, 0, 0 ); //다이렉트 생성할때의 화면 크기의 좌표로 적용됨 global->font->DrawTextA( NULL, //A : 아스키코드 // "global->font->DrawText", outputFps.c_str(), -1, &rc, DT_NOCLIP, //다 출력하겠다라는 의미(화면 크기 연연하지 않겠다인듯??) D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f) ); //쿼터니언 응용 /* Quaternion quat; quat.SetRotationArc(Vector3(0,1,0),Vector3(0,0,1)); //첫번째 인자방향 기준으로 두번째 인자 방향으로 Matrix44 qt = quat.GetMatrix(); */ static float ftheta = 0.f; ftheta += 0.0005f; const float fradian = ftheta / MATH_PI; if( ftheta >= 360.f ) ftheta = 0.f; Matrix44 mat; mat.SetTranslate(Vector3(5, sin(fradian) * 10.f, -490)); //sin(fradian) : 각도에 따른 +-변화 //10.f 곱하기는 범위 // Matrix44 m = global->localTm * mat; // g_pDevice->SetTransform(D3DTS_WORLD, (D3DXMATRIX*)&m); //마우스 회전 잠금 g_pDevice->SetTransform(D3DTS_WORLD, (D3DXMATRIX*)&mat); global->mesh3DText->DrawSubset( 0 ); Vector3 mainPos(-10, 0, -490); Vector3 targetLook = mat.GetPosition() - mainPos; //대상물체와 메인물체와의 거리 판단 targetLook.Normalize(); Quaternion quat; // mainPos.Normalize(); // quat.SetRotationArc(mainPos, targetLook); //첫번째 인자를 물체의 위치로 하니 회전하는 방향이 생각과는 다르게 표현된다...역시 고정된 방향이어야 되나보다... quat.SetRotationArc(Vector3(1,0,0), targetLook); //양의 x축방향으로 대상물체를 바라본다 Matrix44 qm = quat.GetMatrix(); mat.SetTranslate(mainPos); qm *= mat; g_pDevice->SetTransform(D3DTS_WORLD, (D3DXMATRIX*)&qm); global->mesh3DText->DrawSubset( 0 ); //랜더링 끝 g_pDevice->EndScene(); //랜더링이 끝났으면 랜더링된 내용 화면으로 전송 g_pDevice->Present( NULL, NULL, NULL, NULL ); } }