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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
|
#ifndef SKINNEDMESHFILTER_H
#define SKINNEDMESHFILTER_H
#include "Runtime/Filters/Renderer.h"
#include "Runtime/Graphics/Transform.h"
#include "Runtime/Filters/Mesh/Mesh.h"
#include "Runtime/Geometry/AABB.h"
#include "Configuration/UnityConfigure.h"
#include "Runtime/GfxDevice/GfxDeviceTypes.h"
#include "Runtime/Utilities/LinkedList.h"
#include "Runtime/Utilities/dynamic_array.h"
#include "Runtime/GfxDevice/GPUSkinningInfo.h"
#include "Runtime/Modules/ExportModules.h"
#include "Runtime/BaseClasses/NamedObject.h"
class Mesh;
class Animation;
class VBO;
namespace Unity { class SkinnedCloth; }
struct SkinMeshInfo;
struct CalculateSkinMatricesTask;
class EXPORT_COREMODULE SkinnedMeshRenderer : public Renderer
{
PPtr<Mesh> m_Mesh;
Mesh* m_CachedMesh;
// Bones for non-optimized mode
dynamic_array<PPtr<Transform> > m_Bones;
PPtr<Transform> m_RootBone;
// Bones for optimized mode
dynamic_array<UInt16> m_SkeletonIndices;
Unity::Component* m_CachedAnimator;
UInt32 m_CachedBlendShapeCount;
dynamic_array<float> m_BlendShapeWeights;
AABB m_AABB;
int m_Quality; ///< enum { Auto = 0, 1 Bone = 1, 2 Bones = 2, 4 Bones = 4 } Number of bones to use per vertex during skinning.
bool m_UpdateWhenOffscreen;///< Unity will calculate an accurate bounding volume representation every frame.
bool m_DirtyAABB;
bool m_Visible;
VBO* m_VBO;
dynamic_array<UInt8> m_SkinnedVertices;
UInt32 m_ChannelsInVBO;
bool m_SourceMeshDirty;
bool m_UpdateBeforeRendering;
SkinnedCloth* m_Cloth;
GPUSkinningInfo* m_MemExportInfo;
ListNode<Object> m_MeshNode;
#if UNITY_EDITOR
float m_CachedSurfaceArea;
#endif
#if UNITY_EDITOR || SUPPORT_REPRODUCE_LOG
PPtr<Animation> m_DeprecatedDisableAnimationWhenOffscreen;
#endif
ListNode<SkinnedMeshRenderer> m_SkinNode;
void DirtyAndClearCache ();
public:
int GetBonesPerVertexCount ();
REGISTER_DERIVED_CLASS (SkinnedMeshRenderer, Renderer)
DECLARE_OBJECT_SERIALIZE (SkinnedMeshRenderer)
SkinnedMeshRenderer (MemLabelId label, ObjectCreationMode mode);
// ~SkinnedMeshRenderer (); declared-by-macro
virtual void Reset ();
static void InitializeClass ();
static void CleanupClass ();
virtual void AwakeFromLoad(AwakeFromLoadMode mode);
virtual void Deactivate (DeactivateOperation operation);
void Setup (Mesh* lodmesh, const dynamic_array<PPtr<Transform> >& state);
enum SkinningFlags
{
SF_None = 0,
SF_NoUpdateVBO = 1 << 0,
SF_ReadbackBuffer = 1 << 1,
SF_ClothPlaying = 1 << 2,
SF_AllowMemExport = 1 << 3,
};
enum UpdateType
{
kUpdateCloth,
kUpdateNonCloth
};
bool PrepareSkinCommon( UInt32 requiredChannels, int flags, SkinMeshInfo& skin, CalculateSkinMatricesTask* calcSkinMatricesTask=NULL );
bool PrepareSkinPS3( UInt32 requiredChannels, int flags, SkinMeshInfo& skin, CalculateSkinMatricesTask* calcSkinMatricesTask=NULL );
bool PrepareSkinGPU( UInt32 requiredChannels, int flags, SkinMeshInfo& skin, CalculateSkinMatricesTask* calcSkinMatricesTask=NULL );
bool PrepareSkin( UInt32 requiredChannels, int flags, SkinMeshInfo& skin, CalculateSkinMatricesTask* calcSkinMatricesTask=NULL );
bool SkinMesh( SkinMeshInfo& skin, bool lastMemExportThisFrame, UInt32 cpuFence, int flags );
bool SkinMeshImmediate( UInt32 requiredChannels );
bool CalculateAnimatedPoses (Matrix4x4f* poses, size_t size);
#if UNITY_EDITOR
float GetCachedSurfaceArea ();
bool GetSkinnedVerticesAndNormals (dynamic_array<Vector3f>* vertices, dynamic_array<Vector3f>* normals);
bool CalculateVertexBasedBounds (const Matrix4x4f* poseMatrices, MinMaxAABB& output);
#endif
void SetUpdateWhenOffscreen (bool onlyIfVisible);
bool GetUpdateWhenOffscreen () { return m_UpdateWhenOffscreen; }
void SetDisableAnimationWhenOffscreen (Animation* animation);
Animation* GetDisableAnimationWhenOffscreen ();
const dynamic_array<PPtr<Transform> >& GetBones () const { return m_Bones; }
void SetBones (const dynamic_array<PPtr<Transform> >& bones);
bool IsOptimized () { return m_Bones.size()==0 && GetBindposeCount()>0; }
// Before invoking this function, please make sure the SkinnedMeshRenderer is in optimized mode.
const dynamic_array<UInt16>& GetSkeletonIndices();
int GetBindposeCount () const;
int GetBoneCount () const { return m_Bones.size(); }
void SetQuality (int quality);
int GetQuality () { return m_Quality; }
void SetMesh (Mesh* mesh);
Mesh* GetMesh ();
void SetCloth (SkinnedCloth *value) { m_Cloth = value; }
void SetRootBone (Transform* rootBone) { m_RootBone = rootBone; }
Transform* GetRootBone () { return m_RootBone; }
Transform& GetActualRootBone ();
static void UpdateAllSkinnedMeshes(UpdateType updateType, dynamic_array<SkinnedMeshRenderer*>* outMeshes = NULL);
static void UploadSkinnedClothes(const dynamic_array<SkinnedMeshRenderer*>& skinnedMeshes);
void ReadSkinningDataForCloth(const SkinMeshInfo& skin);
#if UNITY_EDITOR
void UpdateClothDataForEditing(const SkinMeshInfo& skin);
#endif
/// Handlers so we only skin when somebody sees us.
virtual void BecameVisible ();
virtual void BecameInvisible ();
#if UNITY_EDITOR || SUPPORT_REPRODUCE_LOG
void HandleOldSkinnedFilter ();
#endif
virtual void UpdateTransformInfo();
void SetLocalAABB(const AABB& bounds);
void GetSkinnedMeshLocalAABB(AABB& bounds);
void DidDeleteMesh ();
void DidModifyMesh ();
void UpdateCachedMesh ();
void BakeMesh (Mesh& mesh);
virtual void Render (int materialIndex, const ChannelAssigns& channels);
float GetBlendShapeWeight(UInt32 index) const;
void SetBlendShapeWeight(UInt32 index, float weight);
#if ENABLE_PROFILER
static int GetVisibleSkinnedMeshRendererCount ();
#endif
bool DoesQualifyForMemExport() const;
bool CalculateRootLocalSpaceBounds (MinMaxAABB& minMaxAAbb);
void UnloadVBOFromGfxDevice();
void ReloadVBOToGfxDevice();
protected:
size_t GetValidBlendShapeWeightCount () const;
bool ShouldRecalculateBoundingVolumeEveryFrame () { return m_UpdateWhenOffscreen || m_RootBone.GetInstanceID() != 0; }
// Puts the renderer into the queue of all visible skinned meshes depending on if it is currently visible.
void UpdateVisibleSkinnedMeshQueue (bool active);
bool CalculateAnimatedPosesWithRoot (const Matrix4x4f& rootMatrix, Matrix4x4f* poses, size_t size);
// Main thread only.
bool CalculateSkinningMatrices (const Matrix4x4f& rootPose, Matrix4x4f* poses, size_t size);
bool PrepareVBO (bool hasSkin, bool hasBlendshape, bool doMemExport, int flags);
virtual void UpdateRenderer();
Unity::Component* GetAnimator ();
void CreateCachedAnimatorBinding ();
void ClearCachedAnimatorBinding ();
bool CalculateBoneBasedBounds (const Matrix4x4f* animatedPoses, size_t size, MinMaxAABB& output);
static void AnimatorModifiedCallback(void* userData, void* sender, int eventID);
};
#endif
|