summaryrefslogtreecommitdiff
path: root/Runtime/Filters/Mesh/MeshBlendShape.h
blob: d4d0f41c29681f75e1a249327bcd3fc1c23a333b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#ifndef MESHBLENDSHAPES_H
#define MESHBLENDSHAPES_H

#include "Runtime/Geometry/AABB.h"
#include "Runtime/Math/Vector3.h"
#include "Runtime/Serialize/SerializeUtility.h"
#include "Runtime/Utilities/dynamic_array.h"
#include "Runtime/Containers/ConstantString.h"
#include "Runtime/Containers/ConstantStringSerialization.h"

typedef UInt32 BindingHash;

struct BlendShapeVertex
{
	// vertex, normal & tangent are stored as deltas
	Vector3f  vertex;
	Vector3f  normal;
	Vector3f  tangent;
	UInt32    index;

	BlendShapeVertex() : vertex(Vector3f::zero), normal(Vector3f::zero), tangent(Vector3f::zero), index(0) {}

	DECLARE_SERIALIZE_NO_PPTR (BlendShapeVertex)
};
typedef dynamic_array<BlendShapeVertex> BlendShapeVertices;

struct BlendShapeChannel
{
	ConstantString name;
	BindingHash    nameHash;
	
	int            frameIndex;
	int            frameCount;
	
	DECLARE_SERIALIZE_NO_PPTR(MeshBlendShapeChannel)
};

struct BlendShape
{
	BlendShape() : firstVertex(0), vertexCount(0), hasNormals(false), hasTangents(false) {}
	
	UInt32   firstVertex;
	UInt32   vertexCount;

	bool     hasNormals;
	bool     hasTangents;

	
	///@TODO: MOve
	// updates hasNormals and hasTangents based on data in vertices
	void UpdateFlags(const BlendShapeVertices& sharedSparceVertices);

	DECLARE_SERIALIZE_NO_PPTR (MeshBlendShape)
};

struct BlendShapeData
{
	BlendShapeVertices                 vertices;
	dynamic_array<BlendShape>          shapes;
	std::vector<BlendShapeChannel>     channels;
	dynamic_array<float>               fullWeights;
	
	DECLARE_SERIALIZE_NO_PPTR(BlendShapeData)
};


// Convert between blendshape name and index
const char* GetChannelName (const BlendShapeData& data, int index);
inline size_t GetBlendShapeChannelCount (const BlendShapeData& data) { return data.channels.size(); }
int GetChannelIndex (const BlendShapeData& data, const char* name);
int GetChannelIndex (const BlendShapeData& data, BindingHash name);

// data is passed as non-sparce arrays, i.e. deltaVertices.size() has to be the same as vertex count on the Mesh
void SetBlendShapeVertices(const std::vector<Vector3f>& deltaVertices, const std::vector<Vector3f>& deltaNormals, const std::vector<Vector3f>& deltaTangents, BlendShapeVertices& sharedSparceVertices, BlendShape& frame);
void InitializeChannel (const UnityStr& inName, int frameIndex, int frameCount, BlendShapeChannel& channel);
void ClearBlendShapes (BlendShapeData& data);

template<class TransferFunc>
void BlendShape::Transfer (TransferFunc& transfer)
{
	TRANSFER(firstVertex);
	TRANSFER(vertexCount);
	TRANSFER(hasNormals);
	TRANSFER(hasTangents);
	transfer.Align();
}

template<class TransferFunc>
void BlendShapeData::Transfer (TransferFunc& transfer)
{
	TRANSFER (vertices);
	TRANSFER (shapes);
	TRANSFER (channels);
	TRANSFER (fullWeights);
}

template<class TransferFunc>
void BlendShapeVertex::Transfer (TransferFunc& transfer)
{
	TRANSFER(vertex);
	TRANSFER(normal);
	TRANSFER(tangent);
	TRANSFER(index);
}

template<class TransferFunc>
void BlendShapeChannel::Transfer (TransferFunc& transfer)
{
	TransferConstantString (name, "name", kNoTransferFlags, kMemGeometry, transfer);
	TRANSFER (nameHash);
	TRANSFER (frameIndex);
	TRANSFER (frameCount);
}

#endif