Example #1
0
 public bool IsMarked(FaceInfo faceInfo)
 {
     return((faceInfo.StripId >= 0) || (IsExperiment() && faceInfo.ExperimentId == ExperimentId));
 }
Example #2
0
        /// <summary>
        /// Builds a strip forward as far as we can go, then builds backwards, and joins the two lists.
        /// </summary>
        public void Build(List <EdgeInfo> edgeInfos, List <FaceInfo> faceInfos)
        {
            // used in building the strips forward and backward
            var scratchIndices = new List <ushort>();

            // build forward... start with the initial face
            var forwardFaces  = new List <FaceInfo>();
            var backwardFaces = new List <FaceInfo>();

            forwardFaces.Add(StartInfo.StartFace);

            MarkTriangle(StartInfo.StartFace);

            int v0 = (StartInfo.ToV1 ? StartInfo.StartEdge.V0 : StartInfo.StartEdge.V1);
            int v1 = (StartInfo.ToV1 ? StartInfo.StartEdge.V1 : StartInfo.StartEdge.V0);

            // easiest way to get v2 is to use this function which requires the
            // other indices to already be in the list.
            scratchIndices.Add(( ushort )v0);
            scratchIndices.Add(( ushort )v1);
            int v2 = Stripifier.GetNextIndex(scratchIndices, StartInfo.StartFace);

            scratchIndices.Add(( ushort )v2);

            //
            // build the forward list
            //
            int nv0 = v1;
            int nv1 = v2;

            var nextFace = Stripifier.FindOtherFace(edgeInfos, nv0, nv1, StartInfo.StartFace);

            while (nextFace != null && !IsMarked(nextFace))
            {
                //check to see if this next face is going to cause us to die soon
                int testnv0 = nv1;
                int testnv1 = Stripifier.GetNextIndex(scratchIndices, nextFace);

                var nextNextFace = Stripifier.FindOtherFace(edgeInfos, testnv0, testnv1, nextFace);

                if ((nextNextFace == null) || (IsMarked(nextNextFace)))
                {
                    //uh, oh, we're following a dead end, try swapping
                    var testNextFace = Stripifier.FindOtherFace(edgeInfos, nv0, testnv1, nextFace);

                    if (((testNextFace != null) && !IsMarked(testNextFace)))
                    {
                        //we only swap if it buys us something

                        //add a "fake" degenerate face
                        var tempFace = new FaceInfo(nv0, nv1, nv0, true);

                        forwardFaces.Add(tempFace);
                        MarkTriangle(tempFace);

                        scratchIndices.Add(( ushort )nv0);
                        testnv0 = nv0;

                        ++DegenerateCount;
                    }
                }

                // add this to the strip
                forwardFaces.Add(nextFace);

                MarkTriangle(nextFace);

                // add the index
                //nv0 = nv1;
                //nv1 = Stripifier.GetNextIndex(scratchIndices, nextFace);
                scratchIndices.Add(( ushort )testnv1);

                // and get the next face
                nv0 = testnv0;
                nv1 = testnv1;

                nextFace = Stripifier.FindOtherFace(edgeInfos, nv0, nv1, nextFace);
            }

            // tempAllFaces is going to be forwardFaces + backwardFaces
            // it's used for Unique()
            var tempAllFaces = new List <FaceInfo>();

            for (var i = 0; i < forwardFaces.Count; i++)
            {
                tempAllFaces.Add(forwardFaces[i]);
            }

            //
            // reset the indices for building the strip backwards and do so
            //
            scratchIndices.Clear();
            scratchIndices.Add(( ushort )v2);
            scratchIndices.Add(( ushort )v1);
            scratchIndices.Add(( ushort )v0);
            nv0      = v1;
            nv1      = v0;
            nextFace = Stripifier.FindOtherFace(edgeInfos, nv0, nv1, StartInfo.StartFace);
            while (nextFace != null && !IsMarked(nextFace))
            {
                //this tests to see if a face is "unique", meaning that its vertices aren't already in the list
                // so, strips which "wrap-around" are not allowed
                if (!Unique(tempAllFaces, nextFace))
                {
                    break;
                }

                //check to see if this next face is going to cause us to die soon
                int testnv0 = nv1;
                int testnv1 = Stripifier.GetNextIndex(scratchIndices, nextFace);

                var nextNextFace = Stripifier.FindOtherFace(edgeInfos, testnv0, testnv1, nextFace);

                if ((nextNextFace == null) || (IsMarked(nextNextFace)))
                {
                    //uh, oh, we're following a dead end, try swapping
                    var testNextFace = Stripifier.FindOtherFace(edgeInfos, nv0, testnv1, nextFace);
                    if (((testNextFace != null) && !IsMarked(testNextFace)))
                    {
                        //we only swap if it buys us something

                        //add a "fake" degenerate face
                        var tempFace = new FaceInfo(nv0, nv1, nv0, true);

                        backwardFaces.Add(tempFace);
                        MarkTriangle(tempFace);
                        scratchIndices.Add(( ushort )nv0);
                        testnv0 = nv0;

                        ++DegenerateCount;
                    }
                }

                // add this to the strip
                backwardFaces.Add(nextFace);

                //this is just so Unique() will work
                tempAllFaces.Add(nextFace);

                MarkTriangle(nextFace);

                // add the index
                //nv0 = nv1;
                //nv1 = Stripifier.GetNextIndex(scratchIndices, nextFace);
                scratchIndices.Add(( ushort )testnv1);

                // and get the next face
                nv0      = testnv0;
                nv1      = testnv1;
                nextFace = Stripifier.FindOtherFace(edgeInfos, nv0, nv1, nextFace);
            }

            // Combine the forward and backwards stripification lists and put into our own face vector
            Combine(forwardFaces, backwardFaces);
        }
