private void BuildDuckEndCap( RiverSpline riverSpline, Vector3 duckPortV2, Vector3 duckStarboardV2, Vector3 bankPortV2, Vector3 bankStarboardV2 ) { Vector3 duckWrapPortStart = duckPortV2 - bankPortV2; Vector3 duckWrapPortEnd = riverSpline.CenterSpline.GetDirection(1f) * RenderConfig.RiverDuckWidth; Vector3 duckCircleV2 = duckWrapPortStart; float duckCircleIncr = 2f / RenderConfig.RiverQuadsPerCurve; for (float circleParam = 0f; circleParam < 1; circleParam += duckCircleIncr) { Vector3 duckCircleV1 = duckCircleV2; duckCircleV2 = Vector3.Slerp(duckWrapPortStart, duckWrapPortEnd, circleParam); Grid.RiverDuckMesh.AddTriangle(bankPortV2, bankPortV2 + duckCircleV1, bankPortV2 + duckCircleV2); Grid.RiverDuckMesh.AddTriangleUV(Vector2.one, Vector2.zero, Vector2.zero); } Grid.RiverDuckMesh.AddTriangle(bankPortV2, bankPortV2 + duckCircleV2, bankPortV2 + duckWrapPortEnd); Grid.RiverDuckMesh.AddTriangleUV(Vector2.one, Vector2.zero, Vector2.zero); Vector3 duckWrapStarboardStart = duckStarboardV2 - bankStarboardV2; Vector3 duckWrapStarboardEnd = riverSpline.CenterSpline.GetDirection(1f) * RenderConfig.RiverDuckWidth; duckCircleV2 = duckWrapPortStart; for (float circleParam = 0f; circleParam < 1; circleParam += duckCircleIncr) { Vector3 duckCircleV1 = duckCircleV2; duckCircleV2 = Vector3.Slerp(duckWrapStarboardStart, duckWrapStarboardEnd, circleParam); Grid.RiverDuckMesh.AddTriangle(bankStarboardV2, bankStarboardV2 + duckCircleV2, bankStarboardV2 + duckCircleV1); Grid.RiverDuckMesh.AddTriangleUV(Vector2.one, Vector2.zero, Vector2.zero); } Grid.RiverDuckMesh.AddTriangle(bankStarboardV2, bankStarboardV2 + duckWrapStarboardEnd, bankStarboardV2 + duckCircleV2); Grid.RiverDuckMesh.AddTriangleUV(Vector2.one, Vector2.zero, Vector2.zero); Grid.RiverDuckMesh.AddQuad( bankPortV2, bankStarboardV2, bankPortV2 + duckWrapPortEnd, bankStarboardV2 + duckWrapStarboardEnd ); Grid.RiverDuckMesh.AddQuadUV(Vector2.one, Vector2.one, Vector2.zero, Vector2.zero); }
private void TriangulateRiver(RiverSpline riverSpline) { Vector3 riverYVector = Vector3.up * RenderConfig.WaterY; var centerSpline = riverSpline.CenterSpline; float maxSurfaceWidth = RenderConfig.RiverMaxSurfaceWidth * Mathf.Clamp01((float)centerSpline.CurveCount / RenderConfig.RiverCurvesForMaxWidth); float maxBankWidth = (RenderConfig.RiverMaxSurfaceWidth + RenderConfig.RiverMaxBankWidth) * Mathf.Clamp01((float)centerSpline.CurveCount / RenderConfig.RiverCurvesForMaxWidth); int riverQuadCount = centerSpline.CurveCount * RenderConfig.RiverQuadsPerCurve; float tDelta = 1f / riverQuadCount; float t = 0f; Vector3 surfacePortV1, surfaceStarboardV1, bankPortV1, bankStarboardV1, center1, duckPortV1, duckStarboardV1; Vector3 center2 = centerSpline.GetPoint(tDelta) + riverYVector; float noise = NoiseGenerator.SampleNoise( new Vector2(center2.x, center2.z), RenderConfig.GenericNoiseSource, RenderConfig.RiverWidthNoise, NoiseType.NegativeOneToOne ).x; Vector3 flow1 = centerSpline.GetDirection(t); Vector3 flow2 = centerSpline.GetDirection(tDelta); float surfaceWidth = maxSurfaceWidth * (Mathf.Clamp01(tDelta * RenderConfig.RiverWideningRate) + tDelta * noise); float bankWidth = maxBankWidth * (Mathf.Clamp01(tDelta * RenderConfig.RiverWideningRate) + tDelta * noise); Vector3 surfacePortV2 = center2 + centerSpline.GetNormalXZ(tDelta) * surfaceWidth; Vector3 surfaceStarboardV2 = center2 - centerSpline.GetNormalXZ(tDelta) * surfaceWidth; Vector3 bankPortV2 = center2 + centerSpline.GetNormalXZ(tDelta) * bankWidth; Vector3 bankStarboardV2 = center2 - centerSpline.GetNormalXZ(tDelta) * bankWidth; Grid.RiverSurfaceMesh.AddTriangle(centerSpline.Points[0] + riverYVector, surfacePortV2, surfaceStarboardV2); Grid.RiverSurfaceMesh.AddTriangleUV3(flow1, flow2, flow2); Grid.RiverSurfaceMesh.AddTriangleColor(RenderConfig.RiverWaterColor); Grid.RiverBankMesh.AddTriangle(centerSpline.Points[0] + riverYVector, bankPortV2, bankStarboardV2); Grid.RiverBankMesh.AddTriangleUV(Vector2.one, Vector2.zero, Vector2.zero); Vector3 duckPortV2, duckStarboardV2; BuildDuckStartCap( center2, centerSpline, bankPortV2, bankStarboardV2, tDelta, riverYVector, out duckPortV2, out duckStarboardV2 ); //Triangulating the main body of the river for (int sectionIndex = 0; sectionIndex < riverSpline.WesternCells.Count; sectionIndex++) { List <Vector2> thisEdgeContour = new List <Vector2>(); List <Vector2> neighborEdgeContour = new List <Vector2>(); if (sectionIndex == 0) { thisEdgeContour.Add(new Vector2(centerSpline.Points[0].x, centerSpline.Points[0].z)); neighborEdgeContour.Add(new Vector2(centerSpline.Points[0].x, centerSpline.Points[0].z)); } var sectionFlow = riverSpline.Flows[sectionIndex]; for (int pointIndex = 0; pointIndex < RenderConfig.RiverQuadsPerCurve; pointIndex++) { t += tDelta; surfacePortV1 = surfacePortV2; surfaceStarboardV1 = surfaceStarboardV2; bankPortV1 = bankPortV2; bankStarboardV1 = bankStarboardV2; duckPortV1 = duckPortV2; duckStarboardV1 = duckStarboardV2; center1 = center2; center2 = centerSpline.GetPoint(t) + riverYVector; noise = NoiseGenerator.SampleNoise( new Vector2(center2.x, center2.z), RenderConfig.GenericNoiseSource, RenderConfig.RiverWidthNoise, NoiseType.NegativeOneToOne ).x; surfaceWidth = maxSurfaceWidth * (Mathf.Clamp01(t * RenderConfig.RiverWideningRate) + t * noise); bankWidth = maxBankWidth * (Mathf.Clamp01(t * RenderConfig.RiverWideningRate) + t * noise); flow1 = flow2; flow2 = centerSpline.GetDirection(t); surfacePortV2 = center2 + centerSpline.GetNormalXZ(t) * surfaceWidth; surfaceStarboardV2 = center2 - centerSpline.GetNormalXZ(t) * surfaceWidth; bankPortV2 = center2 + centerSpline.GetNormalXZ(t) * bankWidth; bankStarboardV2 = center2 - centerSpline.GetNormalXZ(t) * bankWidth; duckPortV2 = center2 + centerSpline.GetNormalXZ(t) * RenderConfig.RiverDuckWidth; duckStarboardV2 = center2 - centerSpline.GetNormalXZ(t) * RenderConfig.RiverDuckWidth; Grid.RiverSurfaceMesh.AddQuad(surfacePortV1, surfaceStarboardV1, surfacePortV2, surfaceStarboardV2); Grid.RiverSurfaceMesh.AddQuadUV3(flow1, flow1, flow2, flow2); Grid.RiverSurfaceMesh.AddQuadColor(RenderConfig.RiverWaterColor); Grid.RiverBankMesh.AddQuad(center1, center2, bankPortV1, bankPortV2); Grid.RiverBankMesh.AddQuadUV(Vector2.one, Vector2.one, Vector2.zero, Vector2.zero); Grid.RiverBankMesh.AddQuad(center2, center1, bankStarboardV2, bankStarboardV1); Grid.RiverBankMesh.AddQuadUV(Vector2.one, Vector2.one, Vector2.zero, Vector2.zero); Grid.RiverDuckMesh.AddQuad(bankPortV1, bankPortV2, duckPortV1, duckPortV2); Grid.RiverDuckMesh.AddQuadUV(Vector2.one, Vector2.one, Vector2.zero, Vector2.zero); Grid.RiverDuckMesh.AddQuad(bankPortV2, bankPortV1, bankStarboardV2, bankStarboardV1); Grid.RiverDuckMesh.AddQuadUV(Vector2.one, Vector2.one, Vector2.one, Vector2.one); Grid.RiverDuckMesh.AddQuad(bankStarboardV2, bankStarboardV1, duckStarboardV2, duckStarboardV1); Grid.RiverDuckMesh.AddQuadUV(Vector2.one, Vector2.one, Vector2.zero, Vector2.zero); thisEdgeContour.Add(sectionFlow == RiverFlow.Counterclockwise ? surfacePortV1.ToXZ() : surfaceStarboardV1.ToXZ()); neighborEdgeContour.Add(sectionFlow == RiverFlow.Counterclockwise ? surfaceStarboardV1.ToXZ() : surfacePortV1.ToXZ()); } thisEdgeContour.Add(sectionFlow == RiverFlow.Counterclockwise ? surfacePortV2.ToXZ() : surfaceStarboardV2.ToXZ()); neighborEdgeContour.Add(sectionFlow == RiverFlow.Counterclockwise ? surfaceStarboardV2.ToXZ() : surfacePortV2.ToXZ()); CellEdgeContourCanon.SetContourForCellEdge( riverSpline.WesternCells[sectionIndex], riverSpline.Directions[sectionIndex], thisEdgeContour ); CellEdgeContourCanon.SetContourForCellEdge( riverSpline.EasternCells[sectionIndex], riverSpline.Directions[sectionIndex].Opposite(), neighborEdgeContour ); } BuildDuckEndCap(riverSpline, duckPortV2, duckStarboardV2, bankPortV2, bankStarboardV2); }
private void AssembleRiverSplines() { RiverAssemblyCanon.RefreshRivers(); foreach (var river in RiverAssemblyCanon.Rivers) { RiverSection section = river[0]; var centerSpline = new BezierSpline(section.FlowFromOne == RiverFlow.Clockwise ? section.Start : section.End); Vector3 centerToV1Direction, centerToV4Direction; Vector3 v1Tangent, v4Tangent; Vector3 controlOne, controlTwo; Vector3 v1, v4; bool isV1Internal, isV4Internal; bool isControlOneNegative, isControlTwoNegative; for (int i = 0; i < river.Count; i++) { section = river[i]; if (section.FlowFromOne == RiverFlow.Clockwise) { v1 = section.Start; v4 = section.End; isV1Internal = section.PreviousOnInternalCurve; isV4Internal = section.NextOnInternalCurve; } else { v1 = section.End; v4 = section.Start; isV1Internal = section.NextOnInternalCurve; isV4Internal = section.PreviousOnInternalCurve; } if (isV1Internal) { centerToV1Direction = (v1 - section.AdjacentCellOne.AbsolutePosition).normalized; } else { centerToV1Direction = (v1 - section.AdjacentCellTwo.AbsolutePosition).normalized; } if (isV4Internal) { centerToV4Direction = (v4 - section.AdjacentCellOne.AbsolutePosition).normalized; } else { centerToV4Direction = (v4 - section.AdjacentCellTwo.AbsolutePosition).normalized; } isControlOneNegative = (section.FlowFromOne == RiverFlow.Clockwise && isV1Internal) || (section.FlowFromOne == RiverFlow.Counterclockwise && !isV1Internal); isControlTwoNegative = (section.FlowFromOne == RiverFlow.Clockwise && !isV4Internal) || (section.FlowFromOne == RiverFlow.Counterclockwise && isV4Internal); v1Tangent = new Vector3(-centerToV1Direction.z, centerToV1Direction.y, centerToV1Direction.x); v4Tangent = new Vector3(-centerToV4Direction.z, centerToV4Direction.y, centerToV4Direction.x); controlOne = v1 + v1Tangent * RenderConfig.RiverCurveStrength * (isControlOneNegative ? -1f : 1f); controlTwo = v4 + v4Tangent * RenderConfig.RiverCurveStrength * (isControlTwoNegative ? -1f : 1f); centerSpline.AddCubicCurve(controlOne, controlTwo, v4); } var newRiverSpline = new RiverSpline() { CenterSpline = centerSpline, WesternCells = river.Select(riverSection => riverSection.AdjacentCellOne).ToList(), EasternCells = river.Select(riverSection => riverSection.AdjacentCellTwo).ToList(), Directions = river.Select(riverSection => riverSection.DirectionFromOne).ToList(), Flows = river.Select(riverSection => riverSection.FlowFromOne).ToList() }; RiverSplines.Add(newRiverSpline); } }