void CCameraInputHelper::Reset()
{
	m_fYaw = 0.0f;
	m_fPitch = gf_PI*0.5f;
	m_fInputPitchDelta = 0.0f;
	m_fInputYawDelta = 0.0f;
	//reset interpolation
	m_fInterpolationTargetYaw = 0.0f;
	m_fInterpolationTargetPitch = 0.0f;
	m_bInterpolationTargetActive = false;
	m_fInterpolationTargetTimeout = 0.0f;
	//reset timer
	m_fLastUserInput = 0.0f;
	m_bAutoTracking = false;
	m_bNavCombatModeChanged = false;
	//reset tracking
	m_fTrackingYawDelta = 0.0f;
	m_fTrackingPitchDelta = 0.0f;
	//make sure reset is distributed
	m_bYawModified = true;
	m_bPitchModified = true;

	//make sure the direction is fixed
	SSpherical tmpSpherical;
	CartesianToSpherical(m_pHero->GetEntity()->GetForwardDir(), tmpSpherical);
	ForceCameraDirection(tmpSpherical.m_fYaw, tmpSpherical.m_fPitch, 0.3f);
}
void CCameraInputHelper::SnapToPlayerDir()
{
	//get target direction (player dir)
	Vec3 dir = m_pHero->GetEntity()->GetForwardDir();
	SSpherical sph;
	CartesianToSpherical(dir, sph);
	//snap camera direction (in nav mode) to player direction
	//the camera direction is 90 degrees off and flipped compared to entity space
	sph.m_fYaw -= gf_PI * 0.5f;
	sph.m_fYaw *= -1.0f;
	SetInterpolationTarget(sph.m_fYaw, GetPitch());
}
Пример #3
0
/**
 * Given information about a point in the referenced frame of an icosahedral
 * face (tri, uvw), find the corresponding surface location in geographic
 * coordinate (lon, lat)
 */
