예제 #1
0
        public void Evaluate(float4 point, ref BurstLocalOptimization.SurfacePoint projectedPoint)
        {
            float4 center = shape.center * transform.scale;

            point = transform.InverseTransformPointUnscaled(point) - center;

            if (shape.is2D != 0)
            {
                point[2] = 0;
            }

            int   direction = (int)shape.size.z;
            float radius    = shape.size.x * math.max(transform.scale[(direction + 1) % 3],
                                                      transform.scale[(direction + 2) % 3]);

            float  height     = math.max(radius, shape.size.y * 0.5f * transform.scale[direction]);
            float4 halfVector = float4.zero;

            halfVector[direction] = height - radius;

            float4 centerLine       = BurstMath.NearestPointOnEdge(-halfVector, halfVector, point, out float mu);
            float4 centerToPoint    = point - centerLine;
            float  distanceToCenter = math.length(centerToPoint);

            float4 normal = centerToPoint / (distanceToCenter + BurstMath.epsilon);

            projectedPoint.point  = transform.TransformPointUnscaled(center + centerLine + normal * (radius + shape.contactOffset));
            projectedPoint.normal = transform.TransformDirection(normal);
        }
예제 #2
0
        public static void Contacts(int particleIndex,
                                    float4 position,
                                    quaternion orientation,
                                    float4 radii,
                                    int colliderIndex,
                                    BurstAffineTransform transform,
                                    BurstColliderShape shape,
                                    NativeQueue <BurstContact> .ParallelWriter contacts)
        {
            float4 center = shape.center * transform.scale;

            position = transform.InverseTransformPointUnscaled(position) - center;

            float radius           = shape.size.x * math.cmax(transform.scale.xyz);
            float distanceToCenter = math.length(position);

            float4 normal = position / distanceToCenter;

            BurstContact c = new BurstContact
            {
                entityA = particleIndex,
                entityB = colliderIndex,
                point   = center + normal * radius,
                normal  = normal,
            };

            c.point  = transform.TransformPointUnscaled(c.point);
            c.normal = transform.TransformDirection(c.normal);

            c.distance = distanceToCenter - radius - (shape.contactOffset + BurstMath.EllipsoidRadius(c.normal, orientation, radii.xyz));

            contacts.Enqueue(c);
        }
예제 #3
0
        public void Evaluate(float4 point, ref BurstLocalOptimization.SurfacePoint projectedPoint)
        {
            point = transform.InverseTransformPointUnscaled(point);

            if (shape.is2D != 0)
            {
                point[2] = 0;
            }

            float4 nearestPoint = BurstMath.NearestPointOnTri(tri, point, out float4 bary);
            float4 normal       = math.normalizesafe(point - nearestPoint);

            projectedPoint.point  = transform.TransformPointUnscaled(nearestPoint + normal * shape.contactOffset);
            projectedPoint.normal = transform.TransformDirection(normal);
        }
예제 #4
0
        public void Evaluate(float4 point, ref BurstLocalOptimization.SurfacePoint projectedPoint)
        {
            float4 center = shape.center * transform.scale;
            float4 size   = shape.size * transform.scale * 0.5f;

            // clamp the point to the surface of the box:
            point = transform.InverseTransformPointUnscaled(point) - center;

            if (shape.is2D != 0)
            {
                point[2] = 0;
            }

            // get minimum distance for each axis:
            float4 distances = size - math.abs(point);

            if (distances.x >= 0 && distances.y >= 0 && distances.z >= 0)
            {
                // find minimum distance in all three axes and the axis index:
                float min  = float.MaxValue;
                int   axis = 0;

                for (int i = 0; i < 3; ++i)
                {
                    if (distances[i] < min)
                    {
                        min  = distances[i];
                        axis = i;
                    }
                }

                projectedPoint.normal = float4.zero;
                projectedPoint.point  = point;

                projectedPoint.normal[axis] = point[axis] > 0 ? 1 : -1;
                projectedPoint.point[axis]  = size[axis] * projectedPoint.normal[axis];
            }
            else
            {
                projectedPoint.point  = math.clamp(point, -size, size);
                projectedPoint.normal = math.normalizesafe(point - projectedPoint.point);
            }

            projectedPoint.point  = transform.TransformPointUnscaled(projectedPoint.point + center + projectedPoint.normal * shape.contactOffset);
            projectedPoint.normal = transform.TransformDirection(projectedPoint.normal);
        }
