public void Init()
                {
                    v1 = (float3 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float3>() * 100000, UnsafeUtility.AlignOf <float3>(), Allocator.Persistent);
                    for (int i = 0; i < 100000; ++i)
                    {
                        v1[i] = new float3(1.0f);
                    }

                    v2 = (float3 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float3>() * 100000, UnsafeUtility.AlignOf <float3>(), Allocator.Persistent);
                    for (int i = 0; i < 100000; ++i)
                    {
                        v2[i] = new float3(2.0f);
                    }

                    result = (float3 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float3>() * 100000, UnsafeUtility.AlignOf <float3>(), Allocator.Persistent);
                    for (int i = 0; i < 100000; ++i)
                    {
                        result[i] = new float3(1.0f);
                    }
                }
                public void Init()
                {
                    q = (quaternion *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <quaternion>() * 10000, UnsafeUtility.AlignOf <quaternion>(), Allocator.Persistent);
                    for (int i = 0; i < 10000; ++i)
                    {
                        q[i] = quaternion.identity;
                    }

                    rt = (RigidTransform *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <RigidTransform>() * 10000, UnsafeUtility.AlignOf <RigidTransform>(), Allocator.Persistent);
                    for (int i = 0; i < 10000; ++i)
                    {
                        rt[i] = RigidTransform.identity;
                    }

                    pos = (float3 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float3>() * 10000, UnsafeUtility.AlignOf <float3>(), Allocator.Persistent);
                    for (int i = 0; i < 10000; ++i)
                    {
                        pos[i] = new float3();
                    }
                }
                public void Init()
                {
                    q = (quaternion *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <quaternion>() * 10000, UnsafeUtility.AlignOf <quaternion>(), Allocator.Persistent);
                    for (int i = 0; i < 10000; ++i)
                    {
                        q[i] = quaternion.identity;
                    }

                    f4x4 = (float4x4 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float4x4>() * 10000, UnsafeUtility.AlignOf <float4x4>(), Allocator.Persistent);
                    for (int i = 0; i < 10000; ++i)
                    {
                        f4x4[i] = float4x4.identity;
                    }

                    f3 = (float3 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float3>() * 10000, UnsafeUtility.AlignOf <float3>(), Allocator.Persistent);
                    for (int i = 0; i < 10000; ++i)
                    {
                        f3[i] = new float3();
                    }
                }
                public void Init()
                {
                    forward = (float3 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float3>() * 10000, UnsafeUtility.AlignOf <float3>(), Allocator.Persistent);
                    for (int i = 0; i < 10000; ++i)
                    {
                        forward[i] = math.normalize(new float3(1.0f));
                    }

                    up = (float3 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float3>() * 10000, UnsafeUtility.AlignOf <float3>(), Allocator.Persistent);
                    for (int i = 0; i < 10000; ++i)
                    {
                        up[i] = math.normalize(new float3(0.0f, 1.0f, 0.0f));
                    }

                    m = (float3x3 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float3x3>() * 10000, UnsafeUtility.AlignOf <float3x3>(), Allocator.Persistent);
                    for (int i = 0; i < 10000; ++i)
                    {
                        m[i] = float3x3.identity;
                    }
                }
                public void Init()
                {
                    v = (float3 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float3>() * 10000, UnsafeUtility.AlignOf <float3>(), Allocator.Persistent);
                    for (int i = 0; i < 10000; ++i)
                    {
                        v[i] = math.normalize(new float3(1.0f));
                    }

                    m = (float4x4 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float4x4>() * 10000, UnsafeUtility.AlignOf <float4x4>(), Allocator.Persistent);
                    for (int i = 0; i < 10000; ++i)
                    {
                        m[i] = float4x4.identity;
                    }

                    angle = (float *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float>() * 10000, UnsafeUtility.AlignOf <float>(), Allocator.Persistent);
                    for (int i = 0; i < 10000; ++i)
                    {
                        angle[i] = 1.0f;
                    }
                }
Exemple #6
0
                public void Init()
                {
                    rng = new Random(1);
                    v   = (float3 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float3>() * iterations, UnsafeUtility.AlignOf <float3>(), Allocator.Persistent);
                    for (int i = 0; i < iterations; ++i)
                    {
                        v[i] = math.normalize(new float3(1.0f));
                    }

                    m = (float3x3 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float3x3>() * iterations, UnsafeUtility.AlignOf <float3x3>(), Allocator.Persistent);
                    for (int i = 0; i < iterations; ++i)
                    {
                        m[i] = float3x3.identity;
                    }

                    angle = (float *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float>() * iterations, UnsafeUtility.AlignOf <float>(), Allocator.Persistent);
                    for (int i = 0; i < iterations; ++i)
                    {
                        angle[i] = 1.0f;
                    }
                }
    /// <summary>
    /// Get Frustum Corners
    /// </summary>
    /// <param name="distance"></param> target distance range
    /// <param name="shadMap"></param> shadowmap component
    /// <param name="mask"></param> shadowmask component

    public static void GetfrustumCorners(float2 nearFarPlane, float3 *frustumCorners, float aspect, float relativeFov, float3 right, float3 up, float3 forward, float3 position)
    {
        //x: near width, y: near height z: far width w: far height
        float2 tanValue           = tan(relativeFov) / float2(1, aspect);
        float4 screenDistanceNear = nearFarPlane.xxyy * tanValue.xyxy;
        float3 nearPlane          = position + forward * nearFarPlane.x;
        float3 farPlane           = position + forward * nearFarPlane.y;
        float3 upDir    = screenDistanceNear.y * up;
        float3 rightDir = screenDistanceNear.x * right;

        frustumCorners[0] = nearPlane + rightDir + upDir;
        frustumCorners[1] = nearPlane - rightDir + upDir;
        frustumCorners[2] = nearPlane + rightDir - upDir;
        frustumCorners[3] = nearPlane - rightDir - upDir;
        upDir             = screenDistanceNear.w * up;
        rightDir          = screenDistanceNear.z * right;
        frustumCorners[4] = farPlane + rightDir + upDir;
        frustumCorners[5] = farPlane - rightDir + upDir;
        frustumCorners[6] = farPlane + rightDir - upDir;
        frustumCorners[7] = farPlane - rightDir - upDir;
    }
                public void Init()
                {
                    rng = new Random(1);
                    v1 = (float3*)UnsafeUtility.Malloc(UnsafeUtility.SizeOf<float3>() * iterations, UnsafeUtility.AlignOf<float3>(), Allocator.Persistent);
                    for (int i = 0; i < iterations; ++i)
                    {
                        v1[i] = new float3(1.0f);
                    }

                    v2 = (float3*)UnsafeUtility.Malloc(UnsafeUtility.SizeOf<float3>() * iterations, UnsafeUtility.AlignOf<float3>(), Allocator.Persistent);
                    for (int i = 0; i < iterations; ++i)
                    {
                        v2[i] = new float3(2.0f);
                    }

                    result = (float3*)UnsafeUtility.Malloc(UnsafeUtility.SizeOf<float3>() * iterations, UnsafeUtility.AlignOf<float3>(), Allocator.Persistent);
                    for (int i = 0; i < iterations; ++i)
                    {
                        result[i] = new float3(1.0f);
                    }

                }
