Skip to content

Commit 467ab3b

Browse files
committed
Initial visualization of MorphTarget
- Morphing vertex positions, but not normals/tangents yet - Fixed loading of moprh targets: added CMorphTarget container for CMorphLod - UE4 does conversion in USkeletalMesh4::PostLoad(), otherwise conversion may be performed before morph is serialized
1 parent 8003d18 commit 467ab3b

File tree

10 files changed

+114
-48
lines changed

10 files changed

+114
-48
lines changed

MeshInstance/MeshInstance.h

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,8 @@ class CSkelMeshInstance : public CMeshInstance
137137
CSkeletalMesh *pMesh;
138138

139139
// mesh state
140-
int LodNum;
140+
int LodIndex;
141+
int MorphIndex;
141142
int UVIndex;
142143
int RotationMode; // EAnimRotationOnly
143144

@@ -148,7 +149,6 @@ class CSkelMeshInstance : public CMeshInstance
148149
void SetAnim(const CAnimSet *Anim);
149150

150151
void ClearSkelAnims();
151-
//?? void StopAnimating(bool ClearAllButBase);
152152
virtual void Draw(unsigned flags = 0);
153153

154154
void DumpBones();
@@ -158,7 +158,6 @@ class CSkelMeshInstance : public CMeshInstance
158158

159159
// skeleton configuration
160160
void SetBoneScale(const char *BoneName, float scale = 1.0f);
161-
//!! SetBone[Direction|Location|Rotation]()
162161

163162
// animation control
164163
void PlayAnim(const char *AnimName, float Rate = 1, float TweenTime = 0, int Channel = 0)
@@ -217,10 +216,6 @@ class CSkelMeshInstance : public CMeshInstance
217216
{
218217
GetStage(Channel).SecondaryBlend = BlendAlpha;
219218
}
220-
//?? - AnimBlendToAlpha() - animate BlendAlpha coefficient
221-
//?? - functions to smoothly replace current animation with another in a fixed time
222-
//?? (run new anim as secondary, ramp alpha from 0 to 1, and when blend becomes 1.0f
223-
//?? - replace 1st anim with 2nd, and clear 2nd
224219

225220
// animation enumeration
226221
int GetAnimCount() const;
@@ -235,13 +230,18 @@ class CSkelMeshInstance : public CMeshInstance
235230
CVec3 GetMeshOrigin() const;
236231

237232
protected:
238-
const CAnimSet *Animation;
233+
const CAnimSet* Animation;
239234
// mesh data
240-
void *DataBlock;// all following data is resided here, aligned to 16 bytes
241-
struct CMeshBoneData *BoneData;
242-
struct CSkinVert *Skinned; // soft-skinned vertices
243-
CVec3 *InfColors; // debug: color-by-influence for vertices
244-
int LastLodNum; // used to detect requirement to rebuild Wedges[]
235+
void* DataBlock;
236+
237+
// all of the following data is resides inside "DataBlock", aligned to 16 bytes
238+
struct CMeshBoneData* BoneData;
239+
struct CSkinVert* Skinned; // soft-skinned vertices
240+
struct CSkelMeshVertex* MorphedVerts;
241+
242+
CVec3* InfColors; // debug: color-by-influence for vertices
243+
int LastLodIndex; // used to detect requirement to rebuild InfColors[]
244+
int LastMorphIndex; // used to detect requirement to rebuild MorphedVerts[]
245245
// animation state
246246
CAnimChan Channels[MAX_SKELANIMCHANNELS];
247247
int MaxAnimChannel;
@@ -262,6 +262,7 @@ class CSkelMeshInstance : public CMeshInstance
262262
void PlayAnimInternal(const char *AnimName, float Rate, float TweenTime, int Channel, bool Looped);
263263
void UpdateSkeleton();
264264
void BuildInfColors();
265+
bool BuildMorphVerts();
265266
};
266267

267268

MeshInstance/SkelMeshInstance.cpp

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,12 @@ const char *CSkelMeshInstance::GetAnimName(int Index) const
8787
-----------------------------------------------------------------------------*/
8888

