예제 #1
0
    /*Description - Returns a Vector3[] of the points along a requested path
     * to the requested target value. This will also include the current
     * specified location.
     *
     * Params: 	pathType -> The type of path to calculate
     * 			strength -> The energy to add / remove if negative
     * 			currentLocation -> The points current location
     * 			graphOrigin -> The origin(Translation) of the Mesh specified by graphSpace
     * 			graphSpace -> The type of graph to create the point from
     * */
    public static Vector3[] GetConstraintPath(pathType pathType, double strength, Vector3 currentLocation, Vector3 graphOrigin, graphSpaceEnums graphSpace)
    {
        ArrayList pathInThermoPoints = new ArrayList();		//Used to easily store all of a point's atributes, then depending on graph type use specific attributes
        bool inPositive = (strength > 0);					//Will be used to switch between logic for adding or removing energy, "very nifty this is"
        Vector3[] pathPoints;								//Returned to caller
        int gridPointStart = 0;								//Index in V/T_Vals that provided point starts from
        currentLocation = currentLocation - graphOrigin;				//currentLocation must be adjusted out of unity space
        double currentT = (double)Mathf.Exp(currentLocation.x);			//Real temperature of current point
        double currentV = (double)Mathf.Exp(-currentLocation.z);			//Real volume of current point
        double currentU = ThermoMath.GetU_TV(currentT, currentV, false);		//Real energy at current point
        double currentP = ThermoMath.GetP_TV(currentT, currentV, false);		//Real Pressure at current point
        double currentH = ThermoMath.GetH_TV(currentT, currentV, false);		//Real Enthalpy at current point
        double currentS = ThermoMath.GetS_TV(currentT, currentV, false);		//Real Entropy at current point
        double targetU = currentU + strength;							//Target Internal Energy based on the strength
        double finalV = ThermoMath.VOTX(currentT, targetU, pathType.CONSTANT_U);				//Volume at targetU
        double finalT = ThermoMath.TOVX(currentV, targetU, pathType.CONSTANT_U);				//Temperature at targetU

        //If no positive path exists return an empty array
        if(inPositive ? currentU > targetU : currentU < targetU)
            return new Vector3[]{};

        //Construct path ThermoPoints depending on constraint
        switch(pathType){
        /*CONSTANT TEMPERATURE*/
        case pathType.CONSTANT_T:
            //Find the first specific volume on the grid that is greater than the specific volume of the current point
            for(gridPointStart = 0; gridPointStart < V_Vals.Length; gridPointStart++){
                if(V_Vals[gridPointStart] > currentV)
                    break;
            }

            //Adjust counter depending on if we are adding or removing energy
            gridPointStart = inPositive ? gridPointStart : (gridPointStart - 1);

            //Set the first point in the path to be the current point
            pathInThermoPoints.Add(new ThermoPoint(currentT, currentV, ThermoMath.GetP_TV(currentT, currentV, false),
                ThermoMath.GetU_TV(currentT, currentV, false), ThermoMath.GetH_TV(currentT, currentV, false),
                ThermoMath.GetS_TV(currentT, currentV, false), ThermoMath.area.UNKNOWN, 0));

            //Find all points in the path that line up with the grid (spacing) and are below the target energy value
            for(gridPointStart = gridPointStart + 0; (inPositive ? (gridPointStart <  V_Vals.Length) : (gridPointStart >= 0)) &&
                (inPositive ? (ThermoMath.GetU_TV(currentT, V_Vals[gridPointStart], false) < targetU) : (ThermoMath.GetU_TV(currentT, V_Vals[gridPointStart], false) > targetU));
                gridPointStart = (inPositive ? (gridPointStart+1) : (gridPointStart-1))){

                pathInThermoPoints.Add(new ThermoPoint(currentT, V_Vals[gridPointStart], ThermoMath.GetP_TV(currentT, V_Vals[gridPointStart], false),
                ThermoMath.GetU_TV(currentT, V_Vals[gridPointStart], false), ThermoMath.GetH_TV(currentT, V_Vals[gridPointStart], false),
                ThermoMath.GetS_TV(currentT, V_Vals[gridPointStart], false), ThermoMath.area.UNKNOWN, pathInThermoPoints.Count));
            }

            //Set the final point to the point with the target energy value
            if((inPositive ? (gridPointStart != 0) : (gridPointStart != -1)) && gridPointStart != V_Vals.Length)
                pathInThermoPoints.Add(new ThermoPoint(currentT, finalV, ThermoMath.GetP_TV(currentT, finalV, false),
                targetU, ThermoMath.GetH_TV(currentT, finalV, false),
                ThermoMath.GetS_TV(currentT, finalV, false), ThermoMath.area.UNKNOWN, pathInThermoPoints.Count));
            break;

        /*CONSTANT VOLUME*/
        case pathType.CONSTANT_V:
            //Find the first Temperature on the grid that is greater than the Temperature of the current point
            for(gridPointStart = 0; gridPointStart < T_Vals.Length; gridPointStart++){
                if(T_Vals[gridPointStart] > currentT)
                    break;
            }

            //Adjust counter depending on if we are adding or removing energy
            gridPointStart = inPositive ? gridPointStart : (gridPointStart - 1);

            //Set the first point in the path to be the current point
            pathInThermoPoints.Add(new ThermoPoint(currentT, currentV, ThermoMath.GetP_TV(currentT, currentV, false),
                ThermoMath.GetU_TV(currentT, currentV, false), ThermoMath.GetH_TV(currentT, currentV, false),
                ThermoMath.GetS_TV(currentT, currentV, false), ThermoMath.area.UNKNOWN, 0));

            //Find all points in the path that line up with the grid (spacing) and are below the target energy value
            for(gridPointStart = gridPointStart + 0; (inPositive ? (gridPointStart <  T_Vals.Length) : (gridPointStart >= 0)) &&
                (inPositive ? (ThermoMath.GetU_TV(T_Vals[gridPointStart], currentV, false) < targetU) : (ThermoMath.GetU_TV(T_Vals[gridPointStart], currentV, false) > targetU));
                gridPointStart = (inPositive ? (gridPointStart+1) : (gridPointStart-1))){

                pathInThermoPoints.Add(new ThermoPoint(T_Vals[gridPointStart], currentV, ThermoMath.GetP_TV(T_Vals[gridPointStart], currentV, false),
                ThermoMath.GetU_TV(T_Vals[gridPointStart], currentV, false), ThermoMath.GetH_TV(T_Vals[gridPointStart], currentV, false),
                ThermoMath.GetS_TV(T_Vals[gridPointStart], currentV, false), ThermoMath.area.UNKNOWN, pathInThermoPoints.Count));
            }

            //If we ended on a point not equal to the target energy value set the final point to the point with the
            //target energy value
            if((inPositive ? (gridPointStart != 0) : (gridPointStart != -1)) && gridPointStart != T_Vals.Length)
                pathInThermoPoints.Add(new ThermoPoint(finalT, currentV, ThermoMath.GetP_TV(finalT, currentV, false),
                targetU, ThermoMath.GetH_TV(finalT, currentV, false),
                ThermoMath.GetS_TV(finalT, currentV, false), ThermoMath.area.UNKNOWN, pathInThermoPoints.Count));
            break;
        case pathType.CONSTANT_P:
            //Find the first Volume on the grid that is greater than the Volume of the current point
            for(gridPointStart = 0; gridPointStart < V_Vals.Length; gridPointStart++){
                if(V_Vals[gridPointStart] > currentV)
                    break;
            }

            //Adjust counter depending on if we are adding or removing energy
            gridPointStart = inPositive ? gridPointStart : (gridPointStart - 1);

            //Set the first point in the path to be the current point
            pathInThermoPoints.Add(new ThermoPoint(currentT, currentV, ThermoMath.GetP_TV(currentT, currentV, false),
                ThermoMath.GetU_TV(currentT, currentV, false), ThermoMath.GetH_TV(currentT, currentV, false),
                ThermoMath.GetS_TV(currentT, currentV, false), ThermoMath.area.UNKNOWN, 0));

            //As we will be using currentT throughout the path calculation, set it based on the first volume
            //greater than that of the current position
            currentT = ThermoMath.TOVX(V_Vals[gridPointStart], currentP, pathType.CONSTANT_P);

            //Find all points in the path that line up with the grid (spacing) and are below the target energy value
            for(gridPointStart = gridPointStart + 0; (inPositive ? (gridPointStart <  V_Vals.Length) : (gridPointStart >= 0)) &&
                (inPositive ? (ThermoMath.GetU_TV(currentT, V_Vals[gridPointStart], false) < targetU && currentT < T_Vals[T_Vals.Length-1]) :
                (ThermoMath.GetU_TV(currentT, V_Vals[gridPointStart], false) > targetU && currentT > T_Vals[0]));
                gridPointStart = (inPositive ? (gridPointStart+1) : (gridPointStart-1))){

                pathInThermoPoints.Add(new ThermoPoint(
                    currentT,
                    V_Vals[gridPointStart],
                    currentP,
                    ThermoMath.GetU_TV(currentT, V_Vals[gridPointStart], false),
                    ThermoMath.GetH_TV(currentT, V_Vals[gridPointStart], false),
                    ThermoMath.GetS_TV(currentT, V_Vals[gridPointStart], false),
                    ThermoMath.area.UNKNOWN, pathInThermoPoints.Count)
                    );

                //Update currentT unless we are on the first/last Volume of the grid
                if(inPositive ? (gridPointStart+1 != V_Vals.Length) : (gridPointStart != 0))
                    currentT = ThermoMath.TOVX(V_Vals[gridPointStart+1], currentP, pathType.CONSTANT_P);
            }

            //Adjust final Temperature and Volume values in case we've extended beyond the surface bounds
            if(inPositive ? (finalV > V_Vals[V_Vals.Length-1]) : (finalV < V_Vals[0]))
                finalV = inPositive ? V_Vals[V_Vals.Length-1] : V_Vals[0];

            if(inPositive ? (finalT > T_Vals[T_Vals.Length-1]) : (finalT < T_Vals[0]))
                finalT = inPositive ? T_Vals[T_Vals.Length-1] : T_Vals[0];

            //If we ended on a point not equal to the target energy value set the final point to the point with the
            //target energy value
            if(inPositive ? (gridPointStart == V_Vals.Length) : (gridPointStart == -1))
                pathInThermoPoints.Add(new ThermoPoint(finalT, finalV, currentP,
                targetU, ThermoMath.GetH_TV(finalT, finalV, false),
                ThermoMath.GetS_TV(finalT, finalV, false), ThermoMath.area.UNKNOWN, pathInThermoPoints.Count));
            break;

        //CONSTANT INTERNAL ENERGY
         case pathType.CONSTANT_U:
            targetU = currentU;
            finalT = -1;
            finalV = -1;
            double t;
            double v;
            //double u;
            int length = 0;

            //Find where constant Internal Energy path will go out of bounds.
            for (gridPointStart = 0; gridPointStart < V_Vals.Length; gridPointStart++) {
                t = ThermoMath.TOVX(V_Vals[gridPointStart], targetU, pathType.CONSTANT_U);
                //t = ThermoMath.TOVU(V_Vals[gridPointStart], targetU);
                length++;
                if (t < .011) {
                    break;
                }
            }

            //Find the first specific volume on the grid that is greater / less than the specific volume of the current point
            for(gridPointStart = 0; gridPointStart < V_Vals.Length; gridPointStart++){
                if(V_Vals[gridPointStart] > currentV)
                    break;
            }

            //Adjust depending on whether adding / removing energy
            gridPointStart = (inPositive ? gridPointStart : gridPointStart - 1);

            //Set the first point in the path to be the current point
            pathInThermoPoints.Add(new ThermoPoint(currentT, currentV, ThermoMath.GetP_TV(currentT, currentV, false),
                targetU, ThermoMath.GetH_TV(currentT, currentV, false),
                ThermoMath.GetS_TV(currentT, currentV, false), ThermoMath.area.UNKNOWN, 0));

            //Find all points in the path that line up with the grid (spacing) and are within the surface / formula bounds
            for (int volumeIndex = gridPointStart; (inPositive ? (volumeIndex < length) : (volumeIndex >= 0)); volumeIndex = (inPositive ? (volumeIndex+1) : (volumeIndex-1))) {
                v = V_Vals[volumeIndex];
                t = ThermoMath.TOVX(v, targetU, pathType.CONSTANT_U);	//Retrieve the best Temperature for the constant Internal energy and grid aligned Volume point
                //t = ThermoMath.TOVU(v, targetU);
                //Add a new point to the path based on the retrieved temperature value
                pathInThermoPoints.Add(new ThermoPoint(t, v, ThermoMath.GetP_TV(t, v, false),
                targetU, ThermoMath.GetH_TV(t, v, false),
                ThermoMath.GetS_TV(t, v, false), ThermoMath.area.UNKNOWN, pathInThermoPoints.Count));
            }

            break;
        /*case pathType.CONSTANT_H:

            break;*/
        case pathType.CONSTANT_S:
            bool lowTemp, highTemp, lowVol, highVol;

            //Find the first Volume on the grid that is greater than the Volume of the current point
            for(gridPointStart = 0; gridPointStart < V_Vals.Length; gridPointStart++){
                if(V_Vals[gridPointStart] > currentV)
                    break;
            }

            //Adjust counter depending on if we are adding or removing energy
            gridPointStart = inPositive ? gridPointStart : (gridPointStart - 1);

            //Set the first point in the path to be the current point
            pathInThermoPoints.Add(new ThermoPoint(currentT, currentV, ThermoMath.GetP_TV(currentT, currentV, false),
                ThermoMath.GetU_TV(currentT, currentV, false), ThermoMath.GetH_TV(currentT, currentV, false),
                ThermoMath.GetS_TV(currentT, currentV, false), ThermoMath.area.UNKNOWN, 0));

            //As we will be using currentT and currentV throughout the path calculation, set it based on the first volume
            //greater than that of the current position
            currentT = ThermoMath.TOVX(V_Vals[gridPointStart], currentS, pathType.CONSTANT_S);
            currentV = V_Vals[gridPointStart];

            lowTemp = currentT > T_Vals[1];
            highVol = currentV < V_Vals[V_Vals.Length-1];
            lowVol = currentV > V_Vals[1];
            highTemp = currentT < T_Vals[T_Vals.Length-1];

            //Catches the case where we are at a position so close the surface edge, that we will not enter the path calculation
            //loop.
            if(inPositive ? gridPointStart+1 != V_Vals.Length && !lowTemp || !highVol : gridPointStart != 0 && !lowVol || !highTemp)
                pathInThermoPoints.Add(new ThermoPoint(
                currentT,
                V_Vals[inPositive ? gridPointStart+1 : gridPointStart-1],
                ThermoMath.GetP_TV(currentT, V_Vals[inPositive ? gridPointStart+1 : gridPointStart-1], false),
                ThermoMath.GetU_TV(currentT, V_Vals[inPositive ? gridPointStart+1 : gridPointStart-1], false),
                ThermoMath.GetH_TV(currentT, V_Vals[inPositive ? gridPointStart+1 : gridPointStart-1], false),
                currentS,
                //ThermoMath.GetS_TV(currentT, V_Vals[gridPointStart], false),
                ThermoMath.area.UNKNOWN, pathInThermoPoints.Count)
                );

            //Find all points in the path that line up with the grid (spacing) and are below the target energy value
            for(gridPointStart = gridPointStart + 0; (inPositive ? (gridPointStart <  V_Vals.Length) : (gridPointStart >= 0)) &&
                (inPositive ? (ThermoMath.GetU_TV(currentT, V_Vals[gridPointStart], false) < targetU && lowTemp && highVol) :
                (ThermoMath.GetU_TV(currentT, V_Vals[gridPointStart], false) > targetU && lowVol && highTemp));
                gridPointStart = (inPositive ? (gridPointStart+1) : (gridPointStart-1))){

                pathInThermoPoints.Add(new ThermoPoint(
                    currentT,
                    V_Vals[gridPointStart],
                    ThermoMath.GetP_TV(currentT, V_Vals[gridPointStart], false),
                    ThermoMath.GetU_TV(currentT, V_Vals[gridPointStart], false),
                    ThermoMath.GetH_TV(currentT, V_Vals[gridPointStart], false),
                    currentS,
                    //ThermoMath.GetS_TV(currentT, V_Vals[gridPointStart], false),
                    ThermoMath.area.UNKNOWN, pathInThermoPoints.Count)
                    );

                //Update currentT unless we are on the first/last Volume of the grid
                if(inPositive ? (gridPointStart+1 != V_Vals.Length) : (gridPointStart != 0)){
                    currentT = ThermoMath.TOVX(V_Vals[inPositive ? gridPointStart+1 : gridPointStart-1], currentS, pathType.CONSTANT_S);
                    currentV = V_Vals[inPositive ? gridPointStart+1 : gridPointStart-1];

                    //Edge check
                    lowTemp = currentT >= T_Vals[1];
                    highVol = currentV < V_Vals[V_Vals.Length-1];
                    lowVol = currentV >= V_Vals[1];
                    highTemp = currentT < T_Vals[T_Vals.Length-1];
                }

                //If close to the edge calculate the last point before exiting
                if(inPositive ? !lowTemp || !highVol : !lowVol || !highTemp)
                    pathInThermoPoints.Add(new ThermoPoint(
                    currentT,
                    V_Vals[inPositive ? gridPointStart+1 : gridPointStart-1],
                    ThermoMath.GetP_TV(currentT, V_Vals[inPositive ? gridPointStart+1 : gridPointStart-1], false),
                    ThermoMath.GetU_TV(currentT, V_Vals[inPositive ? gridPointStart+1 : gridPointStart-1], false),
                    ThermoMath.GetH_TV(currentT, V_Vals[inPositive ? gridPointStart+1 : gridPointStart-1], false),
                    currentS,
                    //ThermoMath.GetS_TV(currentT, V_Vals[gridPointStart], false),
                    ThermoMath.area.UNKNOWN, pathInThermoPoints.Count)
                    );
            }

            //Adjust final Temperature and Volume values in case we've extended beyond the surface bounds
            //if(inPositive ? (finalV > V_Vals[V_Vals.Length-1]) : (finalV < V_Vals[0]))
            //	finalV = inPositive ? V_Vals[V_Vals.Length-1] : V_Vals[0];

            //if(inPositive ? (finalT > T_Vals[T_Vals.Length-1]) : (finalT < T_Vals[0]))
            //	finalT = inPositive ? T_Vals[T_Vals.Length-1] : T_Vals[0];
            //finalT = ThermoMath.TOVX(V_Vals[inPositive ? gridPointStart-1 : gridPointStart+1], currentS, pathType.CONSTANT_S);
            //finalV = ThermoMath.VOTX(finalT, currentS, pathType.CONSTANT_S);

            //If we ended on a point not equal to the target energy value set the final point to the point with the
            //target energy value
            //if(inPositive ? (gridPointStart != V_Vals.Length) : (gridPointStart != -1)) //Add catch here for finalT/V
            //	pathInThermoPoints.Add(new ThermoPoint(finalT, finalV, ThermoMath.GetP_TV(finalT, finalV, false),
            //	targetU, ThermoMath.GetH_TV(finalT, finalV, false),
            //	ThermoMath.GetS_TV(finalT, finalV, false), ThermoMath.area.UNKNOWN, pathInThermoPoints.Count));
            break;
        }

        pathPoints = new Vector3[pathInThermoPoints.Count];

        //Depending on graphSpace set the accurate order of quantities defining each point
        //offset by the graphOrigin
        switch(graphSpace){
        case graphSpaceEnums.TPV_Space:
            for(int i = 0; i < pathPoints.Length; i++){
                pathPoints[i] = graphOrigin + new Vector3(Mathf.Log((float)((pathInThermoPoints[i] as ThermoPoint).T)),
                    Mathf.Log((float)((pathInThermoPoints[i] as ThermoPoint).P)),
                    -Mathf.Log((float)((pathInThermoPoints[i] as ThermoPoint).V)));
            }
            break;
        case graphSpaceEnums.TUV_Space:
            for(int i = 0; i < pathPoints.Length; i++){
                pathPoints[i] = graphOrigin + new Vector3(Mathf.Log((float)((pathInThermoPoints[i] as ThermoPoint).T)),
                    Mathf.Log((float)((pathInThermoPoints[i] as ThermoPoint).U)),
                    -Mathf.Log((float)((pathInThermoPoints[i] as ThermoPoint).V)));
            }
            break;
        case graphSpaceEnums.THV_Space:
            for(int i = 0; i < pathPoints.Length; i++){
                pathPoints[i] = graphOrigin + new Vector3(Mathf.Log((float)((pathInThermoPoints[i] as ThermoPoint).T)),
                    Mathf.Log((float)((pathInThermoPoints[i] as ThermoPoint).H)),
                    -Mathf.Log((float)((pathInThermoPoints[i] as ThermoPoint).V)));
            }
            break;
        case graphSpaceEnums.TSV_Space:
            for(int i = 0; i < pathPoints.Length; i++){
                pathPoints[i] = graphOrigin + new Vector3(Mathf.Log((float)((pathInThermoPoints[i] as ThermoPoint).T)),
                    Mathf.Log((float)((pathInThermoPoints[i] as ThermoPoint).S)),
                    -Mathf.Log((float)((pathInThermoPoints[i] as ThermoPoint).V)));
            }
            break;
        }

        return pathPoints;
    }