Exemple #9
0
    public static void GetFrustumCorner(ref PerspCam perspCam, float3 *corners)
    {
        float fov = tan(Mathf.Deg2Rad * perspCam.fov * 0.5f);

        void GetCorner(float dist, ref PerspCam persp)
        {
            float  upLength    = dist * (fov);
            float  rightLength = upLength * persp.aspect;
            float3 farPoint    = persp.position + dist * persp.forward;
            float3 upVec       = upLength * persp.up;
            float3 rightVec    = rightLength * persp.right;

            corners[0] = farPoint - upVec - rightVec;
            corners[1] = farPoint - upVec + rightVec;
            corners[2] = farPoint + upVec - rightVec;
            corners[3] = farPoint + upVec + rightVec;
            corners   += 4;
        }

        GetCorner(perspCam.nearClipPlane, ref perspCam);
        GetCorner(perspCam.farClipPlane, ref perspCam);
    }
Exemple #10
0
        public unsafe void AppendStats(Dictionary <byte, int> stats)
        {
            if (Data == null || Data.Length == 0)
                return;

            fixed(byte *dataPtr = Data)
            {
                DtTileHeader *header = (DtTileHeader *)dataPtr;

                if (header->VertCount == 0)
                {
                    return;
                }

                int headerSize = Navigation.DtAlign4(sizeof(DtTileHeader));
                int vertsSize  = Navigation.DtAlign4(sizeof(float) * 3 * header->VertCount);

                byte *ptr = dataPtr;

                ptr += headerSize;

                float3 *vertexPtr = (float3 *)ptr;

                ptr += vertsSize;
                DtPoly *polyPtr = (DtPoly *)ptr;

                for (int i = 0; i < header->PolyCount; i++)
                {
                    // Expand polygons into triangles
                    DtPoly poly = polyPtr[i];

                    if (!stats.TryGetValue(poly.AreaAndType, out int count))
                    {
                        stats[poly.AreaAndType] = 0;
                    }
                    stats[poly.AreaAndType]++;
                }
            }
        }
    static int DoSphereVsSpheres(Sphere *spheres, int numSpheres, float3 *centerPtr, float radius, out int numIntersections)
    {
        float3 center = *centerPtr;
        int    first  = numSpheres;
        int    n      = 0;

        for (int i = 0; i < numSpheres; i++)
        {
            float r = spheres[i].Radius + radius;
            if (math.distancesq(spheres[i].Position, center) < r * r)
            {
                if (i < first)
                {
                    first = i;
                }
                n++;
            }
        }

        numIntersections = n;

        return(first == numSpheres ? -1 : first);
    }
    void Update()
    {
        var unityRay = m_Camera.ScreenPointToRay(Input.mousePosition);
        var ray      = new RayData
        {
            Direction = unityRay.direction,
            Origin    = unityRay.origin
        };
        float3 *vertices = (float3 *)m_Vertices.GetUnsafeReadOnlyPtr();
        int *   indices  = (int *)m_Indices.GetUnsafeReadOnlyPtr();

        m_FindIntersectionMarker.Begin();
        var rayIntersectionT = m_FindIntersection(vertices, indices, m_Indices.Length / 3, &ray);

        m_FindIntersectionMarker.End();

        m_FindIntersectionSimdMarker.Begin();
        var rayIntersectionTSimd = m_FindIntersectionSimd(vertices, indices, m_Indices.Length / 3, &ray);

        m_FindIntersectionSimdMarker.End();

        float3 intersection        = ray.Origin + rayIntersectionT * ray.Direction;
        bool   hasIntersection     = !float.IsNaN(rayIntersectionT) && !float.IsInfinity(rayIntersectionT);
        bool   hasIntersectionSimd = !float.IsNaN(rayIntersectionTSimd) && !float.IsInfinity(rayIntersectionTSimd);

        if (hasIntersection)
        {
            IntersectionMarker.transform.position = intersection;
        }
        IntersectionMarker.gameObject.SetActive(hasIntersection);

        Assert.AreEqual(hasIntersection, hasIntersectionSimd, "SIMD code doesn't agree with reference as to whether there is an intersection.");
        if (hasIntersection && hasIntersectionSimd)
        {
            Assert.AreApproximatelyEqual(rayIntersectionT, rayIntersectionTSimd, $"SIMD code returned intersection parameter {rayIntersectionTSimd} which is too far from actual intersection {rayIntersectionT}.");
        }
    }
        public void BeforeFrameRendering()
        {
            Transform camTrans = cam.transform;

            perspCam.forward       = camTrans.forward;
            perspCam.up            = camTrans.up;
            perspCam.right         = camTrans.right;
            perspCam.position      = camTrans.position;
            perspCam.nearClipPlane = cam.nearClipPlane;
            perspCam.farClipPlane  = cam.farClipPlane;
            perspCam.aspect        = cam.aspect;
            perspCam.fov           = cam.fieldOfView;
            float3 *corners = stackalloc float3[8];

            PipelineFunctions.GetFrustumCorner(ref perspCam, corners);
            frustumMinPoint = corners[0];
            frustumMaxPoint = corners[0];
            for (int i = 1; i < 8; ++i)
            {
                frustumMinPoint = min(frustumMinPoint, corners[i]);
                frustumMaxPoint = max(frustumMaxPoint, corners[i]);
            }
            PipelineFunctions.GetPerspFrustumPlanesWithCorner(ref perspCam, frustumArray.unsafePtr, corners + 4);
        }
