Esempio n. 1
0
    /*
     *  Compute velocity due to vortons, for a subset of points in a uniform grid
     *  izStart - starting value for z index
     *  izEnd - ending value for z index
     *
     *  This routine assumes CreateInfluenceTree has already executed,
     *  and that the velocity grid has been allocated.
     */
    void ComputeVelocityGridSlice(uint izStart, uint izEnd)
    {
        int numLayers = mInfluenceTree.GetDepth();

        Vector3 vMinCorner = mVelGrid.GetMinCorner();
        float   nudge      = 1.0f - 2.0f * global.GlobalVar.FLT_EPSILON;
        Vector3 vSpacing   = mVelGrid.GetCellSpacing() * nudge;

        uint[] dims = { mVelGrid.GetNumPoints(0)
                        , mVelGrid.GetNumPoints(1)
                        , mVelGrid.GetNumPoints(2) };
        uint   numXY = dims[0] * dims[1];

        uint[] idx = new uint[3];

        for (idx[2] = izStart; idx[2] < izEnd; ++idx[2])
        {   // For subset of z index values...
            Vector3 vPosition;
            // Compute the z-coordinate of the world-space position of this gridpoint.
            vPosition.z = vMinCorner.z + (float)(idx[2]) * vSpacing.z;
            // Precompute the z contribution to the offset into the velocity grid.
            uint offsetZ = idx[2] * numXY;
            for (idx[1] = 0; idx[1] < dims[1]; ++idx[1])
            {   // For every gridpoint along the y-axis...
                // Compute the y-coordinate of the world-space position of this gridpoint.
                vPosition.y = vMinCorner.y + (float)(idx[1]) * vSpacing.y;
                // Precompute the y contribution to the offset into the velocity grid.
                uint offsetYZ = idx[1] * dims[0] + offsetZ;
                for (idx[0] = 0; idx[0] < dims[0]; ++idx[0])
                {   // For every gridpoint along the x-axis...
                    // Compute the x-coordinate of the world-space position of this gridpoint.
                    vPosition.x = vMinCorner.x + (float)(idx[0]) * vSpacing.x;
                    // Compute the offset into the velocity grid.
                    uint offsetXYZ = idx[0] + offsetYZ;

                    // Compute the fluid flow velocity at this gridpoint, due to all vortons.
                    uint[] zeros = { 0, 0, 0 };    // Starter indices for recursive algorithm
                    mVelGrid[offsetXYZ] = ComputeVelocity(vPosition, zeros, numLayers - 1);
                }
            }
        }
    }
Esempio n. 2
0
    public void DebugDrawInfluenceGrid()
    {
        if (mInfluenceTree != null && mInfluenceTree.mLayers.Count != 0)
        {
            for (int u = 0; u < mInfluenceTree.mLayers.Count; ++u)
            {
                //if (u != 0) continue;
                UniformGrid <Vorton> grid = mInfluenceTree.mLayers[u];

                //Gizmos.color = new Vector4(1, 1 - 1 / ((float)u + 1), 1 - 1 / ((float)u + 1), 1.1f - 1 / ((float)u + 1));

                Vector3 cellExtent = grid.GetCellExtent();
                Vector3 gridExtent = grid.GetExtent();
                Vector3 numCells   = new Vector3(grid.GetNumCells(0), grid.GetNumCells(1), grid.GetNumCells(2));
                Vector3 gridOrigin = grid.GetMinCorner();

                for (int i = 0; i < numCells.x; ++i)
                {
                    for (int j = 0; j < numCells.y; ++j)
                    {
                        for (int k = 0; k < numCells.z; ++k)
                        {
                            if (mInfluenceTree[0][0] == null)
                            {
                                break;
                            }

                            uint[] indices   = { (uint)i, (uint)j, (uint)k };
                            uint   offset    = mInfluenceTree[(uint)u].OffsetFromIndices(indices);
                            float  vorticity = mInfluenceTree[(uint)u][offset].vorticity.magnitude;

                            Gizmos.color = new Vector4(vorticity, u / mInfluenceTree.mLayers.Count, u / mInfluenceTree.mLayers.Count, vorticity);
                            Gizmos.DrawWireCube(gridOrigin + new Vector3(cellExtent.x * i + cellExtent.x / 2, cellExtent.y * j + cellExtent.y / 2, cellExtent.z * k + cellExtent.z / 2), cellExtent);
                        }
                    }
                }
            }
        }
    }
