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
7 changes: 4 additions & 3 deletions TombLib/TombLib/GeometryIO/IOMaterial.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ public class IOMaterial
{
public string Name { get; private set; }
public Texture Texture { get; set; }
public bool AdditiveBlending { get; set; }
public BlendMode BlendMode { get; set; }
public bool AdditiveBlending => BlendMode >= BlendMode.Additive;
public bool DoubleSided { get; set; }
public int Shininess { get; set; }

Expand All @@ -20,11 +21,11 @@ public IOMaterial(string name)
Name = name;
}

public IOMaterial(string name, Texture texture, string texturePath,bool additiveBlending, bool doubleSided, int shininess, int page)
public IOMaterial(string name, Texture texture, string texturePath, BlendMode blendMode, bool doubleSided, int shininess, int page)
{
Name = name;
Texture = texture;
AdditiveBlending = additiveBlending;
BlendMode = blendMode;
DoubleSided = doubleSided;
Shininess = shininess;
Path = texturePath;
Expand Down
4 changes: 2 additions & 2 deletions TombLib/TombLib/GeometryIO/IOModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ public BoundingSphere BoundingSphere
}
}

public IOMaterial GetMaterial(Texture texture, bool blending, int page, bool doubleSided, int shininess)
public IOMaterial GetMaterial(Texture texture, BlendMode blendMode, int page, bool doubleSided, int shininess)
{
foreach (var mat in Materials)
if (mat.Page == page)
if (mat.Texture.Equals(texture))
if (mat.AdditiveBlending == blending)
if (mat.BlendMode == blendMode)
if (mat.DoubleSided == doubleSided)
if (mat.Shininess == shininess)
return mat;
Expand Down
18 changes: 12 additions & 6 deletions TombLib/TombLib/GeometryIO/Importers/Assimp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,18 @@ public override IOModel ImportFromFile(string filename)

// Create the new material
material.Texture = textures[i];
material.AdditiveBlending = (mat.HasBlendMode && mat.BlendMode == Assimp.BlendMode.Additive) || mat.Opacity < 1.0f
|| mat.Name.StartsWith(Graphics.Material.Material_AdditiveBlending)
|| mat.Name.StartsWith(Graphics.Material.Material_AdditiveBlendingDoubleSided);
material.DoubleSided = (mat.HasTwoSided && mat.IsTwoSided)
|| mat.Name.StartsWith(Graphics.Material.Material_OpaqueDoubleSided)
|| mat.Name.StartsWith(Graphics.Material.Material_AdditiveBlendingDoubleSided);

if (mat.Name.StartsWith("Te"))
{
material.BlendMode = Graphics.Material.GetBlendModeFromName(mat.Name);
material.DoubleSided = Graphics.Material.GetDoubleSidedFromName(mat.Name);
}
else
{
material.BlendMode = (mat.HasBlendMode && mat.BlendMode == Assimp.BlendMode.Additive) || mat.Opacity < 1.0f
? TombLib.Utils.BlendMode.Additive : TombLib.Utils.BlendMode.Normal;
material.DoubleSided = mat.HasTwoSided && mat.IsTwoSided;
}

// HACK: Ass-imp uses different numbering for shininess in different formats!

Expand Down
3 changes: 2 additions & 1 deletion TombLib/TombLib/GeometryIO/Importers/Metasequoia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ public override IOModel ImportFromFile(string filename)

if (tokens.Length == 4 && float.TryParse(tokens[3], out alpha))
{
material.AdditiveBlending = (alpha < 1.0f);
if (alpha < 1.0f)
material.BlendMode = TombLib.Utils.BlendMode.Additive;
}
}