Exemple #14
0
    public static void GetFrustumCorner(Camera camera, float3 *corners)
    {
        float fov = tan(Mathf.Deg2Rad * camera.fieldOfView * 0.5f);

        void GetCorner(float dist, ref Camera persp)
        {
            Transform trs = camera.transform;

            float  upLength    = dist * (fov);
            float  rightLength = upLength * persp.aspect;
            float3 farPoint    = trs.position + dist * trs.forward;
            float3 upVec       = upLength * trs.up;
            float3 rightVec    = rightLength * trs.right;

            corners[0] = farPoint - upVec - rightVec;
            corners[1] = farPoint - upVec + rightVec;
            corners[2] = farPoint + upVec - rightVec;
            corners[3] = farPoint + upVec + rightVec;
            corners   += 4;
        }

        GetCorner(camera.nearClipPlane, ref camera);
        GetCorner(camera.farClipPlane, ref camera);
    }
        public unsafe void Append(float3 *vertices, int verticesLength, int *indices, int indicesLength, byte area = DtArea.WALKABLE)
        {
            // Copy vertices
            int vbase = Vertices.Length;

            for (int i = 0; i < verticesLength; i++)
            {
                Vertices.Add(vertices[i]);
                BoundingBox = DtBoundingBox.Merge(BoundingBox, vertices[i]);
            }

            // Copy indices with offset applied
            for (int i = 0; i < indicesLength; i++)
            {
                Indices.Add(indices[i] + vbase);
            }

            int triangleCount = indicesLength / 3;

            for (int i = 0; i < triangleCount; i++)
            {
                Areas.Add(area);
            }
        }
        /// <summary>
        /// Schedules a job that converts input data into float3 arrays.
        /// </summary>
        /// <param name="input">Points at the input data in memory</param>
        /// <param name="count">Attribute quantity</param>
        /// <param name="inputType">Input data type</param>
        /// <param name="inputByteStride">Input byte stride</param>
        /// <param name="output">Points at the destination buffer in memory</param>
        /// <param name="outputByteStride">Ouput byte stride</param>
        /// <param name="normalized">If true, integer values have to be normalized</param>
        /// <param name="ensureUnitLength">If true, normalized values will be scaled to have unit length again (only if <see cref="normalized"/>is true)</param>
        /// <returns></returns>
        public static unsafe JobHandle?GetVector3sJob(
            void *input,
            int count,
            GLTFComponentType inputType,
            int inputByteStride,
            float3 *output,
            int outputByteStride,
            bool normalized       = false,
            bool ensureUnitLength = true
            )
        {
            JobHandle?jobHandle;

            Profiler.BeginSample("GetVector3sJob");
            if (inputType == GLTFComponentType.Float)
            {
                var job = new ConvertVector3FloatToFloatInterleavedJob {
                    inputByteStride  = (inputByteStride > 0) ? inputByteStride : 12,
                    input            = (byte *)input,
                    outputByteStride = outputByteStride,
                    result           = output
                };
#if UNITY_JOBS
                jobHandle = job.ScheduleBatch(count, GltfImport.DefaultBatchCount);
#else
                jobHandle = job.Schedule(count, GltfImport.DefaultBatchCount);
#endif
            }
            else
            if (inputType == GLTFComponentType.UnsignedShort)
            {
                if (normalized)
                {
                    var job = new ConvertPositionsUInt16ToFloatInterleavedNormalizedJob {
                        inputByteStride  = (inputByteStride > 0) ? inputByteStride : 6,
                        input            = (byte *)input,
                        outputByteStride = outputByteStride,
                        result           = output
                    };
#if UNITY_JOBS
                    jobHandle = job.ScheduleBatch(count, GltfImport.DefaultBatchCount);
#else
                    jobHandle = job.Schedule(count, GltfImport.DefaultBatchCount);
#endif
                }
                else
                {
                    var job = new ConvertPositionsUInt16ToFloatInterleavedJob {
                        inputByteStride  = (inputByteStride > 0) ? inputByteStride : 6,
                        input            = (byte *)input,
                        outputByteStride = outputByteStride,
                        result           = output
                    };
#if UNITY_JOBS
                    jobHandle = job.ScheduleBatch(count, GltfImport.DefaultBatchCount);
#else
                    jobHandle = job.Schedule(count, GltfImport.DefaultBatchCount);
#endif
                }
            }
            else
            if (inputType == GLTFComponentType.Short)
            {
                if (normalized)
                {
                    if (ensureUnitLength)
                    {
                        // TODO: test. did not have test files
                        var job = new ConvertNormalsInt16ToFloatInterleavedNormalizedJob {
                            inputByteStride  = (inputByteStride > 0) ? inputByteStride : 6,
                            input            = (byte *)input,
                            outputByteStride = outputByteStride,
                            result           = output
                        };
#if UNITY_JOBS
                        jobHandle = job.ScheduleBatch(count, GltfImport.DefaultBatchCount);
#else
                        jobHandle = job.Schedule(count, GltfImport.DefaultBatchCount);
#endif
                    }
                    else
                    {
                        var job = new ConvertVector3Int16ToFloatInterleavedNormalizedJob {
                            inputByteStride  = (inputByteStride > 0) ? inputByteStride : 6,
                            input            = (byte *)input,
                            outputByteStride = outputByteStride,
                            result           = output
                        };
#if UNITY_JOBS
                        jobHandle = job.ScheduleBatch(count, GltfImport.DefaultBatchCount);
#else
                        jobHandle = job.Schedule(count, GltfImport.DefaultBatchCount);
#endif
                    }
                }
                else
                {
                    var job = new ConvertPositionsInt16ToFloatInterleavedJob {
                        inputByteStride  = (inputByteStride > 0) ? inputByteStride : 6,
                        input            = (byte *)input,
                        outputByteStride = outputByteStride,
                        result           = output
                    };
#if UNITY_JOBS
                    jobHandle = job.ScheduleBatch(count, GltfImport.DefaultBatchCount);
#else
                    jobHandle = job.Schedule(count, GltfImport.DefaultBatchCount);
#endif
                }
            }
            else
            if (inputType == GLTFComponentType.Byte)
            {
                if (normalized)
                {
                    if (ensureUnitLength)
                    {
                        var job = new ConvertNormalsInt8ToFloatInterleavedNormalizedJob {
                            input            = (sbyte *)input,
                            inputByteStride  = (inputByteStride > 0) ? inputByteStride : 3,
                            outputByteStride = outputByteStride,
                            result           = output
                        };
    #if UNITY_JOBS
                        jobHandle = job.ScheduleBatch(count, GltfImport.DefaultBatchCount);
    #else
                        jobHandle = job.Schedule(count, GltfImport.DefaultBatchCount);
    #endif
                    }
                    else
                    {
                        var job = new ConvertVector3Int8ToFloatInterleavedNormalizedJob()
                        {
                            input            = (sbyte *)input,
                            inputByteStride  = (inputByteStride > 0) ? inputByteStride : 3,
                            outputByteStride = outputByteStride,
                            result           = output
                        };
#if UNITY_JOBS
                        jobHandle = job.ScheduleBatch(count, GltfImport.DefaultBatchCount);
#else
                        jobHandle = job.Schedule(count, GltfImport.DefaultBatchCount);
#endif
                    }
                }
                else
                {
                    // TODO: test positions. did not have test files
                    var job = new ConvertPositionsInt8ToFloatInterleavedJob {
                        inputByteStride  = inputByteStride > 0 ? inputByteStride : 3,
                        input            = (sbyte *)input,
                        outputByteStride = outputByteStride,
                        result           = output
                    };
#if UNITY_JOBS
                    jobHandle = job.ScheduleBatch(count, GltfImport.DefaultBatchCount);
#else
                    jobHandle = job.Schedule(count, GltfImport.DefaultBatchCount);
#endif
                }
            }
            else
            if (inputType == GLTFComponentType.UnsignedByte)
            {
                // TODO: test. did not have test files
                if (normalized)
                {
                    var job = new ConvertPositionsUInt8ToFloatInterleavedNormalizedJob {
                        input            = (byte *)input,
                        inputByteStride  = (inputByteStride > 0) ? inputByteStride : 3,
                        outputByteStride = outputByteStride,
                        result           = output
                    };
#if UNITY_JOBS
                    jobHandle = job.ScheduleBatch(count, GltfImport.DefaultBatchCount);
#else
                    jobHandle = job.Schedule(count, GltfImport.DefaultBatchCount);
#endif
                }
                else
                {
                    var job = new ConvertPositionsUInt8ToFloatInterleavedJob {
                        input            = (byte *)input,
                        inputByteStride  = (inputByteStride > 0) ? inputByteStride : 3,
                        outputByteStride = outputByteStride,
                        result           = output
                    };
#if UNITY_JOBS
                    jobHandle = job.ScheduleBatch(count, GltfImport.DefaultBatchCount);
#else
                    jobHandle = job.Schedule(count, GltfImport.DefaultBatchCount);
#endif
                }
            }
            else
            {
                Debug.LogError("Unknown componentType");
                jobHandle = null;
            }
            Profiler.EndSample();
            return(jobHandle);
        }
 static float FindTriangleIntersectionSimd(float3 *vertices, int *indices, int numTriangles, RayData *ray)
 {
     // YOUR SIMD CODE HERE
     return(float.PositiveInfinity);
 }
        // TODO: sort by using plane information instead of unreliable floating point math ..
        unsafe static void SortIndices(float3 *vertices, int2 *sortedStack, ushort *indices, int offset, int indicesCount, float3 normal)
        {
            // There's no point in trying to sort a point or a line
            if (indicesCount < 3)
            {
                return;
            }

            float3 tangentX, tangentY;

            if (normal.x > normal.y)
            {
                if (normal.x > normal.z)
                {
                    tangentX = math.cross(normal, new float3(0, 1, 0));
                    tangentY = math.cross(normal, tangentX);
                }
                else
                {
                    tangentX = math.cross(normal, new float3(0, 0, 1));
                    tangentY = math.cross(normal, tangentX);
                }
            }
            else
            {
                if (normal.y > normal.z)
                {
                    tangentX = math.cross(normal, new float3(1, 0, 0));
                    tangentY = math.cross(normal, tangentX);
                }
                else
                {
                    tangentX = math.cross(normal, new float3(0, 1, 0));
                    tangentY = math.cross(normal, tangentX);
                }
            }

            var centroid = FindPolygonCentroid(vertices, indices, offset, indicesCount);
            var center   = new float2(math.dot(tangentX, centroid),  // distance in direction of tangentX
                                      math.dot(tangentY, centroid)); // distance in direction of tangentY


            var sortedStackLength = 1;

            sortedStack[0] = new int2(0, indicesCount - 1);
            while (sortedStackLength > 0)
            {
                var top = sortedStack[sortedStackLength - 1];
                sortedStackLength--;
                var l     = top.x;
                var r     = top.y;
                var left  = l;
                var right = r;
                var va    = vertices[indices[offset + (left + right) / 2]];
                while (true)
                {
                    var a_angle = math.atan2(math.dot(tangentX, va) - center.x, math.dot(tangentY, va) - center.y);

                    {
                        var vb      = vertices[indices[offset + left]];
                        var b_angle = math.atan2(math.dot(tangentX, vb) - center.x, math.dot(tangentY, vb) - center.y);
                        while (b_angle > a_angle)
                        {
                            left++;
                            vb      = vertices[indices[offset + left]];
                            b_angle = math.atan2(math.dot(tangentX, vb) - center.x, math.dot(tangentY, vb) - center.y);
                        }
                    }

                    {
                        var vb      = vertices[indices[offset + right]];
                        var b_angle = math.atan2(math.dot(tangentX, vb) - center.x, math.dot(tangentY, vb) - center.y);
                        while (a_angle > b_angle)
                        {
                            right--;
                            vb      = vertices[indices[offset + right]];
                            b_angle = math.atan2(math.dot(tangentX, vb) - center.x, math.dot(tangentY, vb) - center.y);
                        }
                    }

                    if (left <= right)
                    {
                        if (left != right)
                        {
                            var t = indices[offset + left];
                            indices[offset + left]  = indices[offset + right];
                            indices[offset + right] = t;
                        }

                        left++;
                        right--;
                    }
                    if (left > right)
                    {
                        break;
                    }
                }
                if (l < right)
                {
                    sortedStack[sortedStackLength] = new int2(l, right);
                    sortedStackLength++;
                }
                if (left < r)
                {
                    sortedStack[sortedStackLength] = new int2(left, r);
                    sortedStackLength++;
                }
            }
        }