Example #3
0
        /// <summary>
        /// Generates strips from the given input indices.
        /// </summary>
        /// <param name="indices">Input index list, the indices you would use to render.</param>
        /// <param name="primitiveGroups">Array of optimized/stripified PrimitiveGroups</param>
        /// <param name="validateEnabled">Whether to validate the output or not.</param>
        /// <returns>A boolean indicating whether the operation completed successfully.</returns>
        public bool GenerateStrips(ushort[] indices, out PrimitiveGroup[] primitiveGroups, bool validateEnabled = false)
        {
            var numGroups = 0;

            //put data in format that the stripifier likes
            var    tempIndices = new List <ushort>(indices.Length);
            ushort maxIndex    = 0;
            ushort minIndex    = 0xFFFF;

            for (var i = 0; i < indices.Length; i++)
            {
                tempIndices.Add(indices[i]);
                if (indices[i] > maxIndex)
                {
                    maxIndex = indices[i];
                }
                if (indices[i] < minIndex)
                {
                    minIndex = indices[i];
                }
            }

            var tempStrips = new List <StripInfo>();
            var tempFaces  = new List <FaceInfo>();

            var stripifier = new Stripifier();

            //do actual stripification
            stripifier.Stripify(tempIndices, CacheSize, MinStripSize, maxIndex, tempStrips, tempFaces);

            //stitch strips together
            var  stripIndices      = new List <int>();
            uint numSeparateStrips = 0;

            if (ListsOnly)
            {
                //if we're outputting only lists, we're done
                numGroups       = 1;
                primitiveGroups = new PrimitiveGroup[numGroups];
                var primGroupArray = primitiveGroups;

                //count the total number of indices
                uint numIndices = 0;
                for (var i = 0; i < tempStrips.Count; i++)
                {
                    numIndices += ( uint )(tempStrips[i].Faces.Count * 3);
                }

                //add in the list
                numIndices       += ( uint )(tempFaces.Count * 3);
                primGroupArray[0] = new PrimitiveGroup(PrimitiveType.TriangleList, new ushort[numIndices]);

                //do strips
                uint indexCtr = 0;
                for (var i = 0; i < tempStrips.Count; i++)
                {
                    for (var j = 0; j < tempStrips[i].Faces.Count; j++)
                    {
                        //degenerates are of no use with lists
                        if (!Stripifier.IsDegenerate(tempStrips[i].Faces[j]))
                        {
                            primGroupArray[0].Indices[indexCtr++] = ( ushort )tempStrips[i].Faces[j].V0;
                            primGroupArray[0].Indices[indexCtr++] = ( ushort )tempStrips[i].Faces[j].V1;
                            primGroupArray[0].Indices[indexCtr++] = ( ushort )tempStrips[i].Faces[j].V2;
                        }
                        else
                        {
                            //we've removed a tri, reduce the number of indices
                            var resizedIndices = primGroupArray[0].Indices;
                            Array.Resize(ref resizedIndices, primGroupArray[0].Indices.Length - 3);
                            primGroupArray[0].Indices = resizedIndices;
                        }
                    }
                }

                //do lists
                for (var i = 0; i < tempFaces.Count; i++)
                {
                    primGroupArray[0].Indices[indexCtr++] = ( ushort )tempFaces[i].V0;
                    primGroupArray[0].Indices[indexCtr++] = ( ushort )tempFaces[i].V1;
                    primGroupArray[0].Indices[indexCtr++] = ( ushort )tempFaces[i].V2;
                }
            }
            else
            {
                stripifier.CreateStrips(tempStrips, stripIndices, StitchStrips, ref numSeparateStrips, UseRestart, ( uint )RestartValue);

                //if we're stitching strips together, we better get back only one strip from CreateStrips()
                Debug.Assert(StitchStrips && numSeparateStrips == 1 || !StitchStrips);

                //convert to output format
                numGroups = ( ushort )numSeparateStrips; //for the strips
                if (tempFaces.Count != 0)
                {
                    numGroups++; //we've got a list as well, increment
                }
                primitiveGroups = new PrimitiveGroup[numGroups];

                var primGroupArray = primitiveGroups;

                //first, the strips
                var startingLoc = 0;
                for (var stripCtr = 0; stripCtr < numSeparateStrips; stripCtr++)
                {
                    var stripLength = 0;

                    if (!StitchStrips)
                    {
                        //if we've got multiple strips, we need to figure out the correct length
                        int i;
                        for (i = startingLoc; i < stripIndices.Count; i++)
                        {
                            if (stripIndices[i] == -1)
                            {
                                break;
                            }
                        }

                        stripLength = i - startingLoc;
                    }
                    else
                    {
                        stripLength = stripIndices.Count;
                    }

                    primGroupArray[stripCtr] = new PrimitiveGroup(PrimitiveType.TriangleStrip, new ushort[stripLength]);

                    var indexCtr = 0;
                    for (int i = startingLoc; i < stripLength + startingLoc; i++)
                    {
                        primGroupArray[stripCtr].Indices[indexCtr++] = ( ushort )stripIndices[i];
                    }

                    //we add 1 to account for the -1 separating strips
                    //this doesn't break the stitched case since we'll exit the loop
                    startingLoc += stripLength + 1;
                }

                //next, the list
                if (tempFaces.Count != 0)
                {
                    int faceGroupLoc = numGroups - 1; //the face group is the last one
                    primGroupArray[faceGroupLoc] = new PrimitiveGroup(PrimitiveType.TriangleList, new ushort[tempFaces.Count * 3]);
                    var indexCtr = 0;
                    for (var i = 0; i < tempFaces.Count; i++)
                    {
                        primGroupArray[faceGroupLoc].Indices[indexCtr++] = ( ushort )tempFaces[i].V0;
                        primGroupArray[faceGroupLoc].Indices[indexCtr++] = ( ushort )tempFaces[i].V1;
                        primGroupArray[faceGroupLoc].Indices[indexCtr++] = ( ushort )tempFaces[i].V2;
                    }
                }
            }

            //validate generated data against input
            if (validateEnabled)
            {
                var numbins = 100;

                var inBins = new List <FaceInfo> [numbins];
                for (var i = 0; i < inBins.Length; ++i)
                {
                    inBins[i] = new List <FaceInfo>();
                }

                //hash input indices on first index
                for (var i = 0; i < indices.Length; i += 3)
                {
                    var faceInfo = new FaceInfo(indices[i], indices[i + 1], indices[i + 2]);
                    inBins[indices[i] % numbins].Add(faceInfo);
                }

                for (var i = 0; i < numGroups; ++i)
                {
                    switch (primitiveGroups[i].Type)
                    {
                    case PrimitiveType.TriangleList:
                    {
                        for (var j = 0; j < primitiveGroups[i].Indices.Length; j += 3)
                        {
                            ushort v0 = primitiveGroups[i].Indices[j];
                            ushort v1 = primitiveGroups[i].Indices[j + 1];
                            ushort v2 = primitiveGroups[i].Indices[j + 2];

                            //ignore degenerates
                            if (Stripifier.IsDegenerate(v0, v1, v2))
                            {
                                continue;
                            }

                            if (!TestTriangle(v0, v1, v2, inBins, numbins))
                            {
                                Cleanup(tempStrips, tempFaces);
                                return(false);
                            }
                        }

                        break;
                    }

                    case PrimitiveType.TriangleStrip:
                    {
                        var flip = false;
                        for (var j = 2; j < primitiveGroups[i].Indices.Length; ++j)
                        {
                            ushort v0 = primitiveGroups[i].Indices[j - 2];
                            ushort v1 = primitiveGroups[i].Indices[j - 1];
                            ushort v2 = primitiveGroups[i].Indices[j];

                            if (flip)
                            {
                                //swap v1 and v2
                                ushort swap = v1;
                                v1 = v2;
                                v2 = swap;
                            }

                            //ignore degenerates
                            if (Stripifier.IsDegenerate(v0, v1, v2))
                            {
                                flip = !flip;
                                continue;
                            }

                            if (!TestTriangle(v0, v1, v2, inBins, numbins))
                            {
                                Cleanup(tempStrips, tempFaces);
                                return(false);
                            }

                            flip = !flip;
                        }

                        break;
                    }

                    case PrimitiveType.TriangleFan:
                    default:
                        break;
                    }
                }
            }

            //clean up everything
            Cleanup(tempStrips, tempFaces);

            return(true);
        }