예제 #1
0
 public void Init()
 {
     rng = new Random(1);
     f   = (float2 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float2>() * iterations, UnsafeUtility.AlignOf <float2>(), Allocator.Persistent);
     for (int i = 0; i < iterations; ++i)
     {
         f[i] = new float2(0.0f);
     }
 }
예제 #2
0
 /// <summary>
 /// Insert
 /// </summary>
 public Insertion(Entity obstacle, float4x4 ltw, float2 *vertices, int amount)
 {
     Type     = InsertionType.Insert;
     Obstacle = obstacle;
     Ltw      = ltw;
     Vertices = vertices;
     Amount   = amount;
     Amounts  = default;
 }
예제 #3
0
 /// <summary>
 /// Bulk Insert
 /// </summary>
 public TreeOperation(float4x4 ltw, float2 *verts, int *amounts, int length)
 {
     Type     = TreeOperationType.BulkInsert;
     Obstacle = default;
     Ltw      = ltw;
     Vertices = verts;
     Amount   = length;
     Amounts  = amounts;
 }
예제 #4
0
 /// <summary>
 /// Destroy
 /// </summary>
 public TreeOperation(Entity obstacle)
 {
     Type     = TreeOperationType.Destroy;
     Obstacle = obstacle;
     Ltw      = default;
     Vertices = default;
     Amount   = default;
     Amounts  = default;
 }
