summaryrefslogtreecommitdiff
path: root/Runtime/Filters/Mesh/MeshBlendShape.cpp
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-08-14 22:50:43 +0800
committerchai <chaifix@163.com>2019-08-14 22:50:43 +0800
commit15740faf9fe9fe4be08965098bbf2947e096aeeb (patch)
treea730ec236656cc8cab5b13f088adfaed6bb218fb /Runtime/Filters/Mesh/MeshBlendShape.cpp
+Unity Runtime codeHEADmaster
Diffstat (limited to 'Runtime/Filters/Mesh/MeshBlendShape.cpp')
-rw-r--r--Runtime/Filters/Mesh/MeshBlendShape.cpp234
1 files changed, 234 insertions, 0 deletions
diff --git a/Runtime/Filters/Mesh/MeshBlendShape.cpp b/Runtime/Filters/Mesh/MeshBlendShape.cpp
new file mode 100644
index 0000000..c7588e2
--- /dev/null
+++ b/Runtime/Filters/Mesh/MeshBlendShape.cpp
@@ -0,0 +1,234 @@
+#include "UnityPrefix.h"
+#include "Configuration/UnityConfigure.h"
+#include "MeshBlendShape.h"
+#include "Runtime/mecanim/generic/crc32.h"
+
+static const float kVertexDeltaEpsilon = 1e-5f;
+static const float kNormalDeltaEpsilon = 1e-5f;
+
+void SetBlendShapeVertices(const std::vector<Vector3f>& deltaVertices, const std::vector<Vector3f>& deltaNormals, const std::vector<Vector3f>& deltaTangents, BlendShapeVertices& sharedSparceVertices, BlendShape& frame)
+{
+ Assert(deltaNormals.empty() || deltaVertices.size() == deltaNormals.size());
+ Assert(deltaTangents.empty() || deltaVertices.size() == deltaTangents.size());
+
+ frame.firstVertex = sharedSparceVertices.size();
+
+ // Converting blend shape in to sparse blend shape
+ sharedSparceVertices.reserve(sharedSparceVertices.size() + deltaVertices.size());
+
+ frame.hasNormals = frame.hasTangents = false;
+
+ for (int j = 0; j < deltaVertices.size(); ++j)
+ {
+ const bool vertexHasNormal = (!deltaNormals.empty() && Magnitude(deltaNormals[j]) > kNormalDeltaEpsilon);
+ const bool vertexHasTangent = (!deltaTangents.empty() && Magnitude(deltaTangents[j]) > kNormalDeltaEpsilon);
+
+ frame.hasNormals = frame.hasNormals || vertexHasNormal;
+ frame.hasTangents = frame.hasTangents || vertexHasTangent;
+
+ if (Magnitude(deltaVertices[j]) > kVertexDeltaEpsilon || vertexHasNormal || vertexHasTangent)
+ {
+ BlendShapeVertex v;
+
+ v.vertex = deltaVertices[j];
+ if (!deltaNormals.empty())
+ v.normal = deltaNormals[j];
+ if (!deltaTangents.empty())
+ v.tangent = deltaTangents[j];
+
+ v.index = j;
+ sharedSparceVertices.push_back(v);
+ }
+ }
+
+ frame.vertexCount = sharedSparceVertices.size() - frame.firstVertex;
+}
+
+void BlendShape::UpdateFlags(const BlendShapeVertices& sharedSparceVertices)
+{
+ hasNormals = hasTangents = false;
+
+ for (int j = 0; j < vertexCount; ++j)
+ {
+ const BlendShapeVertex& v = sharedSparceVertices[firstVertex + j];
+ const bool vertexHasNormal = Magnitude(v.normal) > kNormalDeltaEpsilon;
+ const bool vertexHasTangent = Magnitude(v.tangent) > kNormalDeltaEpsilon;
+
+ hasNormals = hasNormals || vertexHasNormal;
+ hasTangents = hasTangents || vertexHasTangent;
+ }
+}
+
+void InitializeChannel (const UnityStr& inName, int frameIndex, int frameCount, BlendShapeChannel& channel)
+{
+ channel.name.assign(inName.c_str(), kMemGeometry);
+ channel.nameHash = mecanim::processCRC32(inName.c_str());
+ channel.frameIndex = frameIndex;
+ channel.frameCount = frameCount;
+}
+
+const char* GetChannelName (const BlendShapeData& data, int index)
+{
+ return data.channels[index].name.c_str();
+}
+
+int GetChannelIndex (const BlendShapeData& data, const char* name)
+{
+ for (int i=0;i<data.channels.size();i++)
+ {
+ if (name == data.channels[i].name)
+ return i;
+ }
+ return -1;
+}
+
+int GetChannelIndex (const BlendShapeData& data, BindingHash name)
+{
+ for (int i=0;i<data.channels.size();i++)
+ {
+ if (name == data.channels[i].nameHash)
+ return i;
+ }
+ return -1;
+}
+
+void ClearBlendShapes (BlendShapeData& data)
+{
+ data.vertices.clear();
+ data.shapes.clear();
+ data.channels.clear();
+ data.fullWeights.clear();
+}
+
+/*
+
+STRUCT BlendShapeChannel
+
+// BlendShape vertex class.
+STRUCT Vertex
+// Vertex delta.
+CSRAW public Vector3 vertex;
+
+// Normal delta.
+CSRAW public Vector3 normal;
+
+// Tangent delta.
+CSRAW public Vector3 tangent;
+
+// Index to [[Mesh]] vertex data.
+CSRAW public int index;
+END
+
+// A class representing a single BlendShape (also called morph-target).
+STRUCT BlendShape
+
+// The weight of the frame
+CSRAW public float weight;
+
+// Sparse vertex data.
+CSRAW public Vertex[] vertices;
+END
+
+// Name of the BlendShape.
+CSRAW public string name;
+
+// The frames making up a blendshape animation.
+// Each frame has a weight, based on the weight of the BlendShape in the SkinnedMeshRenderer, Unity will apply 1 or 2 frames.
+CSRAW public BlendShape[] shapes;
+END
+
+
+C++RAW
+/*
+ struct MonoMeshBlendShape
+ {
+ ScriptingStringPtr name;
+ ScriptingArrayPtr vertices;
+ };
+
+ void BlendShapeVertexToMono (const BlendShapeVertex &src, MonoBlendShapeVertex &dest) {
+ dest.vertex = src.vertex;
+ dest.normal = src.normal;
+ dest.tangent = src.tangent;
+ dest.index = src.index;
+ }
+ void BlendShapeVertexToCpp (const MonoBlendShapeVertex &src, BlendShapeVertex &dest) {
+ dest.vertex = src.vertex;
+ dest.normal = src.normal;
+ dest.tangent = src.tangent;
+ dest.index = src.index;
+ }
+
+ class MeshBlendShapeToMono
+ {
+ public:
+ MeshBlendShapeToMono(const BlendShapeVertices& sharedVertices_) : sharedVertices(sharedVertices_) {}
+
+ void operator() (const MeshBlendShape &src, MonoMeshBlendShape &dest)
+ {
+ dest.name = scripting_string_new(src.m_Name);
+ const BlendShapeVertices vertices(sharedVertices.begin() + src.firstVertex, sharedVertices.begin() + src.firstVertex + src.vertexCount);
+
+ ScriptingTypePtr classVertex = GetScriptingTypeRegistry().GetType("UnityEngine", "BlendShapeVertex");
+ dest.vertices = VectorToScriptingStructArray<BlendShapeVertex, MonoBlendShapeVertex>(vertices, classVertex, BlendShapeVertexToMono);
+ }
+
+ private:
+ const BlendShapeVertices& sharedVertices;
+ };
+
+ class MeshBlendShapeToCpp
+ {
+ public:
+ MeshBlendShapeToCpp(int meshVertexCount_, BlendShapeVertices& sharedVertices_) : meshVertexCount(meshVertexCount_), sharedVertices(sharedVertices_) {}
+
+ void operator() (MonoMeshBlendShape &src, MeshBlendShape &dest)
+ {
+ dest.weight = src.weight;
+
+ const BlendShapeVertex* vertices = Scripting::GetScriptingArrayStart<BlendShapeVertex> (src.vertices);
+ sharedVertices.insert(sharedVertices.end(), vertices, vertices + GetScriptingArraySize(src.vertices));
+
+ for (BlendShapeVertices::iterator it = vertices.begin(), end = vertices.end(); it != end; ++it)
+ {
+ BlendShapeVertex& v = *it;
+ if (v.index < 0 || v.index >= meshVertexCount)
+ {
+ ErrorStringMsg("Value (%d) of BlendShapeVertex.index #%d is out of bounds (Mesh vertex count: %d) on BlendShape '%s'. It will be reset to 0.", v.index, it - vertices.begin(), meshVertexCount, dest.m_Name.c_str());
+ v.index = 0;
+ }
+ }
+
+ dest.firstVertex = sharedVertices.size();
+ dest.vertexCount = vertices.size();
+
+ sharedVertices.insert(sharedVertices.end(), vertices.begin(), vertices.end());
+ dest.UpdateFlags(sharedVertices);
+ }
+
+ private:
+ int meshVertexCount;
+ BlendShapeVertices& sharedVertices;
+ };
+
+
+
+ ----------------
+
+ // BlendShapes for this mesh.
+ CUSTOM_PROP BlendShapeChannel[] blendShapes
+ {
+ // ScriptingTypePtr classBlendShape = GetScriptingTypeRegistry().GetType("UnityEngine", "MeshBlendShape");
+ // return VectorToScriptingStructArray<MeshBlendShape, MonoMeshBlendShape>(self->GetShapesVector(), classBlendShape, MeshBlendShapeToMono(self->GetShapeVertexVector()));
+ return SCRIPTING_NULL;
+ }
+ {
+ // Mesh::MeshBlendShapeContainer shapes;
+ // self->GetShapeVertexVector().clear();
+ // ScriptingStructArrayToVector<MeshBlendShape, MonoMeshBlendShape>(value, shapes, MeshBlendShapeToCpp(self->GetVertexCount(), self->GetShapeVertexVector()));
+ // self->SwapShapesVector(shapes);
+ }
+
+
+
+ */