Пример #1
0
        public RiverRenderer(Transform transform, Material mat, Island island, River river)
        {
            _transform = transform;
            _waterMat  = mat;
            _island    = island;

            _root = new RiverNode(river);

            Queue <RiverTuple> riverQueue = new Queue <RiverTuple>();

            riverQueue.Enqueue(new RiverTuple(river, _root));
            while (riverQueue.Count > 0)
            {
                var currNode = riverQueue.Dequeue();
                if (currNode._dataNode.left != null)
                {
                    var pos = new Vector3((float)currNode._dataNode.left.data.position[0],
                                          currNode._dataNode.left.data.elevation,
                                          (float)currNode._dataNode.left.data.position[1]);
                    currNode._renderNode.AddUpStream(pos, currNode._dataNode.left.discharge);
                    riverQueue.Enqueue(new RiverTuple(currNode._dataNode.left,
                                                      currNode._renderNode._upstream[currNode._renderNode._upstream.Count - 1]));
                }
                if (currNode._dataNode.right != null)
                {
                    var pos = new Vector3((float)currNode._dataNode.right.data.position[0],
                                          currNode._dataNode.right.data.elevation,
                                          (float)currNode._dataNode.right.data.position[1]);
                    currNode._renderNode.AddUpStream(pos, currNode._dataNode.right.discharge);
                    riverQueue.Enqueue(new RiverTuple(currNode._dataNode.right,
                                                      currNode._renderNode._upstream[currNode._renderNode._upstream.Count - 1]));
                }
            }
        }
    private void Update()
    {
        if (isPlaying)
        {
            foreach (FloatingObject obj in observedObjects)
            {
                RiverNode closest = riverAsset.GetNodeFromPosition(obj.transform.position);
                obj.UpdateNodes(closest);
            }

            ArcadeFlowUpdate();

            //OutCommented Its Flattening the river, NO MORE WATERFALS :(
            MeshWaveUpdate();

            ArcadeFloatingUpdate();
        }
        else
        {
            ArcadeFloatingUpdate();

            if (GameController.isPlaying)
            {
                isPlaying = true;
            }
        }
    }
Пример #3
0
 /// <summary>
 /// Checks if the node specified is valid. If so, sets this chunks river to this one.
 /// </summary>
 /// <param name="node"></param>
 public void AddRiver(RiverNode node)
 {
     if (node.NodePosition != Position)
     {
         throw new System.Exception("River Node must have same position as chunk it's added to");
     }
     RiverNode = node;
 }
Пример #4
0
    private bool CheckValidAdjacent(RiverNode node, GBTCorner adjacent, MapArray <int> bitmask, Dictionary <GBTCorner, RiverNode> node_lookup)
    {
        bool result = true;

        result = result && ((bitmask[adjacent] & 2) < 2);
        result = result && (node.Downslope == null || node.Downslope.Vertex != adjacent);
        result = result && (!node_lookup.ContainsKey(adjacent));
        return(result);
    }
Пример #5
0
    private void TriangulateRiverSegment(RiverNode start_node, RiverNode end_node)
    {
        Vector2 start  = start_node.Vertex.position;
        Vector2 end    = end_node.Vertex.position;
        Vector2 diff   = end - start;
        Vector2 offset = (new Vector2(-diff.y, diff.x)).normalized * LineWidth;

        CreateTriangle(start + offset * start_node.Width, RiverColor, end - offset * end_node.Width, RiverColor, start - offset * start_node.Width, RiverColor);
        CreateTriangle(start + offset * start_node.Width, RiverColor, end + offset * end_node.Width, RiverColor, end - offset * end_node.Width, RiverColor);
    }
Пример #6
0
 private float GetRiverWidth(RiverNode node, MapArray <float> river_widths)
 {
     if (node == null)
     {
         return(0.0f);
     }
     node.Width = CombineWidths(GetRiverWidth(node.Left, river_widths), GetRiverWidth(node.Right, river_widths));
     river_widths[node.Vertex] = node.Width;
     return(node.Width);
 }
