예제 #1
0
        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();
            }
        }
예제 #2
0
        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());
        }
예제 #3
0
        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;
            }
        }