| 161 | } |
| 162 | |
| 163 | void SplineCollider::GetGeometry(CollisionShape& collision) |
| 164 | { |
| 165 | // Reset bounds |
| 166 | _box = BoundingBox(_transform.Translation); |
| 167 | BoundingSphere::FromBox(_box, _sphere); |
| 168 | const float minSize = 0.001f; |
| 169 | collision.SetSphere(minSize); |
| 170 | |
| 171 | // Skip if sth is missing |
| 172 | if (!_spline || !IsActiveInHierarchy() || _spline->GetSplinePointsCount() < 2 || !CollisionData || !CollisionData->IsLoaded()) |
| 173 | return; |
| 174 | PROFILE_CPU(); |
| 175 | |
| 176 | // Extract collision geometry |
| 177 | // TODO: cache memory allocation for dynamic colliders |
| 178 | Array<Float3> collisionVertices; |
| 179 | Array<int32> collisionIndices; |
| 180 | CollisionData->ExtractGeometry(collisionVertices, collisionIndices); |
| 181 | if (collisionIndices.IsEmpty()) |
| 182 | return; |
| 183 | |
| 184 | // Apply local mesh transformation |
| 185 | if (!_preTransform.IsIdentity()) |
| 186 | { |
| 187 | for (int32 i = 0; i < collisionVertices.Count(); i++) |
| 188 | collisionVertices[i] = _preTransform.LocalToWorld(collisionVertices[i]); |
| 189 | } |
| 190 | |
| 191 | // Find collision geometry local bounds |
| 192 | BoundingBox localModelBounds; |
| 193 | localModelBounds.Minimum = localModelBounds.Maximum = collisionVertices[0]; |
| 194 | for (int32 i = 1; i < collisionVertices.Count(); i++) |
| 195 | { |
| 196 | Vector3 v = collisionVertices[i]; |
| 197 | localModelBounds.Minimum = Vector3::Min(localModelBounds.Minimum, v); |
| 198 | localModelBounds.Maximum = Vector3::Max(localModelBounds.Maximum, v); |
| 199 | } |
| 200 | auto localModelBoundsSize = localModelBounds.GetSize(); |
| 201 | |
| 202 | // Deform geometry over the spline |
| 203 | const auto& keyframes = _spline->Curve.GetKeyframes(); |
| 204 | const int32 segments = keyframes.Count() - 1; |
| 205 | _vertexBuffer.Resize(collisionVertices.Count() * segments); |
| 206 | _indexBuffer.Resize(collisionIndices.Count() * segments); |
| 207 | const Transform splineTransform = _spline->GetTransform(); |
| 208 | const Transform colliderTransform = GetTransform(); |
| 209 | Transform curveTransform, leftTangent, rightTangent; |
| 210 | for (int32 segment = 0; segment < segments; segment++) |
| 211 | { |
| 212 | // Setup for the spline segment |
| 213 | auto offsetVertices = segment * collisionVertices.Count(); |
| 214 | auto offsetIndices = segment * collisionIndices.Count(); |
| 215 | const auto& start = keyframes[segment]; |
| 216 | const auto& end = keyframes[segment + 1]; |
| 217 | const float tangentScale = (end.Time - start.Time) / 3.0f; |
| 218 | AnimationUtils::GetTangent(start.Value, start.TangentOut, tangentScale, leftTangent); |
| 219 | AnimationUtils::GetTangent(end.Value, end.TangentIn, tangentScale, rightTangent); |
| 220 |
nothing calls this directly
no test coverage detected