| 922 | } |
| 923 | |
| 924 | void Cloth::RunClothDeformer(const MeshBase* mesh, MeshDeformationData& deformation) |
| 925 | { |
| 926 | if (!IsActiveInHierarchy()) |
| 927 | return; |
| 928 | if (!_simulationSettings.ComputeNormals && deformation.Type != MeshBufferType::Vertex0) |
| 929 | return; |
| 930 | #if WITH_CLOTH |
| 931 | PROFILE_CPU_NAMED("Cloth"); |
| 932 | PROFILE_MEM(PhysicsCloth); |
| 933 | PhysicsBackend::LockClothParticles(_cloth); |
| 934 | const Span<const Float4> particles = PhysicsBackend::GetClothParticles(_cloth); |
| 935 | auto vbCount = (uint32)mesh->GetVertexCount(); |
| 936 | ASSERT((uint32)particles.Length() >= vbCount); |
| 937 | |
| 938 | // Calculate normals |
| 939 | Array<Float3> normals; |
| 940 | const ModelInstanceActor::MeshReference meshRef = GetMesh(); |
| 941 | if ((_simulationSettings.ComputeNormals || deformation.Type == MeshBufferType::Vertex1) && meshRef.Actor) |
| 942 | { |
| 943 | MeshAccessor accessor; |
| 944 | MeshBufferType bufferTypes[1] = { MeshBufferType::Index }; |
| 945 | if (!accessor.LoadMesh(meshRef.Get(), false, ToSpan(bufferTypes, 1))) |
| 946 | { |
| 947 | PROFILE_CPU_NAMED("Normals"); |
| 948 | auto indices = accessor.Index(); |
| 949 | auto indicesData = indices.GetData(); |
| 950 | // TODO: optimize memory allocs (eg. use shared allocator) |
| 951 | normals.Resize(vbCount); |
| 952 | Platform::MemoryClear(normals.Get(), vbCount * sizeof(Float3)); |
| 953 | const bool indices16bit = indices.GetFormat() == PixelFormat::R16_UInt; |
| 954 | const int32 trianglesCount = indices.GetCount() / 3; |
| 955 | if (indices16bit) |
| 956 | { |
| 957 | for (int32 triangleIndex = 0; triangleIndex < trianglesCount; triangleIndex++) |
| 958 | { |
| 959 | const int32 index = triangleIndex * 3; |
| 960 | const int32 i0 = indicesData.Get<uint16>()[index]; |
| 961 | const int32 i1 = indicesData.Get<uint16>()[index + 1]; |
| 962 | const int32 i2 = indicesData.Get<uint16>()[index + 2]; |
| 963 | const Float3 v0(particles.Get()[i0]); |
| 964 | const Float3 v1(particles.Get()[i1]); |
| 965 | const Float3 v2(particles.Get()[i2]); |
| 966 | const Float3 normal = Float3::Cross(v1 - v0, v2 - v0); |
| 967 | normals.Get()[i0] += normal; |
| 968 | normals.Get()[i1] += normal; |
| 969 | normals.Get()[i2] += normal; |
| 970 | } |
| 971 | } |
| 972 | else |
| 973 | { |
| 974 | for (int32 triangleIndex = 0; triangleIndex < trianglesCount; triangleIndex++) |
| 975 | { |
| 976 | const int32 index = triangleIndex * 3; |
| 977 | const int32 i0 = indicesData.Get<uint32>()[index]; |
| 978 | const int32 i1 = indicesData.Get<uint32>()[index + 1]; |
| 979 | const int32 i2 = indicesData.Get<uint32>()[index + 2]; |
| 980 | const Float3 v0(particles.Get()[i0]); |
| 981 | const Float3 v1(particles.Get()[i1]); |
nothing calls this directly
no test coverage detected