Пример #7
0
 public RiverNode(River river)
 {
     _pos = new Vector3((float)river.data.position[0],
                        river.data.elevation,
                        (float)river.data.position[1]);
     _flux       = river.discharge;
     _remainFlux = _flux;
     _downstream = null;
     _upstream   = new List <RiverNode>();
 }
    public void UpdateNodes(RiverNode closest)
    {
        if (lastNode.centerVector == Vector3.zero || closestNode.centerVector == Vector3.zero)
        {
            closestNode = closest;
            lastNode    = closest;
            return;
        }

        if (closest.index > closestNode.index)
        {
            lastNode = closestNode;
        }

        //Is using index more efficient? All nodes have index 0, so comparing indexes won't work for now
        //if(closest.index != closestNode.index)
        if (closest != closestNode)
        {
            lastNode                = closestNode;
            closestNode             = closest;
            nodeProgressClosestDist = Vector3.Distance(transform.position, closestNode.centerVector);

            if (trackNodeProgress)
            {
                nodeProgress = Vector3.Distance(transform.position, closestNode.centerVector);
                if (nodeProgress <= nodeProgressClosestDist)
                {
                    nodeProgressClosestDist = nodeProgress;
                    reverseProgress         = false;
                }
                else
                {
                    reverseProgress = true;
                }
            }
        }
        else if (closest.index == lastNode.index)
        {
            if (trackNodeProgress)
            {
                nodeProgress = Vector3.Distance(transform.position, closestNode.centerVector);
                if (nodeProgress >= nodeProgressClosestDist)
                {
                    nodeProgressClosestDist = nodeProgress;
                    reverseProgress         = false;
                }
                else
                {
                    reverseProgress = true;
                }
            }
        }
    }
    public Vector3 GetFlow(Vector3 riverObjectOffset, Vector3 boatPos)
    {
        RiverNode node = null;

        float dist  = Mathf.Infinity;
        int   index = 0;

        for (int i = 0; i < nodes.Length; i++)
        {
            float newDist = Vector3.Distance(boatPos, riverObjectOffset + nodes[i].centerVector);
            if (newDist < dist)
            {
                index = i;
                node  = nodes[index];
                dist  = newDist;
            }
        }

        //Vector3 res = Quaternion.ToEulerAngles(Quaternion.LookRotation(node.flowDirection, Vector3.forward) * Quaternion.AngleAxis(node.flowDirectionOffset_Angle, Vector3.right));
        //return res * -1;

        RiverNode lastNode = null;
        RiverNode nextNode = null;

        if (index - 1 >= 0)
        {
            lastNode = nodes[index - 1];
        }
        if (index + 1 < nodes.Length)
        {
            nextNode = nodes[index + 1];
        }

        if (lastNode == null || nextNode == null)
        {
            return(node.finalFlowDirection);
        }

        float distLast = Vector3.Distance(boatPos, riverObjectOffset + lastNode.centerVector);
        float distNext = Vector3.Distance(boatPos, riverObjectOffset + nextNode.centerVector);

        if (distLast > distNext)
        {
            Vector3 res = node.finalFlowDirection;// + Quaternion.AngleAxis(node.flowDirectionOffset_Angle, Vector3.right).eulerAngles + nextNode.flowDirection + Quaternion.AngleAxis(nextNode.flowDirectionOffset_Angle, Vector3.right).eulerAngles;
            return(res.normalized);
        }
        else
        {
            Vector3 res = node.finalFlowDirection;// + Quaternion.AngleAxis(node.flowDirectionOffset_Angle, Vector3.right).eulerAngles + lastNode.flowDirection + Quaternion.AngleAxis(lastNode.flowDirectionOffset_Angle, Vector3.right).eulerAngles;
            return(res.normalized);
        }
    }
Пример #10
0
            public void AddUpStream(Vector3 pos, float flux)
            {
                if (_remainFlux - flux < 0)
                {
                    throw new UnityException("not enough flux!");
                }

                _remainFlux -= flux;
                var up = new RiverNode(pos, flux);

                up._downstream = this;
                _upstream.Add(up);
            }
Пример #11
0
    private void Start()
    {
        shakeTimer           = shakeDuration;
        skybox               = GetComponent <Skybox>();
        targetNode           = riverController.riverAsset.GetNodeFromPosition(boat.transform.position);
        transform.rotation   = boat.transform.rotation;
        targetRotationVector = transform.rotation.eulerAngles;
        renderer             = victoryFade.GetComponent <Renderer>();
        float alpha = 0;
        Color color = Color.white;

        color.a = alpha;
        renderer.material.color = color;
    }
    public Vector3 GetFlow(Vector3 pos)
    {
        RiverNode node = null;

        pos.y = 0;
        float distance = Mathf.Infinity;
        int   index    = 0;

        for (index = 0; index < nodes.Length; index++)
        {
            float newDist = Vector3.Distance(pos, new Vector3(nodes[index].centerVector.x, 0, nodes[index].centerVector.z));
            if (newDist < distance)
            {
                node     = nodes[index];
                distance = newDist;
            }
        }

        RiverNode lastNode = null;
        RiverNode nextNode = null;

        if (index - 1 >= 0)
        {
            lastNode = nodes[index - 1];
        }
        if (index + 1 < nodes.Length)
        {
            nextNode = nodes[index + 1];
        }

        if (lastNode == null || nextNode == null)
        {
            return(node.finalFlowDirection);
        }

        float distLast = Vector3.Distance(pos, lastNode.centerVector);
        float distNext = Vector3.Distance(pos, nextNode.centerVector);

        if (distLast > distNext)
        {
            Vector3 res = node.finalFlowDirection;// + Quaternion.AngleAxis(node.flowDirectionOffset_Angle, Vector3.right).eulerAngles + nextNode.flowDirection + Quaternion.AngleAxis(nextNode.flowDirectionOffset_Angle, Vector3.right).eulerAngles;
            return(res.normalized);
        }
        else
        {
            Vector3 res = node.finalFlowDirection;// + Quaternion.AngleAxis(node.flowDirectionOffset_Angle, Vector3.right).eulerAngles + lastNode.flowDirection + Quaternion.AngleAxis(lastNode.flowDirectionOffset_Angle, Vector3.right).eulerAngles;
            return(res.normalized);
        }
    }
