void RPG_Effect::UpdateCameraShake(float const deltaTime) { VASSERT(m_cameraShaking); VisContextCamera_cl* camera = VisRenderContext_cl::GetCurrentContext()->GetCamera(); VASSERT(camera); // end camera shake on timeout float const shakeTime = Vision::GetTimer()->GetTime() - m_cameraShakeStartTime; if (shakeTime >= m_cameraShakeDuration) { m_cameraShakeDuration = 0.f; m_cameraShakeStartTime = 0.f; m_cameraShakeMaxAmplitude = 0.f; m_cameraShaking = false; camera->ResetLocalTransformation(); return; } // apply noise to the camera's position camera->ResetLocalTransformation(); // don't allow position updates to be cumulative hkvVec3 camPosition = camera->GetPosition(); camPosition.x += GetCameraShakeNoise(camPosition.x); camPosition.y += GetCameraShakeNoise(camPosition.y); camPosition.z += GetCameraShakeNoise(camPosition.z); camera->SetPosition(camPosition); }
void CRBX_ModelViewCtrl::SetFitModel() { if(!m_pEntity) return; m_fFovV = hkvMathHelpers::getFovY(m_fFovH, GetSize().x / GetSize().y); VisRenderContext_cl::GetMainRenderContext()->SetFOV(m_fFovH,m_fFovV); hkvAlignedBBox modelbox; m_pEntity->GetMesh()->GetVisibilityBoundingBox(modelbox); float fAngleH,fAngleV; VisRenderContext_cl::GetMainRenderContext()->GetFOV(fAngleH,fAngleV); float dx = hkvMath::Max(modelbox.getSizeX(),modelbox.getSizeY()); float zx = 0.5f*dx / hkvMath::tanDeg (fAngleH*0.5f); float zy = 0.5f*modelbox.getSizeZ() / hkvMath::tanDeg (fAngleV*0.5f); float Dist = (hkvMath::Max(zx,zy) + dx*0.5f); VisContextCamera_cl* pMainCamera = Vision::Camera.GetMainCamera(); hkvMat3 vMat; vMat.setFromEulerAngles(0,20,180); m_vCamPos.Set(Dist,0,modelbox.GetSizeZ()); pMainCamera->Set(vMat,m_vCamPos); if( m_pLight == NULL ) { m_pLight = new VisLightSource_cl( VisLightSourceType_e::VIS_LIGHT_DIRECTED , 10.0f ); } m_pLight->SetPosition(pMainCamera->GetPosition()); m_pLight->AttachToParent(pMainCamera); m_pLight->SetDirection(pMainCamera->GetDirection()); m_pLight->SetIntensity(50.0f); /// << 빛의 강도를 조절함. 나중에콜백이나 업데이트 함수에서 조절하시면됩니다. UpdateWorldAxisSystem(); }
/// update all internal data ////////////////////////////////////////////////////////////////////////// bool CScaler::UpdateInternalsAndGetVisibility() { VisRenderContext_cl* pCtx = Vision::Contexts.GetCurrentContext(); const VisMatrix4x4_cl& mtxProjection = pCtx->GetProjectionMatrix(); VisContextCamera_cl* pContextCam = pCtx->GetCamera(); pContextCam->GetWorldMatrix( m_mtxViewProjection ); // it`s View mtx and not all cells are filled?!?, fix below // ogl View to dx View mtx crap float* pGlmatrix = m_mtxViewProjection.GetFloatPtr(); pGlmatrix[ 2 ] = -pGlmatrix[ 2 ]; pGlmatrix[ 6 ] = -pGlmatrix[ 6 ]; pGlmatrix[ 10 ] = -pGlmatrix[ 10 ]; pGlmatrix[ 14 ] = -pGlmatrix[ 14 ]; pGlmatrix[ 15 ] = 1.f; //this must be here, GetWorldMatrix DOES NOT fill all cells !!! // multiply is now DX style (ogl is projection*view*world) m_mtxViewProjection *= mtxProjection; // get transpose mtx of ViewProjection m_mtxViewProjectionT = m_mtxViewProjection; m_mtxViewProjectionT.Transpose(); // gen VPInverse mtx (if sended to shader, must be transposed) m_mtxViewProjectionInv = m_mtxViewProjection; m_mtxViewProjectionInv.InvertEx(); // calculate -far & far plane vectors (homogeneous space) m_NearPlane.v1.SetXYZW( -1, 1, 0, 1 ); m_NearPlane.v2.SetXYZW( 1, 1, 0, 1 ); m_NearPlane.v3.SetXYZW( 1, -1, 0, 1 ); m_NearPlane.v4.SetXYZW( -1, -1, 0, 1 ); m_FarPlane.v1.SetXYZW( -1, 1, 1, 1 ); m_FarPlane.v2.SetXYZW( 1, 1, 1, 1 ); m_FarPlane.v3.SetXYZW( 1, -1, 1, 1 ); m_FarPlane.v4.SetXYZW( -1, -1, 1, 1 ); // w are all ones so Vision may be used m_NearPlane.v1 *= m_mtxViewProjectionInv; m_NearPlane.v2 *= m_mtxViewProjectionInv; m_NearPlane.v3 *= m_mtxViewProjectionInv; m_NearPlane.v4 *= m_mtxViewProjectionInv; m_FarPlane.v1 *= m_mtxViewProjectionInv; m_FarPlane.v2 *= m_mtxViewProjectionInv; m_FarPlane.v3 *= m_mtxViewProjectionInv; m_FarPlane.v4 *= m_mtxViewProjectionInv; _GetWorldPos( m_NearPlane, m_WorldNearPlane ); _GetWorldPos( m_FarPlane, m_WorldFarPlane ); GetIntersectionsAndPointsBeetween(); // will fill m_aIntesections & counter // skip if can`t generate proper matrix ( volume is outside of frustum ) if( m_iInterectionsCount >= 4 ) // valid { // get clip space coords to calculate XY span for( int i=0; i<m_iInterectionsCount; i++ ) { //m_aIntersections[ i ].w = 1.f; // Vision use w as 1 so don`t set m_aIntersections[ i ].z = 0.f; // TODO: should be water level m_aIntersections[ i ] *= m_mtxViewProjectionT; // use transposed mtx m_aIntersections[ i ].x /= m_aIntersections[ i ].w; m_aIntersections[ i ].y /= m_aIntersections[ i ].w; //m_aIntersections[ i ].z /= m_aIntersections[ i ].w; // we dont need Z } float fXMin = FLT_MAX; float fXMax = -FLT_MAX; float fYMin = FLT_MAX; float fYMax = -FLT_MAX; for( int i=0; i<m_iInterectionsCount; i++ ) { if( m_aIntersections[ i ].x > fXMax ) fXMax = m_aIntersections[ i ].x; if ( m_aIntersections[ i ].x < fXMin ) fXMin = m_aIntersections[ i ].x; if( m_aIntersections[ i ].y > fYMax ) fYMax = m_aIntersections[ i ].y; if ( m_aIntersections[ i ].y < fYMin ) fYMin = m_aIntersections[ i ].y; } // build scaling matrix. it prevents h-space verts in shader to run out of range /* normal way VisMatrix4x4_cl mtxScale; mtxScale.Identity(); mtxScale[ 0 ] = fXMax - fXMin; mtxScale[ 5 ] = fYMax - fYMin; mtxScale[ 12 ] = fXMin; mtxScale[ 13 ] = fYMin; mtxScale.Transpose(); */ // faster way m_mtxScale[ 0 ] = fXMax - fXMin; m_mtxScale[ 5 ] = fYMax - fYMin; m_mtxScale[ 3 ] = fXMin; m_mtxScale[ 7 ] = fYMin; m_mtxViewProjectionInv *= m_mtxScale; m_NearPlane.v1.SetXYZW( 0, 1, 0, 1 ); m_NearPlane.v2.SetXYZW( 1, 1, 0, 1 ); m_NearPlane.v3.SetXYZW( 1, 0, 0, 1 ); m_NearPlane.v4.SetXYZW( 0, 0, 0, 1 ); m_FarPlane.v1.SetXYZW( 0, 1, 1, 1 ); m_FarPlane.v2.SetXYZW( 1, 1, 1, 1 ); m_FarPlane.v3.SetXYZW( 1, 0, 1, 1 ); m_FarPlane.v4.SetXYZW( 0, 0, 1, 1 ); m_NearPlane.v1 *= m_mtxViewProjectionInv; m_NearPlane.v2 *= m_mtxViewProjectionInv; m_NearPlane.v3 *= m_mtxViewProjectionInv; m_NearPlane.v4 *= m_mtxViewProjectionInv; m_FarPlane.v1 *= m_mtxViewProjectionInv; m_FarPlane.v2 *= m_mtxViewProjectionInv; m_FarPlane.v3 *= m_mtxViewProjectionInv; m_FarPlane.v4 *= m_mtxViewProjectionInv; return true; }else { // do not render return false; } }
void VShadowMapGenSpotDir::Update(bool force) { VisContextCamera_cl *pMainCam = m_pRendererNode->GetReferenceContext()->GetCamera(); VASSERT(pMainCam); float fCamAngle = hkvMath::Abs (hkvMath::acosDeg (pMainCam->GetDirection().dot (m_vLastCameraDir))); hkvVec3 vCamMove = pMainCam->GetPosition() - m_vLastCameraPos; m_pRendererNode->GetReferenceContext()->GetViewFrustum(m_MainViewFrustum); float fFovX, fFovY; m_pRendererNode->GetReferenceContext()->GetFinalFOV(fFovX, fFovY); float fNear, fFar; m_pRendererNode->GetReferenceContext()->GetClipPlanes(fNear, fFar); VBaseShadowMapComponentSpotDirectional* pComponent = static_cast<VBaseShadowMapComponentSpotDirectional*>(m_pShadowComponent); if (m_eProjectionType == SHADOW_PROJECTION_ORTHOGRAPHIC) { bool bOverestimateCascades = pComponent->GetOverestimateCascades() ? true : false; if (bOverestimateCascades) { if (m_fFovX != fFovX || m_fFovY != fFovY || m_fNear != fNear) { // In case user switches the FOV at runtime we need to update it here float fStartDistance = fNear; for (int iCascade = 0; iCascade < m_iNumParts; iCascade++) { float fEndDistance = pComponent->GetCascadeRange(iCascade) + fNear; m_pParts[iCascade].ComputeOffset(fStartDistance, fEndDistance); fStartDistance = fEndDistance; } m_fFovX = fFovX; m_fFovY = fFovY; m_fNear = fNear; force = true; } if (force || m_vLastLightPos != m_pLightSource->GetPosition() || m_vLastLightDir != m_pLightSource->GetDirection() || vCamMove.getLength() > pComponent->GetShadowMapCameraUpdateInterval() || fCamAngle > pComponent->GetShadowMapCameraUpdateAngle()) { for (int iCascade = 0; iCascade < m_iNumParts; iCascade++) { VShadowMapPart& part = m_pParts[iCascade]; VisContextCamera_cl* pCam = part.GetRenderContext()->GetCamera(); VisContextCamera_cl *pReferenceCam = m_pRendererNode->GetReferenceContext()->GetCamera(); hkvVec3 vCascadeCenter = pReferenceCam->GetPosition() + pReferenceCam->GetDirection() * part.m_fCenterOffset; pCam->SetDirection(GetDirection()); float fRadius = part.m_fRadius + pComponent->GetShadowMapCameraUpdateInterval(); float fCameraDistanceFromCenter = fFar; hkvVec3 vCamPos = vCascadeCenter - GetDirection() * fCameraDistanceFromCenter; pCam->SetPosition(vCamPos); //snapping hkvVec3 offset = pCam->GetWorldToCameraTransformation().getColumn(3).getAsVec3(); float fPixelSize = (fRadius * 2) / (float)m_pShadowComponent->GetShadowMapSize(); offset.x -= floorf(offset.x / fPixelSize) * fPixelSize; offset.y -= floorf(offset.y / fPixelSize) * fPixelSize; vCamPos -= pCam->GetObjDir_Right() * offset.x - pCam->GetObjDir_Up() * offset.y; pCam->SetPosition(vCamPos); // Set far clip plane so that we have z = 1 at the far side of the sphere - the shader expects this when using the BoundingBox cascade selection method. part.GetRenderContext()->SetClipPlanes(0.0f, fCameraDistanceFromCenter + fRadius); part.GetRenderContext()->SetOrthographicSize(fRadius * 2, fRadius * 2); part.Update(); } m_vLastLightPos = m_pLightSource->GetPosition(); m_vLastLightDir = m_pLightSource->GetDirection(); m_vLastCameraPos = pMainCam->GetPosition(); m_vLastCameraDir = pMainCam->GetDirection(); } } else { float fStartDistance = 0.0f; for (int iCascade = 0; iCascade < m_iNumParts; iCascade++) { VShadowMapPart& part = m_pParts[iCascade]; VisContextCamera_cl* pCam = part.GetRenderContext()->GetCamera(); // TODO: Performance // Compute the extremes of the view frustum fragment for this cascade hkvVec3 vCorners[8]; float fEndDistance = pComponent->GetCascadeRange(iCascade); part.m_fCullDistance = fEndDistance; part.GetViewFrustumCornersAtDistance(m_pRendererNode->GetReferenceContext(), fStartDistance, &vCorners[0]); part.GetViewFrustumCornersAtDistance(m_pRendererNode->GetReferenceContext(), fEndDistance, &vCorners[4]); fStartDistance = fEndDistance; pCam->SetDirection(GetDirection()); float fMinRight = FLT_MAX; float fMinUp = FLT_MAX; float fMaxRight = -FLT_MAX; float fMaxUp = -FLT_MAX; float fMinDist = FLT_MAX; float fMaxDist = -FLT_MAX; for (int iCorner = 0; iCorner < 8; iCorner ++ ) { float fRight = pCam->GetObjDir_Right().dot (vCorners[iCorner]); if (fRight < fMinRight) fMinRight = fRight; if (fRight > fMaxRight) fMaxRight = fRight; float fUp = pCam->GetObjDir_Up().dot (vCorners[iCorner]); if (fUp < fMinUp) fMinUp = fUp; if (fUp > fMaxUp) fMaxUp = fUp; float fDist = pCam->GetDirection().dot (vCorners[iCorner]); if (fDist < fMinDist) fMinDist = fDist; if (fDist > fMaxDist) fMaxDist = fDist; } // Since we need to take geometry into account which lies in front of the view frustum, we need to // offset the near clip plane (in this case, the camera position) away from the view frustum fMinDist -= (fFar - fNear); hkvVec3 vCamPos = pCam->GetObjDir_Right() * ((fMinRight + fMaxRight)*0.5f) + pCam->GetObjDir_Up() * ((fMinUp + fMaxUp)*0.5f) + pCam->GetDirection() * fMinDist; float fPadding = pComponent->GetShadowMapCameraUpdateInterval(); pCam->SetPosition(vCamPos); part.GetRenderContext()->SetClipPlanes(0.0f, fMaxDist - fMinDist); part.GetRenderContext()->SetOrthographicSize(fMaxRight - fMinRight + fPadding, fMaxUp - fMinUp + fPadding); part.Update(); } } } else if (m_eProjectionType == SHADOW_PROJECTION_PERSPECTIVE) { if (m_pLightSource->GetRadius() <= 0) //this is the case if triggered is set to false for the light { return; //do render the light at all } if (force || m_vLastLightPos != m_pLightSource->GetPosition() || m_vLastLightDir != m_pLightSource->GetDirection() || m_fLastRadius != m_pLightSource->GetRadius() || m_fLastAngle != m_pLightSource->GetProjectionAngle()) { VShadowMapPart& part = m_pParts[0]; VisContextCamera_cl* pCam = part.GetRenderContext()->GetCamera(); pCam->SetDirection(GetDirection()); pCam->SetPosition(GetPosition()); part.GetRenderContext()->SetClipPlanes(m_pShadowComponent->GetNearClip(), m_pLightSource->GetRadius()); float fAngle = m_pLightSource->GetProjectionAngle(); part.GetRenderContext()->SetFOV(fAngle, fAngle); part.Update(); m_vLastLightPos = m_pLightSource->GetPosition(); m_vLastLightDir = m_pLightSource->GetDirection(); m_fLastRadius = m_pLightSource->GetRadius(); m_fLastAngle = fAngle; } } m_iPartsRendered = 0; }
void VFmodManager::RunTick(float fTimeDelta) { VISION_PROFILE_FUNCTION(PROFILING_FMOD_OVERALL); if (!IsInitialized()) { if (!IsOutputDevicePresent()) InitDevice(); return; } // profiling scope { VISION_PROFILE_FUNCTION(PROFILING_FMOD_PUREUPDATE); VASSERT(m_pEventSystem!=NULL); // update Fmod listener attributes VisObject3D_cl *pListener = m_pListenerObject; if (pListener == NULL) { // The listener is the main camera. Check for teleportation since the last Fmod update, in // which case we won't use the position difference to calculate the listener speed. VisContextCamera_cl* pCamera = Vision::Camera.GetMainCamera(); VisRenderContext_cl* pContext = VisRenderContext_cl::GetMainRenderContext(); if (pCamera != NULL && pContext != NULL) { if (m_bLastListenerPositionValid && pCamera->GetLastTeleported() > m_iFrameOfLastUpdate) m_bLastListenerPositionValid = false; m_iFrameOfLastUpdate = pContext->GetLastRenderedFrame(); pListener = pCamera; } } if (!pListener) return; hkvVec3 vCamPos = pListener->GetPosition(); hkvVec3 vDir(pListener->GetObjDir()), vRight(pListener->GetObjDir_Right()), vUp(pListener->GetObjDir_Up()); // Determine the camera velocity based on the previous known position hkvVec3 vCamVel(m_bLastListenerPositionValid && (fTimeDelta > 0.f) ? (vCamPos - m_vLastListenerPosition) * (1.f / fTimeDelta) : hkvVec3::ZeroVector()); m_vLastListenerPosition = vCamPos; m_bLastListenerPositionValid = true; vUp = -vUp; // compensate for coordinate system m_pEventSystem->set3DListenerAttributes(0, (FMOD_VECTOR *)&vCamPos, (FMOD_VECTOR *)&vCamVel, (FMOD_VECTOR *)&vDir, (FMOD_VECTOR *)&vUp); // update all sound objects SoundInstances().Update(fTimeDelta); // update all events Events().Update(fTimeDelta); // update Fmod event system m_fTimeLeftOver += fTimeDelta; if (m_fTimeLeftOver > m_config.fTimeStep) { m_pEventSystem->update(); #ifdef VFMOD_SUPPORTS_NETWORK if (m_config.bUseNetworkSystem) FMOD::NetEventSystem_Update(); #endif m_fTimeLeftOver = hkvMath::mod (m_fTimeLeftOver, m_config.fTimeStep); } } // do not purge sounds/ events in vForge, in order to allow toggling playback via hotspot button if (Vision::Editor.IsInEditor()) return; if (m_bAnyStopped) { VISION_PROFILE_FUNCTION(PROFILING_FMOD_PURGE); // all sounds/ events that have finished playing are removed from handling SoundInstances().PurgeNotPlaying(); Events().PurgeNotPlaying(); m_bAnyStopped = false; // reset any stopped flag } }