1/*
2 * Copyright (c) 2009-2010 jMonkeyEngine
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 *   notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 *   notice, this list of conditions and the following disclaimer in the
14 *   documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17 *   may be used to endorse or promote products derived from this software
18 *   without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33package jme3tools.converters.model.strip;
34
35/**
36 *
37 */
38class StripInfo {
39
40    StripStartInfo m_startInfo;
41    FaceInfoVec    m_faces = new FaceInfoVec();
42    int              m_stripId;
43    int              m_experimentId;
44
45    boolean visited;
46
47    int m_numDegenerates;
48
49
50    public StripInfo(StripStartInfo startInfo,int stripId, int experimentId) {
51
52        m_startInfo = startInfo;
53        m_stripId      = stripId;
54        m_experimentId = experimentId;
55        visited = false;
56        m_numDegenerates = 0;
57    }
58
59    boolean isExperiment() {
60        return m_experimentId >= 0;
61    }
62
63    boolean isInStrip(FaceInfo faceInfo) {
64        if(faceInfo == null)
65            return false;
66
67        return (m_experimentId >= 0 ? faceInfo.m_testStripId == m_stripId : faceInfo.m_stripId == m_stripId);
68    }
69
70
71///////////////////////////////////////////////////////////////////////////////////////////
72// IsMarked()
73//
74// If either the faceInfo has a real strip index because it is
75// already assign to a committed strip OR it is assigned in an
76// experiment and the experiment index is the one we are building
77// for, then it is marked and unavailable
78    boolean isMarked(FaceInfo faceInfo){
79        return (faceInfo.m_stripId >= 0) || (isExperiment() && faceInfo.m_experimentId == m_experimentId);
80    }
81
82
83///////////////////////////////////////////////////////////////////////////////////////////
84// MarkTriangle()
85//
86// Marks the face with the current strip ID
87//
88    void markTriangle(FaceInfo faceInfo){
89        if (isExperiment()){
90            faceInfo.m_experimentId = m_experimentId;
91            faceInfo.m_testStripId  = m_stripId;
92        }
93        else{
94            faceInfo.m_experimentId = -1;
95            faceInfo.m_stripId      = m_stripId;
96        }
97    }
98
99
100    boolean unique(FaceInfoVec faceVec, FaceInfo face)
101    {
102        boolean bv0, bv1, bv2; //bools to indicate whether a vertex is in the faceVec or not
103        bv0 = bv1 = bv2 = false;
104
105        for(int i = 0; i < faceVec.size(); i++)
106           {
107            if(!bv0)
108               {
109                if( (faceVec.at(i).m_v0 == face.m_v0) ||
110                        (faceVec.at(i).m_v1 == face.m_v0) ||
111                        (faceVec.at(i).m_v2 == face.m_v0) )
112                    bv0 = true;
113            }
114
115            if(!bv1)
116               {
117                if( (faceVec.at(i).m_v0 == face.m_v1) ||
118                        (faceVec.at(i).m_v1 == face.m_v1) ||
119                        (faceVec.at(i).m_v2 == face.m_v1) )
120                    bv1 = true;
121            }
122
123            if(!bv2)
124               {
125                if( (faceVec.at(i).m_v0 == face.m_v2) ||
126                        (faceVec.at(i).m_v1 == face.m_v2) ||
127                        (faceVec.at(i).m_v2 == face.m_v2) )
128                    bv2 = true;
129            }
130
131            //the face is not unique, all it's vertices exist in the face vector
132            if(bv0 && bv1 && bv2)
133                return false;
134        }
135
136        //if we get out here, it's unique
137        return true;
138    }
139
140
141///////////////////////////////////////////////////////////////////////////////////////////
142// Build()
143//
144// Builds a strip forward as far as we can go, then builds backwards, and joins the two lists
145//
146    void build(EdgeInfoVec edgeInfos, FaceInfoVec faceInfos)
147    {
148        // used in building the strips forward and backward
149        IntVec scratchIndices = new IntVec();
150
151        // build forward... start with the initial face
152        FaceInfoVec forwardFaces = new FaceInfoVec();
153        FaceInfoVec backwardFaces = new FaceInfoVec();
154        forwardFaces.add(m_startInfo.m_startFace);
155
156        markTriangle(m_startInfo.m_startFace);
157
158        int v0 = (m_startInfo.m_toV1 ? m_startInfo.m_startEdge.m_v0 : m_startInfo.m_startEdge.m_v1);
159        int v1 = (m_startInfo.m_toV1 ? m_startInfo.m_startEdge.m_v1 : m_startInfo.m_startEdge.m_v0);
160
161        // easiest way to get v2 is to use this function which requires the
162        // other indices to already be in the list.
163        scratchIndices.add(v0);
164        scratchIndices.add(v1);
165        int v2 = Stripifier.getNextIndex(scratchIndices, m_startInfo.m_startFace);
166        scratchIndices.add(v2);
167
168        //
169        // build the forward list
170        //
171        int nv0 = v1;
172        int nv1 = v2;
173
174        FaceInfo nextFace = Stripifier.findOtherFace(edgeInfos, nv0, nv1, m_startInfo.m_startFace);
175        while (nextFace != null && !isMarked(nextFace))
176           {
177            //check to see if this next face is going to cause us to die soon
178            int testnv0 = nv1;
179            int testnv1 = Stripifier.getNextIndex(scratchIndices, nextFace);
180
181            FaceInfo nextNextFace = Stripifier.findOtherFace(edgeInfos, testnv0, testnv1, nextFace);
182
183            if( (nextNextFace == null) || (isMarked(nextNextFace)) )
184               {
185                //uh, oh, we're following a dead end, try swapping
186                FaceInfo testNextFace = Stripifier.findOtherFace(edgeInfos, nv0, testnv1, nextFace);
187
188                if( ((testNextFace != null) && !isMarked(testNextFace)) )
189                   {
190                    //we only swap if it buys us something
191
192                    //add a "fake" degenerate face
193                    FaceInfo tempFace = new FaceInfo(nv0, nv1, nv0);
194
195                    forwardFaces.add(tempFace);
196                    markTriangle(tempFace);
197
198                    scratchIndices.add(nv0);
199                    testnv0 = nv0;
200
201                    ++m_numDegenerates;
202                }
203
204            }
205
206            // add this to the strip
207            forwardFaces.add(nextFace);
208
209            markTriangle(nextFace);
210
211            // add the index
212            //nv0 = nv1;
213            //nv1 = NvStripifier::GetNextIndex(scratchIndices, nextFace);
214            scratchIndices.add(testnv1);
215
216            // and get the next face
217            nv0 = testnv0;
218            nv1 = testnv1;
219
220            nextFace = Stripifier.findOtherFace(edgeInfos, nv0, nv1, nextFace);
221
222        }
223
224        // tempAllFaces is going to be forwardFaces + backwardFaces
225        // it's used for Unique()
226        FaceInfoVec tempAllFaces = new FaceInfoVec();
227        for(int i = 0; i < forwardFaces.size(); i++)
228            tempAllFaces.add(forwardFaces.at(i));
229
230        //
231        // reset the indices for building the strip backwards and do so
232        //
233        scratchIndices.clear();
234        scratchIndices.add(v2);
235        scratchIndices.add(v1);
236        scratchIndices.add(v0);
237        nv0 = v1;
238        nv1 = v0;
239        nextFace = Stripifier.findOtherFace(edgeInfos, nv0, nv1, m_startInfo.m_startFace);
240        while (nextFace != null && !isMarked(nextFace))
241           {
242            //this tests to see if a face is "unique", meaning that its vertices aren't already in the list
243            // so, strips which "wrap-around" are not allowed
244            if(!unique(tempAllFaces, nextFace))
245                break;
246
247            //check to see if this next face is going to cause us to die soon
248            int testnv0 = nv1;
249            int testnv1 = Stripifier.getNextIndex(scratchIndices, nextFace);
250
251            FaceInfo nextNextFace = Stripifier.findOtherFace(edgeInfos, testnv0, testnv1, nextFace);
252
253            if( (nextNextFace == null) || (isMarked(nextNextFace)) )
254               {
255                //uh, oh, we're following a dead end, try swapping
256                FaceInfo testNextFace = Stripifier.findOtherFace(edgeInfos, nv0, testnv1, nextFace);
257                if( ((testNextFace != null) && !isMarked(testNextFace)) )
258                   {
259                    //we only swap if it buys us something
260
261                    //add a "fake" degenerate face
262                    FaceInfo tempFace = new FaceInfo(nv0, nv1, nv0);
263
264                    backwardFaces.add(tempFace);
265                    markTriangle(tempFace);
266                    scratchIndices.add(nv0);
267                    testnv0 = nv0;
268
269                    ++m_numDegenerates;
270                }
271
272            }
273
274            // add this to the strip
275            backwardFaces.add(nextFace);
276
277            //this is just so Unique() will work
278            tempAllFaces.add(nextFace);
279
280            markTriangle(nextFace);
281
282            // add the index
283            //nv0 = nv1;
284            //nv1 = NvStripifier::GetNextIndex(scratchIndices, nextFace);
285            scratchIndices.add(testnv1);
286
287            // and get the next face
288            nv0 = testnv0;
289            nv1 = testnv1;
290            nextFace = Stripifier.findOtherFace(edgeInfos, nv0, nv1, nextFace);
291        }
292
293        // Combine the forward and backwards stripification lists and put into our own face vector
294        combine(forwardFaces, backwardFaces);
295    }
296
297
298///////////////////////////////////////////////////////////////////////////////////////////
299// Combine()
300//
301// Combines the two input face vectors and puts the result into m_faces
302//
303    void combine(FaceInfoVec forward, FaceInfoVec backward){
304
305        // add backward faces
306        int numFaces = backward.size();
307        for (int i = numFaces - 1; i >= 0; i--)
308            m_faces.add(backward.at(i));
309
310        // add forward faces
311        numFaces = forward.size();
312        for (int i = 0; i < numFaces; i++)
313            m_faces.add(forward.at(i));
314    }
315
316
317///////////////////////////////////////////////////////////////////////////////////////////
318// SharesEdge()
319//
320// Returns true if the input face and the current strip share an edge
321//
322    boolean sharesEdge(FaceInfo faceInfo, EdgeInfoVec edgeInfos)
323    {
324        //check v0.v1 edge
325        EdgeInfo currEdge = Stripifier.findEdgeInfo(edgeInfos, faceInfo.m_v0, faceInfo.m_v1);
326
327        if(isInStrip(currEdge.m_face0) || isInStrip(currEdge.m_face1))
328            return true;
329
330        //check v1.v2 edge
331        currEdge = Stripifier.findEdgeInfo(edgeInfos, faceInfo.m_v1, faceInfo.m_v2);
332
333        if(isInStrip(currEdge.m_face0) || isInStrip(currEdge.m_face1))
334            return true;
335
336        //check v2.v0 edge
337        currEdge = Stripifier.findEdgeInfo(edgeInfos, faceInfo.m_v2, faceInfo.m_v0);
338
339        if(isInStrip(currEdge.m_face0) || isInStrip(currEdge.m_face1))
340            return true;
341
342        return false;
343
344    }
345
346
347
348
349
350
351
352
353
354
355}
356