Exemple #19
0
 public static unsafe extern IntPtr Build2(IntPtr builder, float3 *verts, int numVerts, int *inds, int numInds, byte *areas);
        // Add but make the assumption we're not growing any list
        public unsafe static ushort AddNoResize(ushort *hashTable, ushort *chainedIndicesPtr, float3 *verticesPtr, ref int verticesLength, float3 vertex)
        {
            var centerIndex = new int3((int)(vertex.x / HashedVertices.kCellSize), (int)(vertex.y / HashedVertices.kCellSize), (int)(vertex.z / HashedVertices.kCellSize));
            var offsets     = stackalloc int3[]
            {
                new int3(-1, -1, -1), new int3(-1, -1, 0), new int3(-1, -1, +1),
                new int3(-1, 0, -1), new int3(-1, 0, 0), new int3(-1, 0, +1),
                new int3(-1, +1, -1), new int3(-1, +1, 0), new int3(-1, +1, +1),

                new int3(0, -1, -1), new int3(0, -1, 0), new int3(0, -1, +1),
                new int3(0, 0, -1), new int3(0, 0, 0), new int3(0, 0, +1),
                new int3(0, +1, -1), new int3(0, +1, 0), new int3(0, +1, +1),

                new int3(+1, -1, -1), new int3(+1, -1, 0), new int3(+1, -1, +1),
                new int3(+1, 0, -1), new int3(+1, 0, 0), new int3(+1, 0, +1),
                new int3(+1, +1, -1), new int3(+1, +1, 0), new int3(+1, +1, +1)
            };

            ushort closestVertexIndex = ushort.MaxValue;

            for (int i = 0; i < 3 * 3 * 3; i++)
            {
                var index      = centerIndex + offsets[i];
                var chainIndex = ((int)hashTable[GetHash(index)]) - 1;
                {
                    float closestDistance = CSGConstants.kSqrVertexEqualEpsilon;
                    while (chainIndex != -1)
                    {
                        var nextChainIndex = chainedIndicesPtr[chainIndex] - 1;
                        var sqrDistance    = math.lengthsq(verticesPtr[chainIndex] - vertex);
                        if (sqrDistance < closestDistance)
                        {
                            closestVertexIndex = (ushort)chainIndex;
                            closestDistance    = sqrDistance;
                        }
                        chainIndex = nextChainIndex;
                    }
                }
            }
            if (closestVertexIndex != ushort.MaxValue)
            {
                return(closestVertexIndex);
            }

            // Add Unique vertex
            {
                var newChainIndex = verticesLength;
                verticesLength++;

                var hashCode       = GetHash(centerIndex);
                var prevChainIndex = hashTable[hashCode];
                hashTable[(int)hashCode] = (ushort)(newChainIndex + 1);

                verticesPtr[newChainIndex]       = vertex;
                chainedIndicesPtr[newChainIndex] = (ushort)prevChainIndex;

                return((ushort)newChainIndex);
            }
        }
    }
Exemple #21
0
 /// <summary>
 /// Generalized convex-convex distance.
 /// </summary>
 /// <param name="verticesA">Vertices of the first collider in local space</param>
 /// <param name="verticesB">Vertices of the second collider in local space</param>
 /// <param name="aFromB">Transform from the local space of B to the local space of A</param>
 /// <param name="penetrationHandling">How to compute penetration.</param>
 /// <returns></returns>
 public static unsafe Result ConvexConvex(
     float3 *verticesA, int numVerticesA, float3 *verticesB, int numVerticesB,
     [NoAlias] in MTransform aFromB, PenetrationHandling penetrationHandling)
		/// <summary>
		/// Creates a new CudaRegisteredHostMemory_float3 from an existing IntPtr. IntPtr must be page size aligned (4KBytes)!
		/// </summary>
		/// <param name="hostPointer">must be page size aligned (4KBytes)</param>
		/// <param name="size">In elements</param>
		public CudaRegisteredHostMemory_float3(IntPtr hostPointer, SizeT size)
		{
			_intPtr = hostPointer;
			_size = size;
			_typeSize = (SizeT)Marshal.SizeOf(typeof(float3));
			_ptr = (float3*)_intPtr;
		}