Пример #13
0
    private void TriangulateRiver(RiverNode node)
    {
        if (node == null)
        {
            return;
        }

        if (node.Downslope != null && node.Width > MinimumWidth)
        {
            TriangulateRiverSegment(node, node.Downslope);
        }

        TriangulateRiver(node.Left);
        TriangulateRiver(node.Right);
    }
    void Update()
    {
        closestNode = river.riverAsset.GetNodeFromPosition(transform.position);
        if (closestNode.index > lastPassedNodeIndex)
        {
            lastPassedNodeIndex = closestNode.index;
        }

        if (closestNode.index < lastPassedNodeIndex)
        {
            GetComponent <Rigidbody>().AddForce(river.riverAsset.GetNodeFromIndex(closestNode.index).flowDirection *force *Time.deltaTime *(lastPassedNodeIndex - closestNode.index));
            applyingForce = true;
        }
        else
        {
            applyingForce = false;
        }
    }
    public RiverNode GetNodeFromPosition(Vector3 pos)
    {
        RiverNode node = null;

        pos.y = 0;
        float distance = Mathf.Infinity;

        for (int i = 0; i < nodes.Length; i++)
        {
            float newDist = Vector3.Distance(pos, new Vector3(nodes[i].centerVector.x, 0, nodes[i].centerVector.z));
            if (newDist < distance)
            {
                node     = nodes[i];
                distance = newDist;
            }
        }
        return(node);
    }
    public RiverNode GetNodeFromPosition(Vector3 offset, Vector3 pos)
    {
        RiverNode node = null;

        float dist  = Mathf.Infinity;
        int   index = 0;

        for (index = 0; index < nodes.Length; index++)
        {
            float newDist = Vector3.Distance(pos, offset + nodes[index].centerVector);
            if (newDist < dist)
            {
                node = nodes[index];
                dist = newDist;
            }
        }

        return(node);
    }
Пример #17
0
    private ChunkData GenerateChunk(int[,] landClone, ChunkBase cb)
    {
        int x = cb.Position.x;
        int z = cb.Position.z;

        //If there is a river passing through here
        if (cb.RiverNode != null)
        {
            float sqrt2 = Mathf.Sqrt(2);
            int[,] tiles            = new int[World.ChunkSize, World.ChunkSize];
            WorldObjectData[,] data = new WorldObjectData[World.ChunkSize, World.ChunkSize];

            RiverNode rn        = cb.RiverNode;
            Vec2i     exitDelta = rn.RiverExitDelta;
            Vec2i     entrDelta = rn.RiverEntranceDelta;

            if (exitDelta == null)
            {
                exitDelta = new Vec2i(0, 0);
            }
            if (entrDelta == null)
            {
                entrDelta = new Vec2i(0, 0);
            }

            //Calculatee the tile position of the entrance and exit point of the river
            int entrX = (entrDelta.x == 1) ? 16 : ((entrDelta.x == 0) ? 8 : 0);
            int entrZ = (entrDelta.z == 1) ? 16 : ((entrDelta.z == 0) ? 8 : 0);

            int exitX = (exitDelta.x == 1) ? 16 : ((exitDelta.x == 0) ? 8 : 0);
            int exitZ = (exitDelta.z == 1) ? 16 : ((exitDelta.z == 0) ? 8 : 0);



            float dx = entrX - exitX;
            float dz = entrZ - exitZ;
            //If dx or dz is 0, then
            float a, b, c;
            bool  angle = (dx != 0 && dz != 0);
            float divBy = angle ? 2 : 1;
            if (dx == 0)
            {
                a = 0;
                b = 1;
                c = -entrX;
            }
            else if (dz == 0)
            {
                a = 1;
                b = 0;
                c = -entrZ;
            }
            else
            {
                float m = dz / dx;
                c = -(entrZ - m * entrX);

                a = 1;
                b = -m;
            }


            float dem_sqr = (a * a + b * b);

            for (int tx = 0; tx < World.ChunkSize; tx++)
            {
                for (int tz = 0; tz < World.ChunkSize; tz++)
                {
                    float dist_sqr = ((a * tz + b * tx + c) * (a * tz + b * tx + c)) / dem_sqr;
                    if (dist_sqr < (cb.RiverNode.EntranceWidth * cb.RiverNode.EntranceWidth) / divBy)
                    {
                        Vector2 off = new Vector2(x * World.ChunkSize + tx, z * World.ChunkSize + tz);
                        //Debug.Log("here");
                        tiles[tx, tz] = Tile.WATER.ID;

                        if (!(data[tx, tz] is Water))
                        {
                            data[tx, tz] = new Water(new Vec2i(x * World.ChunkSize + tx, z * World.ChunkSize + tz));
                            (data[tx, tz] as Water).SetUVOffset(off);
                        }

                        if (tx < World.ChunkSize - 1 && !(data[tx + 1, tz] is Water))
                        {
                            data[tx + 1, tz] = new Water(new Vec2i(x * World.ChunkSize + tx + 1, z * World.ChunkSize + tz));
                            (data[tx + 1, tz] as Water).SetUVOffset(off + new Vector2(1, 0));
                        }
                        if (tz < World.ChunkSize - 1 && !(data[tx, tz + 1] is Water))
                        {
                            data[tx, tz + 1] = new Water(new Vec2i(x * World.ChunkSize + tx, z * World.ChunkSize + tz + 1));
                            (data[tx, tz + 1] as Water).SetUVOffset(off + new Vector2(0, 1));
                        }
                        if (tx < World.ChunkSize - 1 && tz < World.ChunkSize - 1 && !(data[tx + 1, tz + 1] is Water))
                        {
                            data[tx + 1, tz + 1] = new Water(new Vec2i(x * World.ChunkSize + tx + 1, z * World.ChunkSize + tz + 1));
                            (data[tx + 1, tz + 1] as Water).SetUVOffset(off + new Vector2(1, 1));
                        }

                        if (tx > 0 && !(data[tx - 1, tz] is Water))
                        {
                            data[tx - 1, tz] = new Water(new Vec2i(x * World.ChunkSize + tx - 1, z * World.ChunkSize + tz));
                            (data[tx - 1, tz] as Water).SetUVOffset(off + new Vector2(-1, 0));
                        }
                        if (tz > 0 && !(data[tx, tz - 1] is Water))
                        {
                            data[tx, tz - 1] = new Water(new Vec2i(x * World.ChunkSize + tx, z * World.ChunkSize + tz - 1));
                            (data[tx, tz - 1] as Water).SetUVOffset(off + new Vector2(0, -1));
                        }
                        if (tx > 0 && tz > 0 && !(data[tx - 1, tz - 1] is Water))
                        {
                            data[tx - 1, tz - 1] = new Water(new Vec2i(x * World.ChunkSize + tx - 1, z * World.ChunkSize + tz - 1));
                            (data[tx - 1, tz - 1] as Water).SetUVOffset(off + new Vector2(-1, -1));
                        }

                        if (tx > 0 && tz < World.ChunkSize - 1 && !(data[tx - 1, tz + 1] is Water))
                        {
                            data[tx - 1, tz + 1] = new Water(new Vec2i(x * World.ChunkSize + tx - 1, z * World.ChunkSize + tz + 1));
                            (data[tx - 1, tz + 1] as Water).SetUVOffset(off + new Vector2(-1, +1));
                        }
                        if (tz > 0 && tx < World.ChunkSize - 1 && !(data[tx + 1, tz - 1] is Water))
                        {
                            data[tx + 1, tz - 1] = new Water(new Vec2i(x * World.ChunkSize + tx + 1, z * World.ChunkSize + tz - 1));
                            (data[tx + 1, tz - 1] as Water).SetUVOffset(off + new Vector2(1, -1));
                        }
                    }
                    else if (dist_sqr < (cb.RiverNode.EntranceWidth * cb.RiverNode.EntranceWidth) * 1.4f / divBy)
                    {
                        tiles[tx, tz] = Tile.SAND.ID;
                    }
                    else
                    {
                        tiles[tx, tz] = Tile.GRASS.ID;
                    }
                }
            }

            data[0, 0] = new Tree(new Vec2i(x * World.ChunkSize, z * World.ChunkSize));


            Dictionary <int, WorldObjectData> data_ = new Dictionary <int, WorldObjectData>();

            for (int i = 0; i < World.ChunkSize; i++)
            {
                for (int j = 0; j < World.ChunkSize; j++)
                {
                    if (data[i, j] != null)
                    {
                        data_.Add(WorldObject.ObjectPositionHash(i, j), data[i, j]);
                    }
                }
            }

            return(new ChunkData(x, z, tiles, cb.IsLand, data_));

            //Debug.Log("river");
        }
        else
        {
            ChunkData cd = new ChunkData(x, z, landClone, cb.IsLand);
            return(cd);
        }
    }
