private static void CloneVertices(List <Segment> segments, int segIndex, GeneratingModel model, List <int> output, ref int wrapPoint) { var input = output.ToArray(); output.Clear(); var seg = segments[segIndex]; bool wrapProcessed = false; for (int i = 0; i < input.Length; ++i) { var rdv = model.rdv[input[i]]; var deg = seg.Rotation0Fraction + seg.RotationStepFraction * i; if (deg >= 1) { if (i != input.Length - 1) { continue; //should never happen } deg = 0; } rdv.Normal = CalculateNormal(segments, segIndex, deg, true); output.Add(model.AddRDV(rdv)); if (rdv.UV.Y == 0 && wrapPoint != -1) { if (wrapProcessed) { throw new Exception(); } var rdv2 = new ModelVertex { Position = model.rdv[wrapPoint].Position, Normal = rdv.Normal, UV = model.rdv[wrapPoint].UV, }; wrapPoint = model.AddRDV(rdv2); wrapProcessed = true; } } if (!wrapProcessed && wrapPoint != -1) { throw new Exception(); } }
public static SingleMaterialModel Generate(List <Segment> segments) { if (segments.Count < 2) { throw new InvalidOperationException(); } var totalUDistance = segments.Sum(x => x.UStep); var currentU = 0f; GeneratingModel model = new GeneratingModel(); List <int> lastSegment = new List <int>(); //rdv index List <int> thisSegment = new List <int>(); int lastWrapPoint, thisWrapPoint; int GetLast(int index) { if (index == lastSegment.Count) { return(lastWrapPoint); } return(lastSegment[index]); } int GetThis(int index) { if (index == thisSegment.Count) { return(thisWrapPoint); } return(thisSegment[index]); } CreateVertices(segments, 0, currentU / totalUDistance, model, lastSegment, out lastWrapPoint); for (int i = 1; i < segments.Count; ++i) { //Creating new vertices currentU += segments[i].UStep; CreateVertices(segments, i, currentU / totalUDistance, model, thisSegment, out thisWrapPoint); //Clone old vertices if (!segments[i - 1].ContinuousNormal) { CloneVertices(segments, i - 1, model, lastSegment, ref lastWrapPoint); } //Check index mapping bool lastF = segments[i - 1].Rotation0Fraction != 0; bool thisF = segments[i].Rotation0Fraction != 0; int lastN = lastSegment.Count - (lastF ? 1 : 0); int thisN = thisSegment.Count - (thisF ? 1 : 0); if (lastN != 1 && thisN != 1 && lastN != thisN) { throw new ArgumentException("Vertices number mismatch"); } if (lastN == 1 && thisN == 1) { throw new ArgumentException("Invalid segment"); } if (segments[i].Rotation0Fraction > segments[i].RotationStepFraction) { throw new ArgumentException("Invalid rotation"); } //Create triangles if (lastN == 1) { //TODO make the order same for F and non-F if (thisF) { model.AddTriangle(lastSegment[0], GetThis(0), GetThis(thisSegment.Count - 1)); for (int j = 0; j < thisSegment.Count - 2; ++j) { model.AddTriangle(lastSegment[0], GetThis(j + 1), GetThis(j)); } model.AddTriangle(lastSegment[0], GetThis(thisSegment.Count), GetThis(thisSegment.Count - 2)); } else { for (int j = 0; j < thisSegment.Count; ++j) { model.AddTriangle(lastSegment[0], GetThis(j + 1), GetThis(j)); } } } else if (thisN == 1) { if (lastF) { model.AddTriangle(thisSegment[0], GetLast(lastSegment.Count - 1), GetLast(0)); for (int j = 0; j < lastSegment.Count - 2; ++j) { model.AddTriangle(thisSegment[0], GetLast(j), GetLast(j + 1)); } model.AddTriangle(thisSegment[0], GetLast(lastSegment.Count - 2), GetLast(lastSegment.Count)); } else { for (int j = 0; j < lastSegment.Count; ++j) { model.AddTriangle(thisSegment[0], GetLast(j), GetLast(j + 1)); } } } else { bool old0new1 = lastF && !thisF; int normalN = thisN; if (lastF || thisF) { normalN -= 1; } for (int j = 0; j < normalN; ++j) { var old0 = GetLast(j); var old1 = GetLast(j + 1); var new0 = GetThis(j); var new1 = GetThis(j + 1); if (old0new1) { model.AddTriangle(old0, old1, new1); model.AddTriangle(old0, new1, new0); } else { model.AddTriangle(old0, old1, new0); model.AddTriangle(new0, old1, new1); } } if (lastF && thisF) { //ignore old0new1 flag var old0 = lastSegment[normalN]; var old1 = lastSegment[normalN + 1]; var old1r = lastWrapPoint; var old2 = lastSegment[0]; var new0 = thisSegment[normalN]; var new1 = thisSegment[normalN + 1]; var new1r = thisWrapPoint; var new2 = thisSegment[0]; //ignore old0new1 flag model.AddTriangle(old0, old1r, new1r); model.AddTriangle(old0, new1r, new0); model.AddTriangle(old1, old2, new2); model.AddTriangle(old1, new2, new1); } else if (lastF) { var old0 = lastSegment[normalN]; var old1 = lastSegment[normalN + 1]; var old1r = lastWrapPoint; var old2 = lastSegment[0]; var new0 = thisSegment[normalN]; var new2 = thisSegment[0]; var new2r = thisWrapPoint; model.AddTriangle(old0, old1r, new2r); model.AddTriangle(old1, old2, new2); model.AddTriangle(new0, old0, new2r); } else if (thisF) { var old0 = lastSegment[normalN]; var old2 = lastSegment[0]; var old2r = lastWrapPoint; var new0 = thisSegment[normalN]; var new1 = thisSegment[normalN + 1]; var new1r = thisWrapPoint; var new2 = thisSegment[0]; model.AddTriangle(old0, old2r, new0); model.AddTriangle(old2, new2, new1); model.AddTriangle(old2r, new1r, new0); } } //Move vertex list { var e = lastSegment; lastSegment = thisSegment; thisSegment = e; lastWrapPoint = thisWrapPoint; } } return(model.ToModel()); }
private static void CreateVertices(List <Segment> segments, int segIndex, float u, GeneratingModel model, List <int> output, out int wrapPoint) { var seg = segments[segIndex]; output.Clear(); for (int i = 0; seg.Rotation0Fraction + seg.RotationStepFraction * i < 1; ++i) { var frac = seg.Rotation0Fraction + seg.RotationStepFraction * i; var pos = CalculatePosition(seg, frac); var rdx = model.AddRDV(new ModelVertex { Position = pos, Normal = CalculateNormal(segments, segIndex, frac, false), UV = new Vector2(u, frac), }); output.Add(rdx); } if (seg.Rotation0Fraction != 0) { if (output.Count < 2) { throw new ArgumentException("Invalid segment"); } var pos = (model.rdv[output[0]].Position + model.rdv[output[output.Count - 1]].Position) / 2; var rdx = model.AddRDV(new ModelVertex { Position = pos, Normal = CalculateNormal(segments, segIndex, 0, false), UV = new Vector2(u, 0), }); output.Add(rdx); } if (output.Count == 1) { wrapPoint = -1; //Move v to 0.5 var rtv = model.rdv[output[0]]; rtv.UV.Y = 0.5f; model.rdv[output[0]] = rtv; } else { var zero = output.Where(ii => model.rdv[ii].UV.Y == 0).First(); var rdx = model.AddRDV(new ModelVertex { Position = model.rdv[zero].Position, Normal = model.rdv[zero].Normal, UV = new Vector2(u, 1), }); wrapPoint = rdx; } }