Exemple #23
0
        /// <summary>
        /// Generalized convex-convex distance.
        /// </summary>
        /// <param name="verticesA">Vertices of the first collider in local space</param>
        /// <param name="verticesB">Vertices of the second collider in local space</param>
        /// <param name="aFromB">Transform from the local space of B to the local space of A</param>
        /// <param name="penetrationHandling">How to compute penetration.</param>
        /// <returns></returns>
        public static unsafe Result ConvexConvex(
            float3 *verticesA, int numVerticesA, float3 *verticesB, int numVerticesB,
            MTransform aFromB, PenetrationHandling penetrationHandling)
        {
            const float epsTerminationSq = 1e-8f; // Main loop quits when it cannot find a point that improves the simplex by at least this much
            const float epsPenetrationSq = 1e-9f; // Epsilon used to check for penetration.  Should be smaller than shape cast ConvexConvex keepDistance^2.

            // Initialize simplex.
            Simplex simplex = new Simplex();

            simplex.NumVertices    = 1;
            simplex.A              = GetSupportingVertex(new float3(1, 0, 0), verticesA, numVerticesA, verticesB, numVerticesB, aFromB);
            simplex.Direction      = simplex.A.Xyz;
            simplex.ScaledDistance = math.lengthsq(simplex.A.Xyz);
            float scaleSq = simplex.ScaledDistance;

            // Iterate.
            int       iteration     = 0;
            bool      penetration   = false;
            const int maxIterations = 64;

            for (; iteration < maxIterations; ++iteration)
            {
                // Find a new support vertex
                SupportVertex newSv = GetSupportingVertex(-simplex.Direction, verticesA, numVerticesA, verticesB, numVerticesB, aFromB);

                // If the new vertex is not significantly closer to the origin, quit
                float scaledImprovement = math.dot(simplex.A.Xyz - newSv.Xyz, simplex.Direction);
                if (scaledImprovement * math.abs(scaledImprovement) < epsTerminationSq * scaleSq)
                {
                    break;
                }

                // Add the new vertex and reduce the simplex
                switch (simplex.NumVertices++)
                {
                case 1: simplex.B = newSv; break;

                case 2: simplex.C = newSv; break;

                default: simplex.D = newSv; break;
                }
                simplex.SolveDistance();

                // Check for penetration
                scaleSq = math.lengthsq(simplex.Direction);
                float scaledDistanceSq = simplex.ScaledDistance * simplex.ScaledDistance;
                if (simplex.NumVertices == 4 || scaledDistanceSq <= epsPenetrationSq * scaleSq)
                {
                    penetration = true;
                    break;
                }
            }

            // Finalize result.
            var ret = new Result {
                Iterations = iteration + 1
            };

            // Handle penetration.
            if (penetration && penetrationHandling != PenetrationHandling.DotNotCompute)
            {
                // Allocate a hull for EPA
                int verticesCapacity = 64;
                int triangleCapacity = 2 * verticesCapacity;
                ConvexHullBuilder.Vertex *  vertices  = stackalloc ConvexHullBuilder.Vertex[verticesCapacity];
                ConvexHullBuilder.Triangle *triangles = stackalloc ConvexHullBuilder.Triangle[triangleCapacity];
                var hull = new ConvexHullBuilder(vertices, verticesCapacity, triangles, triangleCapacity);

                // Initialize int space
                // TODO - either the hull should be robust when int space changes after points are already added, or the ability to do so should be removed, probably the latter
                // Currently for example a valid triangle can collapse to a line segment when the bounds grow
                hull.IntegerSpaceAabb = GetSupportingAabb(verticesA, numVerticesA, verticesB, numVerticesB, aFromB);

                // Add simplex vertices to the hull, remove any vertices from the simplex that do not increase the hull dimension
                hull.AddPoint(simplex.A.Xyz, simplex.A.Id);
                if (simplex.NumVertices > 1)
                {
                    hull.AddPoint(simplex.B.Xyz, simplex.B.Id);
                    if (simplex.NumVertices > 2)
                    {
                        int dimension = hull.Dimension;
                        hull.AddPoint(simplex.C.Xyz, simplex.C.Id);
                        if (dimension == 0 && hull.Dimension == 1)
                        {
                            simplex.B = simplex.C;
                        }
                        if (simplex.NumVertices > 3)
                        {
                            dimension = hull.Dimension;
                            hull.AddPoint(simplex.D.Xyz, simplex.D.Id);
                            if (dimension > hull.Dimension)
                            {
                                if (dimension == 0)
                                {
                                    simplex.B = simplex.D;
                                }
                                else if (dimension == 1)
                                {
                                    simplex.C = simplex.D;
                                }
                            }
                        }
                    }
                }
                simplex.NumVertices = (hull.Dimension + 1);

                // If the simplex is not 3D, try expanding the hull in all directions
                while (hull.Dimension < 3)
                {
                    // Choose expansion directions
                    float3 support0, support1, support2;
                    switch (simplex.NumVertices)
                    {
                    case 1:
                        support0 = new float3(1, 0, 0);
                        support1 = new float3(0, 1, 0);
                        support2 = new float3(0, 0, 1);
                        break;

                    case 2:
                        Math.CalculatePerpendicularNormalized(math.normalize(simplex.B.Xyz - simplex.A.Xyz), out support0, out support1);
                        support2 = float3.zero;
                        break;

                    default:
                        UnityEngine.Assertions.Assert.IsTrue(simplex.NumVertices == 3);
                        support0 = math.cross(simplex.B.Xyz - simplex.A.Xyz, simplex.C.Xyz - simplex.A.Xyz);
                        support1 = float3.zero;
                        support2 = float3.zero;
                        break;
                    }

                    // Try each one
                    int  numSupports = 4 - simplex.NumVertices;
                    bool success     = false;
                    for (int i = 0; i < numSupports; i++)
                    {
                        for (int j = 0; j < 2; j++) // +/- each direction
                        {
                            SupportVertex vertex = GetSupportingVertex(support0, verticesA, numVerticesA, verticesB, numVerticesB, aFromB);
                            hull.AddPoint(vertex.Xyz, vertex.Id);
                            if (hull.Dimension == simplex.NumVertices)
                            {
                                switch (simplex.NumVertices)
                                {
                                case 1: simplex.B = vertex; break;

                                case 2: simplex.C = vertex; break;

                                default: simplex.D = vertex; break;
                                }

                                // Next dimension
                                success = true;
                                simplex.NumVertices++;
                                i = numSupports;
                                break;
                            }
                            support0 = -support0;
                        }
                        support0 = support1;
                        support1 = support2;
                    }

                    if (!success)
                    {
                        break;
                    }
                }

                // We can still fail to build a tetrahedron if the minkowski difference is really flat.
                // In those cases just find the closest point to the origin on the infinite extension of the simplex (point / line / plane)
                if (hull.Dimension != 3)
                {
                    switch (simplex.NumVertices)
                    {
                    case 1:
                    {
                        ret.ClosestPoints.Distance  = math.length(simplex.A.Xyz);
                        ret.ClosestPoints.NormalInA = -math.normalizesafe(simplex.A.Xyz, new float3(1, 0, 0));
                        break;
                    }

                    case 2:
                    {
                        float3 edge      = math.normalize(simplex.B.Xyz - simplex.A.Xyz);
                        float3 direction = math.cross(math.cross(edge, simplex.A.Xyz), edge);
                        Math.CalculatePerpendicularNormalized(edge, out float3 safeNormal, out float3 unused);     // backup, take any direction perpendicular to the edge
                        float3 normal = math.normalizesafe(direction, safeNormal);
                        ret.ClosestPoints.Distance  = math.dot(normal, simplex.A.Xyz);
                        ret.ClosestPoints.NormalInA = -normal;
                        break;
                    }

                    default:
                    {
                        UnityEngine.Assertions.Assert.IsTrue(simplex.NumVertices == 3);
                        float3 normal = math.normalize(math.cross(simplex.B.Xyz - simplex.A.Xyz, simplex.C.Xyz - simplex.A.Xyz));
                        float  dot    = math.dot(normal, simplex.A.Xyz);
                        ret.ClosestPoints.Distance  = math.abs(dot);
                        ret.ClosestPoints.NormalInA = math.select(-normal, normal, dot < 0);
                        break;
                    }
                    }
                }
                else
                {
                    int   closestTriangleIndex;
                    Plane closestPlane  = new Plane();
                    float stopThreshold = 1e-4f;
                    uint *uidsCache     = stackalloc uint[triangleCapacity];
                    for (int i = 0; i < triangleCapacity; i++)
                    {
                        uidsCache[i] = 0;
                    }
                    float *distancesCache = stackalloc float[triangleCapacity];
                    do
                    {
                        // Select closest triangle.
                        closestTriangleIndex = -1;
                        foreach (int triangleIndex in hull.Triangles.Indices)
                        {
                            if (hull.Triangles[triangleIndex].Uid != uidsCache[triangleIndex])
                            {
                                uidsCache[triangleIndex]      = hull.Triangles[triangleIndex].Uid;
                                distancesCache[triangleIndex] = hull.ComputePlane(triangleIndex).Distance;
                            }
                            if (closestTriangleIndex == -1 || distancesCache[closestTriangleIndex] < distancesCache[triangleIndex])
                            {
                                closestTriangleIndex = triangleIndex;
                            }
                        }
                        closestPlane = hull.ComputePlane(closestTriangleIndex);

                        // Add supporting vertex or exit.
                        SupportVertex sv  = GetSupportingVertex(closestPlane.Normal, verticesA, numVerticesA, verticesB, numVerticesB, aFromB);
                        float         d2P = math.dot(closestPlane.Normal, sv.Xyz) + closestPlane.Distance;
                        if (math.abs(d2P) > stopThreshold && hull.AddPoint(sv.Xyz, sv.Id))
                        {
                            stopThreshold *= 1.3f;
                        }
                        else
                        {
                            break;
                        }
                    } while (++iteration < maxIterations);

                    // Generate simplex.
                    ConvexHullBuilder.Triangle triangle = hull.Triangles[closestTriangleIndex];
                    simplex.NumVertices    = 3;
                    simplex.A.Xyz          = hull.Vertices[triangle.Vertex0].Position; simplex.A.Id = hull.Vertices[triangle.Vertex0].UserData;
                    simplex.B.Xyz          = hull.Vertices[triangle.Vertex1].Position; simplex.B.Id = hull.Vertices[triangle.Vertex1].UserData;
                    simplex.C.Xyz          = hull.Vertices[triangle.Vertex2].Position; simplex.C.Id = hull.Vertices[triangle.Vertex2].UserData;
                    simplex.Direction      = -closestPlane.Normal;
                    simplex.ScaledDistance = closestPlane.Distance;

                    // Set normal and distance.
                    ret.ClosestPoints.NormalInA = -closestPlane.Normal;
                    ret.ClosestPoints.Distance  = closestPlane.Distance;
                }
            }
            else
            {
                // Compute distance and normal.
                float lengthSq    = math.lengthsq(simplex.Direction);
                float invLength   = math.rsqrt(lengthSq);
                bool  smallLength = lengthSq < 1e-10f;
                ret.ClosestPoints.Distance  = math.select(simplex.ScaledDistance * invLength, 0.0f, smallLength);
                ret.ClosestPoints.NormalInA = math.select(simplex.Direction * invLength, new float3(1, 0, 0), smallLength);

                // Make sure the normal is always valid.
                if (!math.all(math.isfinite(ret.ClosestPoints.NormalInA)))
                {
                    ret.ClosestPoints.NormalInA = new float3(1, 0, 0);
                }
            }

            // Compute position.
            float3 closestPoint = ret.ClosestPoints.NormalInA * ret.ClosestPoints.Distance;
            float4 coordinates  = simplex.ComputeBarycentricCoordinates(closestPoint);

            ret.ClosestPoints.PositionOnAinA =
                verticesA[simplex.A.IdA] * coordinates.x +
                verticesA[simplex.B.IdA] * coordinates.y +
                verticesA[simplex.C.IdA] * coordinates.z +
                verticesA[simplex.D.IdA] * coordinates.w;

            // Encode simplex.
            ret.Simplex.x = simplex.A.Id;
            ret.Simplex.y = simplex.NumVertices >= 2 ? simplex.B.Id : Result.InvalidSimplexVertex;
            ret.Simplex.z = simplex.NumVertices >= 3 ? simplex.C.Id : Result.InvalidSimplexVertex;

            // Done.
            UnityEngine.Assertions.Assert.IsTrue(math.isfinite(ret.ClosestPoints.Distance));
            UnityEngine.Assertions.Assert.IsTrue(math.abs(math.lengthsq(ret.ClosestPoints.NormalInA) - 1.0f) < 1e-5f);
            return(ret);
        }
    protected override unsafe void OnUpdate()
    {
        EntityQuery          query   = GetEntityQuery(ComponentType.ReadWrite <TrailBufferElement>());
        NativeArray <Entity> entitis = query.ToEntityArray(Allocator.Persistent);
        int segmentCount             = entitis.Length;
        int trailElementCount        = 0;
        BufferFromEntity <TrailBufferElement> buffers = GetBufferFromEntity <TrailBufferElement>();

        for (int i = 0; i < entitis.Length; ++i)
        {
            trailElementCount += buffers[entitis[i]].Length;
        }

        if (!m_TrailElements.IsCreated || m_TrailElements.Length < trailElementCount)
        {
            if (m_TrailElements.IsCreated)
            {
                m_TrailElements.Dispose();
            }
            m_TrailElements = new NativeArray <float3>(CalcWrappingArraySize(trailElementCount), Allocator.Persistent);

            m_TrailElementBufferInShader?.Dispose();
            m_TrailElementBufferInShader = new ComputeBuffer(m_TrailElements.Length, sizeof(TrailBufferElement));
        }

        if (!m_Segments.IsCreated || m_Segments.Length < segmentCount)
        {
            if (m_Segments.IsCreated)
            {
                m_Segments.Dispose();
            }
            m_Segments = new NativeArray <int3>(CalcWrappingArraySize(segmentCount), Allocator.Persistent);

            m_SegmentBufferInShader?.Dispose();
            m_SegmentBufferInShader = new ComputeBuffer(m_Segments.Length, sizeof(TrailBufferElement));
        }

        int     offset           = 0;
        float3 *trailElementsPtr = (float3 *)m_TrailElements.GetUnsafePtr();
        int3 *  segmentsPtr      = (int3 *)m_Segments.GetUnsafePtr();

        for (int i = 0; i < segmentCount; ++i)
        {
            DynamicBuffer <float3> trailbuffer = buffers[entitis[i]].Reinterpret <float3>();
            Entity entity = entitis[i];

            int bufferlength = trailbuffer.Length;

            UnsafeUtility.MemCpy(trailElementsPtr, trailbuffer.GetUnsafePtr(), sizeof(float3) * bufferlength);
            *segmentsPtr = new int3(offset, bufferlength, entity.Index);

            offset += bufferlength;

            segmentsPtr++;
            trailElementsPtr += bufferlength;

            for (int j = 0; j < trailbuffer.Length; ++j)
            {
                if (trailbuffer[j].x == 0.0f && trailbuffer[j].y == 0.0f && trailbuffer[j].z == 0.0f)
                {
                    Debug.Log(entity.Index);
                }
            }
        }

        m_TrailElementBufferInShader.SetData(m_TrailElements);
        m_SegmentBufferInShader.SetData(m_Segments);

        m_MaterialPropertyBlock.SetBuffer("_Positions", m_TrailElementBufferInShader);
        m_MaterialPropertyBlock.SetBuffer("_Segments", m_SegmentBufferInShader);

        m_MeshInstancedArgs.SetData(m_TrailMesh, (uint)segmentCount);

        Graphics.DrawMeshInstancedIndirect(
            m_TrailMesh, 0, m_Material,
            new Bounds(Vector3.zero, Vector3.one * 1000),
            m_MeshInstancedArgs.m_Buffer, 0, m_MaterialPropertyBlock
            );

        entitis.Dispose();
    }