Пример #18
0
 public RiverNode(Vector3 pos, float flux)
 {
     _pos        = pos; _flux = flux; _remainFlux = _flux;
     _downstream = null;
     _upstream   = new List <RiverNode>();
 }
Пример #19
0
    void Update()
    {
        if (skybox != null)
        {
            skybox.material.SetFloat("_Rotation", Time.time);
        }

        if (shaking)
        {
            ShakeCam();
        }

        if (GameController.instance.GetClearGame())
        {
            var heading1   = transform.position - (boat.transform.position + new Vector3(0, 10, 0));
            var distance1  = heading1.magnitude;
            var direction1 = heading1 / distance1; // This is now the normalized direction.

            targetRotation = Quaternion.LookRotation(-direction1, Vector3.up);

            if (offset == Vector3.zero && slopeAngle == 0)
            {
                targetRotation.x = 0;
                targetRotation.z = 0;
            }

            transform.Rotate(new Vector3(-offsetAngle, 0, 0));
            transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * rotationSpeed);

            transform.Rotate(new Vector3(offsetAngle, 0, 0));

            if (beforeFade < waitBeforeFade)
            {
                beforeFade += Time.deltaTime;
            }
            else if (duringFade < waitDuringFade)
            {
                duringFade += Time.deltaTime;

                float alpha = duringFade / waitDuringFade;
                Color color = Color.white;
                color.a = alpha;

                renderer.material.color = color;
            }
            else if (afterFade < waitAfterFade)
            {
                afterFade += Time.deltaTime;
            }
            else
            {
                GameController.instance.OnCompletedLevel();
            }
            return;
        }

        if (boat.reverseProgress)
        {
            transform.position = boat.transform.position + boatOffset + shakeOffset;
            //return;
        }

        Vector3 heading;
        float   distance;
        Vector3 direction; // This is the normalized direction.
        Vector3 basePos   = transform.position;
        Vector3 adjustPos = Vector3.zero;

        heading   = basePos - (boat.transform.position + new Vector3(0, 5, 0));
        distance  = heading.magnitude;
        direction = heading / distance;

        RaycastHit hit;

        //Debug.DrawRay(transform.position, -heading, Color.red);

        blocked = false;
        offset  = Vector3.zero;
        bool centerBlocked = false;

        if (Physics.Raycast(transform.position, -heading, out hit, distance))
        {
            blockedHorizontal = false;

            if (hit.collider.gameObject.tag == "Untagged")
            {
                blocked           = true;
                centerBlocked     = true;
                blockedHorizontal = true;
            }
        }

        {
            adjustPos = transform.right * autoCorrectRadius;

            //Debug.DrawRay(transform.position - adjustPos, -heading, Color.red);
            //Debug.DrawRay(transform.position + adjustPos, -heading, Color.red);
            if (Physics.Raycast(transform.position + adjustPos, -heading, out hit, distance))
            {
                if (hit.collider.gameObject.tag == "Untagged")
                {
                    blockedHorizontal = true;
                    blocked           = true;
                }
            }
            if (Physics.Raycast(transform.position - adjustPos, -heading, out hit, distance))
            {
                if (hit.collider.gameObject.tag == "Untagged")
                {
                    if (blockedHorizontal == true)
                    {
                        blockedHorizontal = false;
                    }
                    else
                    {
                        blockedHorizontal = true;
                    }


                    blocked   = true;
                    adjustPos = -adjustPos;
                }
            }
            if (blocked)
            {
                adjustPos = -adjustPos;
            }
        }

        if (blocked)
        {
            offset = FixBlockedCamera(basePos, adjustPos, blockedVertical, blockedHorizontal);
        }

        RiverNode boatNode = boat.GetNodes().closest;

        if (boatNode != targetNode)
        {
            if (targetNode.centerVector == Vector3.zero)
            {
                targetNode = boatNode;
            }

            if (boatNode != oldTargetNode)
            {
                slopeAngle = targetNode.centerVector.y - boatNode.centerVector.y;
                //if (boat.transform.position.y - boatNode.centerVector.y < 0) slopeAngle = 0;
                heading   = (targetNode.centerVector + offset + new Vector3(0, slopeAngle, 0)) - boatNode.centerVector;
                distance  = heading.magnitude;
                direction = heading / distance; // This is now the normalized direction.

                oldTargetNode = targetNode;
                targetNode    = boatNode;

                targetRotation = Quaternion.LookRotation(-direction, Vector3.up);

                newTarget = true;
            }
        }
        else
        {
            if (oldTargetNode.centerVector != Vector3.zero)
            {
                heading   = (oldTargetNode.centerVector + offset + new Vector3(0, slopeAngle, 0)) - targetNode.centerVector;
                distance  = heading.magnitude;
                direction = heading / distance; // This is now the normalized direction.

                targetRotation = Quaternion.LookRotation(-direction, Vector3.up);

                if (offset == Vector3.zero && slopeAngle == 0)
                {
                    targetRotation.x = 0;
                    targetRotation.z = 0;
                }
            }
        }


        transform.Rotate(new Vector3(-offsetAngle, 0, 0));
        if (centerBlocked)
        {
            transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * (rotationSpeed + blockRotationSpeed));
        }
        else if (blocked)
        {
            transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * (rotationSpeed * 2));
        }
        else
        {
            transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * rotationSpeed);
        }

        transform.Rotate(new Vector3(offsetAngle, 0, 0));
        //Gets target position
        targetRotationVector = transform.rotation.eulerAngles;
        Quaternion boatOffsetRot = Quaternion.Euler(targetRotationVector.x, targetRotationVector.y, targetRotationVector.z);

        boatOffset = boatOffsetRot * offsetPosition;

        targetPosition     = boat.transform.position + boatOffset + shakeOffset;
        transform.position = targetPosition;
    }