예제 #2
0
    /*RandomStart
     * Description - Returns a random point for positioning the ball / particle at the
     * start of the game.
     *
     * Params: 	graphOrigin -> The origin(Translation) of the Mesh specified by graphSpace
     * 			graphSpace -> The type of graph to create the point from
     *
     * Error: Will return Vector3(-1, -1, -1) if graphSpace doesn't exist
     * */
    public static Vector3 RandomStart(Vector3 graphOrigin, graphSpaceEnums graphSpace)
    {
        int random_point = Random.Range(0, modelData.Count);

        switch(graphSpace){
        case graphSpaceEnums.TPV_Space:
            return graphOrigin + new Vector3(Mathf.Log((float)((modelData[random_point] as ThermoPoint).T)),
                Mathf.Log((float)((modelData[random_point] as ThermoPoint).P)),
                -Mathf.Log((float)((modelData[random_point] as ThermoPoint).V)));

        case graphSpaceEnums.TUV_Space:
            return graphOrigin + new Vector3(Mathf.Log((float)((modelData[random_point] as ThermoPoint).T)),
                Mathf.Log((float)((modelData[random_point] as ThermoPoint).U)),
                -Mathf.Log((float)((modelData[random_point] as ThermoPoint).V)));

        case graphSpaceEnums.TPU_Space:
            return graphOrigin + new Vector3(Mathf.Log((float)((modelData[random_point] as ThermoPoint).T)),
                Mathf.Log((float)((modelData[random_point] as ThermoPoint).P)),
                -Mathf.Log((float)((modelData[random_point] as ThermoPoint).U)));

        case graphSpaceEnums.TPS_Space:
            return graphOrigin + new Vector3(Mathf.Log((float)((modelData[random_point] as ThermoPoint).T)),
                Mathf.Log((float)((modelData[random_point] as ThermoPoint).P)),
                -Mathf.Log((float)((modelData[random_point] as ThermoPoint).S)));

        case graphSpaceEnums.THV_Space:
            return graphOrigin + new Vector3(Mathf.Log((float)((modelData[random_point] as ThermoPoint).T)),
                Mathf.Log((float)((modelData[random_point] as ThermoPoint).H)),
                -Mathf.Log((float)((modelData[random_point] as ThermoPoint).V)));

        case graphSpaceEnums.TSV_Space:
            return graphOrigin + new Vector3(Mathf.Log((float)((modelData[random_point] as ThermoPoint).T)),
                Mathf.Log((float)((modelData[random_point] as ThermoPoint).S)),
                -Mathf.Log((float)((modelData[random_point] as ThermoPoint).V)));
        }

        return new Vector3(-1, -1, -1);
    }