Exemple #25
0
 public static void GetPerspFrustumPlanesWithCorner(ref PerspCam perspCam, float4 *planes, float3 *corners)
 {
     planes[0] = MathLib.GetPlane(corners[1], corners[0], perspCam.position);
     planes[1] = MathLib.GetPlane(corners[2], corners[3], perspCam.position);
     planes[2] = MathLib.GetPlane(corners[0], corners[2], perspCam.position);
     planes[3] = MathLib.GetPlane(corners[3], corners[1], perspCam.position);
     planes[4] = MathLib.GetPlane(perspCam.forward, perspCam.position + perspCam.forward * perspCam.farClipPlane);
     planes[5] = MathLib.GetPlane(-perspCam.forward, perspCam.position + perspCam.forward * perspCam.nearClipPlane);
 }
        // Tries to generate a manifold between a pair of faces.  It can fail in some cases due to numerical accuracy:
        // 1) both faces are nearly perpendicular to the normal
        // 2) the closest features on the shapes are vertices, so that the intersection of the projection of the faces to the plane perpendicular to the normal contains only one point
        // In those cases, FaceFace() returns false and the caller should generate a contact from the closest points on the shapes.
        private static unsafe bool FaceFace(
            ref ConvexHull convexA, ref ConvexHull convexB, int faceIndexA, int faceIndexB, MTransform worldFromA, MTransform aFromB,
            float3 normal, float distance, ref Manifold manifold)
        {
            // Get the plane of each face
            Plane planeA = convexA.Planes[faceIndexA];
            Plane planeB = TransformPlane(aFromB, convexB.Planes[faceIndexB]);

            // Handle cases where one of the faces is nearly perpendicular to the contact normal
            // This gets around divide by zero / numerical problems from dividing collider planes which often contain some error by a very small number, amplifying that error
            const float cosMaxAngle = 0.05f;
            float       dotA        = math.dot(planeA.Normal, normal);
            float       dotB        = math.dot(planeB.Normal, normal);
            bool        acceptB     = true; // true if vertices of B projected onto the face of A are accepted

            if (dotA > -cosMaxAngle)
            {
                // Handle cases where both faces are nearly perpendicular to the contact normal.
                if (dotB < cosMaxAngle)
                {
                    // Both faces are nearly perpendicular to the contact normal, let the caller generate a single contact
                    return(false);
                }

                // Face of A is nearly perpendicular to the contact normal, don't try to project vertices onto it
                acceptB = false;
            }
            else if (dotB < cosMaxAngle)
            {
                // Face of B is nearly perpendicular to the normal, so we need to clip the edges of B against face A instead
                MTransform bFromA     = Inverse(aFromB);
                float3     normalInB  = math.mul(bFromA.Rotation, -normal);
                MTransform worldFromB = Mul(worldFromA, aFromB);
                bool       result     = FaceFace(ref convexB, ref convexA, faceIndexB, faceIndexA, worldFromB, bFromA, normalInB, distance, ref manifold);
                manifold.Normal = -manifold.Normal;
                manifold.Flip();
                return(result);
            }

            // Check if the manifold gets a point roughly as close as the closest
            distance += closestDistanceTolerance;
            bool foundClosestPoint = false;

            // Transform vertices of B into A-space
            // Initialize validB, which is true for each vertex of B that is inside face A
            ConvexHull.Face faceA        = convexA.Faces[faceIndexA];
            ConvexHull.Face faceB        = convexB.Faces[faceIndexB];
            bool *          validB       = stackalloc bool[faceB.NumVertices];
            float3 *        verticesBinA = stackalloc float3[faceB.NumVertices];
            {
                byte *  indicesB  = convexB.FaceVertexIndicesPtr + faceB.FirstIndex;
                float3 *verticesB = convexB.VerticesPtr;
                for (int i = 0; i < faceB.NumVertices; i++)
                {
                    validB[i]       = acceptB;
                    verticesBinA[i] = Mul(aFromB, verticesB[indicesB[i]]);
                }
            }

            // For each edge of A
            float   invDotB   = math.rcp(dotB);
            float   sumRadii  = convexA.ConvexRadius + convexB.ConvexRadius;
            byte *  indicesA  = convexA.FaceVertexIndicesPtr + faceA.FirstIndex;
            float3 *verticesA = convexA.VerticesPtr;

            for (EdgeIterator edgeA = EdgeIterator.Begin(verticesA, indicesA, -normal, faceA.NumVertices); edgeA.Valid(); edgeA.Advance())
            {
                float fracEnterA = 0.0f;
                float fracExitA  = 1.0f;

                // For each edge of B
                for (EdgeIterator edgeB = EdgeIterator.Begin(verticesBinA, null, normal, faceB.NumVertices); edgeB.Valid(); edgeB.Advance())
                {
                    // Cast edge A against plane B and test if vertex B is inside plane A
                    castRayPlane(edgeA.Vertex0, edgeA.Edge, edgeB.Perp, edgeB.Offset, ref fracEnterA, ref fracExitA);
                    validB[edgeB.Index] &= (math.dot(edgeB.Vertex1, edgeA.Perp) < edgeA.Offset);
                }

                // If edge A hits B, add a contact points
                if (fracEnterA < fracExitA)
                {
                    float  distance0     = (math.dot(edgeA.Vertex0, planeB.Normal) + planeB.Distance) * invDotB;
                    float  deltaDistance = math.dot(edgeA.Edge, planeB.Normal) * invDotB;
                    float3 vertexAOnB    = edgeA.Vertex0 - normal * distance0;
                    float3 edgeAOnB      = edgeA.Edge - normal * deltaDistance;
                    foundClosestPoint |= AddEdgeContact(vertexAOnB, edgeAOnB, distance0, deltaDistance, fracEnterA, normal, convexB.ConvexRadius, sumRadii, worldFromA, distance, ref manifold);
                    if (fracExitA < 1.0f) // If the exit fraction is 1, then the next edge has the same contact point with enter fraction 0
                    {
                        foundClosestPoint |= AddEdgeContact(vertexAOnB, edgeAOnB, distance0, deltaDistance, fracExitA, normal, convexB.ConvexRadius, sumRadii, worldFromA, distance, ref manifold);
                    }
                }
            }

            // For each vertex of B
            float invDotA = math.rcp(dotA);

            for (int i = 0; i < faceB.NumVertices; i++)
            {
                if (validB[i] && manifold.NumContacts < Manifold.k_MaxNumContacts)
                {
                    float3 vertexB   = verticesBinA[i];
                    float  distanceB = (math.dot(vertexB, planeA.Normal) + planeA.Distance) * -invDotA;
                    manifold[manifold.NumContacts++] = new ContactPoint
                    {
                        Position = Mul(worldFromA, vertexB) + manifold.Normal * convexB.ConvexRadius,
                        Distance = distanceB - sumRadii
                    };
                    foundClosestPoint |= distanceB <= distance;
                }
            }

            return(foundClosestPoint);
        }