Пример #20
0
    private List <RiverNode> GenerateDownslopes(MapArray <int> bitmask)
    {
        var simplex = new Simplex2D(52562);

        MapArray <float> weights = new MapArray <float>(1000.0f);
        var rivernet             = new List <RiverNode>();
        var node_lookup          = new Dictionary <GBTCorner, RiverNode>();
        var queue = new BinaryMinHeap <QueueElement <RiverNode> >();

        // Assign weights to each land vertex and add coast vertices to the queue.
        foreach (KeyValuePair <GBTCorner, int> kvp in bitmask.GetCornerEnumerator())
        {
            if ((kvp.Value & 1) > 0)
            {
                weights[kvp.Key] = simplex.GetFractalNoise(4.0f * kvp.Key.position / Radius);
                if ((kvp.Value & 2) > 0)
                {
                    RiverNode node = new RiverNode(kvp.Key);
                    queue.Push(new QueueElement <RiverNode>(weights[kvp.Key], node));
                    rivernet.Add(node);
                    node_lookup[kvp.Key] = node;
                }
            }
        }

        while (queue.Count > 0)
        {
            RiverNode node = queue.Pop().value;

            GBTCorner lowest        = new GBTCorner(-1);
            float     lowest_weight = 999.0f;

            // Find the neighboring land node with the lowest weight which has not already
            // been added to the network.
            foreach (GBTCorner adjacent in node.Vertex.GetAdjacent())
            {
                if (CheckValidAdjacent(node, adjacent, bitmask, node_lookup) && weights[adjacent] < lowest_weight)
                {
                    lowest_weight = weights[adjacent];
                    lowest        = adjacent;
                }
            }

            // Add the lowest node to the network, and push it and the into the queue.
            if (lowest.isValid())
            {
                var new_node = new RiverNode(lowest);
                new_node.Downslope = node;
                if (node.Left == null)
                {
                    node.Left = new_node;
                    // If the node hasn't been filled, add it to the queue again, but with a lower weight.
                    weights[node.Vertex] += 0.05f;
                    queue.Push(new QueueElement <RiverNode>(weights[node.Vertex], node));
                }
                else if (node.Right == null)
                {
                    node.Right = new_node;
                }
                node_lookup[lowest] = new_node;
                queue.Push(new QueueElement <RiverNode>(weights[lowest], new_node));
            }
        }

        return(rivernet);
    }
Пример #21
0
 public RiverTuple(River dataNode, RiverNode renderNode)
 {
     _dataNode   = dataNode;
     _renderNode = renderNode;
 }
