Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions TombEditor/Controls/Panel3D/Panel3DDraw.cs
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,10 @@ private void DrawLights(Effect effect, Room[] roomsWhoseObjectsToDraw, List<Text
color = new Vector4(1.0f, 1.0f, 0.25f, 1.0f);
if (light.Type == LightType.Sun)
color = new Vector4(1.0f, 0.5f, 0.0f, 1.0f);
if (light.Type == LightType.Glow)
color = new Vector4(0.0f, 1.0f, 1.0f, 1.0f);
if (light.Type == LightType.Move)
color = new Vector4(0.5f, 1.0f, 0.5f, 1.0f);
if (_highlightedObjects.Contains(light))
color = _editor.Configuration.UI_ColorScheme.ColorSelection;

Expand All @@ -531,15 +535,17 @@ private void DrawLights(Effect effect, Room[] roomsWhoseObjectsToDraw, List<Text
{
var light = (LightInstance)_editor.SelectedObject;
if (ShowLightMeshes)
if (light.Type == LightType.Point || light.Type == LightType.Shadow || light.Type == LightType.FogBulb)
if (light.Type == LightType.Point || light.Type == LightType.Shadow || light.Type == LightType.FogBulb ||
light.Type == LightType.Glow || light.Type == LightType.Move)
{
_legacyDevice.SetVertexBuffer(_sphere.VertexBuffer);
_legacyDevice.SetVertexInputLayout(_sphere.InputLayout);
_legacyDevice.SetIndexBuffer(_sphere.IndexBuffer, _sphere.IsIndex32Bits);

Matrix4x4 model;

if (light.Type == LightType.Point || light.Type == LightType.Shadow)
if (light.Type == LightType.Point || light.Type == LightType.Shadow ||
light.Type == LightType.Glow || light.Type == LightType.Move)
{
model = Matrix4x4.CreateScale(light.InnerRange * 2.0f) * light.ObjectMatrix;
effect.Parameters["ModelViewProjection"].SetValue((model * _viewProjection).ToSharpDX());
Expand Down
13 changes: 11 additions & 2 deletions TombEditor/ToolWindows/Lighting.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ obj is Editor.ObjectChangedEvent ||
bool CanCastShadows = false;
bool CanCastDynamicShadows = false;
bool CanIlluminateGeometry = false;
bool CanImportedGeometry = false;

cmbLightQuality.Enabled = false;

Expand All @@ -81,6 +82,14 @@ obj is Editor.ObjectChangedEvent ||
HasOutRange = true;
break;

case LightType.Glow:
case LightType.Move:
HasInRange = true;
HasOutRange = true;
CanCastShadows = true;
CanImportedGeometry = true;
break;

case LightType.FogBulb:
HasOutRange = true;
break;
Expand Down Expand Up @@ -111,7 +120,7 @@ obj is Editor.ObjectChangedEvent ||
cbLightCastsShadow.Enabled = CanCastDynamicShadows;
cbLightIsDynamicallyUsed.Enabled = CanIlluminateGeometry;
cbLightIsStaticallyUsed.Enabled = CanIlluminateGeometry;
cbLightIsUsedForImportedGeometry.Enabled = CanIlluminateGeometry;
cbLightIsUsedForImportedGeometry.Enabled = CanIlluminateGeometry || CanImportedGeometry;
numIntensity.Enabled = light != null;
numInnerRange.Enabled = HasInRange;
numOuterRange.Enabled = HasOutRange;
Expand All @@ -136,7 +145,7 @@ obj is Editor.ObjectChangedEvent ||
cbLightIsStaticallyUsed.Checked = light?.IsStaticallyUsed ?? false;
cbLightIsUsedForImportedGeometry.Checked = light?.IsUsedForImportedGeometry ?? false;
cbLightCastsShadow.Checked = light?.CastDynamicShadows ?? false;
cmbLightQuality.Enabled = light != null;
cmbLightQuality.Enabled = light != null && light.Type != LightType.Glow && light.Type != LightType.Move;
cmbLightQuality.SelectedIndex = (int)(light?.Quality ?? 0);
cmbLightTypes.SelectedIndex = (int)(light?.Type ?? (LightType)cmbLightTypes.SelectedIndex);
}
Expand Down
8 changes: 8 additions & 0 deletions TombLib/TombLib.Rendering/Rendering/ServiceObjectTextures.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public enum ServiceObjectTexture
memo,
light_effect,
light_fog,
light_glow,
light_move,
light_point,
light_shadow,
light_spot,
Expand Down Expand Up @@ -110,6 +112,12 @@ public static ServiceObjectTexture GetType(ISpatial instance)
case LightType.FogBulb:
type = ServiceObjectTexture.light_fog;
break;
case LightType.Glow:
type = ServiceObjectTexture.light_glow;
break;
case LightType.Move:
type = ServiceObjectTexture.light_move;
break;
case LightType.Point:
type = ServiceObjectTexture.light_point;
break;
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions TombLib/TombLib.Rendering/TombLib.Rendering.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@
<EmbeddedResource Include="Rendering\ServiceObjectTextures\imp_geo.png" />
<EmbeddedResource Include="Rendering\ServiceObjectTextures\light_effect.png" />
<EmbeddedResource Include="Rendering\ServiceObjectTextures\light_fog.png" />
<EmbeddedResource Include="Rendering\ServiceObjectTextures\light_glow.png" />
<EmbeddedResource Include="Rendering\ServiceObjectTextures\light_move.png" />
<EmbeddedResource Include="Rendering\ServiceObjectTextures\light_point.png" />
<EmbeddedResource Include="Rendering\ServiceObjectTextures\light_shadow.png" />
<EmbeddedResource Include="Rendering\ServiceObjectTextures\light_spot.png" />
Expand Down
2 changes: 2 additions & 0 deletions TombLib/TombLib/LevelData/Compilers/Rooms.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1240,6 +1240,8 @@ private void ConvertLights(Room room, tr_room newRoom)
newLight.Length = light.Intensity; // Store float intensity as length
break;
case LightType.Effect:
case LightType.Glow:
case LightType.Move:
continue;
default:
throw new Exception("Unknown light type '" + light.Type + "' encountered.");
Expand Down
31 changes: 31 additions & 0 deletions TombLib/TombLib/LevelData/Compilers/TombEngine/Rooms.cs
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,8 @@ private TombEngineRoom BuildRoom(Room room)
}
}

int importedGeometryVertexStart = 0;

// Generate geometry
{
// Add room geometry
Expand Down Expand Up @@ -555,6 +557,7 @@ private TombEngineRoom BuildRoom(Room room)

// Add geometry imported objects

importedGeometryVertexStart = roomVertices.Count;
foreach (var geometry in room.Objects.OfType<ImportedGeometryInstance>())
{
if (geometry.Model?.DirectXModel == null)
Expand Down Expand Up @@ -731,6 +734,10 @@ private TombEngineRoom BuildRoom(Room room)

// Assign vertex effects

var vertexEffectLights = room.Objects.OfType<LightInstance>()
.Where(l => l.Enabled && (l.Type == LightType.Glow || l.Type == LightType.Move))
.ToList();

for (int i = 0; i < newRoom.Vertices.Count; ++i)
{
var trVertex = newRoom.Vertices[i];
Expand All @@ -739,9 +746,31 @@ private TombEngineRoom BuildRoom(Room room)
var xv = (int)(trVertex.Position.X / Level.SectorSizeUnit);
var zv = (int)(trVertex.Position.Z / Level.SectorSizeUnit);

// Apply vertex effects from Glow and Move light objects to all vertices,
// including border/wall vertices that are skipped by the sector bounds check below.
var vertexPosLocal = new Vector3(trVertex.Position.X, -trVertex.Position.Y - room.WorldPos.Y, trVertex.Position.Z);
bool isImportedGeometryVertex = i >= importedGeometryVertexStart;
foreach (var effectLight in vertexEffectLights)
{
if (isImportedGeometryVertex && !effectLight.IsUsedForImportedGeometry)
continue;

float strength = RoomGeometry.CalculateVertexEffectStrength(room, effectLight, vertexPosLocal);
if (strength <= 0f)
continue;

if (effectLight.Type == LightType.Glow)
trVertex.Glow = Math.Max(trVertex.Glow, strength);
else if (effectLight.Type == LightType.Move)
trVertex.Move = Math.Max(trVertex.Move, strength);
}

// Check for vertex out of room bounds
if (xv <= 0 || zv <= 0 || xv >= room.NumXSectors || zv >= room.NumZSectors)
{
newRoom.Vertices[i] = trVertex;
continue;
}

foreach (var portal in room.PortalsCache)
{
Expand Down Expand Up @@ -1001,6 +1030,8 @@ private void ConvertLights(Room room, TombEngineRoom newRoom)
newLight.Out = light.OuterRange * Level.SectorSizeUnit;
break;
case LightType.Effect:
case LightType.Glow:
case LightType.Move:
continue;
default:
throw new Exception("Unknown light type '" + light.Type + "' encountered.");
Expand Down
7 changes: 6 additions & 1 deletion TombLib/TombLib/LevelData/Instances/LightInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public enum LightQuality : byte
}
public enum LightType : byte
{
Point, Shadow, Spot, Effect, Sun, FogBulb
Point, Shadow, Spot, Effect, Sun, FogBulb, Glow, Move
}

public class LightInstance : PositionBasedObjectInstance, IColorable, IReplaceable, IRotateableYX
Expand Down Expand Up @@ -65,6 +65,11 @@ public LightInstance(LightType type)
IsStaticallyUsed = false;
IsUsedForImportedGeometry = false;
break;
case LightType.Glow:
case LightType.Move:
IsDynamicallyUsed = false;
CastDynamicShadows = false;
break;
}
}

Expand Down
23 changes: 23 additions & 0 deletions TombLib/TombLib/LevelData/RoomGeometry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1163,6 +1163,7 @@ public static Vector3 CalculateLightForVertex(Room room, LightInstance light, Ve
LightType.Effect => CalculateEffectLight(light, position),
LightType.Sun => CalculateSunLight(room, light, position, normal, highQuality),
LightType.Spot => CalculateSpotLight(room, light, position, normal, highQuality),
LightType.Glow or LightType.Move => Vector3.Zero,
_ => Vector3.Zero
};
}
Expand Down Expand Up @@ -1229,6 +1230,28 @@ private static Vector3 CalculateEffectLight(LightInstance light, Vector3 positio
return finalIntensity * light.Color * ColorNormalization;
}

// Calculates the strength of a Glow or Move vertex effect at a given position.
// Returns a value in [0, 1] based on linear falloff from InnerRange to OuterRange,
// scaled by Intensity. Respects IsObstructedByRoomGeometry via raytrace.
public static float CalculateVertexEffectStrength(Room room, LightInstance light, Vector3 position)
{
float distance = Vector3.Distance(position, light.Position);
float outerRadius = light.OuterRange * Level.SectorSizeUnit;

if (distance > outerRadius)
return 0.0f;

float innerRadius = light.InnerRange * Level.SectorSizeUnit;
float rangeDelta = outerRadius - innerRadius;
float attenuation = rangeDelta > 0 ? Math.Clamp((outerRadius - distance) / rangeDelta, 0.0f, 1.0f) : 1.0f;

if (attenuation <= 0.0f)
return 0.0f;

float raytraceResult = light.IsObstructedByRoomGeometry && LightRayTrace(room, position, light.Position) ? 0.0f : 1.0f;
return Math.Clamp(light.Intensity * attenuation * raytraceResult, 0.0f, 1.0f);
}

private static Vector3 CalculateSunLight(Room room, LightInstance light, Vector3 position,
Vector3 normal, bool highQuality)
{
Expand Down