Expand Down
20 changes: 9 additions & 11 deletions TombLib/TombLib/GeometryIO/RoomGeometryExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,13 @@ public static RoomExportResult ExportRooms(IEnumerable<Room> roomsToExport, stri
var page = new SplitPageReference(tex, y * numXPages + x, x, y, Path.Combine(Path.GetDirectoryName(filePath), textureFileName));
splitPages.Add(page);

var matOpaque = new IOMaterial(Material.Material_Opaque + "_" + j + "_" + page.Index, tex, page.Path, false, false, 0, page.Index);
var matOpaqueDoubleSided = new IOMaterial(Material.Material_OpaqueDoubleSided + "_" + j + "_" + page.Index, tex, page.Path, false, true, 0, page.Index);
var matAdditiveBlending = new IOMaterial(Material.Material_AdditiveBlending + "_" + j + "_" + page.Index, tex, page.Path, true, false, 0, page.Index);
var matAdditiveBlendingDoubleSided = new IOMaterial(Material.Material_AdditiveBlendingDoubleSided + "_" + j + "_" + page.Index, tex, page.Path, true, true, 0, page.Index);

model.Materials.Add(matOpaque);
model.Materials.Add(matOpaqueDoubleSided);
model.Materials.Add(matAdditiveBlending);
model.Materials.Add(matAdditiveBlendingDoubleSided);
foreach (BlendMode mode in Enum.GetValues(typeof(BlendMode)))
{
var prefix = Material.GetPrefixForBlendMode(mode);
var suffix = j + "_" + page.Index;
model.Materials.Add(new IOMaterial(prefix + "_" + suffix, tex, page.Path, mode, false, 0, page.Index));
model.Materials.Add(new IOMaterial(prefix + Material.DoubleSidedSuffix + "_" + suffix, tex, page.Path, mode, true, 0, page.Index));
}
}
}
}
Expand Down Expand Up @@ -250,7 +248,7 @@ public static RoomExportResult ExportRooms(IEnumerable<Room> roomsToExport, stri
}

