Compare commits
No commits in common. "a5078b0f2be1110a88c28e57f57b91f4a0f7197b" and "86829421023cd79d1cb76715fecf73410de98412" have entirely different histories.
a5078b0f2b
...
8682942102
|
@ -699,11 +699,20 @@ public class LightMapper
|
|||
|
||||
var light = _lights[lightIdx - 1];
|
||||
|
||||
// If the light is behind the plane we'll never be directly lit by this light.
|
||||
// Additionally, if the distance from the plane is more than the light's radius
|
||||
// we know no points on the plane will be lit.
|
||||
var planeDist = MathUtils.DistanceFromPlane(plane, light.Position);
|
||||
if (planeDist <= MathUtils.Epsilon || planeDist > light.Radius)
|
||||
// Check if plane normal is facing towards the light
|
||||
// If it's not then we're never going to be (directly) lit by this
|
||||
// light.
|
||||
var centerDirection = renderPoly.Center - light.Position;
|
||||
if (Vector3.Dot(plane.Normal, centerDirection) >= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// If there aren't *any* points on the plane that are in range of the light
|
||||
// then none of the lightmap points will be so we can discard.
|
||||
// The more compact a map is the less effective this is
|
||||
var planeDist = Math.Abs(MathUtils.DistanceFromPlane(plane, light.Position));
|
||||
if (planeDist > light.Radius)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -730,7 +739,7 @@ public class LightMapper
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!TraceOcclusion(light.Position, point))
|
||||
if (TraceRay(light.Position, point))
|
||||
{
|
||||
strength += targetWeights[idx] * light.StrengthAtPoint(point, plane, settings.AnimLightCutoff);
|
||||
}
|
||||
|
@ -817,58 +826,81 @@ public class LightMapper
|
|||
{
|
||||
var offset = offsets[i];
|
||||
var pos = basePosition + offset;
|
||||
|
||||
|
||||
// Embree has robustness issues when hitting poly edges which
|
||||
// results in false misses. To alleviate this we pre-push everything
|
||||
// slightly towards the center of the poly.
|
||||
var centerOffset = polyCenter - pos;
|
||||
if (centerOffset.LengthSquared() > MathUtils.Epsilon)
|
||||
{
|
||||
pos += Vector3.Normalize(centerOffset) * MathUtils.Epsilon;
|
||||
}
|
||||
|
||||
// If we can't see our target point from the center of the poly
|
||||
// then we need to clip the point to slightly inside the poly
|
||||
// and retrace to avoid two problems:
|
||||
// then it's outside the world. We need to clip the point to slightly
|
||||
// inside the poly and retrace to avoid three problems:
|
||||
// 1. Darkened spots from lightmap pixels whose center is outside
|
||||
// the polygon but is partially contained in the polygon
|
||||
// 2. Darkened spots from linear filtering of points outside the
|
||||
// polygon which have missed
|
||||
var occluded = TraceOcclusion(polyCenter + planeMapper.Normal * 0.25f, pos);
|
||||
if (occluded)
|
||||
// 3. Darkened spots where centers are on the exact edge of a poly
|
||||
// which can sometimes cause Embree to miss casts
|
||||
var inPoly = TraceRay(polyCenter + planeMapper.Normal * 0.25f, pos);
|
||||
if (!inPoly)
|
||||
{
|
||||
var p2d = planeMapper.MapTo2d(pos);
|
||||
p2d = MathUtils.ClipPointToPoly2d(p2d, v2ds);
|
||||
pos = planeMapper.MapTo3d(p2d);
|
||||
}
|
||||
|
||||
|
||||
tracePoints[i] = pos;
|
||||
}
|
||||
|
||||
return tracePoints;
|
||||
}
|
||||
|
||||
private bool TraceOcclusion(Vector3 origin, Vector3 target)
|
||||
private bool TraceRay(Vector3 origin, Vector3 target)
|
||||
{
|
||||
var direction = target - origin;
|
||||
var ray = new Ray
|
||||
var hitDistanceFromTarget = float.MinValue;
|
||||
var hitSurfaceType = SurfaceType.Water;
|
||||
while (hitDistanceFromTarget < -MathUtils.Epsilon && hitSurfaceType == SurfaceType.Water)
|
||||
{
|
||||
Origin = origin,
|
||||
Direction = Vector3.Normalize(direction),
|
||||
};
|
||||
|
||||
// Epsilon is used here to avoid occlusion when origin lies exactly on a poly
|
||||
return _scene.IsOccluded(new ShadowRay(ray, direction.Length() - MathUtils.Epsilon));
|
||||
var direction = target - origin;
|
||||
var hitResult = _scene.Trace(new Ray
|
||||
{
|
||||
Origin = origin,
|
||||
Direction = Vector3.Normalize(direction),
|
||||
});
|
||||
|
||||
hitDistanceFromTarget = hitResult.Distance - direction.Length();
|
||||
hitSurfaceType = _triangleTypeMap[(int)hitResult.PrimId];
|
||||
origin = hitResult.Position += direction * MathUtils.Epsilon;
|
||||
}
|
||||
|
||||
// A large epsilon is used here to fix shadow acne on sloped surfaces :)
|
||||
return Math.Abs(hitDistanceFromTarget) < 10 * MathUtils.Epsilon;
|
||||
}
|
||||
|
||||
// TODO: direction should already be normalised here
|
||||
// TODO: Can this be merged with the above?
|
||||
private bool TraceSunRay(Vector3 origin, Vector3 direction)
|
||||
{
|
||||
// Avoid self intersection
|
||||
origin += direction * MathUtils.Epsilon;
|
||||
|
||||
var hitResult = _scene.Trace(new Ray
|
||||
var hitSurfaceType = SurfaceType.Water;
|
||||
while (hitSurfaceType == SurfaceType.Water)
|
||||
{
|
||||
Origin = origin,
|
||||
Direction = Vector3.Normalize(direction),
|
||||
});
|
||||
|
||||
if (hitResult)
|
||||
{
|
||||
return _triangleTypeMap[(int)hitResult.PrimId] == SurfaceType.Sky;
|
||||
var hitResult = _scene.Trace(new Ray
|
||||
{
|
||||
Origin = origin,
|
||||
Direction = Vector3.Normalize(direction),
|
||||
});
|
||||
|
||||
hitSurfaceType = _triangleTypeMap[(int)hitResult.PrimId];
|
||||
origin = hitResult.Position += direction * MathUtils.Epsilon;
|
||||
}
|
||||
return false;
|
||||
|
||||
return hitSurfaceType == SurfaceType.Sky;
|
||||
}
|
||||
|
||||
private void SetAnimLightCellMaps()
|
||||
|
|
|
@ -43,8 +43,9 @@ public class MeshBuilder
|
|||
var cellIdxOffset = 0;
|
||||
for (var polyIdx = 0; polyIdx < numPolys; polyIdx++)
|
||||
{
|
||||
// There's 2 types of poly that we need to include in the mesh:
|
||||
// There's 3 types of poly that we need to include in the mesh:
|
||||
// - Terrain
|
||||
// - Water surfaces
|
||||
// - Door vision blockers
|
||||
//
|
||||
// Door vision blockers are the interesting one. They're not RenderPolys at all, just flagged Polys.
|
||||
|
@ -55,8 +56,7 @@ public class MeshBuilder
|
|||
}
|
||||
else if (polyIdx < numRenderPolys)
|
||||
{
|
||||
// we no longer want water polys :)
|
||||
continue;
|
||||
primType = SurfaceType.Water;
|
||||
}
|
||||
else if ((cell.Flags & 8) != 0)
|
||||
{
|
||||
|
@ -118,7 +118,7 @@ public class MeshBuilder
|
|||
var modelPath = campaignResources.GetResourcePath(ResourceType.Object, modelName);
|
||||
if (modelPath == null)
|
||||
{
|
||||
Log.Warning("Failed to find model file: {Name}", modelName);
|
||||
Log.Warning("Failed to find model file: {Path}", modelPath);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue