/// <summary> /// 获取传入的三个顶点组成的三角面和水平面相交的线段 /// </summary> /// <returns>The water shore segment.</returns> /// <param name="pos1">Pos1.</param> /// <param name="pos2">Pos2.</param> /// <param name="pos3">Pos3.</param> private WaterShoreSegment GetWaterShoreSegment(Vector3 pos1, Vector3 pos2, Vector3 pos3) { //判断每一个边是否和水平面相交 Vector3[] hitPoss = new Vector3[3]; int curHitIndex = 0; if (IsLineIntersectWater(pos1, pos2, out hitPoss[curHitIndex])) { ++curHitIndex; } if (IsLineIntersectWater(pos2, pos3, out hitPoss[curHitIndex])) { ++curHitIndex; } if (IsLineIntersectWater(pos3, pos1, out hitPoss[curHitIndex])) { ++curHitIndex; } //三条边中只有有两个交点才代表三角面和水平面相交 if (curHitIndex == 2) { WaterShoreSegment line = new WaterShoreSegment(); line.posOne = hitPoss [0]; line.posTwo = hitPoss [1]; return(line); } return(null); }
void OnDrawGizmos() { return; //画所有的串联起来的边界线 Color[] allColors = new Color[5]; allColors [0] = Color.yellow; allColors [1] = Color.green; allColors [2] = Color.blue; allColors [3] = Color.black; for (int i = 0; i < waterList.Count; ++i) { Water water = waterList [i]; Gizmos.color = allColors[i % allColors.Length]; List <WaterShoreSegment> waterShoreSegments = water.GetAllWaterShoreSegment(); for (int j = 0; j < waterShoreSegments.Count; ++j) { WaterShoreSegment waterSHoreSegment = waterShoreSegments [j]; Vector3 posOne = waterSHoreSegment.posOne; Vector3 posTwo = waterSHoreSegment.posTwo; posOne.y += 0f; posTwo.y += 0f; Gizmos.DrawLine(posOne, posTwo); } } }
/// <summary> /// 获取圈中的任意一点 /// </summary> /// <returns>The inside point.</returns> Vector3 GetInsidePoint() { //TODO 并不能保证这个点不是在其他的圈内部 System.Text.StringBuilder sbLog = new System.Text.StringBuilder(); for (int j = 1; j < 2; ++j) { float offsetDis = j * 0.01f; for (int i = 0; i < mWaterShoreSegmentList.Count; ++i) { WaterShoreSegment waterShore = mWaterShoreSegmentList [i]; Vector3 centerPos = (waterShore.posOne + waterShore.posTwo) / 2; Vector3 verticalDir = Vector3.Cross((waterShore.posOne - centerPos).normalized, Vector3.up).normalized; Vector3 offsetPoint = centerPos + verticalDir * offsetDis; if (IsPointInSide(offsetPoint)) { return(offsetPoint); } sbLog.Append(offsetPoint.x + " " + offsetPoint.z + "\n"); offsetPoint = centerPos - verticalDir * offsetDis; if (IsPointInSide(offsetPoint)) { return(offsetPoint); } sbLog.Append(offsetPoint.x + " " + offsetPoint.z + "\n"); } } //TODO 这里真的出现过,需要调查 IsInvalidShore = true; Debug.LogError("居然没有找到在圈内的点 " + ID + "\n" + sbLog.ToString()); return(Vector3.zero); }
/// <summary> /// 把传入的线放入现有的链表中 /// </summary> /// <returns><c>true</c>, if water line was joined, <c>false</c> otherwise.</returns> /// <param name="line">Line.</param> public bool JoinWaterShoreSegment(WaterShoreSegment line) { if (mWaterShoreSegmentList.Count == 0) { mWaterShoreSegmentList.Add(line); return(true); } bool needExchange = false; if (mWaterShoreSegmentList [0].CanJoinAtFront(line, out needExchange)) { if (needExchange) { line.ExchangePos(); } mWaterShoreSegmentList.Insert(0, line); return(true); } if (mWaterShoreSegmentList [mWaterShoreSegmentList.Count - 1].CanJoinAtEnd(line, out needExchange)) { if (needExchange) { line.ExchangePos(); } mWaterShoreSegmentList.Add(line); return(true); } return(false); }
/// <summary> /// 获取所有水岸线的点 /// </summary> /// <returns>The all shore point.</returns> public List <Vector3> GetAllShorePoint() { if (null == mWaterShorePointList) { mWaterShorePointList = new List <Vector3> (); for (int i = 0; i < mWaterShoreSegmentList.Count; ++i) { WaterShoreSegment shoreSegment = mWaterShoreSegmentList [i]; if (mWaterShorePointList.Count == 0) { mWaterShorePointList.Add(shoreSegment.posOne); mWaterShorePointList.Add(shoreSegment.posTwo); } else { if (!shoreSegment.IsPointNear(shoreSegment.posOne, mWaterShorePointList [mWaterShorePointList.Count - 1])) { mWaterShorePointList.Add(shoreSegment.posOne); } mWaterShorePointList.Add(shoreSegment.posTwo); } } } if (mWaterShorePointList[0].Equals(mWaterShorePointList[mWaterShorePointList.Count - 1])) { mWaterShorePointList.RemoveAt(mWaterShorePointList.Count - 1); } return(mWaterShorePointList); }
/// <summary> /// 传入的水的边界线是否能够连接在当前线段的后面,如果能够相连,是否需要自动变换前后坐标 /// </summary> /// <returns><c>true</c>, if in front water line was joined, <c>false</c> otherwise.</returns> /// <param name="waterLine">Water line.</param> public bool CanJoinAtEnd(WaterShoreSegment segment, out bool needExchangePos) { needExchangePos = false; if (IsPointNear(posTwo, segment.posTwo)) { needExchangePos = true; return(true); } if (IsPointNear(posTwo, segment.posOne)) { return(true); } return(false); }
bool IsPointInSide(Vector3 point) { int intersectionCount = 0; for (int i = 0; i < mWaterShoreSegmentList.Count; ++i) { WaterShoreSegment shoreSegment = mWaterShoreSegmentList [i]; if (Utils.IsLineIntersection(point, new Vector3(100f, mWaterHeight, 100f) , shoreSegment.posOne, shoreSegment.posTwo)) { intersectionCount++; } } return(intersectionCount % 2 != 0); }
/// <summary> /// 传入的水岸线是否完全在当前的内部 /// </summary> /// <returns><c>true</c> if this instance is water shore inside the specified other; otherwise, <c>false</c>.</returns> /// <param name="other">Other.</param> public bool IsWaterShoreInside(WaterShore other) { List <WaterShoreSegment> otherSegments = other.GetAllWaterShoreSegment(); for (int i = 0; i < otherSegments.Count; ++i) { WaterShoreSegment waterSegment = otherSegments [i]; if (!IsPointInSide(waterSegment.posOne)) { return(false); } if (!IsPointInSide(waterSegment.posTwo)) { return(false); } } return(true); }
/// <summary> /// 裁减掉极小的不必要的线段 /// </summary> /// <param name="waterLineLength">Water line length.</param> public void CullSmallShoreSegment(float waterLineLength) { if (mWaterShoreSegmentList.Count == 1) { return; } for (int i = mWaterShoreSegmentList.Count - 1; i >= 1; --i) { WaterShoreSegment curSegment = mWaterShoreSegmentList [i]; WaterShoreSegment frontSegment = mWaterShoreSegmentList [i - 1]; if (curSegment.GetLength() < waterLineLength) { mWaterShoreSegmentList.RemoveAt(i); frontSegment.posTwo = curSegment.posTwo; } } GetAllShorePoint(); }
/// <summary> /// 检查是否有问题 /// </summary> public void CheckError() { for (int i = 0; i < mWaterShoreSegmentList.Count - 1; ++i) { WaterShoreSegment curSegment = mWaterShoreSegmentList [i]; WaterShoreSegment nextSegment = mWaterShoreSegmentList [i + 1]; bool needExchange = false; if (curSegment.CanJoinAtEnd(nextSegment, out needExchange)) { if (!needExchange) { continue; } } if (Vector3.Distance(curSegment.posTwo, nextSegment.posOne) > Vector3.Distance(curSegment.posTwo, nextSegment.posTwo)) { Debug.LogError("CheckError 1: " + curSegment.ToString() + " " + nextSegment.ToString()); } Debug.LogError("CheckError 2: " + curSegment.ToString() + " " + nextSegment.ToString()); } }
private List <WaterShoreSegment> GetAllWaterShoreSegment() { List <WaterShoreSegment> waterShoreSegmentList = new List <WaterShoreSegment> (); float[,] heights = terrainData.GetHeights(0, 0, terrainData.heightmapWidth, terrainData.heightmapHeight); for (int i = 0; i < terrainData.heightmapWidth - 1; ++i) { for (int j = 0; j < terrainData.heightmapHeight - 1; ++j) { //遍历每一个正方形,每一个正方形对应两个三角面,正方形顶点反向为 // 1 ----- 2 // | | // | | // 0 ----- 3 Vector3 pos0 = GetWorldPosByTerrainGrid(heights, i, j); Vector3 pos1 = GetWorldPosByTerrainGrid(heights, i, j + 1); Vector3 pos2 = GetWorldPosByTerrainGrid(heights, i + 1, j + 1); Vector3 pos3 = GetWorldPosByTerrainGrid(heights, i + 1, j); //第一个三角面三个顶点为0,1,2; WaterShoreSegment waterShoreSegment = GetWaterShoreSegment(pos0, pos1, pos2); if (waterShoreSegment != null) { waterShoreSegmentList.Add(waterShoreSegment); } //第二个三角面三个顶点为0,2,3 waterShoreSegment = GetWaterShoreSegment(pos0, pos2, pos3); if (waterShoreSegment != null) { waterShoreSegmentList.Add(waterShoreSegment); } } } return(waterShoreSegmentList); }
private List <WaterShore> GenerateWaterShoreList(List <WaterShoreSegment> waterShoreSegmentList) { List <WaterShore> waterShoreList = new List <WaterShore> (); //先把零散的线段第一次刷选,处理成一一系列的WaterInfo for (int i = 0; i < waterShoreSegmentList.Count; ++i) { WaterShoreSegment waterShoreSegment = waterShoreSegmentList [i]; bool hasFind = false; for (int j = 0; j < waterShoreList.Count; ++j) { WaterShore waterShore = waterShoreList [j]; if (waterShore.JoinWaterShoreSegment(waterShoreSegment)) { hasFind = true; break; } } if (!hasFind) { WaterShore waterInfo = new WaterShore(waterHeight); waterInfo.JoinWaterShoreSegment(waterShoreSegment); waterShoreList.Add(waterInfo); } } bool hasJoinSuccess = false; for (int i = 0; i < waterShoreList.Count; ++i) { //之所以j从0开始,因为A连接B失败,但是B连接A有可能成功,可以优化连接函数 for (int j = 0; j < waterShoreList.Count; ++j) { if (i == j) { continue; } WaterShore waterShoreA = waterShoreList [i]; WaterShore waterShoreB = waterShoreList [j]; //可以为每一个WaterInfo设定唯一表示,并且拼接WaterLine后ID改变,在这里缓存拼接失败的ID对 if (waterShoreA.JoinWaterShore(waterShoreB)) { hasJoinSuccess = true; waterShoreList.RemoveAt(j); break; } } //成功拼接后,waterInfos中的某一个数据已经无效,从新开始 if (hasJoinSuccess) { i = -1; hasJoinSuccess = false; } } Debug.Log("waterInfos.cout: " + waterShoreList.Count); for (int i = 0; i < waterShoreList.Count; ++i) { waterShoreList [i].CheckError(); } return(waterShoreList); }