var mat = model.GetMaterial(textureArea1.Texture,
textureArea1.BlendMode >= BlendMode.Additive,
textureArea1.BlendMode,
textureAreaPage,
textureArea1.DoubleSided,
0);
Expand Down Expand Up @@ -295,7 +293,7 @@ public static RoomExportResult ExportRooms(IEnumerable<Room> roomsToExport, stri
mesh.Colors.Add(new Vector4(room.RoomGeometry.VertexColors[i + 2], 1.0f));

var mat = model.GetMaterial(textureArea.Texture,
textureArea.BlendMode >= BlendMode.Additive,
textureArea.BlendMode,
textureAreaPage,
textureArea.DoubleSided,
0);
Expand Down
83 changes: 82 additions & 1 deletion TombLib/TombLib/Graphics/Material.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,51 @@ namespace TombLib.Graphics
{
public class Material
{
public const string DoubleSidedSuffix = "DS";

// Opaque (normal) prefix.
public const string Material_Opaque = "TeOp";
public const string Material_OpaqueDoubleSided = "TeOpDS";
public const string Material_AdditiveBlending = "TeBl";

// Blend mode prefixes. "TeBl" is kept for backward compatibility with Additive.
public const string Material_AdditiveBlending = "TeBl";
public const string Material_AdditiveBlendingDoubleSided = "TeBlDS";
public const string Material_AlphaTest = "TeBlAT";
public const string Material_AlphaTestDoubleSided = "TeBlATDS";
public const string Material_Distortion = "TeBlDis";
public const string Material_DistortionDoubleSided = "TeBlDisDS";
public const string Material_NoZTest = "TeBlNZ";
public const string Material_NoZTestDoubleSided = "TeBlNZDS";
public const string Material_Subtract = "TeBlSub";
public const string Material_SubtractDoubleSided = "TeBlSubDS";
public const string Material_Wireframe = "TeBlWf";
public const string Material_WireframeDoubleSided = "TeBlWfDS";
public const string Material_Exclude = "TeBlExc";
public const string Material_ExcludeDoubleSided = "TeBlExcDS";
public const string Material_Screen = "TeBlScr";
public const string Material_ScreenDoubleSided = "TeBlScrDS";
public const string Material_Lighten = "TeBlLig";
public const string Material_LightenDoubleSided = "TeBlLigDS";
public const string Material_AlphaBlend = "TeBlAB";
public const string Material_AlphaBlendDoubleSided = "TeBlABDS";

// Lookup from prefix to blend mode.
// Longer (more specific) entries must precede shorter generic ones to prevent
// partial matches (e.g., "TeBlSub" must come before "TeBl").
private static readonly (string Prefix, BlendMode Mode)[] BlendModePrefixLookup =
{
(Material_AlphaTest, BlendMode.AlphaTest),
(Material_Distortion, BlendMode.Distortion),
(Material_NoZTest, BlendMode.NoZTest),
(Material_Subtract, BlendMode.Subtract),
(Material_Wireframe, BlendMode.Wireframe),
(Material_Exclude, BlendMode.Exclude),
(Material_Screen, BlendMode.Screen),
(Material_Lighten, BlendMode.Lighten),
(Material_AlphaBlend, BlendMode.AlphaBlend),
(Material_AdditiveBlending, BlendMode.Additive),
(Material_Opaque, BlendMode.Normal),
};

public string Name { get; private set; }
public Texture Texture { get; set; }
Expand Down Expand Up @@ -43,5 +84,45 @@ public void SetStates(SharpDX.Toolkit.Graphics.GraphicsDevice device, bool trans
else
device.SetRasterizerState(device.RasterizerStates.CullBack);
}

// Returns the material name prefix for the given blend mode.
public static string GetPrefixForBlendMode(BlendMode mode)
{
foreach (var (prefix, blendMode) in BlendModePrefixLookup)
if (blendMode == mode)
return prefix;
return Material_Opaque;
}

// Parses the blend mode from a material name using the Te prefix convention.
public static BlendMode GetBlendModeFromName(string name)
{
foreach (var (prefix, mode) in BlendModePrefixLookup)
if (MatchesMaterialPrefix(name, prefix))
return mode;
return BlendMode.Normal;
}

// Returns true if the material name indicates a double-sided surface.
public static bool GetDoubleSidedFromName(string name)
{
foreach (var (prefix, _) in BlendModePrefixLookup)
if (MatchesMaterialPrefix(name, prefix + DoubleSidedSuffix))
return true;
return false;
}

// Returns true if name starts with prefix and is immediately followed by "DS", "_", or end of string.
private static bool MatchesMaterialPrefix(string name, string prefix)
{
if (!name.StartsWith(prefix))
return false;
int after = prefix.Length;
if (after >= name.Length || name[after] == '_')
return true;
if (after + 1 < name.Length && name[after] == 'D' && name[after + 1] == 'S')
return true;
return false;
}
}
}
19 changes: 8 additions & 11 deletions TombLib/TombLib/Wad/WadMesh.cs
Original file line number Diff line number Diff line change
Expand Up @@ -369,15 +369,12 @@ public static IOModel PrepareForExport(string filePath, IOGeometrySettings setti
var textureFileName = name + "_" + i + ".png";
var path = Path.Combine(Path.GetDirectoryName(filePath), textureFileName);

var matOpaque = new IOMaterial(Material.Material_Opaque + "_" + i, pages[i], path, false, false, 0, i);
var matOpaqueDoubleSided = new IOMaterial(Material.Material_OpaqueDoubleSided + "_" + i, pages[i], path, false, true, 0, i);
var matAdditiveBlending = new IOMaterial(Material.Material_AdditiveBlending + "_" + i, pages[i], path, true, false, 0, i);
var matAdditiveBlendingDoubleSided = new IOMaterial(Material.Material_AdditiveBlendingDoubleSided + "_" + i, pages[i], path, true, true, 0, i);

model.Materials.Add(matOpaque);
model.Materials.Add(matOpaqueDoubleSided);
model.Materials.Add(matAdditiveBlending);
model.Materials.Add(matAdditiveBlendingDoubleSided);
foreach (BlendMode mode in Enum.GetValues(typeof(BlendMode)))
{
var prefix = Material.GetPrefixForBlendMode(mode);
model.Materials.Add(new IOMaterial(prefix + "_" + i, pages[i], path, mode, false, 0, i));
model.Materials.Add(new IOMaterial(prefix + Material.DoubleSidedSuffix + "_" + i, pages[i], path, mode, true, 0, i));
}
}

int lastIndex = 0;
Expand Down Expand Up @@ -449,7 +446,7 @@ public static IOModel PrepareForExport(string filePath, IOGeometrySettings setti
foreach (var mt in model.Materials)
if ((mergeIntoPages && mt.Page == texture.Atlas) ||
(!mergeIntoPages && mt.Texture == p.Texture.Texture))
if (mt.AdditiveBlending == (p.Texture.BlendMode >= BlendMode.Additive))
if (mt.BlendMode == p.Texture.BlendMode)
if (mt.DoubleSided == p.Texture.DoubleSided)
if (mt.Shininess == 0)
mat = mt;
Expand Down Expand Up @@ -663,7 +660,7 @@ public static List<WadMesh> ImportFromExternalModel(string fileName, IOGeometryS
}

area.DoubleSided = tmpSubmesh.Value.Material.DoubleSided;
area.BlendMode = tmpSubmesh.Value.Material.AdditiveBlending ? BlendMode.Additive : BlendMode.Normal;
area.BlendMode = tmpSubmesh.Value.Material.BlendMode;

poly.Texture = area;
poly.ShineStrength = (byte)Math.Min(Math.Round(tmpSubmesh.Value.Material.Shininess / 16.0f, MidpointRounding.ToEven), 63);
Expand Down
17 changes: 7 additions & 10 deletions WadTool/WadActions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -406,15 +406,12 @@ private static void UpdateBoneAbsolutePositions(List<WadBone> bones)
var textureFileName = "Texture_" + i + ".png";
var path = Path.Combine(Path.GetDirectoryName(filePath), textureFileName);

var matOpaque = new IOMaterial(Material.Material_Opaque + "_" + i, pages[i], path, false, false, 0, i);
var matOpaqueDoubleSided = new IOMaterial(Material.Material_OpaqueDoubleSided + "_" + i, pages[i], path, false, true, 0, i);
var matAdditiveBlending = new IOMaterial(Material.Material_AdditiveBlending + "_" + i, pages[i], path, true, false, 0, i);
var matAdditiveBlendingDoubleSided = new IOMaterial(Material.Material_AdditiveBlendingDoubleSided + "_" + i, pages[i], path, true, true, 0, i);

model.Materials.Add(matOpaque);
model.Materials.Add(matOpaqueDoubleSided);
model.Materials.Add(matAdditiveBlending);
model.Materials.Add(matAdditiveBlendingDoubleSided);
foreach (BlendMode mode in Enum.GetValues(typeof(BlendMode)))
{
var prefix = Material.GetPrefixForBlendMode(mode);
model.Materials.Add(new IOMaterial(prefix + "_" + i, pages[i], path, mode, false, 0, i));
model.Materials.Add(new IOMaterial(prefix + Material.DoubleSidedSuffix + "_" + i, pages[i], path, mode, true, 0, i));
}
}

UpdateBoneAbsolutePositions(m.Bones);
Expand Down Expand Up @@ -499,7 +496,7 @@ private static void UpdateBoneAbsolutePositions(List<WadBone> bones)
var mat = model.Materials[0];
foreach (var mt in model.Materials)
if (mt.Page == texture.Atlas)
if (mt.AdditiveBlending == (p.Texture.BlendMode >= BlendMode.Additive))
if (mt.BlendMode == p.Texture.BlendMode)
if (mt.DoubleSided == p.Texture.DoubleSided)
if (mt.Shininess == 0)
mat = mt;
Expand Down