/* | |
* Copyright (c) 2009-2010 jMonkeyEngine | |
* All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions are | |
* met: | |
* | |
* * Redistributions of source code must retain the above copyright | |
* notice, this list of conditions and the following disclaimer. | |
* | |
* * Redistributions in binary form must reproduce the above copyright | |
* notice, this list of conditions and the following disclaimer in the | |
* documentation and/or other materials provided with the distribution. | |
* | |
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors | |
* may be used to endorse or promote products derived from this software | |
* without specific prior written permission. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
*/ | |
package jme3tools.converters.model.strip; | |
/** | |
* | |
*/ | |
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){ | |
if (isExperiment()){ | |
faceInfo.m_experimentId = m_experimentId; | |
faceInfo.m_testStripId = m_stripId; | |
} | |
else{ | |
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; | |
} | |
} |