| 178 | } |
| 179 | |
| 180 | void Cloth::SetPaint(Span<const float> value) |
| 181 | { |
| 182 | PROFILE_CPU(); |
| 183 | PROFILE_MEM(PhysicsCloth); |
| 184 | #if USE_CLOTH_SANITY_CHECKS |
| 185 | { |
| 186 | // Sanity check |
| 187 | const float* src = value.Get(); |
| 188 | bool allValid = true; |
| 189 | for (int32 i = 0; i < value.Length(); i++) |
| 190 | allValid &= !isnan(src[i]) && !isinf(src[i]); |
| 191 | ASSERT(allValid); |
| 192 | } |
| 193 | #endif |
| 194 | if (value.IsInvalid()) |
| 195 | { |
| 196 | // Remove paint when set to empty |
| 197 | _paint.SetCapacity(0); |
| 198 | #if WITH_CLOTH |
| 199 | if (_cloth) |
| 200 | { |
| 201 | PhysicsBackend::SetClothPaint(_cloth, value); |
| 202 | } |
| 203 | #endif |
| 204 | return; |
| 205 | } |
| 206 | _paint.Set(value.Get(), value.Length()); |
| 207 | #if WITH_CLOTH |
| 208 | if (_cloth) |
| 209 | { |
| 210 | // Update cloth particles |
| 211 | MeshAccessor accessor; |
| 212 | MeshBufferType bufferTypes[2] = { MeshBufferType::Index, MeshBufferType::Vertex0 }; |
| 213 | if (accessor.LoadMesh(GetMesh().Get(), false, ToSpan(bufferTypes, 2))) |
| 214 | return; |
| 215 | Array<float> invMasses; |
| 216 | CalculateInvMasses(accessor, invMasses); |
| 217 | PhysicsBackend::LockClothParticles(_cloth); |
| 218 | PhysicsBackend::SetClothParticles(_cloth, Span<const Float4>(), Span<const Float3>(), ToSpan<float, const float>(invMasses)); |
| 219 | PhysicsBackend::SetClothPaint(_cloth, value); |
| 220 | PhysicsBackend::UnlockClothParticles(_cloth); |
| 221 | } |
| 222 | #endif |
| 223 | } |
| 224 | |
| 225 | bool Cloth::IntersectsItself(const Ray& ray, Real& distance, Vector3& normal) |
| 226 | { |