summaryrefslogtreecommitdiff
path: root/Runtime/Filters/Mesh/TransformVertex.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/TransformVertex.cpp
+Unity Runtime codeHEADmaster
Diffstat (limited to 'Runtime/Filters/Mesh/TransformVertex.cpp')
-rw-r--r--Runtime/Filters/Mesh/TransformVertex.cpp205
1 files changed, 205 insertions, 0 deletions
diff --git a/Runtime/Filters/Mesh/TransformVertex.cpp b/Runtime/Filters/Mesh/TransformVertex.cpp
new file mode 100644
index 0000000..e9bebc1
--- /dev/null
+++ b/Runtime/Filters/Mesh/TransformVertex.cpp
@@ -0,0 +1,205 @@
+#include "UnityPrefix.h"
+#include "TransformVertex.h"
+
+#include "Runtime/Math/Matrix4x4.h"
+#include "Runtime/Math/Vector4.h"
+#include "Runtime/Math/Vector3.h"
+#include "Runtime/Math/Vector2.h"
+#include "Runtime/Math/Color.h"
+
+#include "Runtime/Misc/CPUInfo.h"
+
+void
+TransformVerticesStridedREF( StrideIterator<Vector3f> inPos, StrideIterator<Vector3f> inNormal,
+ StrideIterator<ColorRGBA32> inColor, StrideIterator<Vector2f> inTexCoord0, StrideIterator<Vector2f> inTexCoord1,
+ StrideIterator<Vector4f> inTangent,
+ UInt8* dstData, const Matrix4x4f& m, unsigned vertexCount, bool multiStream )
+{
+ // NOTE: kill this code once all shaders normalize normals & tangents!
+ //
+ // We batch uniformly scaled objects, so derive the "normal matrix" here by scaling world matrix axes.
+ // On reference code seems much cheaper than full normalization of normal/tangent vectors.
+ // Test with scene of 200k vertices on Core i7 2600K: no handling of scale 3.77ms, normalization 8.00ms,
+ // using scaled normal matrix 3.80ms.
+ //
+ // Note that ARM NEON/VFP transformation code does not handle this, but it's not needed on GLES platforms
+ // since shaders always normalize normal & tangent. Might be needed on WinRT+ARM though (or just disable
+ // dynamic batching with tangents there).
+ Matrix4x4f nm;
+ CopyMatrix(m.GetPtr(), nm.GetPtr());
+ const float axisLen = Magnitude (m.GetAxisX());
+ float scale = axisLen > 1.0e-6f ? 1.0f / axisLen : 1.0f;
+ nm.Get (0, 0) *= scale;
+ nm.Get (1, 0) *= scale;
+ nm.Get (2, 0) *= scale;
+ nm.Get (0, 1) *= scale;
+ nm.Get (1, 1) *= scale;
+ nm.Get (2, 1) *= scale;
+ nm.Get (0, 2) *= scale;
+ nm.Get (1, 2) *= scale;
+ nm.Get (2, 2) *= scale;
+
+ while (vertexCount --> 0)
+ {
+ Vector3f* outPos = reinterpret_cast<Vector3f*> (dstData);
+ m.MultiplyPoint3(*inPos, *outPos);
+ dstData += sizeof(Vector3f);
+ ++inPos;
+
+ if (inNormal.GetPointer())
+ {
+ Vector3f* outNormal = reinterpret_cast<Vector3f*> (dstData);
+ nm.MultiplyVector3(*inNormal, *outNormal);
+ dstData += sizeof(Vector3f);
+ ++inNormal;
+ }
+
+ if (inColor.GetPointer())
+ {
+ memcpy(dstData, inColor.GetPointer(), sizeof(ColorRGBA32));
+ dstData += sizeof(ColorRGBA32);
+ ++inColor;
+ }
+
+ if (inTexCoord0.GetPointer())
+ {
+ memcpy(dstData, inTexCoord0.GetPointer(), sizeof(Vector2f));
+ dstData += sizeof(Vector2f);
+ ++inTexCoord0;
+ }
+
+ if (inTexCoord1.GetPointer())
+ {
+ memcpy(dstData, inTexCoord1.GetPointer(), sizeof(Vector2f));
+ dstData += sizeof(Vector2f);
+ ++inTexCoord1;
+ }
+
+ if (inTangent.GetPointer())
+ {
+ Vector4f* outTangent = reinterpret_cast<Vector4f*> (dstData);
+ Vector3f* outTangentXYZ = reinterpret_cast<Vector3f*> (outTangent);
+ nm.MultiplyVector3(reinterpret_cast<const Vector3f&>(*inTangent), *outTangentXYZ);
+ outTangent->w = inTangent->w;
+ dstData += sizeof(Vector4f);
+ ++inTangent;
+ }
+ }
+}
+
+
+
+#if (UNITY_SUPPORTS_NEON && !UNITY_DISABLE_NEON_SKINNING) || UNITY_SUPPORTS_VFP
+
+typedef void (*TransformFunc)( const void*, const void*, const void*, const float*, void*, int );
+typedef void (*TransformFuncWithTangents)( const void*, const void*, const void*, const float*, void*, int, const void* );
+
+
+#if UNITY_SUPPORTS_NEON
+namespace TransformNEON
+{
+ #define TRANSFORM_FUNC(prefix, addData) s_TransformVertices_Strided_##prefix##_##addData##_NEON
+
+ TransformFunc TransformXYZ[] =
+ {
+ TRANSFORM_FUNC(XYZ,0), TRANSFORM_FUNC(XYZ,1), TRANSFORM_FUNC(XYZ,2), TRANSFORM_FUNC(XYZ,3), TRANSFORM_FUNC(XYZ,4), TRANSFORM_FUNC(XYZ,5)
+ };
+
+ TransformFunc TransformXYZN[] =
+ {
+ TRANSFORM_FUNC(XYZN,0), TRANSFORM_FUNC(XYZN,1), TRANSFORM_FUNC(XYZN,2), TRANSFORM_FUNC(XYZN,3), TRANSFORM_FUNC(XYZN,4), TRANSFORM_FUNC(XYZN,5)
+ };
+
+ TransformFuncWithTangents TransformXYZNT[] =
+ {
+ TRANSFORM_FUNC(XYZNT,0), TRANSFORM_FUNC(XYZNT,1), TRANSFORM_FUNC(XYZNT,2), TRANSFORM_FUNC(XYZNT,3), TRANSFORM_FUNC(XYZNT,4), TRANSFORM_FUNC(XYZNT,5)
+ };
+
+ #undef TRANSFORM_FUNC
+}
+#endif // UNITY_SUPPORTS_NEON
+
+
+#if UNITY_SUPPORTS_VFP
+namespace TransformVFP
+{
+ #define TRANSFORM_FUNC(prefix, addData) s_TransformVertices_Strided_##prefix##_##addData##_VFP
+
+ TransformFunc TransformXYZ[] =
+ {
+ TRANSFORM_FUNC(XYZ,0), TRANSFORM_FUNC(XYZ,1), TRANSFORM_FUNC(XYZ,2), TRANSFORM_FUNC(XYZ,3), TRANSFORM_FUNC(XYZ,4), TRANSFORM_FUNC(XYZ,5)
+ };
+
+ TransformFunc TransformXYZN[] =
+ {
+ TRANSFORM_FUNC(XYZN,0), TRANSFORM_FUNC(XYZN,1), TRANSFORM_FUNC(XYZN,2), TRANSFORM_FUNC(XYZN,3), TRANSFORM_FUNC(XYZN,4), TRANSFORM_FUNC(XYZN,5)
+ };
+
+ TransformFuncWithTangents TransformXYZNT[] =
+ {
+ TRANSFORM_FUNC(XYZNT,0), TRANSFORM_FUNC(XYZNT,1), TRANSFORM_FUNC(XYZNT,2), TRANSFORM_FUNC(XYZNT,3), TRANSFORM_FUNC(XYZNT,4), TRANSFORM_FUNC(XYZNT,5)
+ };
+
+ #undef TRANSFORM_FUNC
+}
+#endif // UNITY_SUPPORTS_VFP
+
+void
+TransformVerticesStridedARM( StrideIterator<Vector3f> inPos, StrideIterator<Vector3f> inNormal,
+ StrideIterator<ColorRGBA32> inColor, StrideIterator<Vector2f> inTexCoord0, StrideIterator<Vector2f> inTexCoord1,
+ StrideIterator<Vector4f> inTangent,
+ UInt8* dstData, const Matrix4x4f& m, unsigned vertexCount, bool multiStream )
+{
+ int addDataSize = 0;
+ if( inColor.GetPointer() ) addDataSize += 1;
+ if( inTexCoord0.GetPointer() ) addDataSize += 2;
+ if( inTexCoord1.GetPointer() ) addDataSize += 2;
+
+ const void* addDataSrc = 0;
+ if( inColor.GetPointer() ) addDataSrc = inColor.GetPointer();
+ else if( inTexCoord0.GetPointer() ) addDataSrc = inTexCoord0.GetPointer();
+ else if( inTexCoord1.GetPointer() ) addDataSrc = inTexCoord1.GetPointer();
+
+ // slow path determination
+ if( (inColor.GetPointer() && inTexCoord1.GetPointer() && !inTexCoord0.GetPointer())
+ || (inTangent.GetPointer() && !inNormal.GetPointer()) || multiStream )
+ {
+ TransformVerticesStridedREF(inPos, inNormal, inColor, inTexCoord0, inTexCoord1, inTangent, dstData, m, vertexCount, multiStream);
+ return;
+ }
+
+ int stride = inPos.GetStride();
+ const UInt8* inDataBegin = static_cast<const UInt8*>(inPos.GetPointer());
+ const UInt8* inDataEnd = inDataBegin + vertexCount * stride;
+
+#if UNITY_SUPPORTS_NEON
+ if (CPUInfo::HasNEONSupport())
+ {
+ using namespace TransformNEON;
+ if( inNormal.GetPointer() && inTangent.GetPointer() )
+ TransformXYZNT[addDataSize]( inDataBegin, inDataEnd, addDataSrc, m.m_Data, dstData, stride, inTangent.GetPointer() );
+ else if( inNormal.GetPointer() )
+ TransformXYZN[addDataSize]( inDataBegin, inDataEnd, addDataSrc, m.m_Data, dstData, stride );
+ else
+ TransformXYZ[addDataSize]( inDataBegin, inDataEnd, addDataSrc, m.m_Data, dstData, stride );
+ }
+ else
+#endif
+#if UNITY_SUPPORTS_VFP
+ {
+ using namespace TransformVFP;
+ if( inNormal.GetPointer() && inTangent.GetPointer() )
+ TransformXYZNT[addDataSize]( inDataBegin, inDataEnd, addDataSrc, m.m_Data, dstData, stride, inTangent.GetPointer() );
+ else if( inNormal.GetPointer() )
+ TransformXYZN[addDataSize]( inDataBegin, inDataEnd, addDataSrc, m.m_Data, dstData, stride );
+ else
+ TransformXYZ[addDataSize]( inDataBegin, inDataEnd, addDataSrc, m.m_Data, dstData, stride );
+ }
+#else
+ {
+ ErrorString("non-NEON path not enabled!");
+ }
+#endif
+}
+#endif
+