Пример #22
0
        public static MapEntry Read(FileEntry entry, BinaryReader br)
        {
            var t = new MapEntry { MapVersion = br.ReadUInt32(), MapFileName = entry.Name }; // 60 < MapVersion < 62

            #region Header
            if (t.MapVersion < 4 || t.MapVersion > 62)
                return null;

            if (t.MapVersion >= 27)
                t.IterationVersion = br.ReadUInt32();

            br.ReadBytes(8);

            t.GridSize = br.ReadSingle();
            t.TileSet = br.ReadByte();
            t.UseRoad = br.ReadBoolean();
            t.Music = br.Read<UInt16>(3);

            if (t.MapVersion >= 11)
            {
                t.UseClouds = br.ReadBoolean();
                t.UseTimeOfDay = br.ReadBoolean();
                t.FileName = br.ReadLengthedString();
            }

            if (t.MapVersion >= 36)
                t.CullingStyle = br.ReadSingle();

            if (t.MapVersion >= 45)
                t.NumOfImports = br.ReadUInt32();
            #endregion

            #region Common Data
            t.EntryX = br.ReadSingle();
            t.EntryY = br.ReadSingle();
            t.EntryZ = br.ReadSingle();
            t.EntryW = br.ReadSingle();
            t.NumModulePlacements = br.ReadInt32();
            t.NumOfVOGOs = br.ReadInt32();
            t.NumOfClientVOGOs = br.ReadInt32();
            t.HighestCoid = br.ReadUInt32();
            t.PerPlayerLoadTrigger = br.ReadInt64();
            t.CreatorLoadTrigger = br.ReadInt64();

            if (t.MapVersion >= 33)
                t.OnKillTrigger = br.ReadInt64();

            if (t.MapVersion >= 34)
                t.LastTeamTrigger = br.ReadInt64();

            var missC = br.ReadUInt32();
            for (var i = 0U; i < missC; ++i)
            {
                var ms = MissionString.Read(br, t.MapVersion);
                t.MissionStrings.Add(ms.StringId, ms);
            }

            var wpC = br.ReadUInt32();
            for (var i = 0U; i < wpC; ++i)
            {
                var wp = VisualWaypoint.Read(br, t.MapVersion);
                t.VisualWaypoints.Add(wp.Id, wp);
            }

            var varC = br.ReadUInt32();
            for (var i = 0U; i < varC; ++i)
            {
                var v = Variable.Read(br, t.MapVersion);
                t.Variables.Add(v.Id, v);
            }

            if (t.MapVersion >= 47)
            {
                t.WeatherStrEffect = br.ReadLengthedString();

                var regionCount = br.ReadUInt32();
                for (var i = 0U; i < regionCount; ++i)
                {
                    var regionId = br.ReadByte();

                    if (!t.WeatherInfos.ContainsKey(regionId))
                        t.WeatherInfos.Add(regionId, new WeatherContainer());

                    var weatherCount = br.ReadUInt32();
                    for (var j = 0U; j < weatherCount; ++j)
                    {
                        t.WeatherInfos[regionId].Weathers.Add(new WeatherInfo
                        {
                            SpecialType = br.ReadUInt32(),
                            Type = br.ReadUInt32(),
                            PercentChance = br.ReadSingle(),
                            SpecialEventSkill = br.ReadInt32(),
                            EventTimesPerMinute = br.ReadByte(),
                            MinTimeToLive = br.ReadUInt32(),
                            MaxTimeToLive = br.ReadUInt32(),
                            LayerBits = t.MapVersion >= 54 ? br.ReadUInt32() : 1,
                            FxName = br.ReadLengthedString()
                        });
                    }

                    t.WeatherInfos[regionId].Effect = br.ReadLengthedString();

                    for (var j = 0; j < 4; ++j)
                        t.WeatherInfos[regionId].Environments.Add(br.ReadLengthedString());
                }
            }

            if (t.MapVersion >= 38)
            {
                // Sea Plane Data
                if (t.MapVersion >= 35)
                {
                    if (br.ReadByte() != 0)
                    {
                        var planeCount = br.ReadInt32();

                        t.SeaPlane.Coords = Vector4.Read(br);
                        t.SeaPlane.CoordsList = new List<Vector4>(planeCount);

                        for (var i = 0; i < planeCount; ++i)
                            t.SeaPlane.CoordsList.Add(Vector4.Read(br));
                    }
                }
            }

            #endregion

            Debug.Assert(t.NumModulePlacements == 0, "WTF Happened?!");

            #region VOGOs
            for (var i = 0; i < t.NumOfClientVOGOs + t.NumOfVOGOs; ++i)
            {
                Byte layer = 0;
                if (t.MapVersion > 5)
                    layer = br.ReadByte();

                var cbid = br.ReadInt32();
                var coid = br.ReadInt32();

                var skipBytes = br.ReadInt32(); // skip this many bytes, if client already loaded this clone base object

                var obj = ClonedObjectBase.AllocateNewObjectFromCBID(cbid);
                if (obj == null)
                {
                    br.BaseStream.Seek(skipBytes, SeekOrigin.Current);
                    continue;
                }

                obj.InitializeFromCBID(cbid, null);
                obj.Layer = layer;
                obj.SetCOID(coid);

                var pos = br.BaseStream.Position;

                try
                {
                    obj.Unserialize(br, t.MapVersion);
                }
                catch (EndOfStreamException)
                {
                    Console.WriteLine("EOS?!?!");
                }

                if (!t.ObjectBasesByType.ContainsKey(obj.Type))
                    t.ObjectBasesByType.Add(obj.Type, new List<ClonedObjectBase>());

                t.ObjectBasesByType[obj.Type].Add(obj);

                if (pos + skipBytes == br.BaseStream.Position)
                    continue;

                Console.WriteLine("COID: {0} ({1}) | {2} reading | Read size: {3} | Total size: {4} | Diff: {5}", coid, obj.Type, (pos + skipBytes > br.BaseStream.Position ? "under" : "over"), Math.Abs(br.BaseStream.Position - pos), skipBytes, skipBytes - Math.Abs(br.BaseStream.Position - pos));
                br.BaseStream.Position = pos + skipBytes;
            }

            #endregion

            #region Roads
            if (t.MapVersion >= 43)
                t.Flags = br.ReadUInt32();

            var numRoads = br.ReadUInt32();
            for (var i = 0U; i < numRoads; ++i)
            {
                /*var unk = */
                br.ReadUInt32();
                var type = br.ReadByte();

                RoadNodeBase roadNodeBase;

                switch (type)
                {
                    case 0:
                        roadNodeBase = new RoadNode();
                        break;

                    case 1:
                        roadNodeBase = new RoadJunction();
                        break;

                    case 2:
                        roadNodeBase = new RiverNode();
                        break;

                    default:
                        throw new InvalidDataException("Invalid road node base type!");
                }

                roadNodeBase.UnSerialize(br, t.MapVersion);

                t.Roads.Add(roadNodeBase);
            }
            #endregion
            #region Music
            if (t.MapVersion >= 42)
            {
                var numMusicRegion = br.ReadUInt32();
                for (var i = 0U; i < numMusicRegion; ++i)
                {
                    /*var unk = */
                    br.ReadUInt32();
                    if (t.MapVersion < 42)
                        continue;

                    /*var musicName = */
                    br.ReadLengthedString();
                    /*var looping = */
                    br.ReadBoolean();
                    /*var silenceatmaxradius = */
                    br.ReadBoolean();
                    /*var durationForRepeat = */
                    br.ReadSingle();
                    /*var fadeintime = */
                    br.ReadSingle();
                    /*var fadeouttime = */
                    br.ReadSingle();
                    /*var maxradius = */
                    br.ReadSingle();
                    /*var x = */
                    br.ReadSingle();
                    /*var y = */
                    br.ReadSingle();
                    /*var z = */
                    br.ReadSingle();
                    /*var musicType = */
                    br.ReadUInt32();
                }
            }
            #endregion
            #region MapFlair
            if (t.MapVersion >= 30)
            {
                /*var streamVer = */
                br.ReadUInt32();
                /*var width = */
                br.ReadInt32();
                /*var height = */
                br.ReadInt32();
                /*var maxobjcountperglomsector = */
                br.ReadInt32();

                var objectcount = br.ReadInt32();
                for (var i = 0; i < objectcount; ++i)
                {
                    /*var streamVer2 = */
                    br.ReadUInt32();
                    /*var cbidVisual = */
                    br.ReadInt32();
                    /*var drawSizeMin = */
                    br.ReadSingle();
                    /*var drawSizeVariance = */
                    br.ReadSingle();
                    /*var thresholdMin = */
                    br.ReadByte();
                    /*var thresholdMax = */
                    br.ReadByte();
                    /*var layerMask = */
                    br.ReadByte();
                    /*var placeWithGroundNormal = */
                    br.ReadByte();
                }

                var inlineDensityMap = br.ReadBoolean();
                Debug.Assert(!inlineDensityMap, "I HOPE THIS IS UNREACHABLE!");
            }
            #endregion

            var stream = AssetManager.GetStreamByName(entry.Name.ToLower().Replace(".fam", ".xml"));
            if (stream != null)
            {
                using (stream)
                {
                    var doc = XDocument.Load(stream);
                    Debug.Assert(doc != null);

                    var element = doc.Element("Map");
                    if (element != null)
                    {
                        t.ContinentId = (UInt32)element.Attribute("continentObjectID");
                        t.Name = (String)element.Element("Name");
                        t.Description = (String)element.Element("Description");
                    }
                }
            }
            else
            {
                Debug.Assert(false, "Nincs a mapnak info-ja ?!?!?!");
            }

            return t;
        }
