blob: a9b1098a528eee955a99dfe637cfa4c8d7a589b4 [file] [log] [blame]
/*
* 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;
}
}