Esempio n. 3
0
    /*
     *  Compute velocity at a given point in space, due to influence of vortons
     *
     *  vPosition - point in space whose velocity to evaluate
     *  indices - indices of cell to visit in the given layer
     *  iLayer - which layer to process
     *
     *  returns velocity at vPosition, due to influence of vortons
     *  This is a recursive algorithm with time complexity O(log(N)).
     *  The outermost caller should pass in mInfluenceTree.GetDepth().
     *
     */
    Vector ComputeVelocity(Vector3 vPosition, uint[] indices, int iLayer)
    {
        Vector velocityAccumulator = new Vector();

        UniformGrid <Vorton> rChildLayer = mInfluenceTree[(uint)iLayer - 1];

        uint[] pClusterDims      = mInfluenceTree.GetDecimations(iLayer);
        uint[] clusterMinIndices = mInfluenceTree.GetChildClusterMinCornerIndex(pClusterDims, indices);

        Vector3 vGridMinCorner = rChildLayer.GetMinCorner();
        Vector3 vSpacing       = rChildLayer.GetCellSpacing();

        uint[] increment  = new uint[3];
        uint   numXchild  = rChildLayer.GetNumPoints(0);
        uint   numXYchild = numXchild * rChildLayer.GetNumPoints(1);

        // The larger this is, the more accurate (and slower) the evaluation.
        // Reasonable values lie in [0.00001,4.0].
        // Setting this to 0 leads to very bad errors, but values greater than (tiny) lead to drastic improvements.
        // Changes in margin have a quantized effect since they effectively indicate how many additional
        // cluster subdivisions to visit.
        float marginFactor = 0.0001f; // 0.4f ; // ship with this number: 0.0001f ; test with 0.4
        // When domain is 2D in XY plane, min.z==max.z so vPos.z test below would fail unless margin.z!=0.
        Vector3 margin = marginFactor * vSpacing + (0.0f == vSpacing.z ? new Vector3(0, 0, float.Epsilon) : Vector3.zero);

        // For each cell of child layer in this grid cluster...
        for (increment[2] = 0; increment[2] < pClusterDims[2]; ++increment[2])
        {
            uint[] idxChild = new uint[3];
            idxChild[2] = clusterMinIndices[2] + increment[2];
            Vector3 vCellMinCorner, vCellMaxCorner;
            vCellMinCorner.z = vGridMinCorner.z + (float)(idxChild[2]) * vSpacing.z;
            vCellMaxCorner.z = vGridMinCorner.z + (float)(idxChild[2] + 1) * vSpacing.z;
            uint offsetZ = idxChild[2] * numXYchild;
            for (increment[1] = 0; increment[1] < pClusterDims[1]; ++increment[1])
            {
                idxChild[1]      = clusterMinIndices[1] + increment[1];
                vCellMinCorner.y = vGridMinCorner.y + (float)(idxChild[1]) * vSpacing.y;
                vCellMaxCorner.y = vGridMinCorner.y + (float)(idxChild[1] + 1) * vSpacing.y;
                uint offsetYZ = idxChild[1] * numXchild + offsetZ;
                for (increment[0] = 0; increment[0] < pClusterDims[0]; ++increment[0])
                {
                    idxChild[0]      = clusterMinIndices[0] + increment[0];
                    vCellMinCorner.x = vGridMinCorner.x + (float)(idxChild[0]) * vSpacing.x;
                    vCellMaxCorner.x = vGridMinCorner.x + (float)(idxChild[0] + 1) * vSpacing.x;
                    if (
                        (iLayer > 1) &&
                        (vPosition.x >= vCellMinCorner.x - margin.x) &&
                        (vPosition.y >= vCellMinCorner.y - margin.y) &&
                        (vPosition.z >= vCellMinCorner.z - margin.z) &&
                        (vPosition.x < vCellMaxCorner.x + margin.x) &&
                        (vPosition.y < vCellMaxCorner.y + margin.y) &&
                        (vPosition.z < vCellMaxCorner.z + margin.z)
                        )
                    {   // Test position is inside childCell and currentLayer > 0...
                        // Recurse child layer.
                        Vector upVelocicy = ComputeVelocity(vPosition, idxChild, iLayer - 1);
                        velocityAccumulator += upVelocicy;
                    }
                    else
                    {   // Test position is outside childCell, or reached leaf node.
                        //    Compute velocity induced by cell at corner point x.
                        //    Accumulate influence, storing in velocityAccumulator.
                        uint offsetXYZ = idxChild[0] + offsetYZ;

                        // Add velocity due to this vorton to the accumulator
                        rChildLayer[offsetXYZ].AccumulateVelocity(ref velocityAccumulator, vPosition);
                    }
                }
            }
        }


        return(velocityAccumulator);
    }