Exemple #27
0
        public void FrameUpdate(PipelineCamera cam, ref PipelineCommandData data)
        {
            CommandBuffer buffer = data.buffer;

            if (!Decal.decalDatas.isCreated)
            {
                buffer.SetGlobalInt(_EnableDecal, 0);
                return;
            }
            buffer.SetGlobalInt(_EnableDecal, 1);
            handle.Complete();
            if (cullJob.count > decalBuffer.count)
            {
                int oldCount = decalBuffer.count;
                decalBuffer.Dispose();
                decalBuffer = new ComputeBuffer((int)max(oldCount * 1.5f, cullJob.count), sizeof(DecalStrct));
            }
            if (!minMaxBoundMat)
            {
                minMaxBoundMat = new Material(data.resources.shaders.minMaxDepthBounding);
            }
            int pixelWidth  = cam.cam.pixelWidth;
            int pixelHeight = cam.cam.pixelHeight;

            decalBuffer.SetDataPtr(sortJob.sortedDecalDatas.unsafePtr, 0, cullJob.count);
            buffer.GetTemporaryRT(_DownSampledDepth0, pixelWidth / 2, pixelHeight / 2, 0, FilterMode.Point, RenderTextureFormat.RGHalf, RenderTextureReadWrite.Linear, 1, false, RenderTextureMemoryless.None, false);
            buffer.GetTemporaryRT(_DownSampledDepth1, pixelWidth / 4, pixelHeight / 4, 0, FilterMode.Point, RenderTextureFormat.RGHalf, RenderTextureReadWrite.Linear, 1, false, RenderTextureMemoryless.None, false);
            buffer.GetTemporaryRT(_DownSampledDepth2, pixelWidth / 8, pixelHeight / 8, 0, FilterMode.Point, RenderTextureFormat.RGHalf, RenderTextureReadWrite.Linear, 1, false, RenderTextureMemoryless.None, false);
            buffer.GetTemporaryRT(_DownSampledDepth3, pixelWidth / 16, pixelHeight / 16, 0, FilterMode.Point, RenderTextureFormat.RGHalf, RenderTextureReadWrite.Linear, 1, false, RenderTextureMemoryless.None, false);
            buffer.BlitSRT(_DownSampledDepth0, minMaxBoundMat, 0);
            buffer.SetGlobalTexture(ShaderIDs._TargetDepthTexture, _DownSampledDepth0);
            buffer.BlitSRT(_DownSampledDepth1, minMaxBoundMat, 1);
            buffer.SetGlobalTexture(ShaderIDs._TargetDepthTexture, _DownSampledDepth1);
            buffer.BlitSRT(_DownSampledDepth2, minMaxBoundMat, 1);
            buffer.SetGlobalTexture(ShaderIDs._TargetDepthTexture, _DownSampledDepth2);
            buffer.BlitSRT(_DownSampledDepth3, minMaxBoundMat, 1);
            int2 tileSize = int2(pixelWidth / 16, pixelHeight / 16);
            RenderTextureDescriptor lightTileDisc = new RenderTextureDescriptor
            {
                autoGenerateMips  = false,
                bindMS            = false,
                colorFormat       = RenderTextureFormat.RInt,
                depthBufferBits   = 0,
                dimension         = TextureDimension.Tex3D,
                enableRandomWrite = true,
                width             = tileSize.x,
                height            = tileSize.y,
                msaaSamples       = 1,
                volumeDepth       = CBDRSharedData.MAXLIGHTPERTILE
            };

            buffer.GetTemporaryRT(ShaderIDs._DecalTile, lightTileDisc);
            tileSizeArray[0] = tileSize.x;
            tileSizeArray[1] = tileSize.y;
            float3 * corners  = stackalloc float3[4];
            PerspCam perspCam = new PerspCam
            {
                fov      = cam.cam.fieldOfView,
                up       = cam.cam.transform.up,
                right    = cam.cam.transform.right,
                forward  = cam.cam.transform.forward,
                position = cam.cam.transform.position,
                aspect   = cam.cam.aspect,
            };

            PipelineFunctions.GetFrustumCorner(ref perspCam, 1, corners);
            for (int i = 0; i < 4; ++i)
            {
                frustumCorners[i] = float4(corners[i], 1);
            }
            buffer.SetComputeVectorArrayParam(cbdrShader, ShaderIDs._FrustumCorners, frustumCorners);
            buffer.SetComputeVectorParam(cbdrShader, ShaderIDs._CameraPos, cam.cam.transform.position);
            buffer.SetComputeIntParams(cbdrShader, ShaderIDs._TileSize, tileSizeArray);
            buffer.SetGlobalVector(ShaderIDs._TileSize, new Vector4(tileSize.x, tileSize.y));
            buffer.SetComputeVectorParam(cbdrShader, ShaderIDs._CameraForward, cam.cam.transform.forward);
            buffer.SetComputeTextureParam(cbdrShader, CBDRSharedData.DecalCull, ShaderIDs._DepthBoundTexture, new RenderTargetIdentifier(_DownSampledDepth3));
            buffer.SetComputeTextureParam(cbdrShader, CBDRSharedData.DecalCull, ShaderIDs._DecalTile, new RenderTargetIdentifier(ShaderIDs._DecalTile));
            buffer.SetComputeBufferParam(cbdrShader, CBDRSharedData.DecalCull, ShaderIDs._AllDecals, decalBuffer);
            buffer.SetComputeIntParam(cbdrShader, ShaderIDs._DecalCount, cullJob.count);
            buffer.SetGlobalBuffer(ShaderIDs._AllDecals, decalBuffer);
            buffer.DispatchCompute(cbdrShader, CBDRSharedData.DecalCull, Mathf.CeilToInt(tileSize.x / 8f), Mathf.CeilToInt(tileSize.y / 8f), 1);
            buffer.ReleaseTemporaryRT(_DownSampledDepth0);
            buffer.ReleaseTemporaryRT(_DownSampledDepth1);
            buffer.ReleaseTemporaryRT(_DownSampledDepth2);
            buffer.ReleaseTemporaryRT(_DownSampledDepth3);
            RenderPipeline.ReleaseRTAfterFrame(ShaderIDs._DecalTile);
            decalCullResults.Dispose();
            decalCompareResults.Dispose();
        }
