Skip to content

Commit

Permalink
Added support for multiple vertex colors.
Browse files Browse the repository at this point in the history
  • Loading branch information
MeltyPlayer committed Oct 14, 2021
1 parent 4fa6efe commit ed90bb6
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 48 deletions.
28 changes: 11 additions & 17 deletions FinModelUtility/Bmd2Fbx/src/Exporter/ModelConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ public IModel Convert(
new BmdMaterialManager(model, bmd, pathsAndBtis);

var jointsAndBones = this.ConvertBones_(model, bmd);
this.ConvertAnimations_(model, bmd, pathsAndBcxs, frameRate, jointsAndBones);
this.ConvertAnimations_(model,
bmd,
pathsAndBcxs,
frameRate,
jointsAndBones);
this.ConvertMesh_(model, bmd, jointsAndBones, materialManager);

return model;
Expand Down Expand Up @@ -235,22 +239,12 @@ private void ConvertMesh_(
vertex.SetBones(weights);
}

// TODO: Do the other colors need to be used too?
var indicesWithColor =
batch
.HasColors
.Select((hasColor, index) => (hasColor, index))
.Where(hasColorAndIndex => hasColorAndIndex.hasColor)
.Select(hasColorAndIndex => hasColorAndIndex.index)
.ToList();
Asserts.True(indicesWithColor.Count <= 1,
"More than one color at a vertex, unsupported!");
if (indicesWithColor.Count == 1) {
var indexWithColor = indicesWithColor[0];
var colorIndex = point.ColorIndex[indexWithColor];
var color = vertexColors[indexWithColor][colorIndex];

vertex.SetColorBytes(color.R, color.G, color.B, color.A);
for (var c = 0; c < 2; ++c) {
if (batch.HasColors[c]) {
var colorIndex = point.ColorIndex[c];
var color = vertexColors[c][colorIndex];
vertex.SetColorBytes(c, color.R, color.G, color.B, color.A);
}
}

for (var i = 0; i < 8; ++i) {
Expand Down
3 changes: 1 addition & 2 deletions FinModelUtility/Bmd2Fbx/src/misc/GCN/BMD.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2128,6 +2128,7 @@ public class MaterialEntry
public ushort[] Unknown2;
public ushort[] Indices2;

// https://github.com/LordNed/WindEditor/wiki/BMD-and-BDL-Model-Format#material-entry
public MaterialEntry(EndianBinaryReader er) {
this.Unknown1 = er.ReadBytes(8);
this.Color1 = er.ReadUInt16s(2);
Expand Down Expand Up @@ -2254,7 +2255,6 @@ public class TevStageProps {

public TevStageProps(EndianBinaryReader er)
{
er.ReadByte();
this.color_a = (GxCc) er.ReadByte();
this.color_b = (GxCc) er.ReadByte();
this.color_c = (GxCc) er.ReadByte();
Expand All @@ -2273,7 +2273,6 @@ public TevStageProps(EndianBinaryReader er)
this.alpha_scale = (TevScale) er.ReadByte();
this.alpha_clamp = er.ReadByte() == (byte) 1;
this.alpha_regid = er.ReadByte();
er.ReadByte();
}

public enum GxCc {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,29 @@ public void Fix(IModel model, Scene sc) {
}
}

var assColors = assMesh.VertexColorChannels[0];
assColors.Clear();
var assColors = assMesh.VertexColorChannels;
for (var c = 0; c < 8; ++c) {
assColors[c].Clear();
}

var hadColor = new bool[2];
foreach (var assColorIndexFloat in assColorIndices) {
var assColorIndex = (int) Math.Round(assColorIndexFloat);

var finVertex =
assColorIndex != -1 ? finVertices[assColorIndex] : null;
var finColor = finVertex?.Color;
if (finColor != null) {
assColors.Add(new Color4D(finColor.Rf,
finColor.Gf,
finColor.Bf,
finColor.Af));
} else {
assColors.Add(nullColor);
}
for (var c = 0; c < 2; ++c) {
var finColor = finVertex?.GetColor(c);
if (finColor != null) {
hadColor[c] = true;
assColors[c].Add(new Color4D(finColor.Rf,
finColor.Gf,
finColor.Bf,
finColor.Af));
} else {
assColors[c].Add(nullColor);
}
}
}


Expand All @@ -75,6 +81,12 @@ public void Fix(IModel model, Scene sc) {
assMesh.UVComponentCount[t] = 2;
}
}

for (var c = 0; c < 2; ++c) {
if (!hadColor[c]) {
assColors[c].Clear();
}
}
}
}
}
Expand Down
32 changes: 21 additions & 11 deletions FinModelUtility/Fin/src/exporter/gltf/GltfMeshBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

namespace fin.exporter.gltf {
using VERTEX =
VertexBuilder<VertexPositionNormal, VertexColor1Texture2, VertexJoints4>;
VertexBuilder<VertexPositionNormal, VertexColor2Texture2, VertexJoints4>;

public class GltfMeshBuilder {
public bool UvIndices { get; set; }
Expand Down Expand Up @@ -92,25 +92,35 @@ public Mesh BuildAndBindMesh(
}

// TODO: Include color
var finColor = point.Color;
var hasColor = finColor != null;
var assColor = hasColor
? new Vector4(finColor.Rf,
finColor.Bf,
finColor.Gf,
finColor.Af)
: new Vector4(1, 1, 1, 1);
var finColor0 = point.GetColor(0);
var hasColor0 = finColor0 != null;
var assColor0 = hasColor0
? new Vector4(finColor0.Rf,
finColor0.Bf,
finColor0.Gf,
finColor0.Af)
: new Vector4(1, 1, 1, 1);
var finColor1 = point.GetColor(1);
var hasColor1 = finColor1 != null;
var assColor1 = hasColor1
? new Vector4(finColor1.Rf,
finColor1.Bf,
finColor1.Gf,
finColor1.Af)
: new Vector4(1, 1, 1, 1);

var hasColor = hasColor0 || hasColor1;

var uvs = point.Uvs;
var hasUvs = (uvs?.Count ?? 0) > 0;
if (!this.UvIndices) {
if (hasUvs) {
var uv = uvs[0];
vertexBuilder =
vertexBuilder.WithMaterial(assColor,
vertexBuilder.WithMaterial(assColor0, assColor1,
new Vector2(uv.U, uv.V));
} else if (hasColor) {
vertexBuilder = vertexBuilder.WithMaterial(assColor);
vertexBuilder = vertexBuilder.WithMaterial(assColor0, assColor1);
}
} else {
// Importing the color directly via Assimp doesn't work for some
Expand Down
6 changes: 5 additions & 1 deletion FinModelUtility/Fin/src/model/SkinInterfaces.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,13 @@ public interface IVertex {
IVertex SetLocalTangent(ITangent? localNormal);
IVertex SetLocalTangent(float x, float y, float z, float w);

IColor? Color { get; }
IReadOnlyDictionary<int, IColor>? Colors { get; }
IVertex SetColor(IColor? color);
IVertex SetColor(int colorIndex, IColor? color);
IVertex SetColorBytes(byte r, byte g, byte b, byte a);
IVertex SetColorBytes(int colorIndex, byte r, byte g, byte b, byte a);
IColor? GetColor();
IColor? GetColor(int colorIndex);

IReadOnlyDictionary<int, ITexCoord>? Uvs { get; }
IVertex SetUv(ITexCoord? uv);
Expand Down
46 changes: 40 additions & 6 deletions FinModelUtility/Fin/src/model/impl/SkinImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ public IPrimitive AddQuads(params IVertex[] vertices) {

private class VertexImpl : IVertex {
private IDictionary<int, ITexCoord>? uvs_;
private IDictionary<int, IColor>? colors_;

public VertexImpl(int index, IPosition position) {
this.Index = index;
Expand Down Expand Up @@ -146,18 +147,50 @@ public IVertex SetLocalTangent(ITangent localTangent) {
}

public IVertex SetLocalTangent(float x, float y, float z, float w)
=> this.SetLocalTangent(new TangentImpl { X = x, Y = y, Z = z, W = w});
=> this.SetLocalTangent(new TangentImpl {X = x, Y = y, Z = z, W = w});


public IColor? Color { get; private set; }
public IReadOnlyDictionary<int, IColor>? Colors { get; private set; }

public IVertex SetColor(IColor? color) => this.SetColor(0, color);

public IVertex SetColor(int colorIndex, IColor? color) {
if (color != null) {
if (this.colors_ == null) {
this.colors_ = new Dictionary<int, IColor>();
this.Colors = new ReadOnlyDictionary<int, IColor>(this.colors_);
}

this.colors_[colorIndex] = color;
} else {
this.colors_?.Remove(colorIndex);
if (this.colors_?.Count == 0) {
this.colors_ = null;
this.Colors = null;
}
}

public IVertex SetColor(IColor? color) {
this.Color = color;
return this;
}

public IVertex SetColorBytes(byte r, byte g, byte b, byte a)
=> this.SetColor(ColorImpl.FromRgbaBytes(r, g, b, a));
=> this.SetColorBytes(0, r, g, b, a);

public IVertex SetColorBytes(
int colorIndex,
byte r,
byte g,
byte b,
byte a)
=> this.SetColor(colorIndex, ColorImpl.FromRgbaBytes(r, g, b, a));

public IColor? GetColor() => this.GetColor(0);

public IColor? GetColor(int colorIndex) {
IColor? color = null;
this.colors_?.TryGetValue(colorIndex, out color);
return color;
}


public IReadOnlyDictionary<int, ITexCoord>? Uvs { get; private set; }
Expand All @@ -177,6 +210,7 @@ public IVertex SetUv(int uvIndex, ITexCoord? uv) {
this.uvs_?.Remove(uvIndex);
if (this.uvs_?.Count == 0) {
this.uvs_ = null;
this.Uvs = null;
}
}

Expand All @@ -190,7 +224,7 @@ public IVertex SetUv(int uvIndex, float u, float v)

public ITexCoord? GetUv(int uvIndex) {
ITexCoord? uv = null;
this.uvs_?.TryGetValue(uvIndex, out uv);
this.uvs_?.TryGetValue(uvIndex, out uv);
return uv;
}
}
Expand Down

0 comments on commit ed90bb6

Please sign in to comment.