예제 #3
0
    /*GenerateGraph
     * Description - Returns a Mesh object with valid points for the
     * space specified.s
     *
     * Params: 	graphSpace -> The type of graph to create (axes)
     * */
    public static Mesh GenerateGraph(graphSpaceEnums graphSpace)
    {
        water_surface = new Mesh();

        switch(graphSpace){
        case graphSpaceEnums.TPV_Space:
            water_surface.Clear();
            water_surface.vertices = TPVverts();
            break;

        case graphSpaceEnums.TUV_Space:
            water_surface.Clear();
            water_surface.vertices = TUVverts();
            break;

        case graphSpaceEnums.TPU_Space:
            water_surface.Clear();
            water_surface.vertices = TPUverts();
            break;

        case graphSpaceEnums.TPS_Space:
            water_surface.Clear();
            water_surface.vertices = TPSverts();
            break;

        case graphSpaceEnums.THV_Space:
            water_surface.Clear();
            water_surface.vertices = THVverts();
            break;

        case graphSpaceEnums.TSV_Space:
            water_surface.Clear();
            water_surface.vertices = TSVverts();
            break;
        }

        water_surface.triangles = mesh_triangles;
        water_surface.uv = mesh_uvs;
        water_surface.Optimize();
        water_surface.RecalculateBounds();
        water_surface.RecalculateNormals();

        return water_surface;
    }