8989
CSkelMeshInstance::CSkelMeshInstance()
90-
: LodNum(0)
90+
: LodIndex(0)
91+
, MorphIndex(-1)
9192
, UVIndex(0)
9293
, RotationMode(EARO_AnimSet)
93-
, LastLodNum(-2) // differs from LodNum and from all other values
94+
, LastLodIndex(-2) // differs from LodNum and from all other values
95+
, LastMorphIndex(-1)
9496
, MaxAnimChannel(-1)
9597
, Animation(NULL)
9698
, DataBlock(NULL)
@@ -202,12 +204,15 @@ void CSkelMeshInstance::SetMesh(CSkeletalMesh *Mesh)
202204
InfColors = NULL;
203205
}
204206
// allocate data arrays in a single block
205-
int DataSize = sizeof(CMeshBoneData) * NumBones + sizeof(CSkinVert) * NumVerts;
207+
int NumMorphVerts = Mesh->Morphs.Num() ? NumVerts : 0;
208+
int DataSize = sizeof(CMeshBoneData) * NumBones + sizeof(CSkinVert) * NumVerts + sizeof(CSkelMeshVertex) * NumMorphVerts;
206209
DataBlock = appMalloc(DataSize, 16);
207210
BoneData = (CMeshBoneData*)DataBlock;
208211
Skinned = (CSkinVert*)(BoneData + NumBones);
212+
MorphedVerts = Mesh->Morphs.Num() ? (CSkelMeshVertex*)(Skinned + NumVerts) : NULL;
209213

210-
LastLodNum = -2;
214+
LastLodIndex = -2;
215+
LastMorphIndex = -1;
211216

212217
CMeshBoneData *data;
213218
for (i = 0, data = BoneData; i < NumBones; i++, data++)
@@ -1003,14 +1008,16 @@ void CSkelMeshInstance::SkinMeshVerts()
10031008
{
10041009
guard(CSkelMeshInstance::SkinMeshVerts);
10051010

1006-
const CSkelMeshLod& Mesh = pMesh->Lods[LodNum];
1011+
const CSkelMeshLod& Mesh = pMesh->Lods[LodIndex];
10071012
int NumVerts = Mesh.NumVerts;
10081013

10091014
memset(Skinned, 0, sizeof(CSkinVert) * NumVerts);
10101015

1016+
const CSkelMeshVertex* MeshVerts = BuildMorphVerts() ? MorphedVerts : Mesh.Verts;
1017+
10111018
for (int i = 0; i < NumVerts; i++)
10121019
{
1013-
const CSkelMeshVertex &V = Mesh.Verts[i];
1020+
const CSkelMeshVertex &V = MeshVerts[i];
10141021
CSkinVert &D = Skinned[i];
10151022

10161023
CVec4 UnpackedWeights;
@@ -1102,7 +1109,7 @@ void CSkelMeshInstance::DrawMesh(unsigned flags)
11021109

11031110
if (!pMesh->Lods.Num()) return;
11041111

1105-
/*const*/ CSkelMeshLod& Mesh = pMesh->Lods[LodNum]; //?? not 'const' because of BuildTangents(); change this?
1112+
/*const*/ CSkelMeshLod& Mesh = pMesh->Lods[LodIndex]; //?? not 'const' because of BuildTangents(); change this?
11061113
int NumSections = Mesh.Sections.Num();
11071114
int NumVerts = Mesh.NumVerts;
11081115
if (!NumSections || !NumVerts) return;
@@ -1356,7 +1363,7 @@ void CSkelMeshInstance::Draw(unsigned flags)
13561363
guard(CSkelMeshInstance::Draw);
13571364

13581365
// switch LOD model
1359-
if (LodNum != LastLodNum)
1366+
if (LodIndex != LastLodIndex)
13601367
{
13611368
// LOD has been changed
13621369

@@ -1365,7 +1372,7 @@ void CSkelMeshInstance::Draw(unsigned flags)
13651372
delete[] InfColors;
13661373
InfColors = NULL;
13671374
}
1368-
LastLodNum = LodNum;
1375+
LastLodIndex = LodIndex;
13691376
}
13701377
// draw ...
13711378
DrawMesh(flags);
@@ -1380,7 +1387,7 @@ void CSkelMeshInstance::BuildInfColors()
13801387

13811388
int i;
13821389

1383-
const CSkelMeshLod &Lod = pMesh->Lods[LodNum];
1390+
const CSkelMeshLod &Lod = pMesh->Lods[LodIndex];
13841391

13851392
if (InfColors) delete[] InfColors;
13861393
InfColors = new CVec3[Lod.NumVerts];
@@ -1407,4 +1414,46 @@ void CSkelMeshInstance::BuildInfColors()
14071414
unguard;
14081415
}
14091416