Пример #23
0
    private void GenerateRiverBridge(ChunkBase cb, WorldObjectData[,] chunkObjs, int bridgeWidth = 5)
    {
        RiverNode rn    = cb.RiverNode;
        int       rDirX = Mathf.Abs(rn.RiverNodeDirection().x);
        int       rDirZ = Mathf.Abs(rn.RiverNodeDirection().z);

        if (rDirX == 1 && rDirZ == 1)
        {
            return;
        }

        Vec2i absDir = new Vec2i(rDirX, rDirZ);

        int riverWidth = (int)rn.EntranceWidth;
        int halfWidth  = bridgeWidth / 2;

        Vec2i start, end;

        if (rDirX == 1)
        {
            start = new Vec2i(World.ChunkSize / 2 - halfWidth, World.ChunkSize / 2 - riverWidth);
            end   = new Vec2i(World.ChunkSize / 2 + halfWidth, World.ChunkSize / 2 + riverWidth + 1);
        }
        else
        {
            start = new Vec2i(World.ChunkSize / 2 - riverWidth, World.ChunkSize / 2 - halfWidth);
            end   = new Vec2i(World.ChunkSize / 2 + riverWidth + 1, World.ChunkSize / 2 + halfWidth);
        }


        RiverBridgeObject rbObj = new RiverBridgeObject(start, end, absDir);

        IMultiTileObjectChild[,] childs = rbObj.GetChildren();

        for (int x = 0; x < rbObj.Size.x; x++)
        {
            for (int z = 0; z < rbObj.Size.z; z++)
            {
                chunkObjs[start.x + x, start.z + z] = childs[x, z] as WorldObjectData;
            }
        }

        /*
         * //If these do not sum to 1, the direction is not simple (i.e, diagonal) and no bridge can be made
         * if (rnDir.x + rnDir.z != 1)
         *  return;
         * //If the river is travelling in the z direction
         * if (rnDir.x == 0)
         * {
         *  Vec2i start = new Vec2i(World.ChunkSize / 2 - halfWidth, World.ChunkSize / 2 - riverWidth);
         *  Vec2i end = new Vec2i(World.ChunkSize / 2 + halfWidth, World.ChunkSize / 2 + riverWidth);
         *
         *  RiverBridgeObject rbObj = new RiverBridgeObject(start, end, new Vec2i(1,0));
         *  IMultiTileObjectChild[,] childs = rbObj.GetChildren();
         *  for(int x=0; x<rbObj.Size.x; x++)
         *  {
         *      for(int z=0; z<rbObj.Size.z; z++)
         *      {
         *          chunkObjs[start.x + x, start.z + z] = childs[x, z] as WorldObjectData;
         *      }
         *  }
         * }
         * else
         * {
         *
         * }*/
    }
 public FloatingObjectNodes(RiverNode c, RiverNode l)
 {
     closest = c; last = l;
 }