예제 #5
0
        public void Evaluate(float4 point, ref BurstLocalOptimization.SurfacePoint projectedPoint)
        {
            point = transform.InverseTransformPointUnscaled(point);

            if (shape.is2D != 0)
            {
                point[2] = 0;
            }

            Edge   t  = edges[header.firstEdge + dataOffset];
            float4 v1 = (new float4(vertices[header.firstVertex + t.i1], 0) + shape.center) * transform.scale;
            float4 v2 = (new float4(vertices[header.firstVertex + t.i2], 0) + shape.center) * transform.scale;

            float4 nearestPoint = BurstMath.NearestPointOnEdge(v1, v2, point, out float mu);
            float4 normal       = math.normalizesafe(point - nearestPoint);

            projectedPoint.normal = transform.TransformDirection(normal);
            projectedPoint.point  = transform.TransformPointUnscaled(nearestPoint + normal * shape.contactOffset);
        }
예제 #6
0
        public void Evaluate(float4 point, ref BurstLocalOptimization.SurfacePoint projectedPoint)
        {
            float4 center = shape.center * transform.scale;

            point = transform.InverseTransformPointUnscaled(point) - center;

            if (shape.is2D != 0)
            {
                point[2] = 0;
            }

            float radius           = shape.size.x * math.cmax(transform.scale.xyz);
            float distanceToCenter = math.length(point);

            float4 normal = point / (distanceToCenter + BurstMath.epsilon);

            projectedPoint.point  = transform.TransformPointUnscaled(center + normal * (radius + shape.contactOffset));
            projectedPoint.normal = transform.TransformDirection(normal);
        }
예제 #7
0
        private static void BIHTraverse(int particleIndex,
                                        int colliderIndex,
                                        float4 particlePosition,
                                        quaternion particleOrientation,
                                        float4 particleVelocity,
                                        float4 particleRadii,
                                        ref BurstAabb particleBounds,
                                        int nodeIndex,
                                        ref NativeArray <BIHNode> bihNodes,
                                        ref NativeArray <Edge> edges,
                                        ref NativeArray <float2> vertices,
                                        ref EdgeMeshHeader header,
                                        ref BurstAffineTransform colliderToSolver,
                                        ref BurstColliderShape shape,
                                        NativeQueue <BurstContact> .ParallelWriter contacts)
        {
            var node = bihNodes[header.firstNode + nodeIndex];

            // amount by which we should inflate aabbs:
            float offset = shape.contactOffset + particleRadii.x;

            if (node.firstChild >= 0)
            {
                // visit min node:
                if (particleBounds.min[node.axis] - offset <= node.min)
                {
                    BIHTraverse(particleIndex, colliderIndex,
                                particlePosition, particleOrientation, particleVelocity, particleRadii, ref particleBounds,
                                node.firstChild, ref bihNodes, ref edges, ref vertices, ref header,
                                ref colliderToSolver, ref shape, contacts);
                }

                // visit max node:
                if (particleBounds.max[node.axis] + offset >= node.max)
                {
                    BIHTraverse(particleIndex, colliderIndex,
                                particlePosition, particleOrientation, particleVelocity, particleRadii, ref particleBounds,
                                node.firstChild + 1, ref bihNodes, ref edges, ref vertices, ref header,
                                ref colliderToSolver, ref shape, contacts);
                }
            }
            else
            {
                // precalculate inverse of velocity vector for ray/aabb intersections:
                float4 invDir = math.rcp(particleVelocity);

                // contacts against all triangles:
                for (int i = node.start; i < node.start + node.count; ++i)
                {
                    Edge t = edges[header.firstEdge + i];

                    float4 v1 = new float4(vertices[header.firstVertex + t.i1], 0, 0) * colliderToSolver.scale;
                    float4 v2 = new float4(vertices[header.firstVertex + t.i2], 0, 0) * colliderToSolver.scale;

                    BurstAabb aabb = new BurstAabb(v1, v2, 0.01f);
                    aabb.Expand(new float4(offset));

                    // only generate a contact if the particle trajectory intersects its inflated aabb:
                    if (aabb.IntersectsRay(particlePosition, invDir, true))
                    {
                        float4 point      = BurstMath.NearestPointOnEdge(v1, v2, particlePosition);
                        float4 pointToTri = particlePosition - point;
                        float  distance   = math.length(pointToTri);

                        if (distance > BurstMath.epsilon)
                        {
                            BurstContact c = new BurstContact()
                            {
                                entityA = particleIndex,
                                entityB = colliderIndex,
                                point   = colliderToSolver.TransformPointUnscaled(point),
                                normal  = colliderToSolver.TransformDirection(pointToTri / distance),
                            };

                            c.distance = distance - (shape.contactOffset + BurstMath.EllipsoidRadius(c.normal, particleOrientation, particleRadii.xyz));

                            contacts.Enqueue(c);
                        }
                    }
                }
            }
        }