1417+
1418+
bool CSkelMeshInstance::BuildMorphVerts()
1419+
{
1420+
guard(CSkelMeshInstance::BuildMorphVerts);
1421+
1422+
if (MorphIndex < 0)
1423+
{
1424+
// Morph is inactive
1425+
return false;
1426+
}
1427+
1428+
if (LodIndex >= pMesh->Morphs[MorphIndex]->Lods.Num())
1429+
{
1430+
// No morph information for this LOD
1431+
return false;
1432+
}
1433+
1434+
if (LastMorphIndex == MorphIndex)
1435+
{
1436+
// Already built
1437+
return true;
1438+
}
1439+
LastMorphIndex = MorphIndex;
1440+
1441+
const CSkelMeshLod& Lod = pMesh->Lods[LodIndex];
1442+
const TArray<CMorphVertex>& Deltas = pMesh->Morphs[MorphIndex]->Lods[LodIndex].Vertices;
1443+
1444+
// Copy unmodified vertices
1445+
memcpy(MorphedVerts, Lod.Verts, Lod.NumVerts * sizeof(CSkelMeshVertex));
1446+
1447+
// Apply delta
1448+
for (const CMorphVertex& Delta : Deltas)
1449+
{
1450+
CSkelMeshVertex& V = MorphedVerts[Delta.VertexIndex];
1451+
VectorAdd(V.Position, Delta.PositionDelta, V.Position);
1452+
}
1453+
1454+
return true;
1455+
1456+
unguard;
1457+
}
1458+
14101459
#endif // RENDERING

Unreal/SkeletalMesh.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,15 @@ struct CMorphVertex
113113

114114
struct CMorphLod
115115
{
116-
FString Name;
117116
TArray<CMorphVertex> Vertices;
118117
};
119118

119+
struct CMorphTarget
120+
{
121+
FString Name;
122+
TArray<CMorphLod> Lods;
123+
};
124+
120125
struct CSkelMeshSocket
121126
{
122127
FName Name;
@@ -143,7 +148,7 @@ class CSkeletalMesh
143148
FRotator RotOrigin;
144149
TArray<CSkelMeshBone> RefSkeleton;
145150
TArray<CSkelMeshLod> Lods;
146-
TArray<CMorphLod*> Morphs;
151+
TArray<CMorphTarget*> Morphs;
147152
TArray<CSkelMeshSocket> Sockets; //?? common (UE4 has StaticMesh sockets)
148153
const class CAnimSet* Anim;
149154

@@ -154,7 +159,7 @@ class CSkeletalMesh
154159

155160
~CSkeletalMesh()
156161
{
157-
for (CMorphLod* morph : Morphs)
162+
for (CMorphTarget* morph : Morphs)
158163
{
159164
delete morph;
160165
}

Unreal/UnMesh.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ void UnpackNormals(const FPackedNormal SrcNormal[3], CMeshVertex &V);
2020
//?? move these declarations outside
2121
class CSkeletalMesh;
2222
struct CSkelMeshLod;
23-
struct CMorphLod;
23+
struct CMorphTarget;
2424
class CAnimSet;
2525
class CAnimSequence;
2626
class CStaticMesh;

Unreal/UnMesh3.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,20 +96,22 @@ void FMorphTargetLODModel::Serialize3(FArchive& Ar, FMorphTargetLODModel& Lod)
9696
unguard;
9797
}
9898

99-
CMorphLod* UMorphTarget::ConvertMorph()
99+
CMorphTarget* UMorphTarget::ConvertMorph()
100100
{
101-
CMorphLod* morph = new CMorphLod;
101+
CMorphTarget* morph = new CMorphTarget;
102102
morph->Name = Name;
103103

104104
for (int lodIndex = 0; lodIndex < MorphLODModels.Num(); lodIndex++)
105105
{
106106
const FMorphTargetLODModel& SrcLod = MorphLODModels[lodIndex];
107+
CMorphLod* Lod = new (morph->Lods) CMorphLod;
108+
107109
int NumVerts = SrcLod.Vertices.Num();
108-
morph->Vertices.AddDefaulted(NumVerts);
110+
Lod->Vertices.AddDefaulted(NumVerts);
109111
for (int i = 0; i < NumVerts; i++)
110112
{
111113
const FMorphTargetDelta& SV = SrcLod.Vertices[i];
112-
CMorphVertex& V = morph->Vertices[i];
114+
CMorphVertex& V = Lod->Vertices[i];
113115
V.PositionDelta = CVT(SV.PositionDelta);
114116
V.NormalDelta = CVT(SV.TangentZDelta);
115117
V.VertexIndex = SV.SourceIdx;

Unreal/UnMesh3.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class UMorphTarget : public UObject
7575
Serialize3(Ar);
7676
}
7777

78-
CMorphLod* ConvertMorph();
78+
CMorphTarget* ConvertMorph();
7979

8080
#if UNREAL4
8181
BEGIN_PROP_TABLE

Unreal/UnMesh4.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,6 +1546,21 @@ void USkeletalMesh4::Serialize(FArchive &Ar)
15461546
unguard;
15471547
}
15481548

1549+
void USkeletalMesh4::PostLoad()
1550+
{
1551+
guard(USkeletalMesh4::PostLoad);
1552+
1553+
assert(ConvertedMesh);
1554+
for (int i = 0; i < MorphTargets.Num(); i++)
1555+
{
1556+
guard(ConvertMorph)
1557+
if (MorphTargets[i])
1558+
ConvertedMesh->Morphs.Add(MorphTargets[i]->ConvertMorph());
1559+
unguardf("%d/%d", i, MorphTargets.Num());
1560+
}
1561+
1562+
unguard;
1563+
}
15491564

15501565
void USkeletalMesh4::ConvertMesh()
15511566
{
@@ -1753,14 +1768,6 @@ void USkeletalMesh4::ConvertMesh()
17531768
}
17541769
unguard; // ProcessSkeleton
17551770

1756-
for (int i = 0; i < MorphTargets.Num(); i++)
1757-
{
1758-
guard(ConvertMorph)
1759-
if (MorphTargets[i])
1760-
Mesh->Morphs.Add(MorphTargets[i]->ConvertMorph());
1761-
unguardf("%d/%d", i, MorphTargets.Num());
1762-
}
1763-
17641771
Mesh->FinalizeMesh();
17651772

17661773
unguard;

Unreal/UnMesh4.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ class USkeletalMesh4 : public UObject
222222
virtual ~USkeletalMesh4();
223223

224224
virtual void Serialize(FArchive &Ar);
225+
virtual void PostLoad();
225226

226227
protected:
227228
void ConvertMesh();

Viewers/ObjectViewer.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,6 @@ class CSkelMeshViewer : public CMeshViewer
153153
{
154154
public:
155155
int AnimIndex;
156-
int MorphIndex;
157156
bool IsFollowingMesh;
158157
int ShowSkel; // 0 - mesh, 1 - mesh+skel, 2 - skel only
159158
bool ShowLabels;

0 commit comments

Comments
 (0)