Exemple #28
0
 private static extern void AddPointToQueryStruct(int queryID, Entity e, float3 *vector3);
Exemple #29
0
 public static void GetfrustumCorners(float *planes, int planesCount, Camera cam, float3 *frustumCorners)
 {
     for (int i = 0; i < planesCount; ++i)
     {
         int   index = i * 4;
         float p     = planes[i];
         frustumCorners[index]     = cam.ViewportToWorldPoint(new Vector3(0, 0, p));
         frustumCorners[1 + index] = cam.ViewportToWorldPoint(new Vector3(0, 1, p));
         frustumCorners[2 + index] = cam.ViewportToWorldPoint(new Vector3(1, 1, p));
         frustumCorners[3 + index] = cam.ViewportToWorldPoint(new Vector3(1, 0, p));
     }
 }
Exemple #30
0
        public unsafe bool TryFindPath(NavQuerySettings querySettings, float3 start, float3 end, float3 *path, out int pathLength)
        {
            pathLength = 0;
            if (DtQuery == IntPtr.Zero)
            {
                return(false);
            }

            DtPathFindQuery query;

            query.Source                = start;
            query.Target                = end;
            query.MaxPathPoints         = querySettings.MaxPathPoints;
            query.FindNearestPolyExtent = querySettings.FindNearestPolyExtent;
            DtPathFindResult queryResult;

            queryResult.PathPoints = new IntPtr(path);
            Navigation.Query.FindStraightPath(DtQuery, ref query, new IntPtr(&queryResult));
            if (!queryResult.PathFound)
            {
                return(false);
            }

            pathLength = queryResult.NumPathPoints;
            return(true);
        }
Exemple #31
0
 private static extern int QueryNearestPoints(int queryID, float3 *vector3Array, float maxDist, float minDist, int nDst, void *dst);