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; } } }
/// <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; }
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); }
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); }
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); }
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); } }
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); }
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); } }
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); }
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); } }
public RiverNode(Vector3 pos, float flux) { _pos = pos; _flux = flux; _remainFlux = _flux; _downstream = null; _upstream = new List <RiverNode>(); }
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; }
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); }
public RiverTuple(River dataNode, RiverNode renderNode) { _dataNode = dataNode; _renderNode = renderNode; }
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; }
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; }
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); }
public RiverNode(GBTCorner vert) { vertex = vert; width = -1.0f; downslope = left = right = null; }