/** * Copyright (C) 2013 Gundog Studios LLC. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.gundogstudios.models.tristripper; class StripInfo { StripStartInfo m_startInfo; FaceInfoVec m_faces = new FaceInfoVec(); int m_stripId; int m_experimentId; boolean visited; int m_numDegenerates; public StripInfo(StripStartInfo startInfo, int stripId, int experimentId) { m_startInfo = startInfo; m_stripId = stripId; m_experimentId = experimentId; visited = false; m_numDegenerates = 0; } boolean isExperiment() { return m_experimentId >= 0; } boolean isInStrip(FaceInfo faceInfo) { if (faceInfo == null) return false; return (m_experimentId >= 0 ? faceInfo.m_testStripId == m_stripId : faceInfo.m_stripId == m_stripId); } // ///////////////////////////////////////////////////////////////////////////////////////// // IsMarked() // // If either the faceInfo has a real strip index because it is // already assign to a committed strip OR it is assigned in an // experiment and the experiment index is the one we are building // for, then it is marked and unavailable boolean isMarked(FaceInfo faceInfo) { return (faceInfo.m_stripId >= 0) || (isExperiment() && faceInfo.m_experimentId == m_experimentId); } // ///////////////////////////////////////////////////////////////////////////////////////// // MarkTriangle() // // Marks the face with the current strip ID // void markTriangle(FaceInfo faceInfo) { assert (!isMarked(faceInfo)); if (isExperiment()) { faceInfo.m_experimentId = m_experimentId; faceInfo.m_testStripId = m_stripId; } else { assert (faceInfo.m_stripId == -1); faceInfo.m_experimentId = -1; faceInfo.m_stripId = m_stripId; } } boolean unique(FaceInfoVec faceVec, FaceInfo face) { boolean bv0, bv1, bv2; // bools to indicate whether a vertex is in the faceVec or not bv0 = bv1 = bv2 = false; for (int i = 0; i < faceVec.size(); i++) { if (!bv0) { if ((faceVec.at(i).m_v0 == face.m_v0) || (faceVec.at(i).m_v1 == face.m_v0) || (faceVec.at(i).m_v2 == face.m_v0)) bv0 = true; } if (!bv1) { if ((faceVec.at(i).m_v0 == face.m_v1) || (faceVec.at(i).m_v1 == face.m_v1) || (faceVec.at(i).m_v2 == face.m_v1)) bv1 = true; } if (!bv2) { if ((faceVec.at(i).m_v0 == face.m_v2) || (faceVec.at(i).m_v1 == face.m_v2) || (faceVec.at(i).m_v2 == face.m_v2)) bv2 = true; } // the face is not unique, all it's vertices exist in the face vector if (bv0 && bv1 && bv2) return false; } // if we get out here, it's unique return true; } // ///////////////////////////////////////////////////////////////////////////////////////// // Build() // // Builds a strip forward as far as we can go, then builds backwards, and joins the two lists // void build(EdgeInfoVec edgeInfos, FaceInfoVec faceInfos) { // used in building the strips forward and backward IntVec scratchIndices = new IntVec(); // build forward... start with the initial face FaceInfoVec forwardFaces = new FaceInfoVec(); FaceInfoVec backwardFaces = new FaceInfoVec(); forwardFaces.add(m_startInfo.m_startFace); markTriangle(m_startInfo.m_startFace); int v0 = (m_startInfo.m_toV1 ? m_startInfo.m_startEdge.m_v0 : m_startInfo.m_startEdge.m_v1); int v1 = (m_startInfo.m_toV1 ? m_startInfo.m_startEdge.m_v1 : m_startInfo.m_startEdge.m_v0); // easiest way to get v2 is to use this function which requires the // other indices to already be in the list. scratchIndices.add(v0); scratchIndices.add(v1); int v2 = Stripifier.getNextIndex(scratchIndices, m_startInfo.m_startFace); scratchIndices.add(v2); // // build the forward list // int nv0 = v1; int nv1 = v2; FaceInfo nextFace = Stripifier.findOtherFace(edgeInfos, nv0, nv1, m_startInfo.m_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); FaceInfo nextNextFace = Stripifier.findOtherFace(edgeInfos, testnv0, testnv1, nextFace); if ((nextNextFace == null) || (isMarked(nextNextFace))) { // uh, oh, we're following a dead end, try swapping FaceInfo 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 FaceInfo tempFace = new FaceInfo(nv0, nv1, nv0); forwardFaces.add(tempFace); markTriangle(tempFace); scratchIndices.add(nv0); testnv0 = nv0; ++m_numDegenerates; } } // add this to the strip forwardFaces.add(nextFace); markTriangle(nextFace); // add the index // nv0 = nv1; // nv1 = NvStripifier::GetNextIndex(scratchIndices, nextFace); scratchIndices.add(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() FaceInfoVec tempAllFaces = new FaceInfoVec(); for (int i = 0; i < forwardFaces.size(); i++) tempAllFaces.add(forwardFaces.at(i)); // // reset the indices for building the strip backwards and do so // scratchIndices.clear(); scratchIndices.add(v2); scratchIndices.add(v1); scratchIndices.add(v0); nv0 = v1; nv1 = v0; nextFace = Stripifier.findOtherFace(edgeInfos, nv0, nv1, m_startInfo.m_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); FaceInfo nextNextFace = Stripifier.findOtherFace(edgeInfos, testnv0, testnv1, nextFace); if ((nextNextFace == null) || (isMarked(nextNextFace))) { // uh, oh, we're following a dead end, try swapping FaceInfo 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 FaceInfo tempFace = new FaceInfo(nv0, nv1, nv0); backwardFaces.add(tempFace); markTriangle(tempFace); scratchIndices.add(nv0); testnv0 = nv0; ++m_numDegenerates; } } // 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 = NvStripifier::GetNextIndex(scratchIndices, nextFace); scratchIndices.add(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); } // ///////////////////////////////////////////////////////////////////////////////////////// // Combine() // // Combines the two input face vectors and puts the result into m_faces // void combine(FaceInfoVec forward, FaceInfoVec backward) { // add backward faces int numFaces = backward.size(); for (int i = numFaces - 1; i >= 0; i--) m_faces.add(backward.at(i)); // add forward faces numFaces = forward.size(); for (int i = 0; i < numFaces; i++) m_faces.add(forward.at(i)); } // ///////////////////////////////////////////////////////////////////////////////////////// // SharesEdge() // // Returns true if the input face and the current strip share an edge // boolean sharesEdge(FaceInfo faceInfo, EdgeInfoVec edgeInfos) { // check v0.v1 edge EdgeInfo currEdge = Stripifier.findEdgeInfo(edgeInfos, faceInfo.m_v0, faceInfo.m_v1); if (isInStrip(currEdge.m_face0) || isInStrip(currEdge.m_face1)) return true; // check v1.v2 edge currEdge = Stripifier.findEdgeInfo(edgeInfos, faceInfo.m_v1, faceInfo.m_v2); if (isInStrip(currEdge.m_face0) || isInStrip(currEdge.m_face1)) return true; // check v2.v0 edge currEdge = Stripifier.findEdgeInfo(edgeInfos, faceInfo.m_v2, faceInfo.m_v0); if (isInStrip(currEdge.m_face0) || isInStrip(currEdge.m_face1)) return true; return false; } }