Пример #25
0
        private Mesh BuildSegmentMesh(RiverNode downStream, RiverNode upStream)
        {
            List <Vector3> vertices    = new List <Vector3>();
            List <int>     indices     = new List <int>();
            Vector3        centralAxis = (upStream._pos - downStream._pos); //axis

            int   radialVertCount = (Mathf.FloorToInt(upStream._flux / 5f) + 1) * 20;
            int   dispTime        = Mathf.Min(5, (Mathf.FloorToInt(centralAxis.magnitude / 5f) + 1));
            float dispScale       = 0.5f;


            Vector3 downProj = Vector3.ProjectOnPlane(Vector3.down, centralAxis);

            if (Mathf.Approximately(downProj.magnitude, 0f))
            {
                throw new UnityException("no waterfall at the very beginning");
            }
            downProj.Normalize();
            float radialAngleInc = 1 / (float)(radialVertCount - 1) * 180f;

            for (int r = 0; r < radialVertCount; r++)
            {
                var radialoffset = Quaternion.AngleAxis(-90 + radialAngleInc * (float)r, centralAxis) * downProj * upStream._flux;
                var vert         = downStream._pos + radialoffset;
                vertices.Add(vert);
            }

            //generate midpoint displacement here
            if (dispTime > 0)
            {
                float[,] disp = new float[(int)Mathf.Pow(2, dispTime) - 1, radialVertCount];

                Queue <Int2> indexQueue = new Queue <Int2>();
                int          mid        = disp.GetLength(0) / 2;
                indexQueue.Enqueue(new Int2(mid, dispTime));
                while (indexQueue.Count > 0)
                {
                    var curr      = indexQueue.Dequeue();
                    var currIndex = curr._x;
                    var currLevel = curr._y;
                    var currScale = Mathf.Pow(2, currLevel - dispTime) * dispScale;
                    for (int r = 0; r < radialVertCount; r++)
                    {
                        disp[currIndex, r] = Random.Range(-currScale, currScale);
                    }

                    currLevel--;
                    if (currLevel > 0)
                    {
                        indexQueue.Enqueue(new Int2(currIndex - currLevel, currLevel));
                        indexQueue.Enqueue(new Int2(currIndex + currLevel, currLevel));
                    }
                }


                //add displaced vertices (and the other end)
                Vector3 axisInc  = centralAxis / Mathf.Pow(2, dispTime);
                Vector3 axisNode = downStream._pos;
                for (int i = 0; i <= disp.GetLength(0); i++)
                {
                    axisNode  += axisInc;
                    axisNode.y = _island.GetElevation(new BenTools.Mathematics.Vector(axisNode.x, axisNode.z));
                    if (i != disp.GetLength(0))
                    {
                        for (int r = 0; r < radialVertCount; r++)
                        {
                            var vert = vertices[r] + (float)(i + 1) * axisInc;
                            vert = axisNode + (vert - axisNode) * (1f + disp[i, r]);
                            vertices.Add(vert);
                        }
                    }
                    else
                    {
                        for (int r = 0; r < radialVertCount; r++)
                        {
                            vertices.Add(vertices[r] + (float)(i + 1) * axisInc);
                        }
                    }
                    //connect triangles
                    for (int r = 0; r < radialVertCount; r++)
                    {
                        indices.Add((i + 1) * radialVertCount + r % radialVertCount);
                        indices.Add(i * radialVertCount + r % radialVertCount);
                        indices.Add(i * radialVertCount + (r + 1) % radialVertCount);

                        indices.Add((i + 1) * radialVertCount + r % radialVertCount);
                        indices.Add(i * radialVertCount + (r + 1) % radialVertCount);
                        indices.Add((i + 1) * radialVertCount + (r + 1) % radialVertCount);
                    }
                }
            }


            Mesh segmentMesh = new Mesh();

            segmentMesh.vertices  = vertices.ToArray();
            segmentMesh.triangles = indices.ToArray();
            return(segmentMesh);
        }
Пример #26
0
 public RiverNode(GBTCorner vert)
 {
     vertex    = vert;
     width     = -1.0f;
     downslope = left = right = null;
 }