예제 #8
0
        public static void Contacts(int particleIndex,
                                    float4 position,
                                    quaternion orientation,
                                    float4 radii,
                                    int colliderIndex,
                                    BurstAffineTransform transform,
                                    BurstColliderShape shape,
                                    NativeQueue <BurstContact> .ParallelWriter contacts)
        {
            BurstContact c = new BurstContact()
            {
                entityA = particleIndex,
                entityB = colliderIndex,
            };

            float4 center = shape.center * transform.scale;

            position = transform.InverseTransformPointUnscaled(position) - center;

            int    direction = (int)shape.size.z;
            float  radius    = shape.size.x * math.max(transform.scale[(direction + 1) % 3], transform.scale[(direction + 2) % 3]);
            float  height    = math.max(radius, shape.size.y * 0.5f * transform.scale[direction]);
            float  d         = position[direction];
            float4 axisProj  = float4.zero;
            float4 cap       = float4.zero;

            axisProj[direction] = d;
            cap[direction]      = height - radius;

            float4 centerToPoint;
            float  centerToPointNorm;

            if (d > height - radius)
            { //one cap
                centerToPoint     = position - cap;
                centerToPointNorm = math.length(centerToPoint);

                c.distance = centerToPointNorm - radius;
                c.normal   = (centerToPoint / (centerToPointNorm + math.FLT_MIN_NORMAL));
                c.point    = cap + c.normal * radius;
            }
            else if (d < -height + radius)
            { // other cap
                centerToPoint     = position + cap;
                centerToPointNorm = math.length(centerToPoint);

                c.distance = centerToPointNorm - radius;
                c.normal   = (centerToPoint / (centerToPointNorm + math.FLT_MIN_NORMAL));
                c.point    = -cap + c.normal * radius;
            }
            else
            {//cylinder
                centerToPoint     = position - axisProj;
                centerToPointNorm = math.length(centerToPoint);

                c.distance = centerToPointNorm - radius;
                c.normal   = (centerToPoint / (centerToPointNorm + math.FLT_MIN_NORMAL));
                c.point    = axisProj + c.normal * radius;
            }

            c.point += center;
            c.point  = transform.TransformPointUnscaled(c.point);
            c.normal = transform.TransformDirection(c.normal);

            c.distance -= shape.contactOffset + BurstMath.EllipsoidRadius(c.normal, orientation, radii.xyz);

            contacts.Enqueue(c);
        }
        public static void Contacts(int particleIndex,
                                    float4 position,
                                    quaternion orientation,
                                    float4 radii,
                                    int colliderIndex,
                                    BurstAffineTransform transform,
                                    BurstColliderShape shape,
                                    NativeQueue <BurstContact> .ParallelWriter contacts)
        {
            BurstContact c = new BurstContact()
            {
                entityA = particleIndex,
                entityB = colliderIndex,
            };

            float4 center = shape.center * transform.scale;
            float4 size   = shape.size * transform.scale * 0.5f;

            position = transform.InverseTransformPointUnscaled(position) - center;

            // Get minimum distance for each axis:
            float4 distances = size - math.abs(position);

            // if we are inside the box:
            if (distances.x >= 0 && distances.y >= 0 && distances.z >= 0)
            {
                // find minimum distance in all three axes and the axis index:
                float min  = float.MaxValue;
                int   axis = 0;
                for (int i = 0; i < 3; ++i)
                {
                    if (distances[i] < min)
                    {
                        min  = distances[i];
                        axis = i;
                    }
                }

                c.normal = float4.zero;
                c.point  = position;

                c.distance     = -distances[axis];
                c.normal[axis] = position[axis] > 0 ? 1 : -1;
                c.point[axis]  = size[axis] * c.normal[axis];
            }
            else // we are outside the box:
            {
                // clamp point to be inside the box:
                c.point = math.clamp(position, -size, size);

                // find distance and direction to clamped point:
                float4 diff = position - c.point;
                c.distance = math.length(diff);
                c.normal   = diff / (c.distance + math.FLT_MIN_NORMAL);
            }

            c.point += center;
            c.point  = transform.TransformPointUnscaled(c.point);
            c.normal = transform.TransformDirection(c.normal);

            c.distance -= shape.contactOffset + BurstMath.EllipsoidRadius(c.normal, orientation, radii.xyz);

            contacts.Enqueue(c);
        }