void CMoon::ReflectSun( SVector& vSunDirLocal_ ) { // 처음에 해는 보름달을 비추는 방향으로 있습니다 (지역좌표계에서) vSunDirLocal_.X = 0.0f; vSunDirLocal_.Y = 0.0f; vSunDirLocal_.Z = 1.0f; // 이제 달이 찬 정도를 이용해서 Pitch 값을 만들고 빛의 방향을 정합니다. SMatrix matSunDirRot; matSunDirRot.SetRotation( SRotator( Rad2Angle(fPi*(1.0f-m_fFillRate)), 0, 0 ) ); vSunDirLocal_ = matSunDirRot.TransformNormal( vSunDirLocal_ ); SMatrix matMoonPitch; matMoonPitch.SetRotation( SRotator( Rad2Angle(m_fPitch), 0, 0 ) ); SMatrix matMoonRot; matMoonRot.SetRotation( SRotator( 0, 0, Rad2Angle(m_fRisingRate*fPi*2.0f)) ); matMoonRot = matMoonRot*matMoonPitch; vSunDirLocal_ = matMoonRot.TransformNormal( vSunDirLocal_ ); }
void GDynamicActor::Tick( float DeltaSeconds ) { Super::Tick( DeltaSeconds ); GrpSuper::TickGrp( DeltaSeconds ); m_ftDelta = DeltaSeconds; float f = max(s_fTotalCullLength, GetCullLength()); // Grid Item if( m_pGridItem ) { m_pGridItem->Sphere().vecCenter = m_Locus.Location; m_pGridItem->Sphere().fRadius = Max( m_vExtent.Y, m_vExtent.X ); } // Grid Field if( m_nGridCell!=INVALIDINDEX && s_pGridField!=NULL ) { // Real Shape Shadow if( m_pShadow ) {// 그림자를 가지고 있다면 자신이 속한 셀에서 가장 가까운 광원정보를 뽑고 전혀 뽑히지 않으면 태양광으로 한다. m_vNearestLightDir = s_vGlobalLightDir; vector<CSceneItem*> aItem; s_pGridField->FindItemOnPosition( m_Locus.Location, aItem ); if( !aItem.empty() ) { float fDistNearSq = 900000.0f; float fDistSq; for( dword nItem=0; nItem<aItem.size(); ++nItem ) { CSceneItem *pItem = aItem[nItem]; if( pItem->GetType()==SIT_LIGHTSOURCE ) { DLightActor *pLightActor = DLightActor::GrpGetActor( pItem->GetSrcID() ); if( pLightActor->GetLightClass().IsValid() ) { fDistSq = (m_Locus.Location-pLightActor->m_Locus.Location).SizeSquared(); if( fDistSq<fDistNearSq ) { fDistNearSq = fDistSq; m_vNearestLightDir = pLightActor->m_Locus.Location-m_Locus.Location; } } } } m_vNearestLightDir.Normalize(); static SVector vUp( 0.0f, 1.0f, 0.0f ); float fDotNearLight = vUp|m_vNearestLightDir; if( fDotNearLight<0.34f ) // 0.34은 약 cos(70도) {// 너무 각도가 작은 광원은 적절한 수준으로 올리기 float fYawNear = atan2f( m_vNearestLightDir.X, m_vNearestLightDir.Z ); SMatrix matRot; matRot.SetRotation( SRotator(Rad2Angle(-0.349f), Rad2Angle(fYawNear), 0) ); m_vNearestLightDir.X = 0.0f; m_vNearestLightDir.Y = 0.0f; m_vNearestLightDir.Z = 1.0f; m_vNearestLightDir = matRot.TransformNormal( m_vNearestLightDir ); } // 그림자 멀어지면 흐릿하게 하기 if( fDistNearSq>400.0f ) { m_pShadow->SetColor( 0xFF777777 ); } else if( fDistNearSq>4.0f ) { float fR = (fDistNearSq-4.0f)/396.0f; if( fR>1.0f ) fR = 1.0f; byte byColor = (byte)(fR*255.0f); if( byColor<0x77 ) byColor = 0x77; m_pShadow->SetColor( byColor|(byColor<<8)|(byColor<<16)|0xFF000000 ); } else { m_pShadow->SetColor( 0xFF777777 ); } } else { m_vNearestLightDir.Normalize(); static SVector vUp( 0.0f, 1.0f, 0.0f ); float fDotNearLight = vUp|m_vNearestLightDir; if( fDotNearLight<0.34f ) // 0.34은 약 cos(70도) {// 너무 각도가 작은 광원은 적절한 수준으로 올리기 float fYawNear = atan2f( m_vNearestLightDir.X, m_vNearestLightDir.Z ); SMatrix matRot; matRot.SetRotation( SRotator(Rad2Angle(-0.349f), Rad2Angle(fYawNear), 0) ); m_vNearestLightDir.X = 0.0f; m_vNearestLightDir.Y = 0.0f; m_vNearestLightDir.Z = 1.0f; m_vNearestLightDir = matRot.TransformNormal( m_vNearestLightDir ); } m_pShadow->SetColor( 0xFF777777 ); } } // Approx. Shape Shadow else if( m_pApproxShadow ) { m_vNearestLightDir = SVector( 0.01f, 15.0f, -0.01f ); m_pApproxShadow->SetColor( 0xFF454545 ); } if( s_pGridField->TestValidity( m_Locus.Location, m_nGridCell ) ) { return; } // Cell 위치가 변해야 한다. s_pGridField->UpdateItemPosition( m_nGridCell, m_pGridItem, m_Locus.Location ); m_pGridItem->Sphere().vecCenter = m_Locus.Location; } }