void DymaxIcosa::FaceUVToGeo(int face, DPoint3 &uvw, double &lon, double &lat)
{
	DPoint3 p_out = m_face[face].base +
				   (m_face[face].vec_a * m_edge_length * uvw.x) +
				   (m_face[face].vec_b * m_edge_length * uvw.y);
	p_out.Normalize();
	DPoint3 p2;
	p2.x = p_out.x;
	p2.y = -p_out.z;
	p2.z = p_out.y;
	CartesianToSpherical(&lon, &lat, p2.x, p2.y, p2.z);
	lon += PId;
	if (lon > PI2d)
		lon -= PI2d;
}
Пример #4
0
bool CCameraTracking::Update(SViewParams &viewParams, float &fHOffObstacleStrength, const SCamModeSettings &camMode, const CPlayer &hero, bool bObstacleFound /* = false */)
{
	if(!g_pGameCVars->cl_cam_tracking || !m_pCamRayScan)
		return false;

	m_fFrameTime = max(g_fCamError, gEnv->pTimer->GetFrameTime());

	//in combat mode this function doesn't really avoid obstacles, it avoids clipping
	float fCombatModeWeight = 5.0f;

	//default angle and minimum
	const float fNow = gEnv->pTimer->GetFrameStartTime().GetSeconds();

	CCameraInputHelper *pCamHelper = hero.GetCameraInputHelper();
	CRY_ASSERT(pCamHelper);
	float fLastUserInput = pCamHelper->GetLastUserInputTime();
	//user input overrides auto-follow
	if(fNow - fLastUserInput < 0.5f)
		return false;

	bool bTrackingActive = camMode.camType == ECT_CamFollow && (camMode.collisionType == ECCT_CollisionTrack || camMode.collisionType == ECCT_CollisionTrackOrCut);

	//get current values
	Vec3 curCamDir = viewParams.position-viewParams.targetPos;
	m_curCamOrientation.Set(0.0f, 0.0f, 0.0f);
	CartesianToSpherical(curCamDir, m_curCamOrientation);
	curCamDir.Normalize();

	if(m_curCamOrientation.m_fDist < g_pGameCVars->cl_cam_min_distance)
		m_curCamOrientation.m_fDist = g_pGameCVars->cl_cam_min_distance;

	//work in 0 .. 2PI
	m_curCamOrientation.m_fYaw += gf_PI; 

	//if there is something in the way
	if(bObstacleFound)	
	{
		//re-start fadeout
		m_fTimeCovered = 0.5f;
		//set last obstacle pos
		m_vLastObstaclePos = viewParams.position;
		
		//scan obstacle
		if(!IdentifyObstacle(curCamDir, hero))
			return false;
	}
	else if(fabsf(m_fYawDelta) > g_fCamError || fabsf(m_fPitchDelta) > g_fCamError)
	{
		//if there is nothing in the way, fade out the movement

		//time based fade
		if(m_fTimeCovered > 0)
		{
			m_fTimeCovered = max(m_fTimeCovered - m_fFrameTime, 0.0f);

			//these interpolators should be time and not frame based
			m_fYawDelta = (g_fInterpolationRate * m_fYawDelta) * g_fInterpolationWeight;
			m_fPitchDelta = (g_fInterpolationRate * m_fPitchDelta) * g_fInterpolationWeight;
			m_fSpeed = (g_fInterpolationRate * m_fSpeed) * g_fInterpolationWeight;
		}
		else
		{
			m_fYawDelta = 0.0f;
			m_fPitchDelta = 0.0f;
			m_fSpeed = 0.0f;
		}
	}

	//apply delta rotation for obstacle avoidance
	if(fabsf(m_fYawDelta) > g_fCamError || fabsf(m_fPitchDelta) > g_fCamError)
	{
		if(bTrackingActive)
		{
			//set new yaw
			float newYaw = m_curCamOrientation.m_fYaw + m_fYawDelta;
			//re-align yaw
			//the camera direction is 90 degrees off and flipped compared to entity space
			newYaw = (newYaw - gf_PI * 0.5f) * -1.0f;
			//set new pitch
			float newPitch = m_curCamOrientation.m_fPitch + m_fPitchDelta;

			if(g_pGameCVars->cl_cam_orbit != 0)
			{
				//pCamHelper->SetTrackingDelta(-m_fYawDelta, m_fPitchDelta);
				pCamHelper->SetYawDelta(-m_fYawDelta);
				pCamHelper->SetPitchDelta(m_fPitchDelta);
			}
			else
			{
				//apply yaw/pitch on camera
				//pCamHelper->SetInterpolationTarget(newYaw, newPitch, gf_PI, 0.1f, 0.0f);
				//this will always reset follow cam interpolation
				pCamHelper->SetYawDelta(m_fYawDelta);
				pCamHelper->SetPitchDelta(m_fPitchDelta);
			}
		}
		else
		{
			//in orbit mode we basically simulate user input
			//pCamHelper->SetTrackingDelta(-fCombatModeWeight*g_fYawDelta, fCombatModeWeight*g_fPitchDelta);

			//in cutting mode we offset the camera to avoid clipping
			float offsetStrength = 0.0f;
			float offsetSpeed = 2.0f;
			if(bObstacleFound)
			{
				offsetStrength = (m_fYawDelta < 0.0f)?-g_fOffsetTrackingDistance:g_fOffsetTrackingDistance;
				offsetSpeed = 0.5f;
			}

			fHOffObstacleStrength = InterpolateTo(fHOffObstacleStrength, offsetStrength, offsetSpeed);
		}

		//CryLogAlways("new yaw %f, yawDelta %f", newYaw, g_yawDelta);
		return true;
	}
	else
		UpdateAutoFollow(viewParams, hero);

	return false;
}
Пример #5
0
bool CCameraTracking::IdentifyObstacle(const Vec3 &vCamDir, const CPlayer &hero)
{
	//check player direction
	Vec3 newDir = -hero.GetEntity()->GetForwardDir();
	newDir.z += vCamDir.z;
	newDir.normalize();

	//compute rotation speed
	const float fHeroSpeedModifier = clamp(hero.GetActorStats()->speedFlat / 4.0f, 0.3f, 1.0f);
	const float fNewSpeed = g_pGameCVars->cl_cam_tracking_rotation_speed * m_fFrameTime * fHeroSpeedModifier;
	m_fSpeed = InterpolateTo(m_fSpeed, fNewSpeed, (fNewSpeed>m_fSpeed)?0.1f:0.3f); 
	//m_fSpeed = (g_fInterpolationRate * m_fSpeed + speed) * g_fInterpolationWeight;

	//get ray data from camera ray tests
	ray_hit *pRayHit = m_pCamRayScan->GetHit(eRAY_TOP_RIGHT);
	if(!pRayHit || pRayHit->dist == 0.0f)
		pRayHit = m_pCamRayScan->GetHit(eRAY_BOTTOM_RIGHT);
	bool bHitsRight = (pRayHit && pRayHit->dist > 0.0f);
	Vec3 dirRight = (pRayHit)?-(m_pCamRayScan->GetRayDir(eRAY_TOP_RIGHT)):Vec3(ZERO);

	//ray data left side
	pRayHit = m_pCamRayScan->GetHit(eRAY_TOP_LEFT);
	if(!pRayHit || pRayHit->dist == 0.0f)
		pRayHit = m_pCamRayScan->GetHit(eRAY_BOTTOM_LEFT);
	bool bHitsLeft = (pRayHit && pRayHit->dist > 0.0f);
	Vec3 dirLeft = (pRayHit)?-(m_pCamRayScan->GetRayDir(eRAY_TOP_LEFT)):Vec3(ZERO);

	//left or right
	if(bHitsRight ^ bHitsLeft)
	{
		//find rotation direction
		if(!bHitsRight && !bHitsLeft)
		{
			if(m_eLastDirYaw == eTD_LEFT) //continue last direction
				newDir = dirLeft;
			else
				newDir = dirRight;
		}
		else if(!bHitsRight)
		{
			m_eLastDirYaw = eTD_RIGHT;
			newDir = dirRight;
		}
		else
		{
			m_eLastDirYaw = eTD_LEFT;
			newDir = dirLeft;
		}

		//compute yaw/pitch for target position
		float newYaw = 0.0f;
		float newPitch = 0.0f;
		float newDist = 0.0f;
		CartesianToSpherical(newDir * m_curCamOrientation.m_fDist, newYaw, newPitch, newDist);

		newYaw += gf_PI;

		//now interpolate to target

		//compute delta yaw
		m_fYawDelta = (newYaw - m_curCamOrientation.m_fYaw) * m_fSpeed;
		if(m_eLastDirYaw == eTD_RIGHT && m_fYawDelta < 0.0f || m_eLastDirYaw == eTD_LEFT && m_fYawDelta > 0.0f)
			m_fYawDelta *= -1.0f;
	}

	//compute top/bottom rotation

	//ray data top side
	pRayHit = m_pCamRayScan->GetHit(eRAY_TOP_CENTER);
	bool bHitsTop = (pRayHit && pRayHit->dist > 0.0f)?true:false;
	Vec3 vDirTop = (pRayHit)?-(m_pCamRayScan->GetRayDir(eRAY_TOP_CENTER)):Vec3(ZERO);

	//ray data bottom side
	pRayHit = m_pCamRayScan->GetHit(eRAY_BOTTOM_CENTER);
	bool bHitsBottom = (pRayHit && pRayHit->dist > 0.0f)?true:false;
	Vec3 vDirBottom = (pRayHit)?-(m_pCamRayScan->GetRayDir(eRAY_BOTTOM_CENTER)):Vec3(ZERO);

	//top or bottom (if not left or right)
	if(g_pGameCVars->cl_cam_tracking_allow_pitch && (bHitsTop ^ bHitsBottom) && !(bHitsRight ^ bHitsLeft))
	{
		//find rotation direction
		if(!bHitsTop && !bHitsBottom)
		{
			if(m_eLastDirPitch == eTD_TOP) //continue last direction
				newDir = vDirTop;
			else
				newDir = vDirBottom;
		}
		else if(!bHitsBottom)
		{
			m_eLastDirPitch = eTD_BOTTOM;
			newDir = vDirBottom;
		}
		else
		{
			m_eLastDirPitch = eTD_TOP;
			newDir = vDirTop;
		}

		//compute yaw/pitch for target position
		float newYaw = 0.0f;
		float newPitch = 0.0f;
		float newDist = 0.0f; //newdist (raydist) will be ignored
		CartesianToSpherical(newDir, newYaw, newPitch, newDist);

		//compute delta pitch
		m_fPitchDelta = (newPitch - m_curCamOrientation.m_fPitch) * m_fSpeed * 10.0f;
	}

	//if all rays hit - don't bother!
	//this is a termination condition when the camera is pulled through geometry
	if(bHitsLeft & bHitsRight & bHitsBottom & bHitsTop)
	{
		if(m_bViewCovered)
		{
			//if obstacle behind player
			//if(g_rHit.dist > 0.0f)
			//this is a strange fix, but it's working better and is much cheaper than a raycast
			if(fabsf(m_fYawDelta) < 0.01f && fabsf(m_fPitchDelta) > 0.001f)
				return false;
		}
		m_bViewCovered = true;
	}
	else
		m_bViewCovered = false;

	return true;
}
Пример #6
0
	SpherePoint::SpherePoint(Vec3f &v)
	{
		CartesianToSpherical(v.x, v.y, v.z, &p, &phi, &theta);
	}