예제 #5
0
        public void InsertObstacle(Entity key, float4x4 ltw, float2 *vertices, int amount)
        {
            Assert.IsTrue(amount > 1);
            Assert.IsTrue(key != Entity.Null);
            Assert.IsTrue(!Map.ContainsKey(key));
            Assert.IsTrue(amount > 2 && math.all(vertices[0] == vertices[amount - 1]), "Obstacle needs to be counter cockwise wound and closed");

            Obstacle *first    = default;
            Obstacle *previous = default;

            var prevPos  = Math.Mul2D(ltw, vertices[0]);
            var prevPos2 = Math.Mul2D(ltw, vertices[amount - 2]);

            for (var i = 0; i < amount - 1; ++i)
            {
                var obstacle = ObstaclePool.GetElementPointer();
                obstacle->Point = prevPos;
                var pos  = Math.Mul2D(ltw, vertices[i + 1]);
                var aabb = AABB.FromOpposingCorners(prevPos, pos);
                obstacle->Id        = Tree.Insert(aabb, (IntPtr)obstacle);
                obstacle->Direction = math.normalize(pos - prevPos);

                if (amount == 2)
                {
                    obstacle->Convex = true;
                }
                else
                {
                    obstacle->Convex = LeftOf(prevPos2, prevPos, pos) >= 0;
                }

                prevPos2 = prevPos;
                prevPos  = pos;

                if (i == 0)
                {
                    first    = obstacle;
                    previous = obstacle;
                }
                else if (i < amount - 2)
                {
                    obstacle->Previous = previous;
                    previous->Next     = obstacle;
                    previous           = obstacle;
                }
                else
                {
                    obstacle->Previous = previous;
                    previous->Next     = obstacle;
                    first->Previous    = obstacle;
                    obstacle->Next     = first;
                }
            }

            Map.Add(key, (IntPtr)first);
예제 #6
0
        public void Execute(int i)
        {
            Particle p = ps[i];

            p.v = 0;

            uint2   cell_idx  = (uint2)p.pos;
            float2  cell_diff = (p.pos - cell_idx) - 0.5f;
            float2 *w         = stackalloc float2[3];

            w[0] = 0.5f * math.pow(0.5f - cell_diff, 2);
            w[1] = 0.75f - math.pow(cell_diff, 2);
            w[2] = 0.5f * math.pow(0.5f + cell_diff, 2);

            float2x2 B = 0;


            for (uint x = 0; x < 3; ++x)
            {
                for (uint y = 0; y < 3; ++y)
                {
                    float weight = w[x].x * w[y].y;

                    uint2  current_cell_idx = math.uint2(cell_idx.x + x - 1, cell_idx.y + y - 1);
                    float2 cell_dist        = (current_cell_idx - p.pos) + 0.5f;

                    int index_1d = (int)current_cell_idx.x * grid_res + (int)current_cell_idx.y;

                    float2 weighted_velocity = grid[index_1d].v * weight;

                    float2x2 term = math.float2x2(weighted_velocity * cell_dist.x, weighted_velocity * cell_dist.y);

                    B   += term;
                    p.v += weighted_velocity;
                }
            }
            p.C    = B * 4;
            p.pos += p.v * dt;
            p.pos  = math.clamp(p.pos, 1, grid_res - 2);

            float2 x_n      = p.pos + p.v;
            float  wall_min = 3 - 1;
            float  wall_max = (float)grid_res - 4 + 1;

            p.v.x += (x_n.x < wall_min) ? wall_min - x_n.x : 0;
            p.v.x += (x_n.x > wall_max) ? wall_max - x_n.x : 0;
            p.v.y += (x_n.y < wall_min) ? wall_min - x_n.y : 0;
            p.v.y += (x_n.y > wall_max) ? wall_max - x_n.y : 0;
            // if (x_n.x < wall_min) p.v.x += wall_min - x_n.x;
            // if (x_n.x > wall_max) p.v.x += wall_max - x_n.x;
            // if (x_n.y < wall_min) p.v.y += wall_min - x_n.y;
            // if (x_n.y > wall_max) p.v.y += wall_max - x_n.y;

            ps[i] = p;
        }
예제 #7
0
        public void Execute(int i)
        {
            Particle p = particles[i];

            // reset particle velocity
            p.v = 0;

            uint2   cell_index = (uint2)p.pos;
            float2  cell_diff  = (p.pos - cell_index) - 0.5f;
            float2 *w          = stackalloc float2[3];

            w[0] = 0.5f * math.pow(0.5f - cell_diff, 2);
            w[1] = 0.75f - math.pow(cell_diff, 2);
            w[2] = 0.5f * math.pow(0.5f + cell_diff, 2);

            // C = B * (D^-1), D=1/4 * (delta_x)^2 * I when using quadratic interpolation
            float2x2 B = 0;

            for (uint x = 0; x < 3; ++x)
            {
                for (uint y = 0; y < 3; ++y)
                {
                    float weight = w[x].x * w[y].y;

                    uint2 current_index = math.uint2(cell_index.x + x - 1, cell_index.y + y - 1);
                    int   index         = (int)current_index.x * grid_res + (int)current_index.y;

                    float2 dist = (current_index - p.pos) + 0.5f;
                    float2 weighted_velocity = grids[index].v * weight;

                    // APIC paper equation 10, constructing inner term for B
                    float2x2 term = math.float2x2(weighted_velocity * dist.x, weighted_velocity * dist.y);

                    B += term;

                    p.v += weighted_velocity;
                }
            }
            p.C    = B * 4;
            p.pos += p.v * dt;
            p.pos  = math.clamp(p.pos, 1, grid_res - 2);

            //deformation gradient update eqation-181
            float2x2 F_new = math.float2x2(
                1, 0,
                0, 1
                );

            F_new += dt * p.C;
            Fs[i]  = math.mul(F_new, Fs[i]);

            particles[i] = p;
        }
예제 #8
0
        public void Execute(int i)
        {
            Particle p      = particles[i];
            float2x2 F      = Fs[i];
            float2x2 stress = 0;

            float J      = math.determinant(F);
            float volume = p.volume0 * J;

            float2x2 F_T             = math.transpose(F);
            float2x2 inv_F_T         = math.inverse(F_T);
            float2x2 F_minus_inv_F_T = F - inv_F_T;

            float2x2 P = elastic_mu * F_minus_inv_F_T + elastic_lambda * math.log(J) * inv_F_T;

            stress = (1.0f / J) * math.mul(P, F_T);

            float2x2 eq_16_term_0 = -volume * 4 * stress * dt;

            uint2   cell_index = (uint2)p.pos;
            float2  cell_diff  = (p.pos - cell_index) - 0.5f;
            float2 *w          = stackalloc float2[3];

            w[0] = 0.5f * math.pow(0.5f - cell_diff, 2);
            w[1] = 0.75f - math.pow(cell_diff, 2);
            w[2] = 0.5f * math.pow(0.5f + cell_diff, 2);

            for (uint x = 0; x < 3; ++x)
            {
                for (uint y = 0; y < 3; ++y)
                {
                    float  weight        = w[x].x * w[y].y;
                    uint2  current_index = math.uint2(cell_index.x + x - 1, cell_index.y + y - 1);
                    float2 dist          = (current_index - p.pos) + 0.5f;
                    float2 Q             = math.mul(p.C, dist);

                    int  index_1d = (int)current_index.x * grid_res + (int)current_index.y;
                    Cell c        = grids[index_1d];

                    float mass_contribute = weight * p.mass;
                    c.mass += mass_contribute;

                    c.v += mass_contribute * (p.v + Q);

                    float2 momentum = math.mul(eq_16_term_0 * weight, dist);
                    c.v += momentum;
                    // current cell.v is w_ij * (dt * M^-1 * p.volume * p.stress + p.mass * p.C)

                    grids[index_1d] = c;
                }
            }
        }
                public void Init()
                {
                    rng = (Random *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <Random>() * 10000, UnsafeUtility.AlignOf <Random>(), Allocator.Persistent);
                    for (int i = 0; i < 10000; ++i)
                    {
                        rng[i] = new Unity.Mathematics.Random(1);
                    }

                    f = (float2 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float2>() * 10000, UnsafeUtility.AlignOf <float2>(), Allocator.Persistent);
                    for (int i = 0; i < 10000; ++i)
                    {
                        f[i] = new float2(0.0f);
                    }
                }
예제 #10
0
                public void Init()
                {
                    m1 = (float2x2 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float2x2>() * 10000, UnsafeUtility.AlignOf <float2x2>(), Allocator.Persistent);
                    for (int i = 0; i < 10000; ++i)
                    {
                        m1[i] = float2x2.identity;
                    }

                    m2 = (float2 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float2>() * 10000, UnsafeUtility.AlignOf <float2>(), Allocator.Persistent);
                    for (int i = 0; i < 10000; ++i)
                    {
                        m2[i] = new float2(1.0f, 0.0f);
                    }
                }
예제 #11
0
                public void Init()
                {
                    sin = (float2 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float2>() * 10000, UnsafeUtility.AlignOf <float2>(), Allocator.Persistent);
                    for (int i = 0; i < 10000; ++i)
                    {
                        sin[i] = new float2(0.0f);
                    }

                    cos = (float2 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float2>() * 10000, UnsafeUtility.AlignOf <float2>(), Allocator.Persistent);
                    for (int i = 0; i < 10000; ++i)
                    {
                        cos[i] = new float2(1.0f);
                    }
                }
예제 #12
0
                public void Init()
                {
                    v = (float2 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float2>() * 100000, UnsafeUtility.AlignOf <float2>(), Allocator.Persistent);
                    for (int i = 0; i < 100000; ++i)
                    {
                        v[i] = new float2(1.0f);
                    }

                    hash = (uint *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <uint>() * 100000, UnsafeUtility.AlignOf <uint>(), Allocator.Persistent);
                    for (int i = 0; i < 100000; ++i)
                    {
                        hash[i] = 0;
                    }
                }
예제 #13
0
        private static unsafe void TessellateBurst(Allocator allocator, float2 *points, int pointCount, int2 *edges, int edgeCount, float2 *outVertices, int *outIndices, int2 *outEdges, int arrayCount, int3 *result)
        {
            NativeArray <int2> _edges = new NativeArray <int2>(edgeCount, allocator);

            for (int i = 0; i < _edges.Length; ++i)
            {
                _edges[i] = edges[i];
            }

            NativeArray <float2> _points = new NativeArray <float2>(pointCount, allocator);

            for (int i = 0; i < _points.Length; ++i)
            {
                _points[i] = points[i];
            }

            NativeArray <int>    _outIndices  = new NativeArray <int>(arrayCount, allocator);
            NativeArray <int2>   _outEdges    = new NativeArray <int2>(arrayCount, allocator);
            NativeArray <float2> _outVertices = new NativeArray <float2>(arrayCount, allocator);

            int outEdgeCount   = 0;
            int outIndexCount  = 0;
            int outVertexCount = 0;

            ModuleHandle.Tessellate(allocator, _points, _edges, ref _outVertices, ref outVertexCount, ref _outIndices, ref outIndexCount, ref _outEdges, ref outEdgeCount);

            for (int i = 0; i < outEdgeCount; ++i)
            {
                outEdges[i] = _outEdges[i];
            }
            for (int i = 0; i < outIndexCount; ++i)
            {
                outIndices[i] = _outIndices[i];
            }
            for (int i = 0; i < outVertexCount; ++i)
            {
                outVertices[i] = _outVertices[i];
            }

            result->x = outVertexCount;
            result->y = outIndexCount;
            result->z = outEdgeCount;

            _outVertices.Dispose();
            _outEdges.Dispose();
            _outIndices.Dispose();
            _points.Dispose();
            _edges.Dispose();
        }
                public void Init()
                {
                    rng = new Random(1);
                    v   = (float2 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float2>() * iterations, UnsafeUtility.AlignOf <float2>(), Allocator.Persistent);
                    for (int i = 0; i < iterations; ++i)
                    {
                        v[i] = new float2(1.0f);
                    }

                    hash = (uint *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <uint>() * iterations, UnsafeUtility.AlignOf <uint>(), Allocator.Persistent);
                    for (int i = 0; i < iterations; ++i)
                    {
                        hash[i] = 0;
                    }
                }
예제 #15
0
                public void Init()
                {
                    rng = new Random(1);
                    m1  = (float2x2 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float2x2>() * iterations, UnsafeUtility.AlignOf <float2x2>(), Allocator.Persistent);
                    for (int i = 0; i < iterations; ++i)
                    {
                        m1[i] = float2x2.identity;
                    }

                    m2 = (float2 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float2>() * iterations, UnsafeUtility.AlignOf <float2>(), Allocator.Persistent);
                    for (int i = 0; i < iterations; ++i)
                    {
                        m2[i] = new float2(1.0f, 0.0f);
                    }
                }
예제 #16
0
        private static unsafe void SubdivideBurst(Allocator allocator, float2 *points, int pointCount, int2 *edges, int edgeCount, float2 *outVertices, int *outIndices, int2 *outEdges, int arrayCount, float areaFactor, float areaThreshold, int refineIterations, int smoothenIterations, int3 *result)
        {
            NativeArray <int2> _edges = new NativeArray <int2>(edgeCount, allocator);

            for (int i = 0; i < _edges.Length; ++i)
            {
                _edges[i] = edges[i];
            }

            NativeArray <float2> _points = new NativeArray <float2>(pointCount, allocator);

            for (int i = 0; i < _points.Length; ++i)
            {
                _points[i] = points[i];
            }

            NativeArray <int>    _outIndices  = new NativeArray <int>(arrayCount, allocator);
            NativeArray <int2>   _outEdges    = new NativeArray <int2>(arrayCount, allocator);
            NativeArray <float2> _outVertices = new NativeArray <float2>(arrayCount, allocator);
            int outEdgeCount   = 0;
            int outIndexCount  = 0;
            int outVertexCount = 0;

            ModuleHandle.Subdivide(allocator, _points, _edges, ref _outVertices, ref outVertexCount, ref _outIndices, ref outIndexCount, ref _outEdges, ref outEdgeCount, areaFactor, areaThreshold, refineIterations, smoothenIterations);

            for (int i = 0; i < outEdgeCount; ++i)
            {
                outEdges[i] = _outEdges[i];
            }
            for (int i = 0; i < outIndexCount; ++i)
            {
                outIndices[i] = _outIndices[i];
            }
            for (int i = 0; i < outVertexCount; ++i)
            {
                outVertices[i] = _outVertices[i];
            }

            result->x = outVertexCount;
            result->y = outIndexCount;
            result->z = outEdgeCount;

            _outVertices.Dispose();
            _outEdges.Dispose();
            _outIndices.Dispose();
            _points.Dispose();
            _edges.Dispose();
        }
        public MTerrainBoundingTree(int treeLevel)
        {
            isCreate       = false;
            this.treeLevel = treeLevel;
            offset         = MUnsafeUtility.Malloc <long>(sizeof(long) * treeLevel, Unity.Collections.Allocator.Persistent);
            offset[0]      = 0;
            int j = 1;

            for (int i = 1; i < treeLevel; ++i, j *= 2)
            {
                int ofst = (int)(0.1 + pow(2, i));
                offset[i] = offset[i - 1] + j * j;
            }
            byteSize      = (offset[treeLevel - 1] + j * j) * sizeof(float2);
            boundingValue = MUnsafeUtility.Malloc <float2>(byteSize, Unity.Collections.Allocator.Persistent);
        }
                public void Init()
                {
                    v1 = (float2 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float2>() * 100000, UnsafeUtility.AlignOf <float2>(), Allocator.Persistent);
                    for (int i = 0; i < 100000; ++i)
                    {
                        v1[i] = new float2(1.0f);
                    }

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

                    result = (float2 *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <float2>() * 100000, UnsafeUtility.AlignOf <float2>(), Allocator.Persistent);
                    for (int i = 0; i < 100000; ++i)
                    {
                        result[i] = new float2(1.0f);
                    }
                }
예제 #19
0
        public static bool IntersectTriangle(float3 orig, float3 dir, float3 v0, float3 v1, float3 v2
                                             , float *t, float2 *uv)
        {
            float3 e1  = v1 - v0;
            float3 e2  = v2 - v0;
            float3 p   = cross(dir, e2);
            float  det = dot(e1, p);
            float3 T;

            if (det > 0)
            {
                T = orig - v0;
            }
            else
            {
                T   = v0 - orig;
                det = -det;
            }
            if (det < 0.0001)
            {
                return(false);
            }
            uv->x = dot(T, p);
            if (uv->x < 0.0f || uv->x > det)
            {
                return(false);
            }
            float3 Q = cross(T, e1);

            uv->y = dot(dir, Q);
            if (uv->y < 0.0f || (uv->x + uv->y) > det)
            {
                return(false);
            }
            *t = dot(e2, Q);
            float fInvDet = 1 / det;

            *t  *= fInvDet;
            *uv *= fInvDet;
            return(true);
        }
예제 #20
0
        public static Mesh GeneratePlaneMeshFromCoord(NativeList <float4> coords, float4x4 localToModelMatrix, float2 startUV, float2 endUV)
        {
            List <Vector3> allVertices = new List <Vector3>(coords.Length * 4);
            List <Vector2> uvs         = new List <Vector2>(allVertices.Capacity);
            List <Vector3> normals     = new List <Vector3>(allVertices.Capacity);
            List <Vector4> tans        = new List <Vector4>(allVertices.Capacity);
            List <int>     triangles   = new List <int>(allVertices.Capacity * 3 / 2 + 1);

            void AddPoint(float2 leftUpCorner, float2 rightDownCorner)
            {
                int *   triangleCount = stackalloc int[] { 0, 1, 2, 1, 3, 2 };
                float2 *verts         = stackalloc float2[] { leftUpCorner, float2(rightDownCorner.x, leftUpCorner.y), float2(leftUpCorner.x, rightDownCorner.y), rightDownCorner };
                int     len           = allVertices.Count;

                for (int i = 0; i < 6; ++i)
                {
                    triangles.Add(triangleCount[i] + len);
                }
                for (int i = 0; i < 4; ++i)
                {
                    allVertices.Add(mul(localToModelMatrix, float4(verts[i], 0, 1)).xyz);
                    uvs.Add(lerp(startUV, endUV, verts[i]));
                    normals.Add(mul(localToModelMatrix, float4(0, 0, 1, 0)).xyz);
                    tans.Add(float4(mul(localToModelMatrix, float4(1, 0, 0, 0)).xyz, 1));
                }
            }

            Mesh m = new Mesh();

            foreach (var i in coords)
            {
                AddPoint(i.xy, i.zw);
            }
            m.SetVertices(allVertices);
            m.SetUVs(0, uvs);
            m.SetTangents(tans);
            m.SetNormals(normals);
            m.SetTriangles(triangles, 0);
            return(m);
        }
                public void Init()
                {
                    rng = new Random(1);
                    v1 = (float2*)UnsafeUtility.Malloc(UnsafeUtility.SizeOf<float2>() * iterations, UnsafeUtility.AlignOf<float2>(), Allocator.Persistent);
                    for (int i = 0; i < iterations; ++i)
                    {
                        v1[i] = new float2(1.0f);
                    }

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

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

                }
예제 #22
0
            public unsafe void Draw()
            {
                if (VertexCount < 3)
                {
                    return;
                }

                BeginLineStrip(Color);

                fixed(byte *array = Vertices)
                {
                    float2 *vertexArray = (float2 *)array;

                    for (var i = 0; i < VertexCount; ++i)
                    {
                        var vertex = PhysicsMath.mul(Transform, vertexArray[i]);
                        DrawLineVertex(vertex);
                    }
                    DrawLineVertex(PhysicsMath.mul(Transform, vertexArray[0]));
                }

                EndDraw();
            }
예제 #23
0
        unsafe JobHandle?GetUvsJob(
            void *input,
            int count,
            GLTFComponentType inputType,
            int inputByteStride,
            float2 *output,
            int outputByteStride,
            bool normalized = false
            )
        {
            Profiler.BeginSample("PrepareUVs");
            JobHandle?jobHandle = null;

            switch (inputType)
            {
            case GLTFComponentType.Float:
            {
                var jobUv = new Jobs.ConvertUVsFloatToFloatInterleavedJob {
                    inputByteStride  = (inputByteStride > 0) ? inputByteStride : 8,
                    input            = (byte *)input,
                    outputByteStride = outputByteStride,
                    result           = output
                };
#if UNITY_JOBS
                jobHandle = jobUv.ScheduleBatch(count, GltfImport.DefaultBatchCount);
#else
                jobHandle = jobUv.Schedule(count, GltfImport.DefaultBatchCount);
#endif
            }
            break;

            case GLTFComponentType.UnsignedByte:
                if (normalized)
                {
                    var jobUv = new Jobs.ConvertUVsUInt8ToFloatInterleavedNormalizedJob {
                        inputByteStride  = (inputByteStride > 0) ? inputByteStride : 2,
                        input            = (byte *)input,
                        outputByteStride = outputByteStride,
                        result           = output
                    };
                    jobHandle = jobUv.Schedule(count, GltfImport.DefaultBatchCount);
                }
                else
                {
                    var jobUv = new Jobs.ConvertUVsUInt8ToFloatInterleavedJob {
                        inputByteStride  = (inputByteStride > 0) ? inputByteStride : 2,
                        input            = (byte *)input,
                        outputByteStride = outputByteStride,
                        result           = output
                    };
#if UNITY_JOBS
                    jobHandle = jobUv.ScheduleBatch(count, GltfImport.DefaultBatchCount);
#else
                    jobHandle = jobUv.Schedule(count, GltfImport.DefaultBatchCount);
#endif
                }
                break;

            case GLTFComponentType.UnsignedShort:
                if (normalized)
                {
                    var jobUv = new Jobs.ConvertUVsUInt16ToFloatInterleavedNormalizedJob {
                        inputByteStride  = (inputByteStride > 0) ? inputByteStride : 4,
                        input            = (byte *)input,
                        outputByteStride = outputByteStride,
                        result           = output
                    };
                    jobHandle = jobUv.Schedule(count, GltfImport.DefaultBatchCount);
                }
                else
                {
                    var jobUv = new Jobs.ConvertUVsUInt16ToFloatInterleavedJob {
                        inputByteStride  = (inputByteStride > 0) ? inputByteStride : 4,
                        input            = (byte *)input,
                        outputByteStride = outputByteStride,
                        result           = output
                    };
#if UNITY_JOBS
                    jobHandle = jobUv.ScheduleBatch(count, GltfImport.DefaultBatchCount);
#else
                    jobHandle = jobUv.Schedule(count, GltfImport.DefaultBatchCount);
#endif
                }
                break;

            case GLTFComponentType.Short:
                if (normalized)
                {
                    var job = new Jobs.ConvertUVsInt16ToFloatInterleavedNormalizedJob {
                        inputByteStride  = inputByteStride > 0 ? inputByteStride : 4,
                        input            = (System.Int16 *)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 Jobs.ConvertUVsInt16ToFloatInterleavedJob {
                        inputByteStride  = inputByteStride > 0 ? inputByteStride : 4,
                        input            = (System.Int16 *)input,
                        outputByteStride = outputByteStride,
                        result           = output
                    };
#if UNITY_JOBS
                    jobHandle = job.ScheduleBatch(count, GltfImport.DefaultBatchCount);
#else
                    jobHandle = job.Schedule(count, GltfImport.DefaultBatchCount);
#endif
                }
                break;

            case GLTFComponentType.Byte:
                var byteStride = inputByteStride > 0 ? inputByteStride : 2;
                if (normalized)
                {
                    var jobInt8 = new Jobs.ConvertUVsInt8ToFloatInterleavedNormalizedJob {
                        inputByteStride  = inputByteStride > 0 ? inputByteStride : 2,
                        input            = (sbyte *)input,
                        outputByteStride = outputByteStride,
                        result           = output
                    };
#if UNITY_JOBS
                    jobHandle = jobInt8.ScheduleBatch(count, GltfImport.DefaultBatchCount);
#else
                    jobHandle = jobInt8.Schedule(count, GltfImport.DefaultBatchCount);
#endif
                }
                else
                {
                    var jobInt8 = new Jobs.ConvertUVsInt8ToFloatInterleavedJob {
                        inputByteStride  = inputByteStride > 0 ? inputByteStride : 2,
                        input            = (sbyte *)input,
                        outputByteStride = outputByteStride,
                        result           = output
                    };
#if UNITY_JOBS
                    jobHandle = jobInt8.ScheduleBatch(count, GltfImport.DefaultBatchCount);
#else
                    jobHandle = jobInt8.Schedule(count, GltfImport.DefaultBatchCount);
#endif
                }
                break;

            default:
                logger?.Error(LogCode.TypeUnsupported, "UV", inputType.ToString());
                break;
            }
            Profiler.EndSample();
            return(jobHandle);
        }
        // This differs from CullIntermediateLights in 3 ways:
        // - tile-frustums/light intersection use different algorithm
        // - depth range of the light shape intersecting the tile-frustums is output in the tile list header section
        // - light indices written out are indexing visible_lights, rather than the array of PrePunctualLights.
        unsafe public void CullFinalLights(ref NativeArray <PrePunctualLight> punctualLights,
                                           ref NativeArray <ushort> lightIndices, int lightStartIndex, int lightCount,
                                           int istart, int iend, int jstart, int jend)
        {
            // Interestingly, 2-3% faster when using unsafe arrays.
            PrePunctualLight *_punctualLights = (PrePunctualLight *)NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(punctualLights);
            ushort *          _lightIndices   = (ushort *)NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(lightIndices);
            uint *            _tileHeaders    = (uint *)NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(m_TileHeaders);

            if (lightCount == 0)
            {
                for (int j = jstart; j < jend; ++j)
                {
                    for (int i = istart; i < iend; ++i)
                    {
                        int headerOffset = GetTileHeaderOffset(i, j);
                        _tileHeaders[headerOffset + 0] = 0;
                        _tileHeaders[headerOffset + 1] = 0;
                        _tileHeaders[headerOffset + 2] = 0;
                        _tileHeaders[headerOffset + 3] = 0;
                    }
                }
                return;
            }

            // Store culled lights in temporary buffer. Additionally store depth range of each light for a given tile too.
            // the depth range is a 32bit mask, but packed into a 16bits value since the range of the light is continuous
            // (only need to store first bit enabled, and count of enabled bits).
            ushort *tiles       = stackalloc ushort[lightCount * 2];
            float2 *depthRanges = stackalloc float2[lightCount];

            int    maxLightPerTile = 0; // for stats
            int    lightEndIndex   = lightStartIndex + lightCount;
            float2 tileSize        = new float2((m_FrustumPlanes.right - m_FrustumPlanes.left) / m_TileXCount, (m_FrustumPlanes.top - m_FrustumPlanes.bottom) / m_TileYCount);
            float2 tileExtents     = tileSize * 0.5f;
            float2 tileExtentsInv  = new float2(1.0f / tileExtents.x, 1.0f / tileExtents.y);

            for (int j = jstart; j < jend; ++j)
            {
                float tileYCentre = m_FrustumPlanes.top - (tileExtents.y + j * tileSize.y);

                for (int i = istart; i < iend; ++i)
                {
                    float tileXCentre = m_FrustumPlanes.left + tileExtents.x + i * tileSize.x;

                    PreTile preTile          = m_PreTiles[i + j * m_TileXCount];
                    int     culledLightCount = 0;

                    // For the current tile's light list, min&max depth range (absolute values).
                    float listMinDepth = float.MaxValue;
                    float listMaxDepth = -float.MaxValue;

                    // Duplicate the inner loop twice. Testing for the ortographic case inside the inner loop would cost an extra 8% otherwise.
                    // Missing C++ template argument here!
                    if (!m_IsOrthographic)
                    {
                        for (int vi = lightStartIndex; vi < lightEndIndex; ++vi)
                        {
                            ushort           lightIndex = _lightIndices[vi];
                            PrePunctualLight ppl        = _punctualLights[lightIndex];

                            // Offset tileCentre toward the light to calculate a more conservative minMax depth bound,
                            // but it must remains inside the tile and must not pass further than the light centre.
                            float2 tileCentre = new float2(tileXCentre, tileYCentre);
                            float2 dir        = ppl.screenPos - tileCentre;
                            float2 d          = abs(dir * tileExtentsInv);

                            float  sInv          = 1.0f / max3(d.x, d.y, 1.0f);
                            float3 tileOffCentre = new float3(tileCentre.x + dir.x * sInv, tileCentre.y + dir.y * sInv, -m_FrustumPlanes.zNear);
                            float3 tileOrigin    = new float3(0.0f);

                            float t0, t1;
                            // This is more expensive than Clip() but allow to compute min&max depth range for the part of the light inside the tile.
                            if (!IntersectionLineSphere(ppl.posVS, ppl.radius, tileOrigin, tileOffCentre, out t0, out t1))
                            {
                                continue;
                            }

                            listMinDepth = listMinDepth < t0 ? listMinDepth : t0;
                            listMaxDepth = listMaxDepth > t1 ? listMaxDepth : t1;
                            depthRanges[culledLightCount] = new float2(t0, t1);
                            // Because this always output to the finest tiles, contrary to CullLights(),
                            // the result are indices into visibleLights, instead of indices into punctualLights.
                            tiles[culledLightCount] = ppl.visLightIndex;
                            ++culledLightCount;
                        }
                    }
                    else
                    {
                        for (int vi = lightStartIndex; vi < lightEndIndex; ++vi)
                        {
                            ushort           lightIndex = _lightIndices[vi];
                            PrePunctualLight ppl        = _punctualLights[lightIndex];

                            // Offset tileCentre toward the light to calculate a more conservative minMax depth bound,
                            // but it must remains inside the tile and must not pass further than the light centre.
                            float2 tileCentre = new float2(tileXCentre, tileYCentre);
                            float2 dir        = ppl.screenPos - tileCentre;
                            float2 d          = abs(dir * tileExtentsInv);

                            float  sInv          = 1.0f / max3(d.x, d.y, 1.0f);
                            float3 tileOffCentre = new float3(0, 0, -m_FrustumPlanes.zNear);
                            float3 tileOrigin    = new float3(tileCentre.x + dir.x * sInv, tileCentre.y + dir.y * sInv, 0.0f);

                            float t0, t1;
                            // This is more expensive than Clip() but allow to compute min&max depth range for the part of the light inside the tile.
                            if (!IntersectionLineSphere(ppl.posVS, ppl.radius, tileOrigin, tileOffCentre, out t0, out t1))
                            {
                                continue;
                            }

                            listMinDepth = listMinDepth < t0 ? listMinDepth : t0;
                            listMaxDepth = listMaxDepth > t1 ? listMaxDepth : t1;
                            depthRanges[culledLightCount] = new float2(t0, t1);
                            // Because this always output to the finest tiles, contrary to CullLights(),
                            // the result are indices into visibleLights, instead of indices into punctualLights.
                            tiles[culledLightCount] = ppl.visLightIndex;
                            ++culledLightCount;
                        }
                    }

                    // Post-multiply by zNear to get actual world unit absolute depth values, then clamp to valid depth range.
                    listMinDepth = max2(listMinDepth * m_FrustumPlanes.zNear, m_FrustumPlanes.zNear);
                    listMaxDepth = min2(listMaxDepth * m_FrustumPlanes.zNear, m_FrustumPlanes.zFar);

                    // Calculate bitmask for 2.5D culling.
                    uint  bitMask       = 0;
                    float depthRangeInv = 1.0f / (listMaxDepth - listMinDepth);
                    for (int culledLightIndex = 0; culledLightIndex < culledLightCount; ++culledLightIndex)
                    {
                        float lightMinDepth = max2(depthRanges[culledLightIndex].x * m_FrustumPlanes.zNear, m_FrustumPlanes.zNear);
                        float lightMaxDepth = min2(depthRanges[culledLightIndex].y * m_FrustumPlanes.zNear, m_FrustumPlanes.zFar);
                        int   firstBit      = (int)((lightMinDepth - listMinDepth) * 32.0f * depthRangeInv);
                        int   lastBit       = (int)((lightMaxDepth - listMinDepth) * 32.0f * depthRangeInv);
                        int   bitCount      = min(lastBit - firstBit + 1, 32 - firstBit);
                        bitMask |= (uint)((0xFFFFFFFF >> (32 - bitCount)) << firstBit);

                        tiles[culledLightCount + culledLightIndex] = (ushort)((uint)firstBit | (uint)(bitCount << 8));
                    }

                    // As listMinDepth and listMaxDepth are used to calculate the geometry 2.5D bitmask,
                    // we can optimize the shader execution (TileDepthInfo.shader) by refactoring the calculation.
                    //   int bitIndex = 32.0h * (geoDepth - listMinDepth) / (listMaxDepth - listMinDepth);
                    // Equivalent to:
                    //   a =                 32.0 / (listMaxDepth - listMinDepth)
                    //   b = -listMinDepth * 32.0 / (listMaxDepth - listMinDepth)
                    //   int bitIndex = geoDepth * a + b;
                    float a = 32.0f * depthRangeInv;
                    float b = -listMinDepth * a;

                    int tileDataSize = culledLightCount * 2;
                    int tileOffset   = culledLightCount > 0 ? AddTileData(tiles, ref tileDataSize) : 0;

                    int headerOffset = GetTileHeaderOffset(i, j);
                    _tileHeaders[headerOffset + 0] = (uint)tileOffset;
                    _tileHeaders[headerOffset + 1] = (uint)(tileDataSize == 0 ? 0 : culledLightCount);
                    _tileHeaders[headerOffset + 2] = _f32tof16(a) | (_f32tof16(b) << 16);
                    _tileHeaders[headerOffset + 3] = bitMask;

                    maxLightPerTile = max(maxLightPerTile, culledLightCount);
                }
            }

            m_Counters[0] = max(m_Counters[0], maxLightPerTile); // TODO make it atomic
        }
예제 #25
0
 protected static extern unsafe int DetailedOverlapInformationNative(IntPtr emr, Entity e, HitBoxOverlap overlap, float2 *result);
예제 #26
0
        public TerrainDrawStreaming(int maximumLength, int meshSize, ComputeShader transformShader)
        {
            current = this;
            if (meshSize % 2 != 0)
            {
                Debug.LogError("Terrain panel's size should be even number!");
                meshSize++;
            }
            this.meshSize = meshSize;
            //Initialize Mesh and triangles
            int vertexCount = meshSize + 1;

            vertSize      = vertexCount;
            heightMapSize = vertSize * vertSize;
            NativeArray <float2> terrainVertexArray = new NativeArray <float2>(vertexCount * vertexCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            float2 *arrPtr = terrainVertexArray.Ptr();

            for (int x = 0; x < vertexCount; ++x)
            {
                for (int y = 0; y < vertexCount; ++y)
                {
                    arrPtr[y * vertexCount + x] = new float2(x, y) / meshSize - new float2(0.5f, 0.5f);
                }
            }
            verticesBuffer = new ComputeBuffer(terrainVertexArray.Length, sizeof(float2));
            verticesBuffer.SetData(terrainVertexArray);
            heightMapBuffer = new ComputeBuffer(maximumLength * (vertexCount * vertexCount), sizeof(float));
            NativeArray <int> triangles = new NativeArray <int>(6 * meshSize * meshSize, Allocator.Temp, NativeArrayOptions.UninitializedMemory);

            int *trianglePtr = triangles.Ptr();

            for (int x = 0, count = 0; x < meshSize; ++x)
            {
                for (int y = 0; y < meshSize; ++y)
                {
                    int4 indices = new int4(vertexCount * y + x, vertexCount * (y + 1) + x, vertexCount * y + (x + 1), vertexCount * (y + 1) + (x + 1));
                    trianglePtr[count]     = indices.x;
                    trianglePtr[count + 1] = indices.y;
                    trianglePtr[count + 2] = indices.z;
                    trianglePtr[count + 3] = indices.y;
                    trianglePtr[count + 4] = indices.w;
                    trianglePtr[count + 5] = indices.z;
                    count += 6;
                }
            }
            triangleBuffer = new ComputeBuffer(triangles.Length, sizeof(int));
            triangleBuffer.SetData(triangles);
            triangles.Dispose();
            terrainVertexArray.Dispose();
            removebuffer = new ComputeBuffer(100, sizeof(int2));
            //Initialize indirect
            clusterBuffer        = new ComputeBuffer(maximumLength, sizeof(TerrainPanel));
            referenceBuffer      = new NativeList <ulong>(maximumLength, Allocator.Persistent);
            this.transformShader = transformShader;
            resultBuffer         = new ComputeBuffer(maximumLength, sizeof(int));
            instanceCountBuffer  = new ComputeBuffer(5, sizeof(int), ComputeBufferType.IndirectArguments);
            NativeArray <int> indirect = new NativeArray <int>(5, Allocator.Temp, NativeArrayOptions.ClearMemory);

            indirect[0] = triangleBuffer.count;
            instanceCountBuffer.SetData(indirect);
            indirect.Dispose();
            notUsedHeightmapIndices = new NativeList <int>(maximumLength, Allocator.Persistent);
            for (int i = 0; i < maximumLength; ++i)
            {
                notUsedHeightmapIndices.Add(i);
            }
        }
예제 #27
0
        private async void Movie_CTF2DChanged(object sender, EventArgs e)
        {
            try
            {
                AdjustGridVisibility();
                ImageSimulated2D.Visibility = Visibility.Hidden;

                if (Movie == null)
                {
                    return;
                }

                if (Movie.OptionsCTF == null || Movie.CTF == null)
                {
                    return;
                }

                this.Width  = Movie.OptionsCTF.Window;
                this.Height = Movie.OptionsCTF.Window;
                ProgressCTF2D.Visibility = Visibility.Visible;

                int Width    = Movie.OptionsCTF.Window / 2;
                CTF MovieCTF = Movie.CTF;

                //await Task.Delay(1000);
                await Task.Run(() =>
                {
                    ImageSource Simulated2D;

                    unsafe
                    {
                        float2[] SimCoords         = new float2[Width *Width];
                        fixed(float2 *SimCoordsPtr = SimCoords)
                        {
                            float2 *SimCoordsP = SimCoordsPtr;
                            for (int y = 0; y < Width; y++)
                            {
                                int ycoord  = Width - 1 - y;
                                int ycoord2 = ycoord *ycoord;
                                for (int x = 0; x < Width; x++)
                                {
                                    int xcoord    = x - Width;
                                    *SimCoordsP++ = new float2((float)Math.Sqrt(xcoord *xcoord + ycoord2) / (Width * 2), (float)Math.Atan2(ycoord, xcoord));
                                }
                            }
                        }
                        float[] Sim2D             = MovieCTF.Get2D(SimCoords, true, true, true);
                        byte[] Sim2DBytes         = new byte[Sim2D.Length];
                        fixed(byte *Sim2DBytesPtr = Sim2DBytes)
                        fixed(float *Sim2DPtr     = Sim2D)
                        {
                            byte *Sim2DBytesP = Sim2DBytesPtr;
                            float *Sim2DP     = Sim2DPtr;
                            for (int i = 0; i < Width *Width; i++)
                            {
                                *Sim2DBytesP++ = (byte)(*Sim2DP++ *128f + 127f);
                            }
                        }

                        Simulated2D = BitmapSource.Create(Width, Width, 96, 96, PixelFormats.Indexed8, BitmapPalettes.Gray256, Sim2DBytes, Width);
                        Simulated2D.Freeze();
                    }

                    Dispatcher.Invoke(() =>
                    {
                        ImageSimulated2D.Source     = Simulated2D;
                        ImageSimulated2D.Visibility = Visibility.Visible;
                    });
                });

                ProgressCTF2D.Visibility = Visibility.Hidden;
            }
            catch
            {
            }
        }
		/// <summary>
		/// Creates a new CudaRegisteredHostMemory_float2 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_float2(IntPtr hostPointer, SizeT size)
		{
			_intPtr = hostPointer;
			_size = size;
			_typeSize = (SizeT)Marshal.SizeOf(typeof(float2));
			_ptr = (float2*)_intPtr;
		}
예제 #29
0
        public static unsafe void PopulateSpriteVertices(ref WorldSpaceMask rectMask, ref DynamicBuffer <ControlVertexData> vertices,
                                                         ref DynamicBuffer <ControlVertexIndex> triangles, ref WorldSpaceRect rectData,
                                                         ref SpriteVertexData spriteVertexData, float4 color)
        {
            float  pixelsPerUnit   = spriteVertexData.PixelsPerUnit / 100.0f;
            Rect   rect            = new Rect(rectData.Min, rectData.Max - rectData.Min);
            float4 adjustedBorders = GetAdjustedBorders(spriteVertexData.Border / pixelsPerUnit, rect);
            var    padding         = spriteVertexData.Padding / pixelsPerUnit;

            float2 *vertScratch = stackalloc float2[4];
            float2 *uvScratch   = stackalloc float2[4];

            vertScratch[0] = new float2(padding.x, padding.y);
            vertScratch[3] = new float2(rect.width - padding.z, rect.height - padding.w);

            vertScratch[1].x = adjustedBorders.x;
            vertScratch[1].y = adjustedBorders.y;

            vertScratch[2].x = rect.width - adjustedBorders.z;
            vertScratch[2].y = rect.height - adjustedBorders.w;

            for (int i = 0; i < 4; ++i)
            {
                vertScratch[i].x += rect.x;
                vertScratch[i].y += rect.y;
            }

            uvScratch[0] = new Vector2(spriteVertexData.Outer.x, spriteVertexData.Outer.y);
            uvScratch[1] = new Vector2(spriteVertexData.Inner.x, spriteVertexData.Inner.y);
            uvScratch[2] = new Vector2(spriteVertexData.Inner.z, spriteVertexData.Inner.w);
            uvScratch[3] = new Vector2(spriteVertexData.Outer.z, spriteVertexData.Outer.w);

            // rect mask support
            var cut = GetRectangleMaskCut(vertScratch[0], vertScratch[3], ref rectMask);

            vertScratch[0] = vertScratch[0] + cut.Min - clamp(cut.Max - float2(rect.size), 0.0f, float.PositiveInfinity);
            vertScratch[1] = vertScratch[1] + math.clamp(cut.Min - adjustedBorders.xy, 0.0f, float.PositiveInfinity) - clamp(cut.Max - (float2(rect.size) - adjustedBorders.xy), 0.0f, float.PositiveInfinity);
            vertScratch[2] = vertScratch[2] + math.clamp(cut.Min - (float2(rect.size) - adjustedBorders.zw), 0.0f, float.PositiveInfinity) - math.clamp(cut.Max - adjustedBorders.wz, 0.0f, float.PositiveInfinity);
            vertScratch[3] = vertScratch[3] + clamp(cut.Min - float2(rect.size), 0.0f, float.PositiveInfinity) - cut.Max;


            int vertexOffset = vertices.Length;

            for (int x = 0; x < 4; ++x)
            {
                for (int y = 0; y < 4; ++y)
                {
                    vertices.Add(new ControlVertexData()
                    {
                        Position  = new float3(vertScratch[x].x, vertScratch[y].y, 0.0f),
                        TexCoord0 = new float2(uvScratch[x].x, uvScratch[y].y),
                        Color     = color
                    });
                }
            }


            for (int x = 0; x < 3; ++x)
            {
                int x2 = x + 1;

                for (int y = 0; y < 3; ++y)
                {
                    int y2 = y + 1;

                    // Ignore empty
                    if (vertScratch[x2].x - vertScratch[x].x <= 0.0f)
                    {
                        continue;
                    }
                    if (vertScratch[y2].y - vertScratch[y].y <= 0.0f)
                    {
                        continue;
                    }

                    triangles.Add(vertexOffset + x * 4 + y);
                    triangles.Add(vertexOffset + x * 4 + y2);
                    triangles.Add(vertexOffset + x2 * 4 + y);

                    triangles.Add(vertexOffset + x2 * 4 + y2);
                    triangles.Add(vertexOffset + x2 * 4 + y);
                    triangles.Add(vertexOffset + x * 4 + y2);
                }
            }


            //            for (int x = 0; x < 3; ++x)
            //            {
            //                int x2 = x + 1;
            //
            //                for (int y = 0; y < 3; ++y)
            //                {
            //                    int y2 = y + 1;
            //
            //
            //                    AddQuad(ref rectMask, ref vertices, ref triangles,
            //                        new float2(vertScratch[x].x, vertScratch[y].y),
            //                        new float2(vertScratch[x2].x, vertScratch[y2].y),
            //                        color,
            //                        new float2(uvScratch[x].x, uvScratch[y].y),
            //                        new float2(uvScratch[x2].x, uvScratch[y2].y));
            //                }
            //            }
        }
예제 #30
0
        public void Execute(int i)
        {
            float2 * w = stackalloc float2[3];
            Particle p = ps[i];

            uint2  cell_idx  = (uint2)p.pos;
            float2 cell_diff = (p.pos - cell_idx) - 0.5f;

            w[0] = 0.5f * math.pow(0.5f - cell_diff, 2);
            w[1] = 0.75f - math.pow(cell_diff, 2);
            w[2] = 0.5f * math.pow(0.5f + cell_diff, 2);

            float density = 0.0f;

            for (uint x = 0; x < 3; ++x)
            {
                for (uint y = 0; y < 3; ++y)
                {
                    float weight   = w[x].x * w[y].y;
                    int   index_1d = (int)(cell_idx.x + x - 1) * grid_res + (int)(cell_idx.y + y - 1);
                    density += grid[index_1d].mass * weight; // m_0 / h^3 in this case h = 1
                }
            }
            float volume = p.mass / density;

            float    pressure = math.max(-0.1f, eos_stiffness * (math.pow(density / rest_density, eos_power) - 1));
            float2x2 stress   = math.float2x2(
                -pressure, 0,
                0, -pressure
                );

            float2x2 velocity_gradient   = p.C;
            float2x2 velocity_gradient_T = math.transpose(velocity_gradient);
            float2x2 strain = velocity_gradient + velocity_gradient_T;
            //float trace = strain.c1.x + strain.c0.y;
            //strain.c0.y = strain.c1.x = trace;

            float2x2 viscosity_term = dynamic_viscosity * strain;

            stress += viscosity_term;

            float2x2 eq_16_term_0 = -volume * 4 * stress * dt;

            for (uint x = 0; x < 3; ++x)
            {
                for (uint y = 0; y < 3; ++y)
                {
                    float weight = w[x].x * w[y].y;

                    uint2  current_cell_idx = math.uint2(cell_idx.x + x - 1, cell_idx.y + y - 1);
                    float2 cell_dist        = (current_cell_idx - p.pos) + 0.5f;

                    int  index_1d = (int)current_cell_idx.x * grid_res + (int)current_cell_idx.y;
                    Cell c        = grid[index_1d];

                    float2 momentum = math.mul(eq_16_term_0 * weight, cell_dist);
                    c.v += momentum;

                    grid[index_1d] = c;
                }
            }
        }