예제 #1
0
void DynamicSkyLight::SetLightParams(float4 newLightDir, float startAngle, float orbitTime) {
	newLightDir.ANormalize();

	sunStartAngle = PI + startAngle; //FIXME WHY +PI?
	sunOrbitTime = orbitTime;
	initialSunAngle = GetRadFromXY(newLightDir.x, newLightDir.z);

	//FIXME This function really really needs comments about what it does!
	if (newLightDir.w == FLT_MAX) {
		// old: newLightDir is position where sun reaches highest altitude
		const float sunLen = newLightDir.Length2D();
		const float sunAzimuth = (sunLen <= 0.001f) ? PI / 2.0f : atan(newLightDir.y / sunLen);
		const float sunHeight = tan(sunAzimuth - 0.001f);

		float3 v1(cos(initialSunAngle), sunHeight, sin(initialSunAngle));
		v1.ANormalize();

		if (v1.y <= orbitMinSunHeight) {
			newLightDir = UpVector;
			sunOrbitHeight = v1.y;
			sunOrbitRad = sqrt(1.0f - sunOrbitHeight * sunOrbitHeight);
		} else {
			float3 v2(cos(initialSunAngle + PI), orbitMinSunHeight, sin(initialSunAngle + PI));
			v2.ANormalize();
			float3 v3 = v2 - v1;
			sunOrbitRad = v3.Length() / 2.0f;
			v3.ANormalize();

			float3 v4 = (v3.cross(UpVector)).ANormalize();
			float3 v5 = (v3.cross(v4)).ANormalize();

			if (v5.y < 0.0f)
				v5 = -v5;

			newLightDir = v5;
			sunOrbitHeight = v5.dot(v1);
		}
	} else {
		// new: newLightDir is center position of orbit, and newLightDir.w is orbit height
		sunOrbitHeight = std::max(-1.0f, std::min(newLightDir.w, 1.0f));
		sunOrbitRad = sqrt(1.0f - sunOrbitHeight * sunOrbitHeight);
	}

	sunRotation.LoadIdentity();
	sunRotation.SetUpVector(newLightDir);

	const float4& peakDir  = CalculateSunPos(0.0f);
	const float peakElev   = std::max(0.01f, peakDir.y);

	shadowDensityFactor = 1.0f / peakElev;

	SetLightDir(CalculateSunPos(sunStartAngle).ANormalize());
}
예제 #2
0
void CGlobalRendering::UpdateSunParams(float4 newSunDir, float startAngle, float orbitTime, bool iscompat) {
	newSunDir.ANormalize();
	sunStartAngle = startAngle;
	sunOrbitTime = orbitTime;

	initialSunAngle = fastmath::coords2angle(newSunDir.x, newSunDir.z);

	if(iscompat) { // backwards compatible: sunDir is position where sun reaches highest altitude
		float sunLen = newSunDir.Length2D();
		float sunAzimuth = (sunLen <= 0.001f) ? PI / 2.0f : atan(newSunDir.y / sunLen);
		float sunHeight = tan(sunAzimuth - 0.001f);

		float orbitMinSunHeight = 0.1f; // the lowest sun altitude for an auto generated orbit
		float3 v1(cos(initialSunAngle), sunHeight, sin(initialSunAngle));
		v1.ANormalize();

		if(v1.y <= orbitMinSunHeight) {
			newSunDir = float3(0.0f, 1.0f, 0.0f);
			sunOrbitHeight = v1.y;
			sunOrbitRad = sqrt(1.0f - sunOrbitHeight * sunOrbitHeight);
		}
		else {
			float3 v2(cos(initialSunAngle + PI), orbitMinSunHeight, sin(initialSunAngle + PI));
			v2.ANormalize();
			float3 v3 = v2 - v1;
			sunOrbitRad = v3.Length() / 2.0f;
			v3.ANormalize();
			float3 v4 = v3.cross(float3(0.0f, 1.0f, 0.0f));
			v4.ANormalize();
			float3 v5 = v3.cross(v4);
			v5.ANormalize();
			if(v5.y < 0)
				v5 = -v5;
			newSunDir = v5;
			sunOrbitHeight = v5.dot(v1);
		}
	}
	else { // new: sunDir is center position of orbit, and sunDir.w is orbit height
		sunOrbitHeight = std::max(-1.0f, std::min(newSunDir.w, 1.0f));
		sunOrbitRad = sqrt(1.0f - sunOrbitHeight * sunOrbitHeight);
	}

	sunRotation.LoadIdentity();
	sunRotation.SetUpVector(newSunDir);

	float4 peakSunDir = CalculateSunDir(0.0f);
	shadowDensityFactor = 1.0f / std::max(0.01f, peakSunDir.y);
	UpdateSun(true);
}