Пример #7
0
    TextureResult HosekWilkieSky(const BufferUploads::TextureDesc& desc, const ParameterBox& parameters)
    {
            // The "turbidity" parameter is Linke’s turbidity factor. Hosek and Wilkie give these example parameters:
            //      T = 2 yields a very clear, Arctic-like sky
            //      T = 3 a clear sky in a temperate climate
            //      T = 6 a sky on a warm, moist day
            //      T = 10 a slightly hazy day
            //      T > 50 represent dense fog

        auto defaultSunDirection = Normalize(Float3(1.f, 1.f, 0.33f));
        Float3 sunDirection = parameters.GetParameter<Float3>(ParameterBox::ParameterNameHash("SunDirection"), defaultSunDirection);
        sunDirection = Normalize(sunDirection);

        auto turbidity = (double)parameters.GetParameter(ParameterBox::ParameterNameHash("turbidity"), 3.f);
        auto albedo = (double)parameters.GetParameter(ParameterBox::ParameterNameHash("albedo"), 0.1f);
        auto elevation = (double)Deg2Rad(parameters.GetParameter(ParameterBox::ParameterNameHash("elevation"), XlASin(sunDirection[2])));
        auto* state = arhosek_rgb_skymodelstate_alloc_init(turbidity, albedo, elevation);

        auto pixels = std::make_unique<Float4[]>(desc._width*desc._height);
        for (unsigned y=0; y<desc._height; ++y)
            for (unsigned x=0; x<desc._width; ++x) {
                auto p = y*desc._width+x;
                pixels[p] = Float4(0.f, 0.f, 0.f, 1.f);

                Float3 direction(0.f, 0.f, 0.f);
                bool hitPanel = false;

                for (unsigned c = 0; c < 6; ++c) {
                    Float2 tc(x / float(desc._width), y / float(desc._height));
                    auto tcMins = s_verticalPanelCoords[c][0];
                    auto tcMaxs = s_verticalPanelCoords[c][1];
                    if (tc[0] >= tcMins[0] && tc[1] >= tcMins[1] && tc[0] <  tcMaxs[0] && tc[1] <  tcMaxs[1]) {
                        tc[0] = 2.0f * (tc[0] - tcMins[0]) / (tcMaxs[0] - tcMins[0]) - 1.0f;
                        tc[1] = 2.0f * (tc[1] - tcMins[1]) / (tcMaxs[1] - tcMins[1]) - 1.0f;

                        hitPanel = true;
                        auto plusX = s_verticalPanels[c][0];
                        auto plusY = s_verticalPanels[c][1];
                        auto center = s_verticalPanels[c][2];
                        direction = center + plusX * tc[0] + plusY * tc[1];
                    }
                }

                if (hitPanel) {
                    auto theta = CartesianToSpherical(direction)[0];
                    theta = std::min(.4998f * gPI, theta);
                    auto gamma = XlACos(std::max(0.f, Dot(Normalize(direction), sunDirection)));

                    auto R = arhosek_tristim_skymodel_radiance(state, theta, gamma, 0);
                    auto G = arhosek_tristim_skymodel_radiance(state, theta, gamma, 1);
                    auto B = arhosek_tristim_skymodel_radiance(state, theta, gamma, 2);

                    pixels[p][0] = (float)R;
                    pixels[p][1] = (float)G;
                    pixels[p][2] = (float)B;
                }
            }

        arhosekskymodelstate_free(state);

        return TextureResult
            {
                BufferUploads::CreateBasicPacket(
                    (desc._width*desc._height)*sizeof(Float4),
                    pixels.get(),
                    BufferUploads::TexturePitches(desc._width*sizeof(Float4), desc._width*desc._height*sizeof(Float4))),
                RenderCore::Metal::NativeFormat::R32G32B32A32_FLOAT,
                UInt2(desc._width, desc._height)
            };
    }