//------------------------------------------------------------------------------ // Camera.cpp // (C) 2005 Webzen Sunstudio //------------------------------------------------------------------------------ #include "SunClientPrecompiledHeader.h" #include "Camera.h" #include "Hero.h" #include "Gamefunc.h" #include "GlobalFunc.h" #include "InterfaceManager.h" #include "Map.h" #define CAMERA_PITCH_RANGE_MIN -0.50f #define CAMERA_PITCH_RANGE_MAX 1.50f #define CAMERA_ROT_STEP_MAX 0.012f #define CAMERA_ROT_SLOWDOWN_LEVEL 0.25f #define CAMERA_ROT_SLOWDOWN 0.30f #define CAMERA_ROT_MIN ( CAMERA_YEW_RANGE_MAX * 0.01f ) #define CAMERA_POS_SPRING_MINIMUM 0.4f #define CAMERA_POS_BASIC_MINIMUM 0.6f #define CAMERA_POS_MAXIMUM 1.2f #ifdef MAP_EDIT_MODE #define CAMERA_DISTANCE_RANGE_MAX ((GENERALPARAM->GetMaxCameraDistance())*(15.0f)) #else #define CAMERA_DISTANCE_RANGE_MAX (GENERALPARAM->GetMaxCameraDistance()) #endif #define INTERPOLATE_TIME 1000 Camera g_Camera; //------------------------------------------------------------------------------ /** */ Camera::Camera( void ) : m_CameraHeight(0.f) { m_bStartMove = FALSE; m_fAngle = sqrt( WZ_PI ); m_vibeType=VIBE_TYPE_ALL; m_eRatio = SR_4_3; m_bIsRotate = FALSE; m_bIsRotateX = FALSE; m_bIsRotateZ = FALSE; m_fPrevAngleYaw = 0.0f; m_fPrevAnglePitch = 0.0f; m_iPreYaw = 0; m_iPrePitch = 0; m_iAngleCheckX = 0; m_iAngleCheckZ = 0; m_bStartRotate = FALSE; m_bStartRotateX = FALSE; m_bStartRotateZ = FALSE; m_bForceSpringCamera=FALSE; m_iTurnState = CAMERA_NOT_TURN; m_fMoveSpeed = CAMERA_DEFAULT_MOVE_SPEED; m_fRotateLevelX = 0.0f; m_fRotateSlowDownX = 0.0f; m_fRotateLevelZ = 0.0f; m_fRotateSlowDownZ = 0.0f; m_fDistanceLevel = 0.0f; m_fDistanceSlowDown = 0.0f; m_bSpring=FALSE; m_fRotationSpeed =CAMERA_DEFAULT_ROTATE_SPEED; m_iRotationLevel = 3; SetRotationRange(1,5); m_bRidingTurn=FALSE; m_pPathExplorer = NULL; } //------------------------------------------------------------------------------ /** */ Camera::~Camera( void ) { Destroy(); } //------------------------------------------------------------------------------ /** */ BOOL Camera::Create( float fMin, float fMax ,float fFOV) { m_fAngleYawDirection = 1.0f; m_fTargetDirectionAngle = 0.0f; SetVector( &m_CameraTargetDirection, 0.0f, -1.0f, 0.0f ); SetVector( &m_wvX, 1.0f, 0.0f, 0.0f ); SetVector( &m_wvY, 0.0f, 1.0f, 0.0f ); SetVector( &m_wvZ, 0.0f, 0.0f, 1.0f ); m_fUp = 1.3f; // default if (GENERALPARAM->GetScreenShotMode()) { m_fDistance = CAMERA_DISTANCE; } else { m_fDistance = GENERALPARAM->GetCameraDistance(); } m_fAngleYaw = 0.0f; m_fAngleYawStep = 0.0f; m_fAnglePitch = 0.5f; SetVector( &m_CameraPosition, 0.0f, 0.0f, 0.0f ); SetVector( &m_CameraDirection, 0.0f, 1.0f, -1.0f ); SetVector( &m_CameraFrom, 0.0f, 0.0f, 0.0f ); SetVector( &m_CameraTo, 0.0f, 0.0f, 0.0f ); if( g_pSunRenderer ) { SetProjection( fMin, fMax ,fFOV); } // ±æÃ£±â ±â´É »ý¼º if (m_pPathExplorer) { Func_ContactTerrain(CT_DELETE_PATH_EXPLORER,m_pPathExplorer); m_pPathExplorer = NULL; } m_pPathExplorer = ( CPathExplorer* )Func_ContactTerrain( CT_NEW_PATH_EXPLORER, 0 ); m_fTurnAccelerate = 0.0f; m_status=0; m_springConst=0.709996f; m_dampConst=6.8f; m_springLen=0.1f; m_springConst=GENERALPARAM->GetSpringConst(); m_dampConst=GENERALPARAM->GetDampConst(); m_springLen=GENERALPARAM-> GetSpringLen(); SetVector(&m_targetOldPos,0.0f,0.0f,0.0f); SetVector(&m_chasePos,0.0f,0.0f,0.0f); m_fMoveSpeed = CAMERA_DEFAULT_MOVE_SPEED; return TRUE; } //------------------------------------------------------------------------------ /** */ void Camera::Destroy( void ) { // ±æÃ£±â ±â´É ÆÄ±« if( m_pPathExplorer ) { Func_ContactTerrain( CT_DELETE_PATH_EXPLORER, m_pPathExplorer ); m_pPathExplorer = NULL; } } //------------------------------------------------------------------------------ /** */ void Camera::SetProjection( float fMin, float fMax ,float fFOV) { m_fFOV = fFOV; m_fNearClip = fMin; m_fFarClip = fMax; RestoreProjection(); } //------------------------------------------------------------------------------ /** ±âº»Àº Ä«¸Þ¶óÀÇ À§Ä¡¸¦ ¼³Á¤ÇÑ´Ù. ¹ÙÀ̺극À̼ÇÀÌ Àִ°æ¿ì ÁÂÇ¥¸¦ ¼öÁ¤ÇØÁØ´Ù. */ void Camera::SetCameraPosition( WzVector* WzTarget ) { m_CameraPosition = *WzTarget; m_CameraPosition.z += CameraHeight(); float fMoveOffset = m_vibePower; if( m_vibeType == VIBE_TYPE_VERTICAL ) { m_CameraPosition.z += fMoveOffset; } else if( m_vibeType==VIBE_TYPE_HORISONTAL ) { m_CameraPosition.x += fMoveOffset; m_CameraPosition.y += fMoveOffset; } else { // VIBE_TYPE_NONE À϶§¿¡µµ 󸮵ǰÚÁö¸¸ ¾Æ¸¶µµ m_vibePower°¡ 0ÀÏ °ÍÀÌ´Ù.. int r = rand()%3; if ( r == 0 ) m_CameraPosition.z += fMoveOffset; else if ( r == 1 ) m_CameraPosition.x += fMoveOffset; else m_CameraPosition.y += fMoveOffset; } } //------------------------------------------------------------------------------ /** spring damp function @param currPos current position @param trgPos target position @param prevTrgPos previous target position @param deltaTime change in time @param springConst hook's constant @param dampConst damping constant @param springLen spring length */ vector3 Camera::SpringDamp( vector3 currPos, // Current Position const vector3& trgPos, // Target Position const vector3& prevTrgPos, // Previous Target Position float deltaTime, // Change in Time float springConst, // Hooke's Constant float dampConst, // Damp Constant float springLen) { static vector3 disp; /// displacement static vector3 velocity; /// velocity static float forceMag; /// force magnitude deltaTime = min(deltaTime,1.0f); //ƽÀÌ ³Ê¹« Å©¸é ¾ÈµÈ´Ù /** Calculate Spring Force */ disp = currPos - trgPos; velocity = (prevTrgPos - trgPos) * deltaTime; forceMag = springConst * (springLen - disp.len()) + dampConst * ((disp % velocity) / disp.len()); /** Apply Spring Force */ disp.norm(); disp *= forceMag * deltaTime; currPos += disp; return currPos; } void Camera::SetBasicCamera( WzVector* wvPos, BOOL bHeightCheck,DWORD dwTick) { // Ä«¸Þ¶óÀÇ À§Ä¡¸¦ ¼³Á¤ if( wvPos != NULL ) { if ( 0.f == m_CameraPosition.x && 0.f == m_CameraPosition.y) { SetCameraPosition( wvPos ); } else { float fOldPlayerZ = m_CameraPosition.z - CameraHeight(); float fDistance = wvPos->z - fOldPlayerZ; if ( -0.01f >= fDistance || 0.01f <= fDistance) { wvPos->z = fOldPlayerZ + (fDistance/2); SetCameraPosition( wvPos ); } else { SetCameraPosition( wvPos ); } } } // Ä«¸Þ¶óÀÇ µ¥ÀÌÅ͸¦ °»½Å WzMatrix CameraMatrix, CameraMatrix1, CameraMatrix2; MatrixIdentity( &CameraMatrix1 ); MatrixRotationZ( &CameraMatrix1, m_fAngleYaw ); MatrixIdentity( &CameraMatrix2 ); MatrixRotationX( &CameraMatrix2, m_fAnglePitch ); MatrixMultiply( &CameraMatrix, &CameraMatrix2, &CameraMatrix1 ); VectorTransformNormal( &m_CameraDirection, &m_wvY, &CameraMatrix ); m_CameraTo = m_CameraPosition; m_CameraFrom = m_CameraTo + ( m_CameraDirection * m_fDistance ); WzVector wvNomal; SetVector(&wvNomal,0.0f,0.0f,0.0f); // ÁöÇü ¸Þ½Ã¿¡ °¡·ÁÁö´Â °æ¿ì º¸Á¤ if ( g_pSunTerrain ) { float fT; WzRay ray; ray.m_wvOrigin = m_CameraPosition; ray.m_wvDirection = m_CameraFrom - m_CameraTo; VectorNormalize( &ray.m_wvDirection, &ray.m_wvDirection); int iTerrainMeshFocussing = g_pSunTerrain->PickTerrainMesh( &ray, &fT ,TRUE,TMGO_HAZE, &wvNomal); if( iTerrainMeshFocussing >= 0 ) { if (fT < m_fDistance) { m_CameraFrom = ray.m_wvOrigin + ray.m_wvDirection * (fT - 0.01f); if(m_CameraFrom!=m_CameraTo) { WzVector temp=m_CameraFrom-m_CameraTo; float fLen=VectorLength(&temp); if(fLen>=1.0f) { m_CameraFrom+=wvNomal*0.5f; } } } } } // õÀå¿¡ ÀÇÇØ °¡·ÁÁö´Â °æ¿ì º¸Á¤ if( bHeightCheck && g_pMap && wvNomal.z >= 0.0f ) { //¸®¼ÂÀÌ ½ÇÆÐÇÏ´Â °æ¿ì°¡ Á¾Á¾ ÀÖ°í ½ÇÆÐÇÒ°æ¿ì Ä«¸Þ¶ó°¡ Ƥ´Ù.-Áö¿Ï WzVector temp = m_CameraFrom; if(g_pSunTerrain->PathExp_Reset(m_pPathExplorer, &temp,-1)) { m_CameraFrom = temp; WzVector wvCameraPos = m_pPathExplorer->GetVisiblePos(); float fAddHeight=CAMERA_POS_SPRING_MINIMUM; if(wvCameraPos!=m_CameraTo) { WzVector tempv; tempv=wvCameraPos-m_CameraTo; float fdis=VectorLength(&tempv); fAddHeight=CAMERA_POS_MAXIMUM; float fRate=fdis/CAMERA_DISTANCE_RANGE_MAX; fAddHeight*=fRate; fAddHeight=min(fAddHeight,CAMERA_POS_MAXIMUM); fAddHeight=max(fAddHeight,CAMERA_POS_BASIC_MINIMUM); } wvCameraPos.z+=fAddHeight;; if( wvCameraPos.z > m_CameraFrom.z ) { m_CameraFrom = wvCameraPos; } } } // ¹Ù¿îµù ¿µ¿ª¿¡ °¡·ÁÁö´Â °æ¿ì º¸Á¤ if( g_pMap && g_pMap->IsLoaded()) { float fT; WzRay ray; //º¯°æ rayÀç¼³Á¤ ray.m_wvOrigin = m_CameraPosition; ray.m_wvDirection = m_CameraFrom - m_CameraTo; VectorNormalize(&ray.m_wvDirection,&ray.m_wvDirection); if(g_pMap->GetCollisionBV(&ray,m_fDistance,&fT)) { //³ë¸»¹æÇâÀÇ·Î ¹Ð±â´Â ¾ÈÇϰÚÀ½(°è»êÀÌ ¸¹À̵é¾î°¨) m_CameraFrom = ray.m_wvOrigin + ray.m_wvDirection * (fT - 0.01f); } } m_targetOldPos = m_CameraFrom; } void Camera::InitSpringCamera(BOOL bSpring) { m_bSpring=bSpring; WzMatrix CameraMatrix, CameraMatrix1, CameraMatrix2; MatrixIdentity( &CameraMatrix1 ); MatrixRotationZ( &CameraMatrix1, m_fAngleYaw ); MatrixIdentity( &CameraMatrix2 ); MatrixRotationX( &CameraMatrix2, m_fAnglePitch ); MatrixMultiply( &CameraMatrix, &CameraMatrix2, &CameraMatrix1 ); VectorTransformNormal( &m_CameraDirection, &m_wvY, &CameraMatrix ); m_CameraFrom = m_CameraTo + ( m_CameraDirection * m_fDistance ); m_targetOldPos = m_CameraFrom; } //------------------------------------------------------------------------------ /** ½ºÇÁ¸µ Ä«¸Þ¶ó ±â´É Ãß°¡ 2006.12.13 ±èÁö¿Ï */ void Camera::SetSpringCamera( WzVector* wvPos, BOOL bHeightCheck ,DWORD dwTick) { //Todo:¿òÁ÷ÀÏ ¶§¸¸ üũ if( wvPos != NULL ) { SetCameraPosition( wvPos); } m_targetOldPos = m_chasePos; // Ä«¸Þ¶ó ¿øº» WzMatrix CameraMatrix, CameraMatrix1, CameraMatrix2; MatrixIdentity( &CameraMatrix1 ); MatrixRotationZ( &CameraMatrix1, m_fAngleYaw ); MatrixIdentity( &CameraMatrix2 ); MatrixRotationX( &CameraMatrix2, m_fAnglePitch ); MatrixMultiply( &CameraMatrix, &CameraMatrix2, &CameraMatrix1 ); VectorTransformNormal( &m_CameraDirection, &m_wvY, &CameraMatrix ); m_CameraTo=m_CameraPosition; m_chasePos = m_CameraTo + ( m_CameraDirection * m_fDistance ); if(m_CameraFrom==m_chasePos) return; WzVector vFirstFrom=m_chasePos; WzVector temp=m_CameraDirection; temp.z=0.0f; WzVector up; SetVector(&up,0.0f,0.0f,1.0f); WzVector wvRight; VectorCrossProduct(&wvRight,&temp,&up); VectorNormalize(&wvRight,&wvRight); float fSideDistance = 1.5f; wvRight *= fSideDistance; WzVector wvLeft = wvRight * -1.0f; WzVector wvPick1, wvPick2; SetVector(&wvPick1,0.0f,0.0f,0.0f); SetVector(&wvPick2,0.0f,0.0f,0.0f); WzRay ray; if (g_pSunTerrain) { //°¡¿îµ¥ üũ float fT=10000.0f; ray.m_wvOrigin = m_CameraTo; ray.m_wvDirection = m_chasePos- m_CameraTo; VectorNormalize(&ray.m_wvDirection,&ray.m_wvDirection); float fT1=10000.0f; WzVector wvNomal; SetVector(&wvNomal,0.0f,0.0f,0.0f); int iTerrainMeshFocussing = g_pSunTerrain->PickTerrainMesh( &ray, &fT ,TRUE,TMGO_HAZE,&wvNomal); if( iTerrainMeshFocussing >= 0 ) { DWORD dwTerrainAttribute=0; if (fT < m_fDistance) { fT=fT - 0.01f; fT=max(fT,0.0f); m_chasePos= ray.m_wvOrigin + ray.m_wvDirection *fT; wvPick1=m_chasePos; if(m_chasePos!=m_CameraTo) { WzVector temp=m_chasePos-m_CameraTo; float fLen=VectorLength(&temp); if(fLen>=1.0f) { wvNomal.x*=2.0f; wvNomal.y*=2.0f; wvNomal.z*=0.5f; m_chasePos+=(wvNomal); } } } } //¹Ù¿îµù°ü·Ã 󸮸¦ ¿©±â¼­ÇÑ´Ù. if(g_pMap && g_pMap->IsLoaded()) { float fT; //º¯°æ rayÀç¼³Á¤ ray.m_wvOrigin = m_CameraTo; ray.m_wvDirection = m_chasePos- m_CameraTo; VectorNormalize(&ray.m_wvDirection,&ray.m_wvDirection); if(g_pMap->GetCollisionBV(&ray,m_fDistance,&fT)) { //³ë¸»¹æÇâÀÇ·Î ¹Ð±â´Â ¾ÈÇϰÚÀ½(°è»êÀÌ ¸¹À̵é¾î°¨) fT=fT - 0.01f; fT=max(fT,0.0f); m_chasePos= ray.m_wvOrigin + ray.m_wvDirection *fT; wvPick1=m_chasePos; } } float fTempLen = m_fDistance-1.0f; fTempLen = max(fTempLen,1.0f); vFirstFrom = m_CameraTo + (m_CameraDirection * fTempLen); WzVector wvTempTo = m_CameraTo; wvTempTo.z += 0.5f; ray.m_wvOrigin = vFirstFrom; ray.m_wvDirection = wvTempTo- vFirstFrom; VectorNormalize(&ray.m_wvDirection,&ray.m_wvDirection); iTerrainMeshFocussing = g_pSunTerrain->PickTerrainMesh( &ray, &fT ,TRUE,0); if( iTerrainMeshFocussing >= 0 ) { if (fT <= m_fDistance) { wvPick2= ray.m_wvOrigin + ray.m_wvDirection *fT; } } if( bHeightCheck && m_pPathExplorer) { float fAddHeight=CAMERA_POS_SPRING_MINIMUM; if(m_chasePos!=m_CameraTo) { WzVector tempv; tempv=m_chasePos-m_CameraTo; float fdis=VectorLength(&tempv); fAddHeight=CAMERA_POS_MAXIMUM; float fRate=fdis/CAMERA_DISTANCE_RANGE_MAX; fAddHeight*=fRate; fAddHeight=min(fAddHeight,CAMERA_POS_MAXIMUM); fAddHeight=max(fAddHeight,CAMERA_POS_SPRING_MINIMUM); } g_pSunTerrain->PathExp_Reset( m_pPathExplorer, &m_chasePos, -1); WzVector wvCameraPos = m_pPathExplorer->GetPos(); wvCameraPos.z +=fAddHeight; if( wvCameraPos.z > m_chasePos.z ) { m_chasePos = wvCameraPos; } } } // ¿öÇÁ¸é if(!m_bSpring) { WarpFrom(); } else if(m_CameraFrom!=m_chasePos) { vector3 from,chasePos,targetOldPos; from.set(m_CameraFrom.x,m_CameraFrom.z,m_CameraFrom.y); chasePos.set(m_chasePos.x,m_chasePos.z,m_chasePos.y); targetOldPos.set(m_targetOldPos.x,m_targetOldPos.z,m_targetOldPos.y); float fTick=(float)dwTick/1000.0f; from = SpringDamp(from, chasePos, targetOldPos, 5.0f * fTick, m_springConst, m_dampConst, m_springLen); SetVector(&m_CameraFrom,from.x,from.z,from.y); } } void Camera::WarpFrom() { m_bSpring=TRUE; m_targetOldPos=m_CameraFrom=m_chasePos; } //------------------------------------------------------------------------------ /** Ä«¸Þ¶ó Ãæµ¹ ·çƾ ¼öÁ¤ 2006.12.6 ±èÁö¿Ï */ void Camera::SetCamera( WzVector* wvPos, BOOL bHeightCheck,DWORD dwTick) { const OptionParam& tempOption = GAMEOPTION->GetGameOption(); if(tempOption.GetOptionValue( nOptionType::USE_SPRING_CAMERA ) || m_bForceSpringCamera ) SetSpringCamera(wvPos,bHeightCheck,dwTick); else SetBasicCamera(wvPos,bHeightCheck,dwTick); } //------------------------------------------------------------------------------ /** */ void Camera::SetTargetDirection( WzVector *wvDir ) { m_CameraDirection.x = wvDir->x; m_CameraDirection.y = wvDir->y; m_CameraDirection.z = 0.0f; } //------------------------------------------------------------------------------ /** */ void Camera::StartMove( void ) { m_bStartMove = TRUE; } //------------------------------------------------------------------------------ /** */ void Camera::InterpolateAngle( void ) { if( m_fTargetDirectionAngle != m_fAngleYaw ) { float fCount = m_fAngleYaw - m_fTargetDirectionAngle; if( fCount < 0.0f ) { fCount += CAMERA_YEW_RANGE_MAX; } if( fCount == 0.0f || fCount < 0.01f ) { m_fAngleYaw = m_fTargetDirectionAngle; m_fAngleYawStep = 0.0f; return; } float fDir; float fPercent; // Á¡Á¡ °¡¼Óµµ Áõ°¡ if( fCount < CAMERA_YEW_RANGE_CENTER ) { // °¨¼ÒÇϸ鼭 µµ´Þ fDir = -1.0f; fPercent = ( fCount / CAMERA_YEW_RANGE_CENTER ); } else { // Áõ°¡Çϸ鼭 µµ´Þ fDir = 1.0f; fPercent = ( (CAMERA_YEW_RANGE_MAX - fCount) / CAMERA_YEW_RANGE_CENTER ); } float fAngleStep = m_fAngle * fPercent; m_fAngleYawStep = (fAngleStep * fAngleStep); if( m_fAngleYawStep > CAMERA_ROT_STEP_MAX ) { m_fAngleYawStep = CAMERA_ROT_STEP_MAX; } // ¿¨±Û Á¶Àý m_fAngleYaw += m_fAngleYawStep * fDir; if( m_fAngleYaw < 0.0f ) { m_fAngleYaw += CAMERA_YEW_RANGE_MAX; } else if( m_fAngleYaw >= CAMERA_YEW_RANGE_MAX ) { m_fAngleYaw -= CAMERA_YEW_RANGE_MAX; } } } //------------------------------------------------------------------------------ /** */ void Camera::KeyboardModeInterpolateAngle(float fDestViewAngle) { if(g_pHero && g_pHero->GetMoveFlag() & (KEYBOARDMOVE_LEFTTURN | KEYBOARDMOVE_RIGHTTURN) ) { const float fTurnSpeed = WZ_PI / 6.0f; // 6µµ ClampAngle(&fDestViewAngle); if (fDestViewAngle != m_fAngleYaw) { // °¢µµ¸¦ ´õÇÏ´Â°Ô ºü¸¥Áö »©´Â°Ô ºü¸¥Áö ÆÇ´ÜÇÑ´Ù. float fLeftDiff; // ÀÌÂÊÀÌ ´õÇϱâ float fRightDiff; // »©±â if ( fDestViewAngle > m_fAngleYaw) { fLeftDiff = fDestViewAngle - m_fAngleYaw; } else { fLeftDiff = fDestViewAngle - m_fAngleYaw + WZ_PI * 2.0f; } // ¹Ý´ëÂÊ È¸Àü°¢µµ¿ÍÀÇ ÇÕÀº 360µµ fRightDiff = WZ_PI * 2.0f - fLeftDiff; if ( fLeftDiff <= fRightDiff ) { if (fLeftDiff > fTurnSpeed) { m_fAngleYaw += fTurnSpeed; ClampAngle(&m_fAngleYaw); } else { m_fAngleYaw = fDestViewAngle; } } else { if (fRightDiff > fTurnSpeed) { m_fAngleYaw -= fTurnSpeed; ClampAngle(&m_fAngleYaw); } else { m_fAngleYaw = fDestViewAngle; } } } } } //------------------------------------------------------------------------------ /** */ BOOL Camera::Process( DWORD dwTick ) { // Áøµ¿ ¸ðµå if(BIT_CHECK(m_status,CAMERA_STATUS_VIBE)) { if(m_twSwitch < (BOOL)dwTick) { m_twSwitch=(BOOL)INIT_SWITCH; static float fWave = -1.0f; m_vibePower*=fWave; } else { m_twSwitch-=dwTick; } if(m_twVibe<=0.0f) { EndVibration(); } else { m_twVibe-=dwTick; } UpdateCamera(); } return TRUE; } //------------------------------------------------------------------------------ /** */ void Camera::StartVibration(float time,float fPower) { BIT_ADD(m_status,CAMERA_STATUS_VIBE); m_twVibe=time; m_vibePower=fPower; m_twSwitch=(BOOL)INIT_SWITCH; } //------------------------------------------------------------------------------ /** */ void Camera::EndVibration() { BIT_REMOVE(m_status,CAMERA_STATUS_VIBE); m_twVibe=0; m_vibePower=0.0f; m_vibeType=VIBE_TYPE_NONE; UpdateCamera(); } #ifdef CAMERA_SMOOTH_DELETE //------------------------------------------------------------------------------ /** */ void Camera::Rotate( int iAngleX, int iAngleZ, int iState ) { const int c_iAngleCheck = 8; const int c_iTotalAngleCheckX = 12; const int c_iTotalAngleCheckZ = 12; float c_fRotate = GetRotationSpeed(); m_iRotateState = iState; m_fAngleYawStep = 0.0f; if( iAngleX == 0 ) { m_iTurnState = CAMERA_NOT_TURN; } else if( iAngleX > 0 ) { m_iTurnState = CAMERA_RIGHT_TURN; } else if( iAngleX < 0 ) { m_iTurnState = CAMERA_LEFT_TURN; } if( m_iPreYaw != iAngleX ) { if( m_bStartRotateX == FALSE ) { if( abs(iAngleX) > c_iAngleCheck ) { m_iAngleCheckX = 0; m_bStartRotateX = TRUE; } else { m_iAngleCheckX += iAngleX; if( abs(m_iAngleCheckX) > c_iTotalAngleCheckX ) { m_iAngleCheckX = 0; m_bStartRotateX = TRUE; } } } if( m_bStartRotateX ) { m_iPreYaw = iAngleX; m_fAngleYaw -= (float)(iAngleX) * c_fRotate; if( m_fAngleYaw < CAMERA_YEW_RANGE_MIN ) { m_fAngleYaw += CAMERA_YEW_RANGE_MAX; } else if( m_fAngleYaw > CAMERA_YEW_RANGE_MAX ) { m_fAngleYaw -= CAMERA_YEW_RANGE_MAX; } // Ä«¸Þ¶ó ȸÀü üũ if( m_fPrevAngleYaw != m_fAngleYaw ) { m_fPrevAngleYaw = m_fAngleYaw; m_bIsRotateX = TRUE; } } } if( m_iPrePitch != iAngleZ ) { if( m_bStartRotateZ == FALSE ) { if( abs(iAngleZ) > c_iAngleCheck ) { m_iAngleCheckZ = 0; m_bStartRotateZ = TRUE; } else { m_iAngleCheckZ += iAngleZ; if( abs(m_iAngleCheckZ) > c_iTotalAngleCheckZ ) { m_iAngleCheckZ = 0; m_bStartRotateZ = TRUE; } } } if( m_bStartRotateZ ) { m_iPrePitch = iAngleZ; m_fAnglePitch += (float)(iAngleZ) * c_fRotate; if( m_fAnglePitch < CAMERA_PITCH_RANGE_MIN ) { m_fAnglePitch = CAMERA_PITCH_RANGE_MIN; } else if( m_fAnglePitch > CAMERA_PITCH_RANGE_MAX ) { m_fAnglePitch = CAMERA_PITCH_RANGE_MAX; } } // Ä«¸Þ¶ó ȸÀü üũ if( m_fPrevAnglePitch != m_fAnglePitch ) { m_fPrevAnglePitch = m_fAnglePitch; m_bIsRotateZ = TRUE; } } // ÃÖÁ¾ °á°ú m_bIsRotate = m_bIsRotateX | m_bIsRotateZ; m_bStartRotate = m_bStartRotateX | m_bStartRotateZ; } #else //------------------------------------------------------------------------------ /** */ void Camera::Rotate( int iAngleX, int iAngleZ, int iState ) { const int c_iAngleCheckX = 16 * 2; const int c_iAngleCheckZ = 8 * 2; const int c_iTotalAngleCheckX = 18 * 2; const int c_iTotalAngleCheckZ = 12 * 2; float c_fRotate = GetRotationSpeed(); m_iRotateState = iState; m_fAngleYawStep = 0.0f; m_fRotateLevelX += (float)iAngleX * CAMERA_ROT_SLOWDOWN_LEVEL; m_fRotateSlowDownX = m_fRotateLevelX * CAMERA_ROT_SLOWDOWN; m_fRotateLevelZ += (float)iAngleZ * CAMERA_ROT_SLOWDOWN_LEVEL; m_fRotateSlowDownZ = m_fRotateLevelZ * CAMERA_ROT_SLOWDOWN; if( iAngleX == 0 ) { m_iTurnState = CAMERA_NOT_TURN; } else if( iAngleX > 0 ) { m_iTurnState = CAMERA_RIGHT_TURN; } else if( iAngleX < 0 ) { m_iTurnState = CAMERA_LEFT_TURN; } if( m_iPreYaw != iAngleX ) { if( m_bStartRotateX == FALSE ) { if( abs(iAngleX) > c_iAngleCheckX ) { m_iAngleCheckX = 0; m_bStartRotateX = TRUE; } else { m_iAngleCheckX += iAngleX; if( abs(m_iAngleCheckX) > c_iTotalAngleCheckX ) { m_iAngleCheckX = 0; m_bStartRotateX = TRUE; } } } if( m_bStartRotateX ) { if(m_iRotateState==Camera::CAMERA_ROTATE_LMOUSE && g_pHero->IsRiding()) { m_bRidingTurn = TRUE; } m_iPreYaw = (int)m_fRotateLevelX; m_fAngleYaw -= (float)(m_fRotateLevelX) * c_fRotate; if( m_fAngleYaw < CAMERA_YEW_RANGE_MIN ) { m_fAngleYaw += CAMERA_YEW_RANGE_MAX; } else if( m_fAngleYaw > CAMERA_YEW_RANGE_MAX ) { m_fAngleYaw -= CAMERA_YEW_RANGE_MAX; } // Ä«¸Þ¶ó ȸÀü üũ if( m_fPrevAngleYaw != m_fAngleYaw ) { m_fPrevAngleYaw = m_fAngleYaw; m_bIsRotateX = TRUE; } } } if( m_iPrePitch != iAngleZ ) { if( m_bStartRotateZ == FALSE ) { if( abs(iAngleZ) > c_iAngleCheckZ ) { m_iAngleCheckZ = 0; m_bStartRotateZ = TRUE; } else { m_iAngleCheckZ += iAngleZ; if( abs(m_iAngleCheckZ) > c_iTotalAngleCheckZ ) { m_iAngleCheckZ = 0; m_bStartRotateZ = TRUE; } } } if( m_bStartRotateZ ) { m_iPrePitch = (int)m_fRotateLevelZ; m_fAnglePitch += (float)(m_fRotateLevelZ) * c_fRotate; if( m_fAnglePitch < CAMERA_PITCH_RANGE_MIN ) { m_fAnglePitch = CAMERA_PITCH_RANGE_MIN; } else if( m_fAnglePitch > CAMERA_PITCH_RANGE_MAX ) { m_fAnglePitch = CAMERA_PITCH_RANGE_MAX; } // Ä«¸Þ¶ó ȸÀü üũ if( m_fPrevAnglePitch != m_fAnglePitch ) { m_fPrevAnglePitch = m_fAnglePitch; m_bIsRotateZ = TRUE; } } } // ÃÖÁ¾ °á°ú m_bIsRotate = m_bIsRotateX | m_bIsRotateZ; m_bStartRotate = m_bStartRotateX | m_bStartRotateZ; m_fRotateLevelX -= m_fRotateSlowDownX; if( (float)abs(m_fRotateLevelX) < CAMERA_ROT_MIN ) { m_fRotateLevelX = 0.0f; m_fRotateSlowDownX = 0.0f; } else { m_fAngleYaw -= (float)(m_fRotateLevelX) * c_fRotate; if( m_fAngleYaw < CAMERA_YEW_RANGE_MIN ) { m_fAngleYaw += CAMERA_YEW_RANGE_MAX; } else if( m_fAngleYaw > CAMERA_YEW_RANGE_MAX ) { m_fAngleYaw -= CAMERA_YEW_RANGE_MAX; } //°¢ÀÌ Á» ½ÉÇÏ°Ô ¹ú¾îÁö¸é ÀÚµ¿È¸Àü½ÃŲ´Ù. if(m_bRidingTurn) { AutoTurnState(); } } m_fRotateLevelZ -= m_fRotateSlowDownZ; if( (float)abs(m_fRotateLevelZ) < CAMERA_ROT_MIN ) { m_fRotateLevelZ = 0.0f; m_fRotateSlowDownZ = 0.0f; } else { m_fAnglePitch += (float)(m_fRotateLevelZ) * c_fRotate; if( m_fAnglePitch < CAMERA_PITCH_RANGE_MIN ) { m_fAnglePitch = CAMERA_PITCH_RANGE_MIN; } else if( m_fAnglePitch > CAMERA_PITCH_RANGE_MAX ) { m_fAnglePitch = CAMERA_PITCH_RANGE_MAX; } } } #endif //------------------------------------------------------------------------------ /** */ void Camera::SetRotateState( BOOL bState ) { m_bIsRotate = bState; m_bIsRotateX = bState; m_bIsRotateZ = bState; if(bState==FALSE) { CheckTurnState(); m_bRidingTurn = FALSE; } } //------------------------------------------------------------------------------ /** ¶óÀÌ´õ ÀÚµ¿È¸Àü */ void Camera::AutoTurnState() { float fDestAngle = g_pHero->GetAngle(); float fCameraAngle = g_Camera.GetAngle(); int iTurnSTate = TARGET_LEFT; //Ä«¸Þ¶ó°¡ ¿ÞÂÊ¿¡ ÀÖ´Ù. if ( fCameraAngle > fDestAngle) { //¿ÞÂÊ¿¡À־ 180³Ñ¾î¼±°÷¿¡ ÀÖÀ¸¸é Ä«¸Þ¶óÀÇ ¹æÇâÀº ¿À¸¥ÂÊÀÌ¿©¾ßÇÑ´Ù. if( fCameraAngle > fDestAngle+WZ_PI) { iTurnSTate = TARGET_REVERSE_RIGHT; } } else { iTurnSTate = TARGET_RIGHT; //¿À¸¥ÂÊ¿¡ Ä«¸Þ¶ó°¡ À§Ä¡Çصµ 180À» ³Ñ¾î¼±°÷À̶ó¸é ¿ÞÂÊÀ¸·Î µµ´Â°Ô ´õºü¸£´Ù if( fDestAngle > fCameraAngle+WZ_PI) { iTurnSTate = TARGET_REVERSE_LEFT; } } float fAngleGap = 0.f; switch(iTurnSTate) { case TARGET_LEFT: fAngleGap = fabs(m_fAngleYaw-fDestAngle);break; case TARGET_RIGHT: fAngleGap = fabs(fDestAngle-m_fAngleYaw);break; case TARGET_REVERSE_LEFT: fAngleGap = fabs((WZ_PI*2.f)-fDestAngle+m_fAngleYaw);break; case TARGET_REVERSE_RIGHT: fAngleGap = fabs((WZ_PI*2.f)-m_fAngleYaw+fDestAngle);break; } float fAngle = n_rad2deg(fAngleGap); //40'µµÀÌ»ó¹ú¾îÁú°æ¿ì ÀÚµ¿ÀÇ·Î µ¹·Á¹ö¸°´Ù. if(fAngle>40.f) { CheckTurnState(); m_bRidingTurn= FALSE; } } //------------------------------------------------------------------------------ /** ¶óÀÌ´õ ÀÚµ¿È¸Àü */ void Camera::CheckTurnState() { if(!g_pHero ) { return; } //¿ìȸÀüÀÌ ½ÃÀ۵ǴºκÐÀÌ´Ù. if( m_bRidingTurn && g_pHero->IsRiding() && !g_pHero->IsMove() && !g_pHero->IsJumping()) { if(g_pHero->GetCurState()!=STATE::RIDER_TURN && g_pHero->GetNextState()==STATE::NONE) { g_pHero->SetNextState(STATE::RIDER_TURN,g_CurTime); } } } //------------------------------------------------------------------------------ /** */ void Camera::SetYaw(float fYaw) { m_fAngleYaw = fYaw; if( m_fAngleYaw < CAMERA_YEW_RANGE_MIN ) { m_fAngleYaw += CAMERA_YEW_RANGE_MAX; } else if( m_fAngleYaw > CAMERA_YEW_RANGE_MAX ) { m_fAngleYaw -= CAMERA_YEW_RANGE_MAX; } } //------------------------------------------------------------------------------ /** */ float Camera::GetYaw() { return m_fAngleYaw; } //------------------------------------------------------------------------------ /** */ void Camera::SetPitch(float fPitch) { m_fAnglePitch = fPitch; if( m_fAnglePitch < CAMERA_PITCH_RANGE_MIN ) { m_fAnglePitch = CAMERA_PITCH_RANGE_MIN; } else if( m_fAnglePitch > CAMERA_PITCH_RANGE_MAX ) { m_fAnglePitch = CAMERA_PITCH_RANGE_MAX; } } //------------------------------------------------------------------------------ /** */ void Camera::RotateAroundFocus(float fAngle) { SetYaw(m_fAngleYaw + fAngle); } //------------------------------------------------------------------------------ /** */ float Camera::GetFarClip() { return m_fFarClip; } //------------------------------------------------------------------------------ /** */ float Camera::GetNearClip() { return m_fNearClip; } float Camera::GetFOV() { return m_fFOV; } void Camera::RestoreProjection() { g_pSunRenderer->SetProjectionMatrix( m_fFOV, m_fNearClip, m_fFarClip ,m_eRatio); float fFade[2] = { max(0.0f,m_fFarClip - 30.0f),m_fFarClip }; } WzRay Camera::GenerateCameraRay() { WzRay ray; ray.m_wvOrigin = m_CameraPosition; ray.m_wvDirection = m_CameraFrom - m_CameraTo; VectorNormalize(&ray.m_wvDirection,&ray.m_wvDirection); return ray; } //------------------------------------------------------------------------------ /** */ void Camera::UpdateCamera() { if(g_pSunRenderer) { g_pSunRenderer->SetCameraMatrix( &m_CameraFrom, &m_CameraTo, &m_wvZ ); //const St_LightInformation* pstLightInfo; //pstLightInfo = g_pSunRenderer->x_pManagerLight->GetLightInfo( 0 ); //WzVector wvLightDir = pstLightInfo->m_wvDirection; //St_Camera* pCamera = g_pSunRenderer->GetCameraInfo(); //float fDot = fabsf( VectorDotProduct( &pCamera->m_wvDir, &wvLightDir ) ); //float fMin = 0.000001f; //float fMax = 0.0005f; //float fTemp = fMax - fMin; //fTemp = ( 1.0f - fDot ) * fTemp; //fTemp = fMin + fTemp; } } void Camera::SetAspectRatio(ENUM_SCREEN_RATIO eRatio) { m_eRatio = eRatio; RestoreProjection(); } #ifdef _KST_CREATECHARACTER_SPRINGCAMERA_ void Camera::InitSpringCameraPosition( const WzVector& From, const WzVector& To ) { SetVector(&m_wvZ, 0.0, 0.0, 1.0f); m_targetOldPos = m_chasePos; m_CameraTo = To; m_chasePos = From; m_targetOldPos = m_CameraFrom = m_chasePos; UpdateCamera(); } void Camera::SetSpringCameraPosition( const WzVector& From, const WzVector& To, DWORD dwTick ) { SetVector(&m_wvZ, 0.0, 0.0, 1.0f); m_targetOldPos = m_chasePos; m_chasePos = From; m_CameraTo = To; if( m_chasePos != m_CameraFrom ) { vector3 from,chasePos,targetOldPos; from.set(m_CameraFrom.x,m_CameraFrom.z,m_CameraFrom.y); chasePos.set(m_chasePos.x,m_chasePos.z,m_chasePos.y); targetOldPos.set(m_targetOldPos.x,m_targetOldPos.z,m_targetOldPos.y); float fTick=(float)dwTick/1000.0f; from = SpringDamp(from, chasePos, targetOldPos, 5.0f * fTick, m_springConst, m_dampConst, m_springLen); SetVector(&m_CameraFrom,from.x,from.z,from.y); } } #else // _KST_CREATECHARACTER_SPRINGCAMERA_ void Camera::AttachToBone(const WzVector& From, const WzVector& To ) { SetVector(&m_wvZ, 0.0, 0.0, 1.0f); m_CameraFrom = From; m_CameraTo = To; UpdateCamera(); } #endif // _KST_CREATECHARACTER_SPRINGCAMERA_ float Camera::GetCameraDistance() { return m_fDistance; } void Camera::FreeCameraMoveFrontBack( int iDist ) { m_CameraFrom += m_CameraDirection; } float Camera::GetCurrentCameraFocusRange() { WzVector vDiff = m_CameraTo - m_CameraFrom; return VectorLength(&vDiff); } //------------------------------------------------------------------------------ /** */ void Camera::MoveFrontBack( int iDist ) { float c_fRotate = GetRotationSpeed(); m_fDistanceLevel += (float)iDist * CAMERA_ROT_SLOWDOWN_LEVEL; m_fDistanceSlowDown = m_fDistanceLevel * CAMERA_ROT_SLOWDOWN; m_fDistance -= m_fDistanceLevel * c_fRotate; float fRate = 1.0f; CGameOption* pOption = NULL; pOption = CGameOption::Instance(); if (pOption) { const OptionParam& option = pOption->GetGameOption(); if (option.GetOptionValue( nOptionType::USE_EXTENSION_CAMERA_DISTANCE ) ) { fRate = 1.5f; } } if (g_bObserverMode) { fRate = 1.5f; } #ifdef PERF_AUTO_MOVE_TEST fRate = 5.0f; #endif if (m_fDistance < CAMERA_DISTANCE_RANGE_MIN) { m_fDistance = CAMERA_DISTANCE_RANGE_MIN; } else if (m_fDistance > (CAMERA_DISTANCE_RANGE_MAX * fRate)) { m_fDistance = CAMERA_DISTANCE_RANGE_MAX * fRate; } m_fDistanceLevel -= m_fDistanceSlowDown; if ((float)abs(m_fDistanceLevel) < CAMERA_ROT_MIN) { m_fDistanceLevel = 0.0f; m_fDistanceSlowDown = 0.0f; } else { m_fDistance -= m_fDistanceLevel * c_fRotate; if (m_fDistance < CAMERA_DISTANCE_RANGE_MIN) { m_fDistance = CAMERA_DISTANCE_RANGE_MIN; } else if (m_fDistance > (CAMERA_DISTANCE_RANGE_MAX * fRate)) { m_fDistance = CAMERA_DISTANCE_RANGE_MAX * fRate; } } } void Camera::SetRotationSpeed() { switch(m_iRotationLevel) { case 0: m_fRotationSpeed = CAMERA_DEFAULT_ROTATE_SPEED * 0.4f; break; case 1: m_fRotationSpeed = CAMERA_DEFAULT_ROTATE_SPEED * 0.6f; break; case 2: m_fRotationSpeed = CAMERA_DEFAULT_ROTATE_SPEED * 0.8f; break; case 3: m_fRotationSpeed = CAMERA_DEFAULT_ROTATE_SPEED * 1.0f; break; case 4: m_fRotationSpeed = CAMERA_DEFAULT_ROTATE_SPEED * 1.2f; break; case 5: m_fRotationSpeed = CAMERA_DEFAULT_ROTATE_SPEED * 1.4f; break; default: m_fRotationSpeed = CAMERA_DEFAULT_ROTATE_SPEED; break; } } float Camera::GetRotationSpeed() { return m_fRotationSpeed; } void Camera::SetRotationLevel(int iLevel) { m_iRotationLevel = iLevel; SetRotationSpeed(); } int Camera::GetRotationLevel() { return m_iRotationLevel; } void Camera::SetRotationRange(int min, int max) { m_RotationScrollRange.iMin = min; m_RotationScrollRange.iMax = max; } sScope Camera::GetRotationRange() { return m_RotationScrollRange; } int Camera::GetRotationRangeMin() { return m_RotationScrollRange.iMin; } int Camera::GetRotationRangeMax() { return m_RotationScrollRange.iMax; }