mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-15 21:24:18 +01:00
Update Gamedata
This commit is contained in:
parent
4026dd5867
commit
68135f3757
11 changed files with 40 additions and 75 deletions
|
|
@ -1 +1 @@
|
||||||
Subproject commit 19923f8d5649f11edcfae710c26d6273cf2e9d62
|
Subproject commit 62f6acfb0f9e31b2907c02a270d723bfff18b390
|
||||||
|
|
@ -4,11 +4,11 @@ public static class HookSettings
|
||||||
{
|
{
|
||||||
public const bool AllHooks = true;
|
public const bool AllHooks = true;
|
||||||
|
|
||||||
public const bool ObjectHooks = false && AllHooks;
|
public const bool ObjectHooks = true && AllHooks;
|
||||||
public const bool ReplacementHooks = true && AllHooks;
|
public const bool ReplacementHooks = true && AllHooks;
|
||||||
public const bool ResourceHooks = false && AllHooks;
|
public const bool ResourceHooks = true && AllHooks;
|
||||||
public const bool MetaEntryHooks = false && AllHooks;
|
public const bool MetaEntryHooks = true && AllHooks;
|
||||||
public const bool MetaParentHooks = false && AllHooks;
|
public const bool MetaParentHooks = true && AllHooks;
|
||||||
public const bool VfxIdentificationHooks = false && AllHooks;
|
public const bool VfxIdentificationHooks = false && AllHooks;
|
||||||
public const bool PostProcessingHooks = false && AllHooks;
|
public const bool PostProcessingHooks = true && AllHooks;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||||
using OtterGui.Services;
|
using OtterGui.Services;
|
||||||
using Penumbra.Collections;
|
|
||||||
using Penumbra.GameData;
|
using Penumbra.GameData;
|
||||||
using Penumbra.Interop.PathResolving;
|
using Penumbra.Interop.PathResolving;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||||
|
using Lumina.Data.Parsing.Uld;
|
||||||
using OtterGui.Services;
|
using OtterGui.Services;
|
||||||
using Penumbra.GameData;
|
using Penumbra.GameData;
|
||||||
using Penumbra.Interop.PathResolving;
|
using Penumbra.Interop.PathResolving;
|
||||||
|
|
@ -8,12 +10,10 @@ namespace Penumbra.Interop.Hooks.Meta;
|
||||||
|
|
||||||
public unsafe class GmpHook : FastHook<GmpHook.Delegate>, IDisposable
|
public unsafe class GmpHook : FastHook<GmpHook.Delegate>, IDisposable
|
||||||
{
|
{
|
||||||
public delegate nint Delegate(nint gmpResource, uint dividedHeadId);
|
public delegate ulong Delegate(CharacterUtility* characterUtility, ulong* outputEntry, ushort setId);
|
||||||
|
|
||||||
private readonly MetaState _metaState;
|
private readonly MetaState _metaState;
|
||||||
|
|
||||||
private static readonly Finalizer StablePointer = new();
|
|
||||||
|
|
||||||
public GmpHook(HookManager hooks, MetaState metaState)
|
public GmpHook(HookManager hooks, MetaState metaState)
|
||||||
{
|
{
|
||||||
_metaState = metaState;
|
_metaState = metaState;
|
||||||
|
|
@ -21,50 +21,21 @@ public unsafe class GmpHook : FastHook<GmpHook.Delegate>, IDisposable
|
||||||
_metaState.Config.ModsEnabled += Toggle;
|
_metaState.Config.ModsEnabled += Toggle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <remarks>
|
private ulong Detour(CharacterUtility* characterUtility, ulong* outputEntry, ushort setId)
|
||||||
/// This function returns a pointer to the correct block in the GMP file, if it exists - cf. <see cref="ExpandedEqpGmpBase"/>.
|
|
||||||
/// To work around this, we just have a single stable ulong accessible and offset the pointer to this by the required distance,
|
|
||||||
/// which is defined by the modulo of the original ID and the block size, if we return our own custom gmp entry.
|
|
||||||
/// </remarks>
|
|
||||||
private nint Detour(nint gmpResource, uint dividedHeadId)
|
|
||||||
{
|
{
|
||||||
nint ret;
|
ulong ret;
|
||||||
if (_metaState.GmpCollection.TryPeek(out var collection)
|
if (_metaState.GmpCollection.TryPeek(out var collection)
|
||||||
&& collection.Collection is { Valid: true, ModCollection.MetaCache: { } cache }
|
&& collection.Collection is { Valid: true, ModCollection.MetaCache: { } cache }
|
||||||
&& cache.Gmp.TryGetValue(new GmpIdentifier(collection.Id), out var entry))
|
&& cache.Gmp.TryGetValue(new GmpIdentifier(collection.Id), out var entry))
|
||||||
{
|
ret = (*outputEntry) = entry.Entry.Enabled ? entry.Entry.Value : 0ul;
|
||||||
if (entry.Entry.Enabled)
|
|
||||||
{
|
|
||||||
*StablePointer.Pointer = entry.Entry.Value;
|
|
||||||
// This function already gets the original ID divided by the block size, so we can compute the modulo with a single multiplication and addition.
|
|
||||||
// We then go backwards from our pointer because this gets added by the calling functions.
|
|
||||||
ret = (nint)(StablePointer.Pointer - (collection.Id.Id - dividedHeadId * ExpandedEqpGmpBase.BlockSize));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = nint.Zero;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
ret = Task.Result.Original(characterUtility, outputEntry, setId);
|
||||||
ret = Task.Result.Original(gmpResource, dividedHeadId);
|
|
||||||
}
|
|
||||||
|
|
||||||
Penumbra.Log.Excessive($"[GetGmpFlags] Invoked on 0x{gmpResource:X} with {dividedHeadId}, returned {ret:X10}.");
|
Penumbra.Log.Excessive(
|
||||||
|
$"[GetGmpFlags] Invoked on 0x{(ulong)characterUtility:X} for {setId} with 0x{(ulong)outputEntry:X} (={*outputEntry:X}), returned {ret:X10}.");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Allocate and clean up our single stable ulong pointer. </summary>
|
|
||||||
private class Finalizer
|
|
||||||
{
|
|
||||||
public readonly ulong* Pointer = (ulong*)Marshal.AllocHGlobal(8);
|
|
||||||
|
|
||||||
~Finalizer()
|
|
||||||
{
|
|
||||||
Marshal.FreeHGlobal((nint)Pointer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
=> _metaState.Config.ModsEnabled -= Toggle;
|
=> _metaState.Config.ModsEnabled -= Toggle;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ public sealed unsafe class ModelLoadComplete : FastHook<ModelLoadComplete.Delega
|
||||||
{
|
{
|
||||||
_collectionResolver = collectionResolver;
|
_collectionResolver = collectionResolver;
|
||||||
_metaState = metaState;
|
_metaState = metaState;
|
||||||
Task = hooks.CreateHook<Delegate>("Model Load Complete", vtables.HumanVTable[58], Detour, HookSettings.MetaParentHooks);
|
Task = hooks.CreateHook<Delegate>("Model Load Complete", vtables.HumanVTable[59], Detour, HookSettings.MetaParentHooks);
|
||||||
}
|
}
|
||||||
|
|
||||||
public delegate void Delegate(DrawObject* drawObject);
|
public delegate void Delegate(DrawObject* drawObject);
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,7 @@ namespace Penumbra.Interop.Hooks.Meta;
|
||||||
|
|
||||||
public unsafe class RspBustHook : FastHook<RspBustHook.Delegate>, IDisposable
|
public unsafe class RspBustHook : FastHook<RspBustHook.Delegate>, IDisposable
|
||||||
{
|
{
|
||||||
public delegate float* Delegate(nint cmpResource, float* storage, Race race, byte gender, byte isSecondSubRace, byte bodyType,
|
public delegate float* Delegate(nint cmpResource, float* storage, SubRace race, byte gender, byte bodyType, byte bustSize);
|
||||||
byte bustSize);
|
|
||||||
|
|
||||||
private readonly MetaState _metaState;
|
private readonly MetaState _metaState;
|
||||||
private readonly MetaFileManager _metaFileManager;
|
private readonly MetaFileManager _metaFileManager;
|
||||||
|
|
@ -24,7 +23,7 @@ public unsafe class RspBustHook : FastHook<RspBustHook.Delegate>, IDisposable
|
||||||
_metaState.Config.ModsEnabled += Toggle;
|
_metaState.Config.ModsEnabled += Toggle;
|
||||||
}
|
}
|
||||||
|
|
||||||
private float* Detour(nint cmpResource, float* storage, Race race, byte gender, byte isSecondSubRace, byte bodyType, byte bustSize)
|
private float* Detour(nint cmpResource, float* storage, SubRace clan, byte gender, byte bodyType, byte bustSize)
|
||||||
{
|
{
|
||||||
if (gender == 0)
|
if (gender == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -38,7 +37,6 @@ public unsafe class RspBustHook : FastHook<RspBustHook.Delegate>, IDisposable
|
||||||
if (bodyType < 2 && _metaState.RspCollection.TryPeek(out var collection) && collection is { Valid: true, ModCollection.MetaCache: { } cache })
|
if (bodyType < 2 && _metaState.RspCollection.TryPeek(out var collection) && collection is { Valid: true, ModCollection.MetaCache: { } cache })
|
||||||
{
|
{
|
||||||
var bustScale = bustSize / 100f;
|
var bustScale = bustSize / 100f;
|
||||||
var clan = (SubRace)(((int)race - 1) * 2 + 1 + isSecondSubRace);
|
|
||||||
var ptr = CmpFile.GetDefaults(_metaFileManager, clan, RspAttribute.BustMinX);
|
var ptr = CmpFile.GetDefaults(_metaFileManager, clan, RspAttribute.BustMinX);
|
||||||
storage[0] = GetValue(0, RspAttribute.BustMinX, RspAttribute.BustMaxX);
|
storage[0] = GetValue(0, RspAttribute.BustMinX, RspAttribute.BustMaxX);
|
||||||
storage[1] = GetValue(1, RspAttribute.BustMinY, RspAttribute.BustMaxY);
|
storage[1] = GetValue(1, RspAttribute.BustMinY, RspAttribute.BustMaxY);
|
||||||
|
|
@ -58,11 +56,11 @@ public unsafe class RspBustHook : FastHook<RspBustHook.Delegate>, IDisposable
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ret = Task.Result.Original(cmpResource, storage, race, gender, isSecondSubRace, bodyType, bustSize);
|
ret = Task.Result.Original(cmpResource, storage, clan, gender, bodyType, bustSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
Penumbra.Log.Excessive(
|
Penumbra.Log.Excessive(
|
||||||
$"[GetRspBust] Invoked on 0x{cmpResource:X} with {race}, {(Gender)(gender + 1)}, {isSecondSubRace == 1}, {bodyType}, {bustSize}, returned {storage[0]}, {storage[1]}, {storage[2]}.");
|
$"[GetRspBust] Invoked on 0x{cmpResource:X} with {clan}, {(Gender)(gender + 1)}, {bodyType}, {bustSize}, returned {storage[0]}, {storage[1]}, {storage[2]}.");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ namespace Penumbra.Interop.Hooks.Meta;
|
||||||
|
|
||||||
public class RspHeightHook : FastHook<RspHeightHook.Delegate>, IDisposable
|
public class RspHeightHook : FastHook<RspHeightHook.Delegate>, IDisposable
|
||||||
{
|
{
|
||||||
public delegate float Delegate(nint cmpResource, Race clan, byte gender, byte isSecondSubRace, byte bodyType, byte height);
|
public delegate float Delegate(nint cmpResource, SubRace clan, byte gender, byte bodyType, byte height);
|
||||||
|
|
||||||
private readonly MetaState _metaState;
|
private readonly MetaState _metaState;
|
||||||
private readonly MetaFileManager _metaFileManager;
|
private readonly MetaFileManager _metaFileManager;
|
||||||
|
|
@ -23,7 +23,7 @@ public class RspHeightHook : FastHook<RspHeightHook.Delegate>, IDisposable
|
||||||
_metaState.Config.ModsEnabled += Toggle;
|
_metaState.Config.ModsEnabled += Toggle;
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe float Detour(nint cmpResource, Race race, byte gender, byte isSecondSubRace, byte bodyType, byte height)
|
private unsafe float Detour(nint cmpResource, SubRace clan, byte gender, byte bodyType, byte height)
|
||||||
{
|
{
|
||||||
float scale;
|
float scale;
|
||||||
if (bodyType < 2
|
if (bodyType < 2
|
||||||
|
|
@ -36,7 +36,6 @@ public class RspHeightHook : FastHook<RspHeightHook.Delegate>, IDisposable
|
||||||
if (height > 100)
|
if (height > 100)
|
||||||
height = 0;
|
height = 0;
|
||||||
|
|
||||||
var clan = (SubRace)(((int)race - 1) * 2 + 1 + isSecondSubRace);
|
|
||||||
var (minIdent, maxIdent) = gender == 0
|
var (minIdent, maxIdent) = gender == 0
|
||||||
? (new RspIdentifier(clan, RspAttribute.MaleMinSize), new RspIdentifier(clan, RspAttribute.MaleMaxSize))
|
? (new RspIdentifier(clan, RspAttribute.MaleMinSize), new RspIdentifier(clan, RspAttribute.MaleMaxSize))
|
||||||
: (new RspIdentifier(clan, RspAttribute.FemaleMinSize), new RspIdentifier(clan, RspAttribute.FemaleMaxSize));
|
: (new RspIdentifier(clan, RspAttribute.FemaleMinSize), new RspIdentifier(clan, RspAttribute.FemaleMaxSize));
|
||||||
|
|
@ -68,11 +67,11 @@ public class RspHeightHook : FastHook<RspHeightHook.Delegate>, IDisposable
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
scale = Task.Result.Original(cmpResource, race, gender, isSecondSubRace, bodyType, height);
|
scale = Task.Result.Original(cmpResource, clan, gender, bodyType, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
Penumbra.Log.Excessive(
|
Penumbra.Log.Excessive(
|
||||||
$"[GetRspHeight] Invoked on 0x{cmpResource:X} with {race}, {(Gender)(gender + 1)}, {isSecondSubRace == 1}, {bodyType}, {height}, returned {scale}.");
|
$"[GetRspHeight] Invoked on 0x{cmpResource:X} with {clan}, {(Gender)(gender + 1)}, {bodyType}, {height}, returned {scale}.");
|
||||||
return scale;
|
return scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ public sealed unsafe class CopyCharacter : EventWrapperPtr<Character, Character,
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="PathResolving.CutsceneService"/>
|
/// <seealso cref="PathResolving.CutsceneService.OnCharacterCopy"/>
|
||||||
CutsceneService = 0,
|
CutsceneService = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -38,8 +38,7 @@ public sealed unsafe class CopyCharacter : EventWrapperPtr<Character, Character,
|
||||||
|
|
||||||
private ulong Detour(CharacterSetupContainer* target, Character* source, uint unk)
|
private ulong Detour(CharacterSetupContainer* target, Character* source, uint unk)
|
||||||
{
|
{
|
||||||
// TODO: update when CS updated.
|
var character = target->OwnerObject;
|
||||||
var character = ((Character**)target)[1];
|
|
||||||
Penumbra.Log.Verbose($"[{Name}] Triggered with target: 0x{(nint)target:X}, source : 0x{(nint)source:X} unk: {unk}.");
|
Penumbra.Log.Verbose($"[{Name}] Triggered with target: 0x{(nint)target:X}, source : 0x{(nint)source:X} unk: {unk}.");
|
||||||
Invoke(character, source);
|
Invoke(character, source);
|
||||||
return _task.Result.Original(target, source, unk);
|
return _task.Result.Original(target, source, unk);
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ public sealed unsafe class CreateCharacterBase : EventWrapperPtr<ModelCharaId, C
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="PathResolving.MetaState"/>
|
/// <seealso cref="PathResolving.MetaState.OnCreatingCharacterBase"/>
|
||||||
MetaState = 0,
|
MetaState = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,10 +64,10 @@ public sealed unsafe class CreateCharacterBase : EventWrapperPtr<ModelCharaId, C
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="PathResolving.DrawObjectState"/>
|
/// <seealso cref="PathResolving.DrawObjectState.OnCharacterBaseCreated"/>
|
||||||
DrawObjectState = 0,
|
DrawObjectState = 0,
|
||||||
|
|
||||||
/// <seealso cref="PathResolving.MetaState"/>
|
/// <seealso cref="PathResolving.MetaState.OnCharacterBaseCreated"/>
|
||||||
MetaState = 0,
|
MetaState = 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,16 @@ namespace Penumbra.Interop.Structs;
|
||||||
public unsafe struct CharacterUtilityData
|
public unsafe struct CharacterUtilityData
|
||||||
{
|
{
|
||||||
public const int IndexHumanPbd = 63;
|
public const int IndexHumanPbd = 63;
|
||||||
public const int IndexTransparentTex = 72;
|
public const int IndexTransparentTex = 79;
|
||||||
public const int IndexDecalTex = 73;
|
public const int IndexDecalTex = 80;
|
||||||
public const int IndexSkinShpk = 76;
|
public const int IndexSkinShpk = 83;
|
||||||
|
|
||||||
public static readonly MetaIndex[] EqdpIndices = Enum.GetNames<MetaIndex>()
|
public static readonly MetaIndex[] EqdpIndices = Enum.GetNames<MetaIndex>()
|
||||||
.Zip(Enum.GetValues<MetaIndex>())
|
.Zip(Enum.GetValues<MetaIndex>())
|
||||||
.Where(n => n.First.StartsWith("Eqdp"))
|
.Where(n => n.First.StartsWith("Eqdp"))
|
||||||
.Select(n => n.Second).ToArray();
|
.Select(n => n.Second).ToArray();
|
||||||
|
|
||||||
public const int TotalNumResources = 87;
|
public const int TotalNumResources = 89;
|
||||||
|
|
||||||
/// <summary> Obtain the index for the eqdp file corresponding to the given race code and accessory. </summary>
|
/// <summary> Obtain the index for the eqdp file corresponding to the given race code and accessory. </summary>
|
||||||
public static MetaIndex EqdpIdx(GenderRace raceCode, bool accessory)
|
public static MetaIndex EqdpIdx(GenderRace raceCode, bool accessory)
|
||||||
|
|
@ -36,7 +36,7 @@ public unsafe struct CharacterUtilityData
|
||||||
1301 => accessory ? MetaIndex.Eqdp1301Acc : MetaIndex.Eqdp1301,
|
1301 => accessory ? MetaIndex.Eqdp1301Acc : MetaIndex.Eqdp1301,
|
||||||
1401 => accessory ? MetaIndex.Eqdp1401Acc : MetaIndex.Eqdp1401,
|
1401 => accessory ? MetaIndex.Eqdp1401Acc : MetaIndex.Eqdp1401,
|
||||||
1501 => accessory ? MetaIndex.Eqdp1501Acc : MetaIndex.Eqdp1501,
|
1501 => accessory ? MetaIndex.Eqdp1501Acc : MetaIndex.Eqdp1501,
|
||||||
//1601 => accessory ? MetaIndex.Eqdp1601Acc : MetaIndex.Eqdp1601, Female Hrothgar
|
1601 => accessory ? MetaIndex.Eqdp1601Acc : MetaIndex.Eqdp1601,
|
||||||
1701 => accessory ? MetaIndex.Eqdp1701Acc : MetaIndex.Eqdp1701,
|
1701 => accessory ? MetaIndex.Eqdp1701Acc : MetaIndex.Eqdp1701,
|
||||||
1801 => accessory ? MetaIndex.Eqdp1801Acc : MetaIndex.Eqdp1801,
|
1801 => accessory ? MetaIndex.Eqdp1801Acc : MetaIndex.Eqdp1801,
|
||||||
0104 => accessory ? MetaIndex.Eqdp0104Acc : MetaIndex.Eqdp0104,
|
0104 => accessory ? MetaIndex.Eqdp0104Acc : MetaIndex.Eqdp0104,
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ namespace Penumbra.Interop.Structs;
|
||||||
public enum MetaIndex : int
|
public enum MetaIndex : int
|
||||||
{
|
{
|
||||||
Eqp = 0,
|
Eqp = 0,
|
||||||
|
Evp = 1,
|
||||||
Gmp = 2,
|
Gmp = 2,
|
||||||
|
|
||||||
Eqdp0101 = 3,
|
Eqdp0101 = 3,
|
||||||
|
|
@ -21,9 +22,8 @@ public enum MetaIndex : int
|
||||||
Eqdp1301,
|
Eqdp1301,
|
||||||
Eqdp1401,
|
Eqdp1401,
|
||||||
Eqdp1501,
|
Eqdp1501,
|
||||||
|
Eqdp1601,
|
||||||
//Eqdp1601, // TODO: female Hrothgar
|
Eqdp1701,
|
||||||
Eqdp1701 = Eqdp1501 + 2,
|
|
||||||
Eqdp1801,
|
Eqdp1801,
|
||||||
Eqdp0104,
|
Eqdp0104,
|
||||||
Eqdp0204,
|
Eqdp0204,
|
||||||
|
|
@ -51,9 +51,8 @@ public enum MetaIndex : int
|
||||||
Eqdp1301Acc,
|
Eqdp1301Acc,
|
||||||
Eqdp1401Acc,
|
Eqdp1401Acc,
|
||||||
Eqdp1501Acc,
|
Eqdp1501Acc,
|
||||||
|
Eqdp1601Acc,
|
||||||
//Eqdp1601Acc, // TODO: female Hrothgar
|
Eqdp1701Acc,
|
||||||
Eqdp1701Acc = Eqdp1501Acc + 2,
|
|
||||||
Eqdp1801Acc,
|
Eqdp1801Acc,
|
||||||
Eqdp0104Acc,
|
Eqdp0104Acc,
|
||||||
Eqdp0204Acc,
|
Eqdp0204Acc,
|
||||||
|
|
@ -66,7 +65,7 @@ public enum MetaIndex : int
|
||||||
Eqdp9104Acc,
|
Eqdp9104Acc,
|
||||||
Eqdp9204Acc,
|
Eqdp9204Acc,
|
||||||
|
|
||||||
HumanCmp = 64,
|
HumanCmp = 71,
|
||||||
FaceEst,
|
FaceEst,
|
||||||
HairEst,
|
HairEst,
|
||||||
HeadEst,
|
HeadEst,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue