Esempio n. 1
0
bool Scene::IsLightUnblocked(const Light& light, const Point<float>& point) const
{
	Point<float> lightPosition = light.GetPosition();
	Vector3<float> lightDirection = light.IsDirectional() ? Vector3<>(lightPosition.x, lightPosition.y, lightPosition.z) : lightPosition - point;

	// Create a ray to cast at the direction of the light:
	Ray ray(point, lightDirection);

	// Add a little bit of offset to handle the numeric errors:
	ray.origin = ray.origin + ray.direction * 0.00001f;

	// Calculate distance between the light and the intersection point:
	float lightDistance = lightDirection.length();
	
	// Find if there is any object between the light and the object:
	if (!IsLightUnblocked<Sphere>(m_spheres, light, lightDistance, ray) ||
		!IsLightUnblocked<GenericMesh>(m_genericMeshes, light, lightDistance, ray)
		)
		return false;

	return true;
}
void
TerrainPatch::Illuminate(Color ambient, List<Light>& lights)
{
	if (!model || model->NumVerts() < 1) return;
	Surface* s = model->GetSurfaces().first();
	if (!s) return;

	illuminating = true;

	// clear the solid lights to ambient:
	VertexSet*  vset   = s->GetVertexSet();
	int         nverts = vset->nverts;
	DWORD       aval   = ambient.Value();

	for (int i = 0; i < nverts; i++) {
		vset->diffuse[i]  = aval;
	}

	TerrainRegion* trgn     = terrain->GetRegion();
	bool           eclipsed = false;
	bool           first    = terrain->IsFirstPatch(this);

	if (trgn && !first) {
		eclipsed = trgn->IsEclipsed();
	}

	// for sun and back lights:
	ListIter<Light> iter = lights;
	while (++iter) {
		Light* light = iter.value();

		if (!light->IsDirectional())                                // only do sun and
		continue;                                                // back lights

		if (light->CastsShadow() && first) {
			eclipsed  = light->Location().y < -100 ||                // has sun set, or

			scene->IsLightObscured(vset->loc[0],         // is sun in eclipse
			light->Location(),    // by orbital body
			radius);              // such as a moon?
		}

		if (!light->CastsShadow() || !eclipsed) {
			Vec3 vl = light->Location();
			vl.Normalize();

			for (int i = 0; i < nverts; i++) {
				Vec3&  nrm = vset->nrm[i];
				double val = 0;
				double gain = vl * nrm;

				if (gain > 0) {
					val = light->Intensity() * (0.85 * gain);

					if (val > 1)
					val = 1;
				}

				if (val > 0.01)
				vset->diffuse[i] = ((light->GetColor().dim(val)) + vset->diffuse[i]).Value();
			}
		}
	}

	// combine blend weights:
	if (ndetail >= 2) {
		for (int i = 0; i < nverts; i++) {
			vset->diffuse[i] = vset->specular[i] | (vset->diffuse[i] & 0x00ffffff);
		}
	}

	if (trgn && first) {
		trgn->SetEclipsed(eclipsed);
	}

	InvalidateSurfaceData();
	illuminating = false;
}