예제 #1
0
    public void RenderWater(NativeArray <SPHSystem.WaterParticle> waterParticles)
    {
        float3 minPosition = cubeMarchineZone.bounds.min;
        float3 maxPosition = cubeMarchineZone.bounds.max;

        if (useBurst)
        {
            WaterMarchingCube.GenerateMeshBurst(waterParticles, waterParticles.Length, minPosition, maxPosition, marchingCubeResolution, ref mesh);
        }
        else
        {
            WaterMarchingCube.GenerateMesh(waterParticles, waterParticles.Length, minPosition, maxPosition, marchingCubeResolution, ref mesh);
        }

        waterMeshFilter.mesh = mesh;
        waterMeshFilter.transform.localScale    = Vector3.one * cubeMarchineZone.size.x;
        waterMeshFilter.transform.localPosition = -Vector3.one * cubeMarchineZone.size.x * 0.5f;
    }
예제 #2
0
    void UpdateInterWaterParticleCollision(float3 minPosition, float3 maxPosition)
    {
        //cache it
        int resolutionCube = marchingCubeResolution * marchingCubeResolution * marchingCubeResolution;

        if (waterParticleCountPerVoxel == null || waterParticleCountPerVoxel.Length != resolutionCube)
        {
            waterParticleCollisionTensor     = new short[marchingCubeResolution, marchingCubeResolution, marchingCubeResolution, maxWaterParticlePerZone];
            waterParticleCountPerVoxel       = new byte[marchingCubeResolution, marchingCubeResolution, marchingCubeResolution];
            particleIndicesInCollisionTensor = new int3[particleCount];
        }
        else
        {
            Array.Clear(waterParticleCollisionTensor, 0, resolutionCube * maxWaterParticlePerZone);
            Array.Clear(waterParticleCountPerVoxel, 0, resolutionCube);
            Array.Clear(particleIndicesInCollisionTensor, 0, particleCount);
        }

        //float3 minPosition = cubeMarchineZone.bounds.min;
        //float3 maxPosition = cubeMarchineZone.bounds.max;
        float invResolution = 1f / marchingCubeResolution;
        float step          = math.distance(minPosition, maxPosition) * invResolution;
        float invStep       = 1f / step;

        //Broad phase
        for (int i = 0; i < particleCount; i++)
        {
            WaterParticle particle = waterParticles[i];
            int3          index    = WaterMarchingCube.GetPositionIndex(particle.position, minPosition, maxPosition, marchingCubeResolution, invStep);
            int           numberOfParticleInVoxel = waterParticleCountPerVoxel[index.x, index.y, index.z];
            if (numberOfParticleInVoxel < maxWaterParticlePerZone)
            {
                //Store the index of the particle in the grid
                particleIndicesInCollisionTensor[i] = index;
                waterParticleCollisionTensor[index.x, index.y, index.z, numberOfParticleInVoxel] = (short)i;
                waterParticleCountPerVoxel[index.x, index.y, index.z]++;
            }
        }

        //Narrow phase
        for (int i = 0; i < particleCount; i++)
        {
            //TODO check all 26 adjacent cells

            WaterParticle currentParticle         = waterParticles[i];
            int3          index                   = particleIndicesInCollisionTensor[i];
            int           numberOfParticleInVoxel = waterParticleCountPerVoxel[index.x, index.y, index.z];
            for (int j = 0; j < numberOfParticleInVoxel; j++)
            {
                int otherParticleIndex = waterParticleCollisionTensor[index.x, index.y, index.z, j];

                if (i == otherParticleIndex)
                {
                    break;
                }

                WaterParticle otherParticle = waterParticles[otherParticleIndex];
                float3        diff          = otherParticle.position - currentParticle.position;

                //No collision
                if (math.lengthsq(diff) > particleRadius * particleRadius)
                {
                    continue;
                }

                //TODO custom burstable functions
                //On collision vector keep they rejection, but swap projections
                float3 currentProjection = Vector3.Project(currentParticle.velocity, diff);
                float3 currentRejection  = currentParticle.velocity - currentProjection;

                float3 otherProjection = Vector3.Project(otherParticle.velocity, diff);
                float3 otherRejection  = currentParticle.velocity - otherProjection;

                //Swap
                currentParticle.velocity = (currentRejection + otherProjection) * elasticity;
                otherParticle.velocity   = (otherRejection + currentProjection) * elasticity;

                //currentParticle.position -= diff * particleRadius;
                //otherParticle.position += diff * particleRadius;

                waterParticles[i] = currentParticle;
                waterParticles[otherParticleIndex] = otherParticle;
            }
        }
    }
예제 #3
0
        public void Execute(int threadIndex)
        {
            int3 index = indices[threadIndex];

            NativeArray <float> corners = new NativeArray <float>(8, Allocator.Temp);

            for (int j = 0; j < corners.Length; j++)
            {
                int3 corner     = index + cornerTable[j];
                int  cornerFlat = WaterMarchingCube.GetFlatIndex(corner, resolution);
                corners[j] = map[cornerFlat];
            }

            int configIndex = GetConfigIndex(corners);

            //empty config
            if (configIndex == 0 || configIndex == 255)
            {
                corners.Dispose();
                return;
            }

            CubeTriangles cubeTriangle = new CubeTriangles();
            int           edgeIndex    = 0;

            for (int i = 0; i < MAXEDGE; i++)
            {
                Triangle triangle    = new Triangle();
                bool     addTriangle = true;

                for (int j = 0; j < MAXTRI; j++)
                {
                    int triIndex = triangleTable[configIndex * MarchingCubeTables.TriangleWidth + edgeIndex];

                    ////No more triangles
                    if (triIndex == -1)
                    {
                        addTriangle = false;
                        break;
                    }

                    float3 vertex1 = index + edgeTable[triIndex * MarchingCubeTables.EdgeWidth];
                    float3 vertex2 = index + edgeTable[triIndex * MarchingCubeTables.EdgeWidth + 1];

                    //TODO Include smooth lerp
                    float3 vertexPosition = math.lerp(vertex1, vertex2, 0.5f) * scaleFactor;

                    //rofl
                    switch (j)
                    {
                    case 0:
                        triangle.vertex1 = vertexPosition;
                        break;

                    case 1:
                        triangle.vertex2 = vertexPosition;
                        break;

                    case 2:
                        triangle.vertex3 = vertexPosition;
                        break;
                    }
                    edgeIndex++;
                }
                if (addTriangle)
                {
                    cubeTriangle.AddTriangle(triangle);
                    //generate unique hash index
                    //const int separator = 4;
                    //int hashIndex = triangleVertices.m_ThreadIndex * separator + i;
                    //triangleVertices.Add(hashIndex, triangle);
                }
            }
            cubeTriangles[threadIndex] = cubeTriangle;
            corners.Dispose();
        }