diff options
614 files changed, 81498 insertions, 35 deletions
diff --git a/release/scripts/freestyle/data/env_map/brown00.png b/release/scripts/freestyle/data/env_map/brown00.png Binary files differnew file mode 100755 index 00000000000..855f06f4fb9 --- /dev/null +++ b/release/scripts/freestyle/data/env_map/brown00.png diff --git a/release/scripts/freestyle/data/env_map/gray00.png b/release/scripts/freestyle/data/env_map/gray00.png Binary files differnew file mode 100755 index 00000000000..7c9b1a8149e --- /dev/null +++ b/release/scripts/freestyle/data/env_map/gray00.png diff --git a/release/scripts/freestyle/data/env_map/gray01.png b/release/scripts/freestyle/data/env_map/gray01.png Binary files differnew file mode 100755 index 00000000000..06542908e6b --- /dev/null +++ b/release/scripts/freestyle/data/env_map/gray01.png diff --git a/release/scripts/freestyle/data/env_map/gray02.png b/release/scripts/freestyle/data/env_map/gray02.png Binary files differnew file mode 100755 index 00000000000..0208f4920d9 --- /dev/null +++ b/release/scripts/freestyle/data/env_map/gray02.png diff --git a/release/scripts/freestyle/data/env_map/gray03.png b/release/scripts/freestyle/data/env_map/gray03.png Binary files differnew file mode 100755 index 00000000000..aab9b957c21 --- /dev/null +++ b/release/scripts/freestyle/data/env_map/gray03.png diff --git a/release/scripts/freestyle/style_modules/ChainingIterators.py b/release/scripts/freestyle/style_modules/ChainingIterators.py new file mode 100755 index 00000000000..f2d953ddc14 --- /dev/null +++ b/release/scripts/freestyle/style_modules/ChainingIterators.py @@ -0,0 +1,731 @@ +# +# Filename : ChainingIterators.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Chaining Iterators to be used with chaining operators +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * + +## the natural chaining iterator +## It follows the edges of same nature following the topology of +## objects with preseance on silhouettes, then borders, +## then suggestive contours, then everything else. It doesn't chain the same ViewEdge twice +## You can specify whether to stay in the selection or not. +class pyChainSilhouetteIterator(ChainingIterator): + def __init__(self, stayInSelection=1): + ChainingIterator.__init__(self, stayInSelection, 1,None,1) + def getExactTypeName(self): + return "pyChainSilhouetteIterator" + def init(self): + pass + def traverse(self, iter): + winner = None + it = AdjacencyIterator(iter) + tvertex = self.getVertex() + if type(tvertex) is TVertex: + mateVE = tvertex.mate(self.getCurrentEdge()) + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getId() == mateVE.getId() ): + winner = ve + break + it.increment() + else: + ## case of NonTVertex + natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE] + for i in range(len(natures)): + currentNature = self.getCurrentEdge().getNature() + if(natures[i] & currentNature): + count=0 + while(it.isEnd() == 0): + visitNext = 0 + oNature = it.getObject().getNature() + if(oNature & natures[i] != 0): + if(natures[i] != oNature): + for j in range(i): + if(natures[j] & oNature != 0): + visitNext = 1 + break + if(visitNext != 0): + break + count = count+1 + winner = it.getObject() + it.increment() + if(count != 1): + winner = None + break + return winner + +## the natural chaining iterator +## It follows the edges of same nature on the same +## objects with preseance on silhouettes, then borders, +## then suggestive contours, then everything else. It doesn't chain the same ViewEdge twice +## You can specify whether to stay in the selection or not. +## You can specify whether to chain iterate over edges that were +## already visited or not. +class pyChainSilhouetteGenericIterator(ChainingIterator): + def __init__(self, stayInSelection=1, stayInUnvisited=1): + ChainingIterator.__init__(self, stayInSelection, stayInUnvisited,None,1) + def getExactTypeName(self): + return "pyChainSilhouetteGenericIterator" + def init(self): + pass + def traverse(self, iter): + winner = None + it = AdjacencyIterator(iter) + tvertex = self.getVertex() + if type(tvertex) is TVertex: + mateVE = tvertex.mate(self.getCurrentEdge()) + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getId() == mateVE.getId() ): + winner = ve + break + it.increment() + else: + ## case of NonTVertex + natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE] + for i in range(len(natures)): + currentNature = self.getCurrentEdge().getNature() + if(natures[i] & currentNature): + count=0 + while(it.isEnd() == 0): + visitNext = 0 + oNature = it.getObject().getNature() + ve = it.getObject() + if(ve.getId() == self.getCurrentEdge().getId()): + it.increment() + continue + if(oNature & natures[i] != 0): + if(natures[i] != oNature): + for j in range(i): + if(natures[j] & oNature != 0): + visitNext = 1 + break + if(visitNext != 0): + break + count = count+1 + winner = ve + it.increment() + if(count != 1): + winner = None + break + return winner + +class pyExternalContourChainingIterator(ChainingIterator): + def __init__(self): + ChainingIterator.__init__(self, 0, 1,None,1) + self._isExternalContour = ExternalContourUP1D() + + def getExactTypeName(self): + return "pyExternalContourIterator" + + def init(self): + self._nEdges = 0 + self._isInSelection = 1 + + def checkViewEdge(self, ve, orientation): + if(orientation != 0): + vertex = ve.B() + else: + vertex = ve.A() + it = AdjacencyIterator(vertex,1,1) + while(it.isEnd() == 0): + ave = it.getObject() + if(self._isExternalContour(ave)): + return 1 + it.increment() + print("pyExternlContourChainingIterator : didn't find next edge") + return 0 + def traverse(self, iter): + winner = None + it = AdjacencyIterator(iter) + while(it.isEnd() == 0): + ve = it.getObject() + if(self._isExternalContour(ve)): + if (ve.getTimeStamp() == GetTimeStampCF()): + winner = ve + it.increment() + + self._nEdges = self._nEdges+1 + if(winner == None): + orient = 1 + it = AdjacencyIterator(iter) + while(it.isEnd() == 0): + ve = it.getObject() + if(it.isIncoming() != 0): + orient = 0 + good = self.checkViewEdge(ve,orient) + if(good != 0): + winner = ve + it.increment() + return winner + +## the natural chaining iterator +## with a sketchy multiple touch +class pySketchyChainSilhouetteIterator(ChainingIterator): + def __init__(self, nRounds=3,stayInSelection=1): + ChainingIterator.__init__(self, stayInSelection, 0,None,1) + self._timeStamp = GetTimeStampCF()+nRounds + self._nRounds = nRounds + def getExactTypeName(self): + return "pySketchyChainSilhouetteIterator" + def init(self): + self._timeStamp = GetTimeStampCF()+self._nRounds + def traverse(self, iter): + winner = None + it = AdjacencyIterator(iter) + tvertex = self.getVertex() + if type(tvertex) is TVertex: + mateVE = tvertex.mate(self.getCurrentEdge()) + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getId() == mateVE.getId() ): + winner = ve + break + it.increment() + else: + ## case of NonTVertex + natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE] + for i in range(len(natures)): + currentNature = self.getCurrentEdge().getNature() + if(natures[i] & currentNature): + count=0 + while(it.isEnd() == 0): + visitNext = 0 + oNature = it.getObject().getNature() + ve = it.getObject() + if(ve.getId() == self.getCurrentEdge().getId()): + it.increment() + continue + if(oNature & natures[i] != 0): + if(natures[i] != oNature): + for j in range(i): + if(natures[j] & oNature != 0): + visitNext = 1 + break + if(visitNext != 0): + break + count = count+1 + winner = ve + it.increment() + if(count != 1): + winner = None + break + if(winner == None): + winner = self.getCurrentEdge() + if(winner.getChainingTimeStamp() == self._timeStamp): + winner = None + return winner + + +# Chaining iterator designed for sketchy style. +# can chain several times the same ViewEdge +# in order to produce multiple strokes per ViewEdge. +class pySketchyChainingIterator(ChainingIterator): + def __init__(self, nRounds=3, stayInSelection=1): + ChainingIterator.__init__(self, stayInSelection, 0,None,1) + self._timeStamp = GetTimeStampCF()+nRounds + self._nRounds = nRounds + def getExactTypeName(self): + return "pySketchyChainingIterator" + + def init(self): + self._timeStamp = GetTimeStampCF()+self._nRounds + + def traverse(self, iter): + winner = None + it = AdjacencyIterator(iter) + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getId() == self.getCurrentEdge().getId()): + it.increment() + continue + winner = ve + it.increment() + if(winner == None): + winner = self.getCurrentEdge() + if(winner.getChainingTimeStamp() == self._timeStamp): + return None + return winner + + +## Chaining iterator that fills small occlusions +## percent +## The max length of the occluded part +## expressed in % of the total chain length +class pyFillOcclusionsRelativeChainingIterator(ChainingIterator): + def __init__(self, percent): + ChainingIterator.__init__(self, 0, 1,None,1) + self._length = 0 + self._percent = float(percent) + def getExactTypeName(self): + return "pyFillOcclusionsChainingIterator" + def init(self): + # each time we're evaluating a chain length + # we try to do it once. Thus we reinit + # the chain length here: + self._length = 0 + def traverse(self, iter): + winner = None + winnerOrientation = 0 + print(self.getCurrentEdge().getId().getFirst(), self.getCurrentEdge().getId().getSecond()) + it = AdjacencyIterator(iter) + tvertex = self.getVertex() + if type(tvertex) is TVertex: + mateVE = tvertex.mate(self.getCurrentEdge()) + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getId() == mateVE.getId() ): + winner = ve + if(it.isIncoming() == 0): + winnerOrientation = 1 + else: + winnerOrientation = 0 + break + it.increment() + else: + ## case of NonTVertex + natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE] + for nat in natures: + if(self.getCurrentEdge().getNature() & nat != 0): + count=0 + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getNature() & nat != 0): + count = count+1 + winner = ve + if(it.isIncoming() == 0): + winnerOrientation = 1 + else: + winnerOrientation = 0 + it.increment() + if(count != 1): + winner = None + break + if(winner != None): + # check whether this edge was part of the selection + if(winner.getTimeStamp() != GetTimeStampCF()): + #print("---", winner.getId().getFirst(), winner.getId().getSecond()) + # if not, let's check whether it's short enough with + # respect to the chain made without staying in the selection + #------------------------------------------------------------ + # Did we compute the prospective chain length already ? + if(self._length == 0): + #if not, let's do it + _it = pyChainSilhouetteGenericIterator(0,0) + _it.setBegin(winner) + _it.setCurrentEdge(winner) + _it.setOrientation(winnerOrientation) + _it.init() + while(_it.isEnd() == 0): + ve = _it.getObject() + #print("--------", ve.getId().getFirst(), ve.getId().getSecond()) + self._length = self._length + ve.getLength2D() + _it.increment() + if(_it.isBegin() != 0): + break; + _it.setBegin(winner) + _it.setCurrentEdge(winner) + _it.setOrientation(winnerOrientation) + if(_it.isBegin() == 0): + _it.decrement() + while ((_it.isEnd() == 0) and (_it.isBegin() == 0)): + ve = _it.getObject() + #print("--------", ve.getId().getFirst(), ve.getId().getSecond()) + self._length = self._length + ve.getLength2D() + _it.decrement() + + # let's do the comparison: + # nw let's compute the length of this connex non selected part: + connexl = 0 + _cit = pyChainSilhouetteGenericIterator(0,0) + _cit.setBegin(winner) + _cit.setCurrentEdge(winner) + _cit.setOrientation(winnerOrientation) + _cit.init() + while((_cit.isEnd() == 0) and (_cit.getObject().getTimeStamp() != GetTimeStampCF())): + ve = _cit.getObject() + #print("-------- --------", ve.getId().getFirst(), ve.getId().getSecond()) + connexl = connexl + ve.getLength2D() + _cit.increment() + if(connexl > self._percent * self._length): + winner = None + return winner + +## Chaining iterator that fills small occlusions +## size +## The max length of the occluded part +## expressed in pixels +class pyFillOcclusionsAbsoluteChainingIterator(ChainingIterator): + def __init__(self, length): + ChainingIterator.__init__(self, 0, 1,None,1) + self._length = float(length) + def getExactTypeName(self): + return "pySmallFillOcclusionsChainingIterator" + def init(self): + pass + def traverse(self, iter): + winner = None + winnerOrientation = 0 + #print(self.getCurrentEdge().getId().getFirst(), self.getCurrentEdge().getId().getSecond()) + it = AdjacencyIterator(iter) + tvertex = self.getVertex() + if type(tvertex) is TVertex: + mateVE = tvertex.mate(self.getCurrentEdge()) + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getId() == mateVE.getId() ): + winner = ve + if(it.isIncoming() == 0): + winnerOrientation = 1 + else: + winnerOrientation = 0 + break + it.increment() + else: + ## case of NonTVertex + natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE] + for nat in natures: + if(self.getCurrentEdge().getNature() & nat != 0): + count=0 + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getNature() & nat != 0): + count = count+1 + winner = ve + if(it.isIncoming() == 0): + winnerOrientation = 1 + else: + winnerOrientation = 0 + it.increment() + if(count != 1): + winner = None + break + if(winner != None): + # check whether this edge was part of the selection + if(winner.getTimeStamp() != GetTimeStampCF()): + #print("---", winner.getId().getFirst(), winner.getId().getSecond()) + # nw let's compute the length of this connex non selected part: + connexl = 0 + _cit = pyChainSilhouetteGenericIterator(0,0) + _cit.setBegin(winner) + _cit.setCurrentEdge(winner) + _cit.setOrientation(winnerOrientation) + _cit.init() + while((_cit.isEnd() == 0) and (_cit.getObject().getTimeStamp() != GetTimeStampCF())): + ve = _cit.getObject() + #print("-------- --------", ve.getId().getFirst(), ve.getId().getSecond()) + connexl = connexl + ve.getLength2D() + _cit.increment() + if(connexl > self._length): + winner = None + return winner + + +## Chaining iterator that fills small occlusions +## percent +## The max length of the occluded part +## expressed in % of the total chain length +class pyFillOcclusionsAbsoluteAndRelativeChainingIterator(ChainingIterator): + def __init__(self, percent, l): + ChainingIterator.__init__(self, 0, 1,None,1) + self._length = 0 + self._absLength = l + self._percent = float(percent) + def getExactTypeName(self): + return "pyFillOcclusionsChainingIterator" + def init(self): + # each time we're evaluating a chain length + # we try to do it once. Thus we reinit + # the chain length here: + self._length = 0 + def traverse(self, iter): + winner = None + winnerOrientation = 0 + print(self.getCurrentEdge().getId().getFirst(), self.getCurrentEdge().getId().getSecond()) + it = AdjacencyIterator(iter) + tvertex = self.getVertex() + if type(tvertex) is TVertex: + mateVE = tvertex.mate(self.getCurrentEdge()) + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getId() == mateVE.getId() ): + winner = ve + if(it.isIncoming() == 0): + winnerOrientation = 1 + else: + winnerOrientation = 0 + break + it.increment() + else: + ## case of NonTVertex + natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE] + for nat in natures: + if(self.getCurrentEdge().getNature() & nat != 0): + count=0 + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getNature() & nat != 0): + count = count+1 + winner = ve + if(it.isIncoming() == 0): + winnerOrientation = 1 + else: + winnerOrientation = 0 + it.increment() + if(count != 1): + winner = None + break + if(winner != None): + # check whether this edge was part of the selection + if(winner.getTimeStamp() != GetTimeStampCF()): + #print("---", winner.getId().getFirst(), winner.getId().getSecond()) + # if not, let's check whether it's short enough with + # respect to the chain made without staying in the selection + #------------------------------------------------------------ + # Did we compute the prospective chain length already ? + if(self._length == 0): + #if not, let's do it + _it = pyChainSilhouetteGenericIterator(0,0) + _it.setBegin(winner) + _it.setCurrentEdge(winner) + _it.setOrientation(winnerOrientation) + _it.init() + while(_it.isEnd() == 0): + ve = _it.getObject() + #print("--------", ve.getId().getFirst(), ve.getId().getSecond()) + self._length = self._length + ve.getLength2D() + _it.increment() + if(_it.isBegin() != 0): + break; + _it.setBegin(winner) + _it.setCurrentEdge(winner) + _it.setOrientation(winnerOrientation) + if(_it.isBegin() == 0): + _it.decrement() + while ((_it.isEnd() == 0) and (_it.isBegin() == 0)): + ve = _it.getObject() + #print("--------", ve.getId().getFirst(), ve.getId().getSecond()) + self._length = self._length + ve.getLength2D() + _it.decrement() + + # let's do the comparison: + # nw let's compute the length of this connex non selected part: + connexl = 0 + _cit = pyChainSilhouetteGenericIterator(0,0) + _cit.setBegin(winner) + _cit.setCurrentEdge(winner) + _cit.setOrientation(winnerOrientation) + _cit.init() + while((_cit.isEnd() == 0) and (_cit.getObject().getTimeStamp() != GetTimeStampCF())): + ve = _cit.getObject() + #print("-------- --------", ve.getId().getFirst(), ve.getId().getSecond()) + connexl = connexl + ve.getLength2D() + _cit.increment() + if((connexl > self._percent * self._length) or (connexl > self._absLength)): + winner = None + return winner + +## Chaining iterator that fills small occlusions without caring about the +## actual selection +## percent +## The max length of the occluded part +## expressed in % of the total chain length +class pyFillQi0AbsoluteAndRelativeChainingIterator(ChainingIterator): + def __init__(self, percent, l): + ChainingIterator.__init__(self, 0, 1,None,1) + self._length = 0 + self._absLength = l + self._percent = float(percent) + def getExactTypeName(self): + return "pyFillOcclusionsChainingIterator" + def init(self): + # each time we're evaluating a chain length + # we try to do it once. Thus we reinit + # the chain length here: + self._length = 0 + def traverse(self, iter): + winner = None + winnerOrientation = 0 + print(self.getCurrentEdge().getId().getFirst(), self.getCurrentEdge().getId().getSecond()) + it = AdjacencyIterator(iter) + tvertex = self.getVertex() + if type(tvertex) is TVertex: + mateVE = tvertex.mate(self.getCurrentEdge()) + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getId() == mateVE.getId() ): + winner = ve + if(it.isIncoming() == 0): + winnerOrientation = 1 + else: + winnerOrientation = 0 + break + it.increment() + else: + ## case of NonTVertex + natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE] + for nat in natures: + if(self.getCurrentEdge().getNature() & nat != 0): + count=0 + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getNature() & nat != 0): + count = count+1 + winner = ve + if(it.isIncoming() == 0): + winnerOrientation = 1 + else: + winnerOrientation = 0 + it.increment() + if(count != 1): + winner = None + break + if(winner != None): + # check whether this edge was part of the selection + if(winner.qi() != 0): + #print("---", winner.getId().getFirst(), winner.getId().getSecond()) + # if not, let's check whether it's short enough with + # respect to the chain made without staying in the selection + #------------------------------------------------------------ + # Did we compute the prospective chain length already ? + if(self._length == 0): + #if not, let's do it + _it = pyChainSilhouetteGenericIterator(0,0) + _it.setBegin(winner) + _it.setCurrentEdge(winner) + _it.setOrientation(winnerOrientation) + _it.init() + while(_it.isEnd() == 0): + ve = _it.getObject() + #print("--------", ve.getId().getFirst(), ve.getId().getSecond()) + self._length = self._length + ve.getLength2D() + _it.increment() + if(_it.isBegin() != 0): + break; + _it.setBegin(winner) + _it.setCurrentEdge(winner) + _it.setOrientation(winnerOrientation) + if(_it.isBegin() == 0): + _it.decrement() + while ((_it.isEnd() == 0) and (_it.isBegin() == 0)): + ve = _it.getObject() + #print("--------", ve.getId().getFirst(), ve.getId().getSecond()) + self._length = self._length + ve.getLength2D() + _it.decrement() + + # let's do the comparison: + # nw let's compute the length of this connex non selected part: + connexl = 0 + _cit = pyChainSilhouetteGenericIterator(0,0) + _cit.setBegin(winner) + _cit.setCurrentEdge(winner) + _cit.setOrientation(winnerOrientation) + _cit.init() + while((_cit.isEnd() == 0) and (_cit.getObject().qi() != 0)): + ve = _cit.getObject() + #print("-------- --------", ve.getId().getFirst(), ve.getId().getSecond()) + connexl = connexl + ve.getLength2D() + _cit.increment() + if((connexl > self._percent * self._length) or (connexl > self._absLength)): + winner = None + return winner + + +## the natural chaining iterator +## It follows the edges of same nature on the same +## objects with preseance on silhouettes, then borders, +## then suggestive contours, then everything else. It doesn't chain the same ViewEdge twice +## You can specify whether to stay in the selection or not. +class pyNoIdChainSilhouetteIterator(ChainingIterator): + def __init__(self, stayInSelection=1): + ChainingIterator.__init__(self, stayInSelection, 1,None,1) + def getExactTypeName(self): + return "pyChainSilhouetteIterator" + def init(self): + pass + def traverse(self, iter): + winner = None + it = AdjacencyIterator(iter) + tvertex = self.getVertex() + if type(tvertex) is TVertex: + mateVE = tvertex.mate(self.getCurrentEdge()) + while(it.isEnd() == 0): + ve = it.getObject() + feB = self.getCurrentEdge().fedgeB() + feA = ve.fedgeA() + vB = feB.vertexB() + vA = feA.vertexA() + if vA.getId().getFirst() == vB.getId().getFirst(): + winner = ve + break + feA = self.getCurrentEdge().fedgeA() + feB = ve.fedgeB() + vB = feB.vertexB() + vA = feA.vertexA() + if vA.getId().getFirst() == vB.getId().getFirst(): + winner = ve + break + feA = self.getCurrentEdge().fedgeB() + feB = ve.fedgeB() + vB = feB.vertexB() + vA = feA.vertexB() + if vA.getId().getFirst() == vB.getId().getFirst(): + winner = ve + break + feA = self.getCurrentEdge().fedgeA() + feB = ve.fedgeA() + vB = feB.vertexA() + vA = feA.vertexA() + if vA.getId().getFirst() == vB.getId().getFirst(): + winner = ve + break + it.increment() + else: + ## case of NonTVertex + natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE] + for i in range(len(natures)): + currentNature = self.getCurrentEdge().getNature() + if(natures[i] & currentNature): + count=0 + while(it.isEnd() == 0): + visitNext = 0 + oNature = it.getObject().getNature() + if(oNature & natures[i] != 0): + if(natures[i] != oNature): + for j in range(i): + if(natures[j] & oNature != 0): + visitNext = 1 + break + if(visitNext != 0): + break + count = count+1 + winner = it.getObject() + it.increment() + if(count != 1): + winner = None + break + return winner + diff --git a/release/scripts/freestyle/style_modules/Functions0D.py b/release/scripts/freestyle/style_modules/Functions0D.py new file mode 100755 index 00000000000..2881a80c386 --- /dev/null +++ b/release/scripts/freestyle/style_modules/Functions0D.py @@ -0,0 +1,81 @@ +from freestyle_init import * + + +class pyInverseCurvature2DAngleF0D(UnaryFunction0DDouble): + def getName(self): + return "InverseCurvature2DAngleF0D" + + def __call__(self, inter): + func = Curvature2DAngleF0D() + c = func(inter) + return (3.1415 - c) + +class pyCurvilinearLengthF0D(UnaryFunction0DDouble): + def getName(self): + return "CurvilinearLengthF0D" + + def __call__(self, inter): + i0d = inter.getObject() + s = i0d.getExactTypeName() + if (string.find(s, "CurvePoint") == -1): + print("CurvilinearLengthF0D: not implemented yet for", s) + return -1 + cp = castToCurvePoint(i0d) + return cp.t2d() + +## estimate anisotropy of density +class pyDensityAnisotropyF0D(UnaryFunction0DDouble): + def __init__(self,level): + UnaryFunction0DDouble.__init__(self) + self.IsoDensity = ReadCompleteViewMapPixelF0D(level) + self.d0Density = ReadSteerableViewMapPixelF0D(0, level) + self.d1Density = ReadSteerableViewMapPixelF0D(1, level) + self.d2Density = ReadSteerableViewMapPixelF0D(2, level) + self.d3Density = ReadSteerableViewMapPixelF0D(3, level) + def getName(self): + return "pyDensityAnisotropyF0D" + def __call__(self, inter): + c_iso = self.IsoDensity(inter) + c_0 = self.d0Density(inter) + c_1 = self.d1Density(inter) + c_2 = self.d2Density(inter) + c_3 = self.d3Density(inter) + cMax = max( max(c_0,c_1), max(c_2,c_3)) + cMin = min( min(c_0,c_1), min(c_2,c_3)) + if ( c_iso == 0 ): + v = 0 + else: + v = (cMax-cMin)/c_iso + return (v) + +## Returns the gradient vector for a pixel +## l +## the level at which one wants to compute the gradient +class pyViewMapGradientVectorF0D(UnaryFunction0DVec2f): + def __init__(self, l): + UnaryFunction0DVec2f.__init__(self) + self._l = l + self._step = pow(2,self._l) + def getName(self): + return "pyViewMapGradientVectorF0D" + def __call__(self, iter): + p = iter.getObject().getPoint2D() + gx = ReadCompleteViewMapPixelCF(self._l, int(p.x()+self._step), int(p.y()))- ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y())) + gy = ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y()+self._step))- ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y())) + return Vector([gx, gy]) + +class pyViewMapGradientNormF0D(UnaryFunction0DDouble): + def __init__(self, l): + UnaryFunction0DDouble.__init__(self) + self._l = l + self._step = pow(2,self._l) + def getName(self): + return "pyViewMapGradientNormF0D" + def __call__(self, iter): + p = iter.getObject().getPoint2D() + gx = ReadCompleteViewMapPixelCF(self._l, int(p.x()+self._step), int(p.y()))- ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y())) + gy = ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y()+self._step))- ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y())) + grad = Vector([gx, gy]) + return grad.length + + diff --git a/release/scripts/freestyle/style_modules/Functions1D.py b/release/scripts/freestyle/style_modules/Functions1D.py new file mode 100755 index 00000000000..aaf115356cb --- /dev/null +++ b/release/scripts/freestyle/style_modules/Functions1D.py @@ -0,0 +1,45 @@ +from freestyle_init import * +from Functions0D import * +import string + +class pyGetInverseProjectedZF1D(UnaryFunction1DDouble): + def getName(self): + return "pyGetInverseProjectedZF1D" + + def __call__(self, inter): + func = GetProjectedZF1D() + z = func(inter) + return (1.0 - z) + +class pyGetSquareInverseProjectedZF1D(UnaryFunction1DDouble): + def getName(self): + return "pyGetInverseProjectedZF1D" + + def __call__(self, inter): + func = GetProjectedZF1D() + z = func(inter) + return (1.0 - z*z) + +class pyDensityAnisotropyF1D(UnaryFunction1DDouble): + def __init__(self,level, integrationType=IntegrationType.MEAN, sampling=2.0): + UnaryFunction1DDouble.__init__(self, integrationType) + self._func = pyDensityAnisotropyF0D(level) + self._integration = integrationType + self._sampling = sampling + def getName(self): + return "pyDensityAnisotropyF1D" + def __call__(self, inter): + v = integrate(self._func, inter.pointsBegin(self._sampling), inter.pointsEnd(self._sampling), self._integration) + return v + +class pyViewMapGradientNormF1D(UnaryFunction1DDouble): + def __init__(self,l, integrationType, sampling=2.0): + UnaryFunction1DDouble.__init__(self, integrationType) + self._func = pyViewMapGradientNormF0D(l) + self._integration = integrationType + self._sampling = sampling + def getName(self): + return "pyViewMapGradientNormF1D" + def __call__(self, inter): + v = integrate(self._func, inter.pointsBegin(self._sampling), inter.pointsEnd(self._sampling), self._integration) + return v diff --git a/release/scripts/freestyle/style_modules/PredicatesB1D.py b/release/scripts/freestyle/style_modules/PredicatesB1D.py new file mode 100755 index 00000000000..3b7d21039df --- /dev/null +++ b/release/scripts/freestyle/style_modules/PredicatesB1D.py @@ -0,0 +1,70 @@ +from freestyle_init import * +from Functions1D import * +from random import * + +class pyZBP1D(BinaryPredicate1D): + def getName(self): + return "pyZBP1D" + + def __call__(self, i1, i2): + func = GetZF1D() + return (func(i1) > func(i2)) + +class pyZDiscontinuityBP1D(BinaryPredicate1D): + def __init__(self, iType = IntegrationType.MEAN): + BinaryPredicate1D.__init__(self) + self._GetZDiscontinuity = ZDiscontinuityF1D(iType) + + def getName(self): + return "pyZDiscontinuityBP1D" + + def __call__(self, i1, i2): + return (self._GetZDiscontinuity(i1) > self._GetZDiscontinuity(i2)) + +class pyLengthBP1D(BinaryPredicate1D): + def getName(self): + return "LengthBP1D" + + def __call__(self, i1, i2): + return (i1.getLength2D() > i2.getLength2D()) + +class pySilhouetteFirstBP1D(BinaryPredicate1D): + def getName(self): + return "SilhouetteFirstBP1D" + + def __call__(self, inter1, inter2): + bpred = SameShapeIdBP1D() + if (bpred(inter1, inter2) != 1): + return 0 + if (inter1.getNature() & Nature.SILHOUETTE): + return (inter2.getNature() & Nature.SILHOUETTE) + return (inter1.getNature() == inter2.getNature()) + +class pyNatureBP1D(BinaryPredicate1D): + def getName(self): + return "NatureBP1D" + + def __call__(self, inter1, inter2): + return (inter1.getNature() & inter2.getNature()) + +class pyViewMapGradientNormBP1D(BinaryPredicate1D): + def __init__(self,l, sampling=2.0): + BinaryPredicate1D.__init__(self) + self._GetGradient = pyViewMapGradientNormF1D(l, IntegrationType.MEAN) + def getName(self): + return "pyViewMapGradientNormBP1D" + def __call__(self, i1,i2): + print("compare gradient") + return (self._GetGradient(i1) > self._GetGradient(i2)) + +class pyShuffleBP1D(BinaryPredicate1D): + def __init__(self): + BinaryPredicate1D.__init__(self) + seed(1) + def getName(self): + return "pyNearAndContourFirstBP1D" + + def __call__(self, inter1, inter2): + r1 = uniform(0,1) + r2 = uniform(0,1) + return (r1<r2) diff --git a/release/scripts/freestyle/style_modules/PredicatesU0D.py b/release/scripts/freestyle/style_modules/PredicatesU0D.py new file mode 100755 index 00000000000..162254f17ed --- /dev/null +++ b/release/scripts/freestyle/style_modules/PredicatesU0D.py @@ -0,0 +1,103 @@ +from freestyle_init import * +from Functions0D import * + +class pyHigherCurvature2DAngleUP0D(UnaryPredicate0D): + def __init__(self,a): + UnaryPredicate0D.__init__(self) + self._a = a + + def getName(self): + return "HigherCurvature2DAngleUP0D" + + def __call__(self, inter): + func = Curvature2DAngleF0D() + a = func(inter) + return ( a > self._a) + +class pyUEqualsUP0D(UnaryPredicate0D): + def __init__(self,u, w): + UnaryPredicate0D.__init__(self) + self._u = u + self._w = w + + def getName(self): + return "UEqualsUP0D" + + def __call__(self, inter): + func = pyCurvilinearLengthF0D() + u = func(inter) + return ( ( u > (self._u-self._w) ) and ( u < (self._u+self._w) ) ) + +class pyVertexNatureUP0D(UnaryPredicate0D): + def __init__(self,nature): + UnaryPredicate0D.__init__(self) + self._nature = nature + + def getName(self): + return "pyVertexNatureUP0D" + + def __call__(self, inter): + v = inter.getObject() + nat = v.getNature() + if(nat & self._nature): + return 1; + return 0 + +## check whether an Interface0DIterator +## is a TVertex and is the one that is +## hidden (inferred from the context) +class pyBackTVertexUP0D(UnaryPredicate0D): + def __init__(self): + UnaryPredicate0D.__init__(self) + self._getQI = QuantitativeInvisibilityF0D() + def getName(self): + return "pyBackTVertexUP0D" + def __call__(self, iter): + v = iter.getObject() + nat = v.getNature() + if(nat & Nature.T_VERTEX == 0): + return 0 + next = iter + if(next.isEnd()): + return 0 + if(self._getQI(next) != 0): + return 1 + return 0 + +class pyParameterUP0DGoodOne(UnaryPredicate0D): + def __init__(self,pmin,pmax): + UnaryPredicate0D.__init__(self) + self._m = pmin + self._M = pmax + #self.getCurvilinearAbscissa = GetCurvilinearAbscissaF0D() + + def getName(self): + return "pyCurvilinearAbscissaHigherThanUP0D" + + def __call__(self, inter): + #s = self.getCurvilinearAbscissa(inter) + u = inter.u() + #print(u) + return ((u>=self._m) and (u<=self._M)) + +class pyParameterUP0D(UnaryPredicate0D): + def __init__(self,pmin,pmax): + UnaryPredicate0D.__init__(self) + self._m = pmin + self._M = pmax + #self.getCurvilinearAbscissa = GetCurvilinearAbscissaF0D() + + def getName(self): + return "pyCurvilinearAbscissaHigherThanUP0D" + + def __call__(self, inter): + func = Curvature2DAngleF0D() + c = func(inter) + b1 = (c>0.1) + #s = self.getCurvilinearAbscissa(inter) + u = inter.u() + #print(u) + b = ((u>=self._m) and (u<=self._M)) + return b and b1 + + diff --git a/release/scripts/freestyle/style_modules/PredicatesU1D.py b/release/scripts/freestyle/style_modules/PredicatesU1D.py new file mode 100755 index 00000000000..3529ca8b4e3 --- /dev/null +++ b/release/scripts/freestyle/style_modules/PredicatesU1D.py @@ -0,0 +1,381 @@ +from freestyle_init import * +from Functions1D import * + +count = 0 +class pyNFirstUP1D(UnaryPredicate1D): + def __init__(self, n): + UnaryPredicate1D.__init__(self) + self.__n = n + def __call__(self, inter): + global count + count = count + 1 + if count <= self.__n: + return 1 + return 0 + +class pyHigherLengthUP1D(UnaryPredicate1D): + def __init__(self,l): + UnaryPredicate1D.__init__(self) + self._l = l + + def getName(self): + return "HigherLengthUP1D" + + def __call__(self, inter): + return (inter.getLength2D() > self._l) + +class pyNatureUP1D(UnaryPredicate1D): + def __init__(self,nature): + UnaryPredicate1D.__init__(self) + self._nature = nature + self._getNature = CurveNatureF1D() + + def getName(self): + return "pyNatureUP1D" + + def __call__(self, inter): + if(self._getNature(inter) & self._nature): + return 1 + return 0 + +class pyHigherNumberOfTurnsUP1D(UnaryPredicate1D): + def __init__(self,n,a): + UnaryPredicate1D.__init__(self) + self._n = n + self._a = a + + def getName(self): + return "HigherNumberOfTurnsUP1D" + + def __call__(self, inter): + count = 0 + func = Curvature2DAngleF0D() + it = inter.verticesBegin() + while(it.isEnd() == 0): + if(func(it) > self._a): + count = count+1 + if(count > self._n): + return 1 + it.increment() + return 0 + +class pyDensityUP1D(UnaryPredicate1D): + def __init__(self,wsize,threshold, integration = IntegrationType.MEAN, sampling=2.0): + UnaryPredicate1D.__init__(self) + self._wsize = wsize + self._threshold = threshold + self._integration = integration + self._func = DensityF1D(self._wsize, self._integration, sampling) + + def getName(self): + return "pyDensityUP1D" + + def __call__(self, inter): + if(self._func(inter) < self._threshold): + return 1 + return 0 + +class pyLowSteerableViewMapDensityUP1D(UnaryPredicate1D): + def __init__(self,threshold, level,integration = IntegrationType.MEAN): + UnaryPredicate1D.__init__(self) + self._threshold = threshold + self._level = level + self._integration = integration + + def getName(self): + return "pyLowSteerableViewMapDensityUP1D" + + def __call__(self, inter): + func = GetSteerableViewMapDensityF1D(self._level, self._integration) + v = func(inter) + print(v) + if(v < self._threshold): + return 1 + return 0 + +class pyLowDirectionalViewMapDensityUP1D(UnaryPredicate1D): + def __init__(self,threshold, orientation, level,integration = IntegrationType.MEAN): + UnaryPredicate1D.__init__(self) + self._threshold = threshold + self._orientation = orientation + self._level = level + self._integration = integration + + def getName(self): + return "pyLowDirectionalViewMapDensityUP1D" + + def __call__(self, inter): + func = GetDirectionalViewMapDensityF1D(self._orientation, self._level, self._integration) + v = func(inter) + #print(v) + if(v < self._threshold): + return 1 + return 0 + +class pyHighSteerableViewMapDensityUP1D(UnaryPredicate1D): + def __init__(self,threshold, level,integration = IntegrationType.MEAN): + UnaryPredicate1D.__init__(self) + self._threshold = threshold + self._level = level + self._integration = integration + self._func = GetSteerableViewMapDensityF1D(self._level, self._integration) + def getName(self): + return "pyHighSteerableViewMapDensityUP1D" + + def __call__(self, inter): + + v = self._func(inter) + if(v > self._threshold): + return 1 + return 0 + +class pyHighDirectionalViewMapDensityUP1D(UnaryPredicate1D): + def __init__(self,threshold, orientation, level,integration = IntegrationType.MEAN, sampling=2.0): + UnaryPredicate1D.__init__(self) + self._threshold = threshold + self._orientation = orientation + self._level = level + self._integration = integration + self._sampling = sampling + def getName(self): + return "pyLowDirectionalViewMapDensityUP1D" + + def __call__(self, inter): + func = GetDirectionalViewMapDensityF1D(self._orientation, self._level, self._integration, self._sampling) + v = func(inter) + if(v > self._threshold): + return 1 + return 0 + +class pyHighViewMapDensityUP1D(UnaryPredicate1D): + def __init__(self,threshold, level,integration = IntegrationType.MEAN, sampling=2.0): + UnaryPredicate1D.__init__(self) + self._threshold = threshold + self._level = level + self._integration = integration + self._sampling = sampling + self._func = GetCompleteViewMapDensityF1D(self._level, self._integration, self._sampling) # 2.0 is the smpling + + def getName(self): + return "pyHighViewMapDensityUP1D" + + def __call__(self, inter): + #print("toto") + #print(func.getName()) + #print(inter.getExactTypeName()) + v= self._func(inter) + if(v > self._threshold): + return 1 + return 0 + +class pyDensityFunctorUP1D(UnaryPredicate1D): + def __init__(self,wsize,threshold, functor, funcmin=0.0, funcmax=1.0, integration = IntegrationType.MEAN): + UnaryPredicate1D.__init__(self) + self._wsize = wsize + self._threshold = float(threshold) + self._functor = functor + self._funcmin = float(funcmin) + self._funcmax = float(funcmax) + self._integration = integration + + def getName(self): + return "pyDensityFunctorUP1D" + + def __call__(self, inter): + func = DensityF1D(self._wsize, self._integration) + res = self._functor(inter) + k = (res-self._funcmin)/(self._funcmax-self._funcmin) + if(func(inter) < self._threshold*k): + return 1 + return 0 + +class pyZSmallerUP1D(UnaryPredicate1D): + def __init__(self,z, integration=IntegrationType.MEAN): + UnaryPredicate1D.__init__(self) + self._z = z + self._integration = integration + def getName(self): + return "pyZSmallerUP1D" + + def __call__(self, inter): + func = GetProjectedZF1D(self._integration) + if(func(inter) < self._z): + return 1 + return 0 + +class pyIsOccludedByUP1D(UnaryPredicate1D): + def __init__(self,id): + UnaryPredicate1D.__init__(self) + self._id = id + def getName(self): + return "pyIsOccludedByUP1D" + def __call__(self, inter): + func = GetShapeF1D() + shapes = func(inter) + for s in shapes: + if(s.getId() == self._id): + return 0 + it = inter.verticesBegin() + itlast = inter.verticesEnd() + itlast.decrement() + v = it.getObject() + vlast = itlast.getObject() + tvertex = v.viewvertex() + if type(tvertex) is TVertex: + print("TVertex: [ ", tvertex.getId().getFirst(), ",", tvertex.getId().getSecond()," ]") + eit = tvertex.edgesBegin() + while(eit.isEnd() == 0): + ve, incoming = eit.getObject() + if(ve.getId() == self._id): + return 1 + print("-------", ve.getId().getFirst(), "-", ve.getId().getSecond()) + eit.increment() + tvertex = vlast.viewvertex() + if type(tvertex) is TVertex: + print("TVertex: [ ", tvertex.getId().getFirst(), ",", tvertex.getId().getSecond()," ]") + eit = tvertex.edgesBegin() + while(eit.isEnd() == 0): + ve, incoming = eit.getObject() + if(ve.getId() == self._id): + return 1 + print("-------", ve.getId().getFirst(), "-", ve.getId().getSecond()) + eit.increment() + return 0 + +class pyIsInOccludersListUP1D(UnaryPredicate1D): + def __init__(self,id): + UnaryPredicate1D.__init__(self) + self._id = id + def getName(self): + return "pyIsInOccludersListUP1D" + def __call__(self, inter): + func = GetOccludersF1D() + occluders = func(inter) + for a in occluders: + if(a.getId() == self._id): + return 1 + return 0 + +class pyIsOccludedByItselfUP1D(UnaryPredicate1D): + def __init__(self): + UnaryPredicate1D.__init__(self) + self.__func1 = GetOccludersF1D() + self.__func2 = GetShapeF1D() + def getName(self): + return "pyIsOccludedByItselfUP1D" + def __call__(self, inter): + lst1 = self.__func1(inter) + lst2 = self.__func2(inter) + for vs1 in lst1: + for vs2 in lst2: + if vs1.getId() == vs2.getId(): + return 1 + return 0 + +class pyIsOccludedByIdListUP1D(UnaryPredicate1D): + def __init__(self, idlist): + UnaryPredicate1D.__init__(self) + self._idlist = idlist + self.__func1 = GetOccludersF1D() + def getName(self): + return "pyIsOccludedByIdListUP1D" + def __call__(self, inter): + lst1 = self.__func1(inter) + for vs1 in lst1: + for id in self._idlist: + if vs1.getId() == id: + return 1 + return 0 + +class pyShapeIdListUP1D(UnaryPredicate1D): + def __init__(self,idlist): + UnaryPredicate1D.__init__(self) + self._idlist = idlist + self._funcs = [] + for id in idlist : + self._funcs.append(ShapeUP1D(id.getFirst(), id.getSecond())) + + def getName(self): + return "pyShapeIdUP1D" + def __call__(self, inter): + for func in self._funcs : + if(func(inter) == 1) : + return 1 + return 0 + +## deprecated +class pyShapeIdUP1D(UnaryPredicate1D): + def __init__(self,id): + UnaryPredicate1D.__init__(self) + self._id = id + def getName(self): + return "pyShapeIdUP1D" + def __call__(self, inter): + func = GetShapeF1D() + shapes = func(inter) + for a in shapes: + if(a.getId() == self._id): + return 1 + return 0 + +class pyHighDensityAnisotropyUP1D(UnaryPredicate1D): + def __init__(self,threshold, level, sampling=2.0): + UnaryPredicate1D.__init__(self) + self._l = threshold + self.func = pyDensityAnisotropyF1D(level, IntegrationType.MEAN, sampling) + def getName(self): + return "pyHighDensityAnisotropyUP1D" + def __call__(self, inter): + return (self.func(inter) > self._l) + +class pyHighViewMapGradientNormUP1D(UnaryPredicate1D): + def __init__(self,threshold, l, sampling=2.0): + UnaryPredicate1D.__init__(self) + self._threshold = threshold + self._GetGradient = pyViewMapGradientNormF1D(l, IntegrationType.MEAN) + def getName(self): + return "pyHighViewMapGradientNormUP1D" + def __call__(self, inter): + gn = self._GetGradient(inter) + #print(gn) + return (gn > self._threshold) + +class pyDensityVariableSigmaUP1D(UnaryPredicate1D): + def __init__(self,functor, sigmaMin,sigmaMax, lmin, lmax, tmin, tmax, integration = IntegrationType.MEAN, sampling=2.0): + UnaryPredicate1D.__init__(self) + self._functor = functor + self._sigmaMin = float(sigmaMin) + self._sigmaMax = float(sigmaMax) + self._lmin = float(lmin) + self._lmax = float(lmax) + self._tmin = tmin + self._tmax = tmax + self._integration = integration + self._sampling = sampling + + def getName(self): + return "pyDensityUP1D" + + def __call__(self, inter): + sigma = (self._sigmaMax-self._sigmaMin)/(self._lmax-self._lmin)*(self._functor(inter)-self._lmin) + self._sigmaMin + t = (self._tmax-self._tmin)/(self._lmax-self._lmin)*(self._functor(inter)-self._lmin) + self._tmin + if(sigma<self._sigmaMin): + sigma = self._sigmaMin + self._func = DensityF1D(sigma, self._integration, self._sampling) + d = self._func(inter) + if(d<t): + return 1 + return 0 + +class pyClosedCurveUP1D(UnaryPredicate1D): + def __call__(self, inter): + it = inter.verticesBegin() + itlast = inter.verticesEnd() + itlast.decrement() + vlast = itlast.getObject() + v = it.getObject() + print(v.getId().getFirst(), v.getId().getSecond()) + print(vlast.getId().getFirst(), vlast.getId().getSecond()) + if(v.getId() == vlast.getId()): + return 1 + return 0 diff --git a/release/scripts/freestyle/style_modules/anisotropic_diffusion.py b/release/scripts/freestyle/style_modules/anisotropic_diffusion.py new file mode 100755 index 00000000000..7e7ebf647bd --- /dev/null +++ b/release/scripts/freestyle/style_modules/anisotropic_diffusion.py @@ -0,0 +1,74 @@ +# +# Filename : anisotropic_diffusion.py +# Author : Fredo Durand +# Date : 12/08/2004 +# Purpose : Smoothes lines using an anisotropic diffusion scheme +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from shaders import * +from PredicatesU0D import * +from math import * + +## thickness modifiers + +normalInfo=Normal2DF0D() +curvatureInfo=Curvature2DAngleF0D() + +def edgestopping(x, sigma): + return exp(- x*x/(2*sigma*sigma)) + +class pyDiffusion2Shader(StrokeShader): + def __init__(self, lambda1, nbIter): + StrokeShader.__init__(self) + self._lambda = lambda1 + self._nbIter = nbIter + def getName(self): + return "pyDiffusionShader" + def shade(self, stroke): + for i in range (1, self._nbIter): + it = stroke.strokeVerticesBegin() + while it.isEnd() == 0: + v=it.getObject() + p1 = v.getPoint() + p2 = normalInfo(it.castToInterface0DIterator())*self._lambda*curvatureInfo(it.castToInterface0DIterator()) + v.setPoint(p1+p2) + it.increment() + +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D()) +Operators.select( upred ) +bpred = TrueBP1D(); +Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(upred) ) +shaders_list = [ + ConstantThicknessShader(4), + StrokeTextureShader("smoothAlpha.bmp", Stroke.OPAQUE_MEDIUM, 0), + SamplingShader(2), + pyDiffusion2Shader(-0.03, 30), + IncreasingColorShader(1.0,0.0,0.0,1, 0, 1, 0, 1) + ] +Operators.create(TrueUP1D(), shaders_list) + + + diff --git a/release/scripts/freestyle/style_modules/apriori_and_causal_density.py b/release/scripts/freestyle/style_modules/apriori_and_causal_density.py new file mode 100755 index 00000000000..7cdd4b2fd66 --- /dev/null +++ b/release/scripts/freestyle/style_modules/apriori_and_causal_density.py @@ -0,0 +1,45 @@ +# +# Filename : apriori_and_causal_density.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Selects the lines with high a priori density and +# subjects them to the causal density so as to avoid +# cluttering +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from PredicatesU1D import * +from shaders import * + +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), pyHighViewMapDensityUP1D(0.3, IntegrationType.LAST)) +Operators.select(upred) +bpred = TrueBP1D() +Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + ConstantThicknessShader(2), + ConstantColorShader(0.0, 0.0, 0.0,1) + ] +Operators.create(pyDensityUP1D(1,0.1, IntegrationType.MEAN), shaders_list) diff --git a/release/scripts/freestyle/style_modules/apriori_density.py b/release/scripts/freestyle/style_modules/apriori_density.py new file mode 100755 index 00000000000..5ff6c58e77f --- /dev/null +++ b/release/scripts/freestyle/style_modules/apriori_density.py @@ -0,0 +1,43 @@ +# +# Filename : apriori_density.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws lines having a high a priori density +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from PredicatesU1D import * +from shaders import * + +Operators.select(AndUP1D(QuantitativeInvisibilityUP1D(0), pyHighViewMapDensityUP1D(0.1,5))) +bpred = TrueBP1D() +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), pyHighViewMapDensityUP1D(0.0007,5)) +Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + ConstantThicknessShader(2), + ConstantColorShader(0.0, 0.0, 0.0,1) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/backbone_stretcher.py b/release/scripts/freestyle/style_modules/backbone_stretcher.py new file mode 100755 index 00000000000..8a6b9d71a66 --- /dev/null +++ b/release/scripts/freestyle/style_modules/backbone_stretcher.py @@ -0,0 +1,36 @@ +# +# Filename : backbone_stretcher.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Stretches the geometry of visible lines +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [TextureAssignerShader(4), ConstantColorShader(0.5, 0.5, 0.5), BackboneStretcherShader(20)] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/blueprint_circles.py b/release/scripts/freestyle/style_modules/blueprint_circles.py new file mode 100755 index 00000000000..7f3a7564cfe --- /dev/null +++ b/release/scripts/freestyle/style_modules/blueprint_circles.py @@ -0,0 +1,46 @@ +# +# Filename : blueprint_circles.py +# Author : Emmanuel Turquin +# Date : 04/08/2005 +# Purpose : Produces a blueprint using circular contour strokes +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from PredicatesU1D import * +from shaders import * + +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D()) +bpred = SameShapeIdBP1D() +Operators.select(upred) +Operators.bidirectionalChain(ChainPredicateIterator(upred,bpred), NotUP1D(upred)) +Operators.select(pyHigherLengthUP1D(200)) +shaders_list = [ + ConstantThicknessShader(5), + pyBluePrintCirclesShader(3), + pyPerlinNoise1DShader(0.1, 15, 8), + TextureAssignerShader(4), + IncreasingColorShader(0.8, 0.8, 0.3, 0.4, 0.3, 0.3, 0.3, 0.1) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/blueprint_ellipses.py b/release/scripts/freestyle/style_modules/blueprint_ellipses.py new file mode 100755 index 00000000000..a5cfe4ec30b --- /dev/null +++ b/release/scripts/freestyle/style_modules/blueprint_ellipses.py @@ -0,0 +1,46 @@ +# +# Filename : blueprint_ellipses.py +# Author : Emmanuel Turquin +# Date : 04/08/2005 +# Purpose : Produces a blueprint using elliptic contour strokes +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from PredicatesU1D import * +from shaders import * + +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D()) +bpred = SameShapeIdBP1D() +Operators.select(upred) +Operators.bidirectionalChain(ChainPredicateIterator(upred,bpred), NotUP1D(upred)) +Operators.select(pyHigherLengthUP1D(200)) +shaders_list = [ + ConstantThicknessShader(5), + pyBluePrintEllipsesShader(3), + pyPerlinNoise1DShader(0.1, 10, 8), + TextureAssignerShader(4), + IncreasingColorShader(0.6, 0.3, 0.3, 0.7, 0.3, 0.3, 0.3, 0.1) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/blueprint_squares.py b/release/scripts/freestyle/style_modules/blueprint_squares.py new file mode 100755 index 00000000000..7798acc7d47 --- /dev/null +++ b/release/scripts/freestyle/style_modules/blueprint_squares.py @@ -0,0 +1,45 @@ +# Filename : blueprint_squares.py +# Author : Emmanuel Turquin +# Date : 04/08/2005 +# Purpose : Produces a blueprint using square contour strokes +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from PredicatesU1D import * +from shaders import * + +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D()) +bpred = SameShapeIdBP1D() +Operators.select(upred) +Operators.bidirectionalChain(ChainPredicateIterator(upred,bpred), NotUP1D(upred)) +Operators.select(pyHigherLengthUP1D(200)) +shaders_list = [ + ConstantThicknessShader(8), + pyBluePrintSquaresShader(2, 20), + pyPerlinNoise1DShader(0.07, 10, 8), + TextureAssignerShader(4), + IncreasingColorShader(0.6, 0.3, 0.3, 0.7, 0.6, 0.3, 0.3, 0.3), + ConstantThicknessShader(4) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/cartoon.py b/release/scripts/freestyle/style_modules/cartoon.py new file mode 100755 index 00000000000..6ace7e0585a --- /dev/null +++ b/release/scripts/freestyle/style_modules/cartoon.py @@ -0,0 +1,42 @@ +# +# Filename : cartoon.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws colored lines. The color is automatically +# infered from each object's material in a cartoon-like +# fashion. +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + BezierCurveShader(3), + ConstantThicknessShader(4), + pyMaterialColorShader(0.8) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/contour.py b/release/scripts/freestyle/style_modules/contour.py new file mode 100755 index 00000000000..c4b3a0f0827 --- /dev/null +++ b/release/scripts/freestyle/style_modules/contour.py @@ -0,0 +1,42 @@ +# +# Filename : contour.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws each object's visible contour +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from PredicatesU1D import * +from shaders import * + +Operators.select(AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D() ) ) +bpred = SameShapeIdBP1D(); +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D()) +Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + ConstantThicknessShader(5.0), + IncreasingColorShader(0.8,0,0,1,0.1,0,0,1) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/curvature2d.py b/release/scripts/freestyle/style_modules/curvature2d.py new file mode 100755 index 00000000000..fc2bcab4946 --- /dev/null +++ b/release/scripts/freestyle/style_modules/curvature2d.py @@ -0,0 +1,60 @@ +# +# Filename : curvature2d.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : The stroke points are colored in gray levels and depending +# on the 2d curvature value +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from shaders import * + +class py2DCurvatureColorShader(StrokeShader): + def getName(self): + return "py2DCurvatureColorShader" + + def shade(self, stroke): + it = stroke.strokeVerticesBegin() + it_end = stroke.strokeVerticesEnd() + func = Curvature2DAngleF0D() + while it.isEnd() == 0: + it0D = it.castToInterface0DIterator() + sv = it.getObject() + att = sv.attribute() + c = func(it0D) + if (c<0): + print("negative 2D curvature") + color = 10.0 * c/3.1415 + att.setColor(color,color,color); + it.increment() + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + StrokeTextureShader("smoothAlpha.bmp", Stroke.OPAQUE_MEDIUM, 0), + ConstantThicknessShader(5), + py2DCurvatureColorShader() + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/external_contour.py b/release/scripts/freestyle/style_modules/external_contour.py new file mode 100755 index 00000000000..2a39b79a410 --- /dev/null +++ b/release/scripts/freestyle/style_modules/external_contour.py @@ -0,0 +1,43 @@ +# +# Filename : external_contour.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws the external contour of the scene +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from PredicatesU1D import * +from ChainingIterators import * +from shaders import * + +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D()) +Operators.select(upred ) +bpred = TrueBP1D(); +Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(upred)) +shaders_list = [ + ConstantThicknessShader(3), + ConstantColorShader(0.0, 0.0, 0.0,1) + ] +Operators.create(TrueUP1D(), shaders_list)
\ No newline at end of file diff --git a/release/scripts/freestyle/style_modules/external_contour_sketchy.py b/release/scripts/freestyle/style_modules/external_contour_sketchy.py new file mode 100755 index 00000000000..8a4c570b279 --- /dev/null +++ b/release/scripts/freestyle/style_modules/external_contour_sketchy.py @@ -0,0 +1,48 @@ +# +# Filename : external_contour_sketchy.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws the external contour of the scene using a sketchy +# chaining iterator (in particular each ViewEdge can be drawn +# several times +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + + +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from shaders import * + + +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D()) +Operators.select(upred) +Operators.bidirectionalChain(pySketchyChainingIterator(), NotUP1D(upred)) +shaders_list = [ + SamplingShader(4), + SpatialNoiseShader(10, 150, 2, 1, 1), + IncreasingThicknessShader(4, 10), + SmoothingShader(400, 0.1, 0, 0.2, 0, 0, 0, 1), + IncreasingColorShader(1,0,0,1,0,1,0,1), + TextureAssignerShader(4) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/external_contour_smooth.py b/release/scripts/freestyle/style_modules/external_contour_smooth.py new file mode 100755 index 00000000000..201dc271388 --- /dev/null +++ b/release/scripts/freestyle/style_modules/external_contour_smooth.py @@ -0,0 +1,44 @@ +# +# Filename : external_contour_smooth.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws a smooth external contour +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from PredicatesU1D import * +from shaders import * +from ChainingIterators import * + +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D()) +Operators.select(upred) +bpred = TrueBP1D(); +Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(upred)) +shaders_list = [ + SamplingShader(2), + IncreasingThicknessShader(4,20), + IncreasingColorShader(1.0, 0.0, 0.5,1, 0.5,1, 0.3, 1), + SmoothingShader(100, 0.05, 0, 0.2, 0, 0, 0, 1) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/extra-lines.sml b/release/scripts/freestyle/style_modules/extra-lines.sml new file mode 100755 index 00000000000..c63cd40945d --- /dev/null +++ b/release/scripts/freestyle/style_modules/extra-lines.sml @@ -0,0 +1,3 @@ +1suggestive.py +1ridges.py +1nor_suggestive_or_ridges.py diff --git a/release/scripts/freestyle/style_modules/freestyle_init.py b/release/scripts/freestyle/style_modules/freestyle_init.py new file mode 100644 index 00000000000..9eb8b2d6340 --- /dev/null +++ b/release/scripts/freestyle/style_modules/freestyle_init.py @@ -0,0 +1,2 @@ +from Freestyle import * +from mathutils import Vector diff --git a/release/scripts/freestyle/style_modules/haloing.py b/release/scripts/freestyle/style_modules/haloing.py new file mode 100755 index 00000000000..afa46173d54 --- /dev/null +++ b/release/scripts/freestyle/style_modules/haloing.py @@ -0,0 +1,50 @@ +# +# Filename : haloing.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : This style module selects the lines that +# are connected (in the image) to a specific +# object and trims them in order to produce +# a haloing effect around the target shape +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesU1D import * +from PredicatesB1D import * +from shaders import * + +# id corresponds to the id of the target object +# (accessed by SHIFT+click) +id = Id(3,0) +upred = AndUP1D(QuantitativeInvisibilityUP1D(0) , pyIsOccludedByUP1D(id)) +Operators.select(upred) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred)) +shaders_list = [ + IncreasingThicknessShader(3, 5), + IncreasingColorShader(1,0,0, 1,0,1,0,1), + SamplingShader(1.0), + pyTVertexRemoverShader(), + TipRemoverShader(3.0) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/ignore_small_occlusions.py b/release/scripts/freestyle/style_modules/ignore_small_occlusions.py new file mode 100755 index 00000000000..ff6efa89ade --- /dev/null +++ b/release/scripts/freestyle/style_modules/ignore_small_occlusions.py @@ -0,0 +1,41 @@ +# +# Filename : ignore_small_oclusions.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : The strokes are drawn through small occlusions +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +#Operators.bidirectionalChain(pyFillOcclusionsChainingIterator(0.1)) +Operators.bidirectionalChain(pyFillOcclusionsAbsoluteChainingIterator(12)) +shaders_list = [ + SamplingShader(5.0), + ConstantThicknessShader(3), + ConstantColorShader(0.0,0.0,0.0), + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/invisible_lines.py b/release/scripts/freestyle/style_modules/invisible_lines.py new file mode 100755 index 00000000000..ea509463bfd --- /dev/null +++ b/release/scripts/freestyle/style_modules/invisible_lines.py @@ -0,0 +1,42 @@ +# +# Filename : invisible_lines.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws all lines whose Quantitative Invisibility +# is different from 0 +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from shaders import * + +upred = NotUP1D(QuantitativeInvisibilityUP1D(0)) +Operators.select(upred) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred)) +shaders_list = [ + SamplingShader(5.0), + ConstantThicknessShader(3.0), + ConstantColorShader(0.7,0.7,0.7) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/japanese_bigbrush.py b/release/scripts/freestyle/style_modules/japanese_bigbrush.py new file mode 100755 index 00000000000..7f109598aaa --- /dev/null +++ b/release/scripts/freestyle/style_modules/japanese_bigbrush.py @@ -0,0 +1,60 @@ +# +# Filename : japanese_bigbrush.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Simulates a big brush fr oriental painting +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesU1D import * +from PredicatesB1D import * +from Functions0D import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(),NotUP1D(QuantitativeInvisibilityUP1D(0))) +## Splits strokes at points of highest 2D curavture +## when there are too many abrupt turns in it +func = pyInverseCurvature2DAngleF0D() +Operators.recursiveSplit(func, pyParameterUP0D(0.2,0.8), NotUP1D(pyHigherNumberOfTurnsUP1D(3, 0.5)), 2) +## Keeps only long enough strokes +Operators.select(pyHigherLengthUP1D(100)) +## Sorts so as to draw the longest strokes first +## (this will be done using the causal density) +Operators.sort(pyLengthBP1D()) +shaders_list = [ + pySamplingShader(10), + BezierCurveShader(30), + SamplingShader(50), + ConstantThicknessShader(10), + pyNonLinearVaryingThicknessShader(4,25, 0.6), + TextureAssignerShader(6), + ConstantColorShader(0.2, 0.2, 0.2,1.0), + TipRemoverShader(10) + ] + +## Use the causal density to avoid cluttering +Operators.create(pyDensityUP1D(8,0.4, IntegrationType.MEAN), shaders_list) + + diff --git a/release/scripts/freestyle/style_modules/logical_operators.py b/release/scripts/freestyle/style_modules/logical_operators.py new file mode 100755 index 00000000000..0ecf6623697 --- /dev/null +++ b/release/scripts/freestyle/style_modules/logical_operators.py @@ -0,0 +1,36 @@ +from freestyle_init import * + +class AndUP1D(UnaryPredicate1D): + def __init__(self, pred1, pred2): + UnaryPredicate1D.__init__(self) + self.__pred1 = pred1 + self.__pred2 = pred2 + + def getName(self): + return "AndUP1D" + + def __call__(self, inter): + return self.__pred1(inter) and self.__pred2(inter) + +class OrUP1D(UnaryPredicate1D): + def __init__(self, pred1, pred2): + UnaryPredicate1D.__init__(self) + self.__pred1 = pred1 + self.__pred2 = pred2 + + def getName(self): + return "OrUP1D" + + def __call__(self, inter): + return self.__pred1(inter) or self.__pred2(inter) + +class NotUP1D(UnaryPredicate1D): + def __init__(self, pred): + UnaryPredicate1D.__init__(self) + self.__pred = pred + + def getName(self): + return "NotUP1D" + + def __call__(self, inter): + return self.__pred(inter) == 0 diff --git a/release/scripts/freestyle/style_modules/long_anisotropically_dense.py b/release/scripts/freestyle/style_modules/long_anisotropically_dense.py new file mode 100755 index 00000000000..155ee489680 --- /dev/null +++ b/release/scripts/freestyle/style_modules/long_anisotropically_dense.py @@ -0,0 +1,81 @@ +# +# Filename : long_anisotropically_dense.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Selects the lines that are long and have a high anisotropic +# a priori density and uses causal density +# to draw without cluttering. Ideally, half of the +# selected lines are culled using the causal density. +# +# ********************* WARNING ************************************* +# ******** The Directional a priori density maps must ****** +# ******** have been computed prior to using this style module ****** +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesU1D import * +from PredicatesU0D import * +from PredicatesB1D import * +from Functions0D import * +from Functions1D import * +from shaders import * + +## custom density predicate +class pyDensityUP1D(UnaryPredicate1D): + def __init__(self,wsize,threshold, integration = IntegrationType.MEAN, sampling=2.0): + UnaryPredicate1D.__init__(self) + self._wsize = wsize + self._threshold = threshold + self._integration = integration + self._func = DensityF1D(self._wsize, self._integration, sampling) + self._func2 = DensityF1D(self._wsize, IntegrationType.MAX, sampling) + + def getName(self): + return "pyDensityUP1D" + + def __call__(self, inter): + c = self._func(inter) + m = self._func2(inter) + if(c < self._threshold): + return 1 + if( m > 4* c ): + if ( c < 1.5*self._threshold ): + return 1 + return 0 + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(),NotUP1D(QuantitativeInvisibilityUP1D(0))) +Operators.select(pyHigherLengthUP1D(40)) +## selects lines having a high anisotropic a priori density +Operators.select(pyHighDensityAnisotropyUP1D(0.3,4)) +Operators.sort(pyLengthBP1D()) +shaders_list = [ + SamplingShader(2.0), + ConstantThicknessShader(2), + ConstantColorShader(0.2,0.2,0.25,1), + ] +## uniform culling +Operators.create(pyDensityUP1D(3.0,2.0e-2, IntegrationType.MEAN, 0.1), shaders_list) + + diff --git a/release/scripts/freestyle/style_modules/multiple_parameterization.py b/release/scripts/freestyle/style_modules/multiple_parameterization.py new file mode 100755 index 00000000000..3f0409db5fa --- /dev/null +++ b/release/scripts/freestyle/style_modules/multiple_parameterization.py @@ -0,0 +1,51 @@ +# +# Filename : multiple_parameterization.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : The thickness and the color of the strokes vary continuously +# independently from occlusions although only +# visible lines are actually drawn. This is equivalent +# to assigning the thickness using a parameterization covering +# the complete silhouette (visible+invisible) and drawing +# the strokes using a second parameterization that only +# covers the visible portions. +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +## Chain following the same nature, but without the restriction +## of staying inside the selection (0). +Operators.bidirectionalChain(ChainSilhouetteIterator(0)) +shaders_list = [ + SamplingShader(20), + IncreasingThicknessShader(1.5, 30), + ConstantColorShader(0.0,0.0,0.0), + IncreasingColorShader(1,0,0,1,0,1,0,1), + TextureAssignerShader(-1), + pyHLRShader() ## this shader draws only visible portions + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/nature.py b/release/scripts/freestyle/style_modules/nature.py new file mode 100755 index 00000000000..b5481a8e519 --- /dev/null +++ b/release/scripts/freestyle/style_modules/nature.py @@ -0,0 +1,43 @@ +# +# Filename : nature.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Uses the NatureUP1D predicate to select the lines +# of a given type (among Nature.SILHOUETTE, Nature.CREASE, Nature.SUGGESTIVE_CONTOURS, +# Nature.BORDERS). +# The suggestive contours must have been enabled in the +# options dialog to appear in the View Map. +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from shaders import * + +Operators.select(pyNatureUP1D(Nature.SILHOUETTE)) +Operators.bidirectionalChain(ChainSilhouetteIterator(),NotUP1D( pyNatureUP1D( Nature.SILHOUETTE) ) ) +shaders_list = [ + IncreasingThicknessShader(3, 10), + IncreasingColorShader(0.0,0.0,0.0, 1, 0.8,0,0,1) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/near_lines.py b/release/scripts/freestyle/style_modules/near_lines.py new file mode 100755 index 00000000000..565bca1fe1f --- /dev/null +++ b/release/scripts/freestyle/style_modules/near_lines.py @@ -0,0 +1,44 @@ +# +# Filename : near_lines.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws the lines that are "closer" than a threshold +# (between 0 and 1) +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from PredicatesU1D import * +from shaders import * + +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), pyZSmallerUP1D(0.5, IntegrationType.MEAN)) +Operators.select(upred) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred)) +shaders_list = [ + TextureAssignerShader(-1), + ConstantThicknessShader(5), + ConstantColorShader(0.0, 0.0, 0.0) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/occluded_by_specific_object.py b/release/scripts/freestyle/style_modules/occluded_by_specific_object.py new file mode 100755 index 00000000000..09ce39d5dd6 --- /dev/null +++ b/release/scripts/freestyle/style_modules/occluded_by_specific_object.py @@ -0,0 +1,45 @@ +# +# Filename : occluded_by_specific_object.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws only the lines that are occluded by a given object +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesU1D import * +from shaders import * + +## the id of the occluder (use SHIFT+click on the ViewMap to +## retrieve ids) +id = Id(3,0) +upred = AndUP1D(NotUP1D(QuantitativeInvisibilityUP1D(0)), +pyIsInOccludersListUP1D(id)) +Operators.select(upred) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred)) +shaders_list = [ + SamplingShader(5), + ConstantThicknessShader(3), + ConstantColorShader(0.3,0.3,0.3,1) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/polygonalize.py b/release/scripts/freestyle/style_modules/polygonalize.py new file mode 100755 index 00000000000..4446c4c1dcc --- /dev/null +++ b/release/scripts/freestyle/style_modules/polygonalize.py @@ -0,0 +1,40 @@ +# +# Filename : polygonalize.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Make the strokes more "polygonal" +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(),NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + SamplingShader(2.0), + ConstantThicknessShader(3), + ConstantColorShader(0.0,0.0,0.0), + PolygonalizationShader(8) + ] +Operators.create(TrueUP1D(), shaders_list)
\ No newline at end of file diff --git a/release/scripts/freestyle/style_modules/qi0.py b/release/scripts/freestyle/style_modules/qi0.py new file mode 100755 index 00000000000..d35d23cb7c3 --- /dev/null +++ b/release/scripts/freestyle/style_modules/qi0.py @@ -0,0 +1,41 @@ +# +# Filename : qi0.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws the visible lines (chaining follows same nature lines) +# (most basic style module) +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + SamplingShader(5.0), + ConstantThicknessShader(4.0), + ConstantColorShader(0.0,0.0,0.0) + ] +Operators.create(TrueUP1D(), shaders_list)
\ No newline at end of file diff --git a/release/scripts/freestyle/style_modules/qi0_not_external_contour.py b/release/scripts/freestyle/style_modules/qi0_not_external_contour.py new file mode 100755 index 00000000000..eed41af32b4 --- /dev/null +++ b/release/scripts/freestyle/style_modules/qi0_not_external_contour.py @@ -0,0 +1,43 @@ +# +# Filename : qi0_not_external_contour.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws the visible lines (chaining follows same nature lines) +# that do not belong to the external contour of the scene +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * + +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D()) +Operators.select(upred) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred)) +shaders_list = [ + SamplingShader(4), + SpatialNoiseShader(4, 150, 2, True, True), + IncreasingThicknessShader(2, 5), + BackboneStretcherShader(20), + IncreasingColorShader(1,0,0,1,0,1,0,1), + TextureAssignerShader(4) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/qi1.py b/release/scripts/freestyle/style_modules/qi1.py new file mode 100755 index 00000000000..8d248376138 --- /dev/null +++ b/release/scripts/freestyle/style_modules/qi1.py @@ -0,0 +1,42 @@ +# +# Filename : qi1.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws lines hidden by one surface. +# *** Quantitative Invisibility must have been +# enabled in the options dialog to use this style module **** +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(1)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(1))) +shaders_list = [ + SamplingShader(5.0), + ConstantThicknessShader(3), + ConstantColorShader(0.5,0.5,0.5, 1) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/qi2.py b/release/scripts/freestyle/style_modules/qi2.py new file mode 100755 index 00000000000..ba5e97b6982 --- /dev/null +++ b/release/scripts/freestyle/style_modules/qi2.py @@ -0,0 +1,42 @@ +# +# Filename : qi2.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws lines hidden by two surfaces. +# *** Quantitative Invisibility must have been +# enabled in the options dialog to use this style module **** +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(2)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(2))) +shaders_list = [ + SamplingShader(10), + ConstantThicknessShader(1.5), + ConstantColorShader(0.7,0.7,0.7, 1) + ] +Operators.create(TrueUP1D(), shaders_list)
\ No newline at end of file diff --git a/release/scripts/freestyle/style_modules/sequentialsplit_sketchy.py b/release/scripts/freestyle/style_modules/sequentialsplit_sketchy.py new file mode 100755 index 00000000000..53fa03103aa --- /dev/null +++ b/release/scripts/freestyle/style_modules/sequentialsplit_sketchy.py @@ -0,0 +1,68 @@ +# +# Filename : sequentialsplit_sketchy.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Use the sequential split with two different +# predicates to specify respectively the starting and +# the stopping extremities for strokes +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesU1D import * +from PredicatesU0D import * +from Functions0D import * + +## Predicate to tell whether a TVertex +## corresponds to a change from 0 to 1 or not. +class pyBackTVertexUP0D(UnaryPredicate0D): + def __init__(self): + UnaryPredicate0D.__init__(self) + self._getQI = QuantitativeInvisibilityF0D() + def getName(self): + return "pyBackTVertexUP0D" + def __call__(self, iter): + v = iter.getObject() + nat = v.getNature() + if(nat & Nature.T_VERTEX == 0): + return 0 + if(self._getQI(iter) != 0): + return 1 + return 0 + + +upred = QuantitativeInvisibilityUP1D(0) +Operators.select(upred) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred)) +## starting and stopping predicates: +start = pyVertexNatureUP0D(Nature.NON_T_VERTEX) +stop = pyBackTVertexUP0D() +Operators.sequentialSplit(start, stop, 10) +shaders_list = [ + SpatialNoiseShader(7, 120, 2, True, True), + IncreasingThicknessShader(5, 8), + ConstantColorShader(0.2, 0.2, 0.2, 1), + TextureAssignerShader(4) + ] +Operators.create(TrueUP1D(), shaders_list) + diff --git a/release/scripts/freestyle/style_modules/shaders.py b/release/scripts/freestyle/style_modules/shaders.py new file mode 100755 index 00000000000..4d8ddeb0ce8 --- /dev/null +++ b/release/scripts/freestyle/style_modules/shaders.py @@ -0,0 +1,1291 @@ +from freestyle_init import * +from PredicatesU0D import * +from PredicatesB1D import * +from PredicatesU1D import * +from logical_operators import * +from ChainingIterators import * +from random import * +from math import * + +## thickness modifiers +###################### + +class pyDepthDiscontinuityThicknessShader(StrokeShader): + def __init__(self, min, max): + StrokeShader.__init__(self) + self.__min = float(min) + self.__max = float(max) + self.__func = ZDiscontinuityF0D() + def getName(self): + return "pyDepthDiscontinuityThicknessShader" + def shade(self, stroke): + it = stroke.strokeVerticesBegin() + z_min=0.0 + z_max=1.0 + a = (self.__max - self.__min)/(z_max-z_min) + b = (self.__min*z_max-self.__max*z_min)/(z_max-z_min) + it = stroke.strokeVerticesBegin() + while it.isEnd() == 0: + z = self.__func(it.castToInterface0DIterator()) + thickness = a*z+b + it.getObject().attribute().setThickness(thickness, thickness) + it.increment() + +class pyConstantThicknessShader(StrokeShader): + def __init__(self, thickness): + StrokeShader.__init__(self) + self._thickness = thickness + + def getName(self): + return "pyConstantThicknessShader" + def shade(self, stroke): + it = stroke.strokeVerticesBegin() + it_end = stroke.strokeVerticesEnd() + while it.isEnd() == 0: + att = it.getObject().attribute() + t = self._thickness/2.0 + att.setThickness(t, t) + it.increment() + +class pyFXSThicknessShader(StrokeShader): + def __init__(self, thickness): + StrokeShader.__init__(self) + self._thickness = thickness + + def getName(self): + return "pyFXSThicknessShader" + def shade(self, stroke): + it = stroke.strokeVerticesBegin() + it_end = stroke.strokeVerticesEnd() + while it.isEnd() == 0: + att = it.getObject().attribute() + t = self._thickness/2.0 + att.setThickness(t, t) + it.increment() + +class pyFXSVaryingThicknessWithDensityShader(StrokeShader): + def __init__(self, wsize, threshold_min, threshold_max, thicknessMin, thicknessMax): + StrokeShader.__init__(self) + self.wsize= wsize + self.threshold_min= threshold_min + self.threshold_max= threshold_max + self._thicknessMin = thicknessMin + self._thicknessMax = thicknessMax + + def getName(self): + return "pyVaryingThicknessWithDensityShader" + def shade(self, stroke): + n = stroke.strokeVerticesSize() + i = 0 + it = stroke.strokeVerticesBegin() + it_end = stroke.strokeVerticesEnd() + func = DensityF0D(self.wsize) + while it.isEnd() == 0: + att = it.getObject().attribute() + toto = it.castToInterface0DIterator() + c= func(toto) + if (c < self.threshold_min ): + c = self.threshold_min + if (c > self.threshold_max ): + c = self.threshold_max +## t = (c - self.threshold_min)/(self.threshold_max - self.threshold_min)*(self._thicknessMax-self._thicknessMin) + self._thicknessMin + t = (self.threshold_max - c )/(self.threshold_max - self.threshold_min)*(self._thicknessMax-self._thicknessMin) + self._thicknessMin + att.setThickness(t/2.0, t/2.0) + i = i+1 + it.increment() +class pyIncreasingThicknessShader(StrokeShader): + def __init__(self, thicknessMin, thicknessMax): + StrokeShader.__init__(self) + self._thicknessMin = thicknessMin + self._thicknessMax = thicknessMax + + def getName(self): + return "pyIncreasingThicknessShader" + def shade(self, stroke): + n = stroke.strokeVerticesSize() + i = 0 + it = stroke.strokeVerticesBegin() + it_end = stroke.strokeVerticesEnd() + while it.isEnd() == 0: + att = it.getObject().attribute() + c = float(i)/float(n) + if(i < float(n)/2.0): + t = (1.0 - c)*self._thicknessMin + c * self._thicknessMax + else: + t = (1.0 - c)*self._thicknessMax + c * self._thicknessMin + att.setThickness(t/2.0, t/2.0) + i = i+1 + it.increment() + +class pyConstrainedIncreasingThicknessShader(StrokeShader): + def __init__(self, thicknessMin, thicknessMax, ratio): + StrokeShader.__init__(self) + self._thicknessMin = thicknessMin + self._thicknessMax = thicknessMax + self._ratio = ratio + + def getName(self): + return "pyConstrainedIncreasingThicknessShader" + def shade(self, stroke): + slength = stroke.getLength2D() + tmp = self._ratio*slength + maxT = 0.0 + if(tmp < self._thicknessMax): + maxT = tmp + else: + maxT = self._thicknessMax + n = stroke.strokeVerticesSize() + i = 0 + it = stroke.strokeVerticesBegin() + it_end = stroke.strokeVerticesEnd() + while it.isEnd() == 0: + att = it.getObject().attribute() + c = float(i)/float(n) + if(i < float(n)/2.0): + t = (1.0 - c)*self._thicknessMin + c * maxT + else: + t = (1.0 - c)*maxT + c * self._thicknessMin + att.setThickness(t/2.0, t/2.0) + if(i == n-1): + att.setThickness(self._thicknessMin/2.0, self._thicknessMin/2.0) + i = i+1 + it.increment() + +class pyDecreasingThicknessShader(StrokeShader): + def __init__(self, thicknessMax, thicknessMin): + StrokeShader.__init__(self) + self._thicknessMin = thicknessMin + self._thicknessMax = thicknessMax + + def getName(self): + return "pyDecreasingThicknessShader" + def shade(self, stroke): + l = stroke.getLength2D() + tMax = self._thicknessMax + if(self._thicknessMax > 0.33*l): + tMax = 0.33*l + tMin = self._thicknessMin + if(self._thicknessMin > 0.1*l): + tMin = 0.1*l + n = stroke.strokeVerticesSize() + i = 0 + it = stroke.strokeVerticesBegin() + it_end = stroke.strokeVerticesEnd() + while it.isEnd() == 0: + att = it.getObject().attribute() + c = float(i)/float(n) + t = (1.0 - c)*tMax +c*tMin + att.setThickness(t/2.0, t/2.0) + i = i+1 + it.increment() + +def smoothC( a, exp ): + c = pow(float(a),exp)*pow(2.0,exp) + return c + +class pyNonLinearVaryingThicknessShader(StrokeShader): + def __init__(self, thicknessExtremity, thicknessMiddle, exponent): + StrokeShader.__init__(self) + self._thicknessMin = thicknessMiddle + self._thicknessMax = thicknessExtremity + self._exponent = exponent + + def getName(self): + return "pyNonLinearVaryingThicknessShader" + def shade(self, stroke): + n = stroke.strokeVerticesSize() + i = 0 + it = stroke.strokeVerticesBegin() + it_end = stroke.strokeVerticesEnd() + while it.isEnd() == 0: + att = it.getObject().attribute() + if(i < float(n)/2.0): + c = float(i)/float(n) + else: + c = float(n-i)/float(n) + c = smoothC(c, self._exponent) + t = (1.0 - c)*self._thicknessMax + c * self._thicknessMin + att.setThickness(t/2.0, t/2.0) + i = i+1 + it.increment() + +## Spherical linear interpolation (cos) +class pySLERPThicknessShader(StrokeShader): + def __init__(self, thicknessMin, thicknessMax, omega=1.2): + StrokeShader.__init__(self) + self._thicknessMin = thicknessMin + self._thicknessMax = thicknessMax + self._omega = omega + + def getName(self): + return "pySLERPThicknessShader" + def shade(self, stroke): + slength = stroke.getLength2D() + tmp = 0.33*slength + maxT = self._thicknessMax + if(tmp < self._thicknessMax): + maxT = tmp + + n = stroke.strokeVerticesSize() + i = 0 + it = stroke.strokeVerticesBegin() + it_end = stroke.strokeVerticesEnd() + while it.isEnd() == 0: + att = it.getObject().attribute() + c = float(i)/float(n) + if(i < float(n)/2.0): + t = sin((1-c)*self._omega)/sinh(self._omega)*self._thicknessMin + sin(c*self._omega)/sinh(self._omega) * maxT + else: + t = sin((1-c)*self._omega)/sinh(self._omega)*maxT + sin(c*self._omega)/sinh(self._omega) * self._thicknessMin + att.setThickness(t/2.0, t/2.0) + i = i+1 + it.increment() + +class pyTVertexThickenerShader(StrokeShader): ## FIXME + def __init__(self, a=1.5, n=3): + StrokeShader.__init__(self) + self._a = a + self._n = n + + def getName(self): + return "pyTVertexThickenerShader" + + def shade(self, stroke): + it = stroke.strokeVerticesBegin() + predTVertex = pyVertexNatureUP0D(Nature.T_VERTEX) + while it.isEnd() == 0: + if(predTVertex(it) == 1): + it2 = StrokeVertexIterator(it) + it2.increment() + if not(it.isBegin() or it2.isEnd()): + it.increment() + continue + n = self._n + a = self._a + if(it.isBegin()): + it3 = StrokeVertexIterator(it) + count = 0 + while (it3.isEnd() == 0 and count < n): + att = it3.getObject().attribute() + tr = att.getThicknessR(); + tl = att.getThicknessL(); + r = (a-1.0)/float(n-1)*(float(n)/float(count+1) - 1) + 1 + #r = (1.0-a)/float(n-1)*count + a + att.setThickness(r*tr, r*tl) + it3.increment() + count = count + 1 + if(it2.isEnd()): + it4 = StrokeVertexIterator(it) + count = 0 + while (it4.isBegin() == 0 and count < n): + att = it4.getObject().attribute() + tr = att.getThicknessR(); + tl = att.getThicknessL(); + r = (a-1.0)/float(n-1)*(float(n)/float(count+1) - 1) + 1 + #r = (1.0-a)/float(n-1)*count + a + att.setThickness(r*tr, r*tl) + it4.decrement() + count = count + 1 + if ((it4.isBegin() == 1)): + att = it4.getObject().attribute() + tr = att.getThicknessR(); + tl = att.getThicknessL(); + r = (a-1.0)/float(n-1)*(float(n)/float(count+1) - 1) + 1 + #r = (1.0-a)/float(n-1)*count + a + att.setThickness(r*tr, r*tl) + it.increment() + +class pyImportance2DThicknessShader(StrokeShader): + def __init__(self, x, y, w, kmin, kmax): + StrokeShader.__init__(self) + self._x = x + self._y = y + self._w = float(w) + self._kmin = float(kmin) + self._kmax = float(kmax) + + def getName(self): + return "pyImportanceThicknessShader" + def shade(self, stroke): + origin = Vector([self._x, self._y]) + it = stroke.strokeVerticesBegin() + while it.isEnd() == 0: + v = it.getObject() + p = Vector([v.getProjectedX(), v.getProjectedY()]) + d = (p-origin).length + if(d>self._w): + k = self._kmin + else: + k = (self._kmax*(self._w-d) + self._kmin*d)/self._w + att = v.attribute() + tr = att.getThicknessR() + tl = att.getThicknessL() + att.setThickness(k*tr/2.0, k*tl/2.0) + it.increment() + +class pyImportance3DThicknessShader(StrokeShader): + def __init__(self, x, y, z, w, kmin, kmax): + StrokeShader.__init__(self) + self._x = x + self._y = y + self._z = z + self._w = float(w) + self._kmin = float(kmin) + self._kmax = float(kmax) + + def getName(self): + return "pyImportance3DThicknessShader" + def shade(self, stroke): + origin = Vector([self._x, self._y, self._z]) + it = stroke.strokeVerticesBegin() + while it.isEnd() == 0: + v = it.getObject() + p = Vector([v.getX(), v.getY(), v.getZ()]) + d = (p-origin).length + if(d>self._w): + k = self._kmin + else: + k = (self._kmax*(self._w-d) + self._kmin*d)/self._w + att = v.attribute() + tr = att.getThicknessR() + tl = att.getThicknessL() + att.setThickness(k*tr/2.0, k*tl/2.0) + it.increment() + +class pyZDependingThicknessShader(StrokeShader): + def __init__(self, min, max): + StrokeShader.__init__(self) + self.__min = min + self.__max = max + self.__func = GetProjectedZF0D() + def getName(self): + return "pyZDependingThicknessShader" + def shade(self, stroke): + it = stroke.strokeVerticesBegin() + z_min = 1 + z_max = 0 + while it.isEnd() == 0: + z = self.__func(it.castToInterface0DIterator()) + if z < z_min: + z_min = z + if z > z_max: + z_max = z + it.increment() + z_diff = 1 / (z_max - z_min) + it = stroke.strokeVerticesBegin() + while it.isEnd() == 0: + z = (self.__func(it.castToInterface0DIterator()) - z_min) * z_diff + thickness = (1 - z) * self.__max + z * self.__min + it.getObject().attribute().setThickness(thickness, thickness) + it.increment() + + +## color modifiers +################## + +class pyConstantColorShader(StrokeShader): + def __init__(self,r,g,b, a = 1): + StrokeShader.__init__(self) + self._r = r + self._g = g + self._b = b + self._a = a + def getName(self): + return "pyConstantColorShader" + def shade(self, stroke): + it = stroke.strokeVerticesBegin() + it_end = stroke.strokeVerticesEnd() + while it.isEnd() == 0: + att = it.getObject().attribute() + att.setColor(self._r, self._g, self._b) + att.setAlpha(self._a) + it.increment() + +#c1->c2 +class pyIncreasingColorShader(StrokeShader): + def __init__(self,r1,g1,b1,a1, r2,g2,b2,a2): + StrokeShader.__init__(self) + self._c1 = [r1,g1,b1,a1] + self._c2 = [r2,g2,b2,a2] + def getName(self): + return "pyIncreasingColorShader" + def shade(self, stroke): + n = stroke.strokeVerticesSize() - 1 + inc = 0 + it = stroke.strokeVerticesBegin() + it_end = stroke.strokeVerticesEnd() + while it.isEnd() == 0: + att = it.getObject().attribute() + c = float(inc)/float(n) + + att.setColor( (1-c)*self._c1[0] + c*self._c2[0], + (1-c)*self._c1[1] + c*self._c2[1], + (1-c)*self._c1[2] + c*self._c2[2],) + att.setAlpha((1-c)*self._c1[3] + c*self._c2[3],) + inc = inc+1 + it.increment() + +# c1->c2->c1 +class pyInterpolateColorShader(StrokeShader): + def __init__(self,r1,g1,b1,a1, r2,g2,b2,a2): + StrokeShader.__init__(self) + self._c1 = [r1,g1,b1,a1] + self._c2 = [r2,g2,b2,a2] + def getName(self): + return "pyInterpolateColorShader" + def shade(self, stroke): + n = stroke.strokeVerticesSize() - 1 + inc = 0 + it = stroke.strokeVerticesBegin() + it_end = stroke.strokeVerticesEnd() + while it.isEnd() == 0: + att = it.getObject().attribute() + u = float(inc)/float(n) + c = 1-2*(fabs(u-0.5)) + att.setColor( (1-c)*self._c1[0] + c*self._c2[0], + (1-c)*self._c1[1] + c*self._c2[1], + (1-c)*self._c1[2] + c*self._c2[2],) + att.setAlpha((1-c)*self._c1[3] + c*self._c2[3],) + inc = inc+1 + it.increment() + +class pyMaterialColorShader(StrokeShader): + def __init__(self, threshold=50): + StrokeShader.__init__(self) + self._threshold = threshold + + def getName(self): + return "pyMaterialColorShader" + + def shade(self, stroke): + it = stroke.strokeVerticesBegin() + it_end = stroke.strokeVerticesEnd() + func = MaterialF0D() + xn = 0.312713 + yn = 0.329016 + Yn = 1.0 + un = 4.* xn/ ( -2.*xn + 12.*yn + 3. ) + vn= 9.* yn/ ( -2.*xn + 12.*yn +3. ) + while it.isEnd() == 0: + toto = it.castToInterface0DIterator() + mat = func(toto) + + r = mat.diffuseR() + g = mat.diffuseG() + b = mat.diffuseB() + + X = 0.412453*r + 0.35758 *g + 0.180423*b + Y = 0.212671*r + 0.71516 *g + 0.072169*b + Z = 0.019334*r + 0.119193*g + 0.950227*b + + if((X == 0) and (Y == 0) and (Z == 0)): + X = 0.01 + Y = 0.01 + Z = 0.01 + u = 4.*X / (X + 15.*Y + 3.*Z) + v = 9.*Y / (X + 15.*Y + 3.*Z) + + L= 116. * pow((Y/Yn),(1./3.)) -16 + U = 13. * L * (u - un) + V = 13. * L * (v - vn) + + if (L > self._threshold): + L = L/1.3 + U = U+10 + else: + L = L +2.5*(100-L)/5. + U = U/3.0 + V = V/3.0 + u = U / (13. * L) + un + v = V / (13. * L) + vn + + Y = Yn * pow( ((L+16.)/116.), 3.) + X = -9. * Y * u / ((u - 4.)* v - u * v) + Z = (9. * Y - 15*v*Y - v*X) /( 3. * v) + + r = 3.240479 * X - 1.53715 * Y - 0.498535 * Z + g = -0.969256 * X + 1.875991 * Y + 0.041556 * Z + b = 0.055648 * X - 0.204043 * Y + 1.057311 * Z + + r = max(0,r) + g = max(0,g) + b = max(0,b) + + att = it.getObject().attribute() + att.setColor(r, g, b) + it.increment() + +class pyRandomColorShader(StrokeShader): + def getName(self): + return "pyRandomColorShader" + def __init__(self, s=1): + StrokeShader.__init__(self) + seed(s) + def shade(self, stroke): + ## pick a random color + c0 = float(uniform(15,75))/100.0 + c1 = float(uniform(15,75))/100.0 + c2 = float(uniform(15,75))/100.0 + print(c0, c1, c2) + it = stroke.strokeVerticesBegin() + while(it.isEnd() == 0): + it.getObject().attribute().setColor(c0,c1,c2) + it.increment() + +class py2DCurvatureColorShader(StrokeShader): + def getName(self): + return "py2DCurvatureColorShader" + + def shade(self, stroke): + it = stroke.strokeVerticesBegin() + it_end = stroke.strokeVerticesEnd() + func = Curvature2DAngleF0D() + while it.isEnd() == 0: + toto = it.castToInterface0DIterator() + sv = it.getObject() + att = sv.attribute() + c = func(toto) + if (c<0): + print("negative 2D curvature") + color = 10.0 * c/3.1415 + print(color) + att.setColor(color,color,color); + it.increment() + +class pyTimeColorShader(StrokeShader): + def __init__(self, step=0.01): + StrokeShader.__init__(self) + self._t = 0 + self._step = step + def shade(self, stroke): + c = self._t*1.0 + it = stroke.strokeVerticesBegin() + it_end = stroke.strokeVerticesEnd() + while it.isEnd() == 0: + att = it.getObject().attribute() + att.setColor(c,c,c) + it.increment() + self._t = self._t+self._step + +## geometry modifiers + +class pySamplingShader(StrokeShader): + def __init__(self, sampling): + StrokeShader.__init__(self) + self._sampling = sampling + def getName(self): + return "pySamplingShader" + def shade(self, stroke): + stroke.Resample(float(self._sampling)) + +class pyBackboneStretcherShader(StrokeShader): + def __init__(self, l): + StrokeShader.__init__(self) + self._l = l + def getName(self): + return "pyBackboneStretcherShader" + def shade(self, stroke): + it0 = stroke.strokeVerticesBegin() + it1 = StrokeVertexIterator(it0) + it1.increment() + itn = stroke.strokeVerticesEnd() + itn.decrement() + itn_1 = StrokeVertexIterator(itn) + itn_1.decrement() + v0 = it0.getObject() + v1 = it1.getObject() + vn_1 = itn_1.getObject() + vn = itn.getObject() + p0 = Vector([v0.getProjectedX(), v0.getProjectedY()]) + pn = Vector([vn.getProjectedX(), vn.getProjectedY()]) + p1 = Vector([v1.getProjectedX(), v1.getProjectedY()]) + pn_1 = Vector([vn_1.getProjectedX(), vn_1.getProjectedY()]) + d1 = p0-p1 + d1.normalize() + dn = pn-pn_1 + dn.normalize() + newFirst = p0+d1*float(self._l) + newLast = pn+dn*float(self._l) + v0.setPoint(newFirst) + vn.setPoint(newLast) + +class pyLengthDependingBackboneStretcherShader(StrokeShader): + def __init__(self, l): + StrokeShader.__init__(self) + self._l = l + def getName(self): + return "pyBackboneStretcherShader" + def shade(self, stroke): + l = stroke.getLength2D() + stretch = self._l*l + it0 = stroke.strokeVerticesBegin() + it1 = StrokeVertexIterator(it0) + it1.increment() + itn = stroke.strokeVerticesEnd() + itn.decrement() + itn_1 = StrokeVertexIterator(itn) + itn_1.decrement() + v0 = it0.getObject() + v1 = it1.getObject() + vn_1 = itn_1.getObject() + vn = itn.getObject() + p0 = Vector([v0.getProjectedX(), v0.getProjectedY()]) + pn = Vector([vn.getProjectedX(), vn.getProjectedY()]) + p1 = Vector([v1.getProjectedX(), v1.getProjectedY()]) + pn_1 = Vector([vn_1.getProjectedX(), vn_1.getProjectedY()]) + d1 = p0-p1 + d1.normalize() + dn = pn-pn_1 + dn.normalize() + newFirst = p0+d1*float(stretch) + newLast = pn+dn*float(stretch) + v0.setPoint(newFirst) + vn.setPoint(newLast) + + +## Shader to replace a stroke by its corresponding tangent +class pyGuidingLineShader(StrokeShader): + def getName(self): + return "pyGuidingLineShader" + ## shading method + def shade(self, stroke): + it = stroke.strokeVerticesBegin() ## get the first vertex + itlast = stroke.strokeVerticesEnd() ## + itlast.decrement() ## get the last one + t = itlast.getObject().getPoint() - it.getObject().getPoint() ## tangent direction + itmiddle = StrokeVertexIterator(it) ## + while(itmiddle.getObject().u()<0.5): ## look for the stroke middle vertex + itmiddle.increment() ## + it = StrokeVertexIterator(itmiddle) + it.increment() + while(it.isEnd() == 0): ## position all the vertices along the tangent for the right part + it.getObject().setPoint(itmiddle.getObject().getPoint() \ + +t*(it.getObject().u()-itmiddle.getObject().u())) + it.increment() + it = StrokeVertexIterator(itmiddle) + it.decrement() + while(it.isBegin() == 0): ## position all the vertices along the tangent for the left part + it.getObject().setPoint(itmiddle.getObject().getPoint() \ + -t*(itmiddle.getObject().u()-it.getObject().u())) + it.decrement() + it.getObject().setPoint(itmiddle.getObject().getPoint()-t*(itmiddle.getObject().u())) ## first vertex + + +class pyBackboneStretcherNoCuspShader(StrokeShader): + def __init__(self, l): + StrokeShader.__init__(self) + self._l = l + def getName(self): + return "pyBackboneStretcherNoCuspShader" + def shade(self, stroke): + it0 = stroke.strokeVerticesBegin() + it1 = StrokeVertexIterator(it0) + it1.increment() + itn = stroke.strokeVerticesEnd() + itn.decrement() + itn_1 = StrokeVertexIterator(itn) + itn_1.decrement() + v0 = it0.getObject() + v1 = it1.getObject() + if((v0.getNature() & Nature.CUSP == 0) and (v1.getNature() & Nature.CUSP == 0)): + p0 = v0.getPoint() + p1 = v1.getPoint() + d1 = p0-p1 + d1.normalize() + newFirst = p0+d1*float(self._l) + v0.setPoint(newFirst) + vn_1 = itn_1.getObject() + vn = itn.getObject() + if((vn.getNature() & Nature.CUSP == 0) and (vn_1.getNature() & Nature.CUSP == 0)): + pn = vn.getPoint() + pn_1 = vn_1.getPoint() + dn = pn-pn_1 + dn.normalize() + newLast = pn+dn*float(self._l) + vn.setPoint(newLast) + +normalInfo=Normal2DF0D() +curvatureInfo=Curvature2DAngleF0D() + +def edgestopping(x, sigma): + return exp(- x*x/(2*sigma*sigma)) + +class pyDiffusion2Shader(StrokeShader): + def __init__(self, lambda1, nbIter): + StrokeShader.__init__(self) + self._lambda = lambda1 + self._nbIter = nbIter + self._normalInfo = Normal2DF0D() + self._curvatureInfo = Curvature2DAngleF0D() + def getName(self): + return "pyDiffusionShader" + def shade(self, stroke): + for i in range (1, self._nbIter): + it = stroke.strokeVerticesBegin() + while it.isEnd() == 0: + v=it.getObject() + p1 = v.getPoint() + p2 = self._normalInfo(it.castToInterface0DIterator())*self._lambda*self._curvatureInfo(it.castToInterface0DIterator()) + v.setPoint(p1+p2) + it.increment() + +class pyTipRemoverShader(StrokeShader): + def __init__(self, l): + StrokeShader.__init__(self) + self._l = l + def getName(self): + return "pyTipRemoverShader" + def shade(self, stroke): + originalSize = stroke.strokeVerticesSize() + if(originalSize<4): + return + verticesToRemove = [] + oldAttributes = [] + it = stroke.strokeVerticesBegin() + while(it.isEnd() == 0): + v = it.getObject() + if((v.curvilinearAbscissa() < self._l) or (v.strokeLength()-v.curvilinearAbscissa() < self._l)): + verticesToRemove.append(v) + oldAttributes.append(StrokeAttribute(v.attribute())) + it.increment() + if(originalSize-len(verticesToRemove) < 2): + return + for sv in verticesToRemove: + stroke.RemoveVertex(sv) + stroke.Resample(originalSize) + if(stroke.strokeVerticesSize() != originalSize): + print("pyTipRemover: Warning: resampling problem") + it = stroke.strokeVerticesBegin() + for a in oldAttributes: + if(it.isEnd() == 1): + break + v = it.getObject() + v.setAttribute(a) + it.increment() + +class pyTVertexRemoverShader(StrokeShader): + def getName(self): + return "pyTVertexRemoverShader" + def shade(self, stroke): + if(stroke.strokeVerticesSize() <= 3 ): + return + predTVertex = pyVertexNatureUP0D(Nature.T_VERTEX) + it = stroke.strokeVerticesBegin() + itlast = stroke.strokeVerticesEnd() + itlast.decrement() + if(predTVertex(it) == 1): + stroke.RemoveVertex(it.getObject()) + if(predTVertex(itlast) == 1): + stroke.RemoveVertex(itlast.getObject()) + +class pyExtremitiesOrientationShader(StrokeShader): + def __init__(self, x1,y1,x2=0,y2=0): + StrokeShader.__init__(self) + self._v1 = Vector([x1,y1]) + self._v2 = Vector([x2,y2]) + def getName(self): + return "pyExtremitiesOrientationShader" + def shade(self, stroke): + print(self._v1.x,self._v1.y) + stroke.setBeginningOrientation(self._v1.x,self._v1.y) + stroke.setEndingOrientation(self._v2.x,self._v2.y) + +def getFEdge(it1, it2): + return it1.getFEdge(it2) + +class pyHLRShader(StrokeShader): + def getName(self): + return "pyHLRShader" + def shade(self, stroke): + originalSize = stroke.strokeVerticesSize() + if(originalSize<4): + return + it = stroke.strokeVerticesBegin() + invisible = 0 + it2 = StrokeVertexIterator(it) + it2.increment() + fe = getFEdge(it.getObject(), it2.getObject()) + if(fe.viewedge().qi() != 0): + invisible = 1 + while(it2.isEnd() == 0): + v = it.getObject() + vnext = it2.getObject() + if(v.getNature() & Nature.VIEW_VERTEX): + #if(v.getNature() & Nature.T_VERTEX): + fe = getFEdge(v,vnext) + qi = fe.viewedge().qi() + if(qi != 0): + invisible = 1 + else: + invisible = 0 + if(invisible == 1): + v.attribute().setVisible(0) + it.increment() + it2.increment() + +class pyTVertexOrientationShader(StrokeShader): + def __init__(self): + StrokeShader.__init__(self) + self._Get2dDirection = Orientation2DF1D() + def getName(self): + return "pyTVertexOrientationShader" + ## finds the TVertex orientation from the TVertex and + ## the previous or next edge + def findOrientation(self, tv, ve): + mateVE = tv.mate(ve) + if((ve.qi() != 0) or (mateVE.qi() != 0)): + ait = AdjacencyIterator(tv,1,0) + winner = None + incoming = 1 + while(ait.isEnd() == 0): + ave = ait.getObject() + if((ave.getId() != ve.getId()) and (ave.getId() != mateVE.getId())): + winner = ait.getObject() + if(ait.isIncoming() == 0): + incoming = 0 + break + ait.increment() + if(winner != None): + if(incoming != 0): + direction = self._Get2dDirection(winner.fedgeB()) + else: + direction = self._Get2dDirection(winner.fedgeA()) + return direction + def shade(self, stroke): + it = stroke.strokeVerticesBegin() + it2 = StrokeVertexIterator(it) + it2.increment() + ## case where the first vertex is a TVertex + v = it.getObject() + if(v.getNature() & Nature.T_VERTEX): + tv = v.castToTVertex() + ve = getFEdge(v, it2.getObject()).viewedge() + if(tv != None): + dir = self.findOrientation(tv, ve) + #print(dir.x, dir.y) + v.attribute().setAttributeVec2f("orientation", dir) + while(it2.isEnd() == 0): + vprevious = it.getObject() + v = it2.getObject() + if(v.getNature() & Nature.T_VERTEX): + tv = v.castToTVertex() + ve = getFEdge(vprevious, v).viewedge() + if(tv != None): + dir = self.findOrientation(tv, ve) + #print(dir.x, dir.y) + v.attribute().setAttributeVec2f("orientation", dir) + it.increment() + it2.increment() + ## case where the last vertex is a TVertex + v = it.getObject() + if(v.getNature() & Nature.T_VERTEX): + itPrevious = StrokeVertexIterator(it) + itPrevious.decrement() + tv = v.castToTVertex() + ve = getFEdge(itPrevious.getObject(), v).viewedge() + if(tv != None): + dir = self.findOrientation(tv, ve) + #print(dir.x, dir.y) + v.attribute().setAttributeVec2f("orientation", dir) + +class pySinusDisplacementShader(StrokeShader): + def __init__(self, f, a): + StrokeShader.__init__(self) + self._f = f + self._a = a + self._getNormal = Normal2DF0D() + + def getName(self): + return "pySinusDisplacementShader" + def shade(self, stroke): + it = stroke.strokeVerticesBegin() + while it.isEnd() == 0: + v = it.getObject() + #print(self._getNormal.getName()) + n = self._getNormal(it.castToInterface0DIterator()) + p = v.getPoint() + u = v.u() + a = self._a*(1-2*(fabs(u-0.5))) + n = n*a*cos(self._f*u*6.28) + #print(n.x, n.y) + v.setPoint(p+n) + #v.setPoint(v.getPoint()+n*a*cos(f*v.u())) + it.increment() + +class pyPerlinNoise1DShader(StrokeShader): + def __init__(self, freq = 10, amp = 10, oct = 4): + StrokeShader.__init__(self) + self.__noise = Noise() + self.__freq = freq + self.__amp = amp + self.__oct = oct + def getName(self): + return "pyPerlinNoise1DShader" + def shade(self, stroke): + i = randint(0, 50) + it = stroke.strokeVerticesBegin() + while it.isEnd() == 0: + v = it.getObject() + nres = self.__noise.turbulence1(i, self.__freq, self.__amp, self.__oct) + v.setPoint(v.getProjectedX() + nres, v.getProjectedY() + nres) + i = i+1 + it.increment() + +class pyPerlinNoise2DShader(StrokeShader): + def __init__(self, freq = 10, amp = 10, oct = 4): + StrokeShader.__init__(self) + self.__noise = Noise() + self.__freq = freq + self.__amp = amp + self.__oct = oct + def getName(self): + return "pyPerlinNoise2DShader" + def shade(self, stroke): + it = stroke.strokeVerticesBegin() + while it.isEnd() == 0: + v = it.getObject() + vec = Vector([v.getProjectedX(), v.getProjectedY()]) + nres = self.__noise.turbulence2(vec, self.__freq, self.__amp, self.__oct) + v.setPoint(v.getProjectedX() + nres, v.getProjectedY() + nres) + it.increment() + +class pyBluePrintCirclesShader(StrokeShader): + def __init__(self, turns = 1): + StrokeShader.__init__(self) + self.__turns = turns + def getName(self): + return "pyBluePrintCirclesShader" + def shade(self, stroke): + p_min = Vector([10000, 10000]) + p_max = Vector([0, 0]) + it = stroke.strokeVerticesBegin() + while it.isEnd() == 0: + p = it.getObject().getPoint() + if (p.x < p_min.x): + p_min.x = p.x + if (p.x > p_max.x): + p_max.x = p.x + if (p.y < p_min.y): + p_min.y = p.y + if (p.y > p_max.y): + p_max.y = p.y + it.increment() + stroke.Resample(32 * self.__turns) + sv_nb = stroke.strokeVerticesSize() +# print("min :", p_min.x, p_min.y) # DEBUG +# print("mean :", p_sum.x, p_sum.y) # DEBUG +# print("max :", p_max.x, p_max.y) # DEBUG +# print("----------------------") # DEBUG +####################################################### + sv_nb = sv_nb / self.__turns + center = (p_min + p_max) / 2 + radius = (center.x - p_min.x + center.y - p_min.y) / 2 + p_new = Vector([0, 0]) +####################################################### + it = stroke.strokeVerticesBegin() + for j in range(self.__turns): + radius = radius + randint(-3, 3) + center.x = center.x + randint(-5, 5) + center.y = center.y + randint(-5, 5) + i = 0 + while i < sv_nb: + p_new.x = center.x + radius * cos(2 * pi * float(i) / float(sv_nb - 1)) + p_new.y = center.y + radius * sin(2 * pi * float(i) / float(sv_nb - 1)) + it.getObject().setPoint(p_new) + i = i + 1 + it.increment() + while it.isEnd() == 0: + stroke.RemoveVertex(it.getObject()) + it.increment() + +class pyBluePrintEllipsesShader(StrokeShader): + def __init__(self, turns = 1): + StrokeShader.__init__(self) + self.__turns = turns + def getName(self): + return "pyBluePrintEllipsesShader" + def shade(self, stroke): + p_min = Vector([10000, 10000]) + p_max = Vector([0, 0]) + it = stroke.strokeVerticesBegin() + while it.isEnd() == 0: + p = it.getObject().getPoint() + if (p.x < p_min.x): + p_min.x = p.x + if (p.x > p_max.x): + p_max.x = p.x + if (p.y < p_min.y): + p_min.y = p.y + if (p.y > p_max.y): + p_max.y = p.y + it.increment() + stroke.Resample(32 * self.__turns) + sv_nb = stroke.strokeVerticesSize() + sv_nb = sv_nb / self.__turns + center = (p_min + p_max) / 2 + radius_x = center.x - p_min.x + radius_y = center.y - p_min.y + p_new = Vector([0, 0]) +####################################################### + it = stroke.strokeVerticesBegin() + for j in range(self.__turns): + radius_x = radius_x + randint(-3, 3) + radius_y = radius_y + randint(-3, 3) + center.x = center.x + randint(-5, 5) + center.y = center.y + randint(-5, 5) + i = 0 + while i < sv_nb and it.isEnd() == 0: + p_new.x = center.x + radius_x * cos(2 * pi * float(i) / float(sv_nb - 1)) + p_new.y = center.y + radius_y * sin(2 * pi * float(i) / float(sv_nb - 1)) + it.getObject().setPoint(p_new) + i = i + 1 + it.increment() + while it.isEnd() == 0: + stroke.RemoveVertex(it.getObject()) + it.increment() + + +class pyBluePrintSquaresShader(StrokeShader): + def __init__(self, turns = 1, bb_len = 10): + StrokeShader.__init__(self) + self.__turns = turns + self.__bb_len = bb_len + + def getName(self): + return "pyBluePrintSquaresShader" + + def shade(self, stroke): + p_min = Vector([10000, 10000]) + p_max = Vector([0, 0]) + it = stroke.strokeVerticesBegin() + while it.isEnd() == 0: + p = it.getObject().getPoint() + if (p.x < p_min.x): + p_min.x = p.x + if (p.x > p_max.x): + p_max.x = p.x + if (p.y < p_min.y): + p_min.y = p.y + if (p.y > p_max.y): + p_max.y = p.y + it.increment() + stroke.Resample(32 * self.__turns) + sv_nb = stroke.strokeVerticesSize() +####################################################### + sv_nb = sv_nb / self.__turns + first = sv_nb / 4 + second = 2 * first + third = 3 * first + fourth = sv_nb + vec_first = Vector([p_max.x - p_min.x + 2 * self.__bb_len, 0]) + vec_second = Vector([0, p_max.y - p_min.y + 2 * self.__bb_len]) + vec_third = vec_first * -1 + vec_fourth = vec_second * -1 + p_first = Vector([p_min.x - self.__bb_len, p_min.y]) + p_second = Vector([p_max.x, p_min.y - self.__bb_len]) + p_third = Vector([p_max.x + self.__bb_len, p_max.y]) + p_fourth = Vector([p_min.x, p_max.y + self.__bb_len]) +####################################################### + it = stroke.strokeVerticesBegin() + visible = 1 + for j in range(self.__turns): + i = 0 + while i < sv_nb and it.isEnd() == 0: + if i < first: + p_new = p_first + vec_first * float(i)/float(first - 1) + if i == first - 1: + visible = 0 + elif i < second: + p_new = p_second + vec_second * float(i - first)/float(second - first - 1) + if i == second - 1: + visible = 0 + elif i < third: + p_new = p_third + vec_third * float(i - second)/float(third - second - 1) + if i == third - 1: + visible = 0 + else: + p_new = p_fourth + vec_fourth * float(i - third)/float(fourth - third - 1) + if i == fourth - 1: + visible = 0 + if it.getObject() == None: + i = i + 1 + it.increment() + if visible == 0: + visible = 1 + continue + it.getObject().setPoint(p_new) + it.getObject().attribute().setVisible(visible) + if visible == 0: + visible = 1 + i = i + 1 + it.increment() + while it.isEnd() == 0: + stroke.RemoveVertex(it.getObject()) + it.increment() + + +class pyBluePrintDirectedSquaresShader(StrokeShader): + def __init__(self, turns = 1, bb_len = 10, mult = 1): + StrokeShader.__init__(self) + self.__mult = mult + self.__turns = turns + self.__bb_len = 1 + float(bb_len) / 100 + def getName(self): + return "pyBluePrintDirectedSquaresShader" + def shade(self, stroke): + stroke.Resample(32 * self.__turns) + p_mean = Vector([0, 0]) + p_min = Vector([10000, 10000]) + p_max = Vector([0, 0]) + it = stroke.strokeVerticesBegin() + while it.isEnd() == 0: + p = it.getObject().getPoint() + p_mean = p_mean + p +## if (p.x < p_min.x): +## p_min.x = p.x +## if (p.x > p_max.x): +## p_max.x = p.x +## if (p.y < p_min.y): +## p_min.y = p.y +## if (p.y > p_max.y): +## p_max.y = p.y + it.increment() + sv_nb = stroke.strokeVerticesSize() + p_mean = p_mean / sv_nb + p_var_xx = 0 + p_var_yy = 0 + p_var_xy = 0 + it = stroke.strokeVerticesBegin() + while it.isEnd() == 0: + p = it.getObject().getPoint() + p_var_xx = p_var_xx + pow(p.x - p_mean.x, 2) + p_var_yy = p_var_yy + pow(p.y - p_mean.y, 2) + p_var_xy = p_var_xy + (p.x - p_mean.x) * (p.y - p_mean.y) + it.increment() + p_var_xx = p_var_xx / sv_nb + p_var_yy = p_var_yy / sv_nb + p_var_xy = p_var_xy / sv_nb +## print(p_var_xx, p_var_yy, p_var_xy) + trace = p_var_xx + p_var_yy + det = p_var_xx * p_var_yy - p_var_xy * p_var_xy + sqrt_coeff = sqrt(trace * trace - 4 * det) + lambda1 = (trace + sqrt_coeff) / 2 + lambda2 = (trace - sqrt_coeff) / 2 +## print(lambda1, lambda2) + theta = atan(2 * p_var_xy / (p_var_xx - p_var_yy)) / 2 +## print(theta) + if p_var_yy > p_var_xx: + e1 = Vector([cos(theta + pi / 2), sin(theta + pi / 2)]) * sqrt(lambda1) * self.__mult + e2 = Vector([cos(theta + pi), sin(theta + pi)]) * sqrt(lambda2) * self.__mult + else: + e1 = Vector([cos(theta), sin(theta)]) * sqrt(lambda1) * self.__mult + e2 = Vector([cos(theta + pi / 2), sin(theta + pi / 2)]) * sqrt(lambda2) * self.__mult +####################################################### + sv_nb = sv_nb / self.__turns + first = sv_nb / 4 + second = 2 * first + third = 3 * first + fourth = sv_nb + bb_len1 = self.__bb_len + bb_len2 = 1 + (bb_len1 - 1) * sqrt(lambda1 / lambda2) + p_first = p_mean - e1 - e2 * bb_len2 + p_second = p_mean - e1 * bb_len1 + e2 + p_third = p_mean + e1 + e2 * bb_len2 + p_fourth = p_mean + e1 * bb_len1 - e2 + vec_first = e2 * bb_len2 * 2 + vec_second = e1 * bb_len1 * 2 + vec_third = vec_first * -1 + vec_fourth = vec_second * -1 +####################################################### + it = stroke.strokeVerticesBegin() + visible = 1 + for j in range(self.__turns): + i = 0 + while i < sv_nb: + if i < first: + p_new = p_first + vec_first * float(i)/float(first - 1) + if i == first - 1: + visible = 0 + elif i < second: + p_new = p_second + vec_second * float(i - first)/float(second - first - 1) + if i == second - 1: + visible = 0 + elif i < third: + p_new = p_third + vec_third * float(i - second)/float(third - second - 1) + if i == third - 1: + visible = 0 + else: + p_new = p_fourth + vec_fourth * float(i - third)/float(fourth - third - 1) + if i == fourth - 1: + visible = 0 + it.getObject().setPoint(p_new) + it.getObject().attribute().setVisible(visible) + if visible == 0: + visible = 1 + i = i + 1 + it.increment() + while it.isEnd() == 0: + stroke.RemoveVertex(it.getObject()) + it.increment() + +class pyModulateAlphaShader(StrokeShader): + def __init__(self, min = 0, max = 1): + StrokeShader.__init__(self) + self.__min = min + self.__max = max + def getName(self): + return "pyModulateAlphaShader" + def shade(self, stroke): + it = stroke.strokeVerticesBegin() + while it.isEnd() == 0: + alpha = it.getObject().attribute().getAlpha() + p = it.getObject().getPoint() + alpha = alpha * p.y / 400 + if alpha < self.__min: + alpha = self.__min + elif alpha > self.__max: + alpha = self.__max + it.getObject().attribute().setAlpha(alpha) + it.increment() + + +## various +class pyDummyShader(StrokeShader): + def getName(self): + return "pyDummyShader" + def shade(self, stroke): + it = stroke.strokeVerticesBegin() + it_end = stroke.strokeVerticesEnd() + while it.isEnd() == 0: + toto = it.castToInterface0DIterator() + att = it.getObject().attribute() + att.setColor(0.3, 0.4, 0.4) + att.setThickness(0, 5) + it.increment() + +class pyDebugShader(StrokeShader): + def getName(self): + return "pyDebugShader" + + def shade(self, stroke): + fe = GetSelectedFEdgeCF() + id1=fe.vertexA().getId() + id2=fe.vertexB().getId() + #print(id1.getFirst(), id1.getSecond()) + #print(id2.getFirst(), id2.getSecond()) + it = stroke.strokeVerticesBegin() + found = 0 + foundfirst = 0 + foundsecond = 0 + while it.isEnd() == 0: + cp = it.getObject() + if((cp.A().getId() == id1) or (cp.B().getId() == id1)): + foundfirst = 1 + if((cp.A().getId() == id2) or (cp.B().getId() == id2)): + foundsecond = 1 + if((foundfirst != 0) and (foundsecond != 0)): + found = 1 + break + it.increment() + if(found != 0): + print("The selected Stroke id is: ", stroke.getId().getFirst(), stroke.getId().getSecond()) diff --git a/release/scripts/freestyle/style_modules/sketchy_multiple_parameterization.py b/release/scripts/freestyle/style_modules/sketchy_multiple_parameterization.py new file mode 100755 index 00000000000..163c891fa90 --- /dev/null +++ b/release/scripts/freestyle/style_modules/sketchy_multiple_parameterization.py @@ -0,0 +1,48 @@ +# +# Filename : sketchy_multiple_parameterization.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Builds sketchy strokes whose topology relies on a +# parameterization that covers the complete lines (visible+invisible) +# whereas only the visible portions are actually drawn +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from shaders import * + + +Operators.select(QuantitativeInvisibilityUP1D(0)) +## 0: don't restrict to selection +Operators.bidirectionalChain(pySketchyChainSilhouetteIterator(3,0)) +shaders_list = [ + SamplingShader(2), + SpatialNoiseShader(15, 120, 2, 1, 1), + IncreasingThicknessShader(5, 30), + SmoothingShader(100, 0.05, 0, 0.2, 0, 0, 0, 1), + IncreasingColorShader(0,0.2,0,1,0.2,0.7,0.2,1), + TextureAssignerShader(6), + pyHLRShader() + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/sketchy_topology_broken.py b/release/scripts/freestyle/style_modules/sketchy_topology_broken.py new file mode 100755 index 00000000000..9ec0cffcfec --- /dev/null +++ b/release/scripts/freestyle/style_modules/sketchy_topology_broken.py @@ -0,0 +1,89 @@ +# +# Filename : sketchy_topology_broken.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : The topology of the strokes is, first, built +# independantly from the 3D topology of objects, +# and, second, so as to chain several times the same ViewEdge. +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from shaders import * + +## Backbone stretcher that leaves cusps intact to avoid cracks +class pyBackboneStretcherNoCuspShader(StrokeShader): + def __init__(self, l): + StrokeShader.__init__(self) + self._l = l + def getName(self): + return "pyBackboneStretcherNoCuspShader" + def shade(self, stroke): + it0 = stroke.strokeVerticesBegin() + it1 = StrokeVertexIterator(it0) + it1.increment() + itn = stroke.strokeVerticesEnd() + itn.decrement() + itn_1 = StrokeVertexIterator(itn) + itn_1.decrement() + v0 = it0.getObject() + v1 = it1.getObject() + if((v0.getNature() & Nature.CUSP == 0) and (v1.getNature() & Nature.CUSP == 0)): + p0 = v0.getPoint() + p1 = v1.getPoint() + d1 = p0-p1 + d1.normalize() + newFirst = p0+d1*float(self._l) + v0.setPoint(newFirst) + else: + print("got a v0 cusp") + vn_1 = itn_1.getObject() + vn = itn.getObject() + if((vn.getNature() & Nature.CUSP == 0) and (vn_1.getNature() & Nature.CUSP == 0)): + pn = vn.getPoint() + pn_1 = vn_1.getPoint() + dn = pn-pn_1 + dn.normalize() + newLast = pn+dn*float(self._l) + vn.setPoint(newLast) + else: + print("got a vn cusp") + + +Operators.select(QuantitativeInvisibilityUP1D(0)) +## Chain 3 times each ViewEdge indpendantly from the +## initial objects topology +Operators.bidirectionalChain(pySketchyChainingIterator(3)) +shaders_list = [ + SamplingShader(4), + SpatialNoiseShader(6, 120, 2, 1, 1), + IncreasingThicknessShader(4, 10), + SmoothingShader(100, 0.1, 0, 0.2, 0, 0, 0, 1), + pyBackboneStretcherNoCuspShader(20), + #ConstantColorShader(0.0,0.0,0.0) + IncreasingColorShader(0.2,0.2,0.2,1,0.5,0.5,0.5,1), + #IncreasingColorShader(1,0,0,1,0,1,0,1), + TextureAssignerShader(4) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/sketchy_topology_preserved.py b/release/scripts/freestyle/style_modules/sketchy_topology_preserved.py new file mode 100755 index 00000000000..85e11af38b9 --- /dev/null +++ b/release/scripts/freestyle/style_modules/sketchy_topology_preserved.py @@ -0,0 +1,49 @@ +# +# Filename : sketchy_topology_preserved.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : The topology of the strokes is built +# so as to chain several times the same ViewEdge. +# The topology of the objects is preserved +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from PredicatesU1D import * +from shaders import * + +upred = QuantitativeInvisibilityUP1D(0) +Operators.select(upred) +Operators.bidirectionalChain(pySketchyChainSilhouetteIterator(3,1)) +shaders_list = [ + SamplingShader(4), + SpatialNoiseShader(20, 220, 2, 1, 1), + IncreasingThicknessShader(4, 8), + SmoothingShader(300, 0.05, 0, 0.2, 0, 0, 0, 0.5), + ConstantColorShader(0.6,0.2,0.0), + TextureAssignerShader(4), + ] + +Operators.create(TrueUP1D(), shaders_list) + diff --git a/release/scripts/freestyle/style_modules/split_at_highest_2d_curvatures.py b/release/scripts/freestyle/style_modules/split_at_highest_2d_curvatures.py new file mode 100755 index 00000000000..52cc10a9c60 --- /dev/null +++ b/release/scripts/freestyle/style_modules/split_at_highest_2d_curvatures.py @@ -0,0 +1,41 @@ +# +# Filename : split_at_highest_2d_curvature.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws the visible lines (chaining follows same nature lines) +# (most basic style module) +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesU0D import * +from PredicatesU1D import * +from Functions0D import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0))) +func = pyInverseCurvature2DAngleF0D() +Operators.recursiveSplit(func, pyParameterUP0D(0.4,0.6), NotUP1D(pyHigherLengthUP1D(100)), 2) +shaders_list = [ConstantThicknessShader(10), IncreasingColorShader(1,0,0,1,0,1,0,1), TextureAssignerShader(3)] +Operators.create(TrueUP1D(), shaders_list) + diff --git a/release/scripts/freestyle/style_modules/split_at_tvertices.py b/release/scripts/freestyle/style_modules/split_at_tvertices.py new file mode 100755 index 00000000000..78f781dd290 --- /dev/null +++ b/release/scripts/freestyle/style_modules/split_at_tvertices.py @@ -0,0 +1,42 @@ +# +# Filename : split_at_tvertices.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws strokes that starts and stops at Tvertices (visible or not) +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesU1D import * +from PredicatesU0D import * +from Functions0D import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0))) +start = pyVertexNatureUP0D(Nature.T_VERTEX) +## use the same predicate to decide where to start and where to stop +## the strokes: +Operators.sequentialSplit(start, start, 10) +shaders_list = [ConstantThicknessShader(5), IncreasingColorShader(1,0,0,1,0,1,0,1), TextureAssignerShader(3)] +Operators.create(TrueUP1D(), shaders_list) + diff --git a/release/scripts/freestyle/style_modules/stroke_texture.py b/release/scripts/freestyle/style_modules/stroke_texture.py new file mode 100755 index 00000000000..afebbe30a90 --- /dev/null +++ b/release/scripts/freestyle/style_modules/stroke_texture.py @@ -0,0 +1,43 @@ +# +# Filename : stroke_texture.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws textured strokes (illustrate the StrokeTextureShader shader) +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from shaders import * +from ChainingIterators import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + SamplingShader(3), + BezierCurveShader(4), + StrokeTextureShader("washbrushAlpha.bmp", Stroke.DRY_MEDIUM, 1), + ConstantThicknessShader(40), + ConstantColorShader(0,0,0,1), + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/suggestive.py b/release/scripts/freestyle/style_modules/suggestive.py new file mode 100755 index 00000000000..39d8515ed6c --- /dev/null +++ b/release/scripts/freestyle/style_modules/suggestive.py @@ -0,0 +1,43 @@ +# +# Filename : suggestive.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws the suggestive contours. +# ***** The suggestive contours must be enabled +# in the options dialog ***** +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from PredicatesU1D import * +from shaders import * + +upred = AndUP1D(pyNatureUP1D(Nature.SUGGESTIVE_CONTOUR), QuantitativeInvisibilityUP1D(0)) +Operators.select(upred) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred)) +shaders_list = [ + IncreasingThicknessShader(1, 3), + ConstantColorShader(0.2,0.2,0.2, 1) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/thickness_fof_depth_discontinuity.py b/release/scripts/freestyle/style_modules/thickness_fof_depth_discontinuity.py new file mode 100755 index 00000000000..21f6c7bdf35 --- /dev/null +++ b/release/scripts/freestyle/style_modules/thickness_fof_depth_discontinuity.py @@ -0,0 +1,62 @@ +# +# Filename : thickness_fof_depth_discontinuity.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Assigns to strokes a thickness that depends on the depth discontinuity +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from shaders import * + +class pyDepthDiscontinuityThicknessShader(StrokeShader): + def __init__(self, min, max): + StrokeShader.__init__(self) + self.__min = float(min) + self.__max = float(max) + self.__func = ZDiscontinuityF0D() + def getName(self): + return "pyDepthDiscontinuityThicknessShader" + def shade(self, stroke): + it = stroke.strokeVerticesBegin() + z_min=0.0 + z_max=1.0 + a = (self.__max - self.__min)/(z_max-z_min) + b = (self.__min*z_max-self.__max*z_min)/(z_max-z_min) + it = stroke.strokeVerticesBegin() + while it.isEnd() == 0: + z = self.__func(it.castToInterface0DIterator()) + thickness = a*z+b + it.getObject().attribute().setThickness(thickness, thickness) + it.increment() + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + SamplingShader(1), + ConstantThicknessShader(3), + ConstantColorShader(0.0,0.0,0.0), + pyDepthDiscontinuityThicknessShader(0.8, 6) + ] +Operators.create(TrueUP1D(), shaders_list)
\ No newline at end of file diff --git a/release/scripts/freestyle/style_modules/tipremover.py b/release/scripts/freestyle/style_modules/tipremover.py new file mode 100755 index 00000000000..3e495b7d332 --- /dev/null +++ b/release/scripts/freestyle/style_modules/tipremover.py @@ -0,0 +1,42 @@ +# +# Filename : tipremover.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Removes strokes extremities +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + + +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + SamplingShader(5), + ConstantThicknessShader(3), + ConstantColorShader(0,0,0), + TipRemoverShader(20) + ] +Operators.create(TrueUP1D(), shaders_list)
\ No newline at end of file diff --git a/release/scripts/freestyle/style_modules/tvertex_remover.py b/release/scripts/freestyle/style_modules/tvertex_remover.py new file mode 100755 index 00000000000..c328f4c98ec --- /dev/null +++ b/release/scripts/freestyle/style_modules/tvertex_remover.py @@ -0,0 +1,42 @@ +# +# Filename : tvertex_remover.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Removes TVertices +# +############################################################################# +# +# Copyright (C) : Please refer to the COPYRIGHT file distributed +# with this source distribution. +# +# 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 2 +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################# + + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + IncreasingThicknessShader(3, 5), + ConstantColorShader(0.2,0.2,0.2, 1), + SamplingShader(10.0), + pyTVertexRemoverShader() + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/uniformpruning_zsort.py b/release/scripts/freestyle/style_modules/uniformpruning_zsort.py new file mode 100755 index 00000000000..50a2f6423fd --- /dev/null +++ b/release/scripts/freestyle/style_modules/uniformpruning_zsort.py @@ -0,0 +1,40 @@ +from freestyle_init import * +from logical_operators import * +from PredicatesU1D import * +from PredicatesU0D import * +from PredicatesB1D import * +from Functions0D import * +from Functions1D import * +from shaders import * + +class pyDensityUP1D(UnaryPredicate1D): + def __init__(self,wsize,threshold, integration = IntegrationType.MEAN, sampling=2.0): + UnaryPredicate1D.__init__(self) + self._wsize = wsize + self._threshold = threshold + self._integration = integration + self._func = DensityF1D(self._wsize, self._integration, sampling) + + def getName(self): + return "pyDensityUP1D" + + def __call__(self, inter): + d = self._func(inter) + print("For Chain ", inter.getId().getFirst(), inter.getId().getSecond(), "density is ", d) + if(d < self._threshold): + return 1 + return 0 + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator()) +#Operators.sequentialSplit(pyVertexNatureUP0D(Nature.VIEW_VERTEX), 2) +Operators.sort(pyZBP1D()) +shaders_list = [ + StrokeTextureShader("smoothAlpha.bmp", Stroke.OPAQUE_MEDIUM, 0), + ConstantThicknessShader(3), + SamplingShader(5.0), + ConstantColorShader(0,0,0,1) + ] +Operators.create(pyDensityUP1D(2,0.05, IntegrationType.MEAN,4), shaders_list) +#Operators.create(pyDensityFunctorUP1D(8,0.03, pyGetInverseProjectedZF1D(), 0,1, IntegrationType.MEAN), shaders_list) + diff --git a/release/scripts/ui/properties_render.py b/release/scripts/ui/properties_render.py index 829416b86d3..e94d17a0a18 100644 --- a/release/scripts/ui/properties_render.py +++ b/release/scripts/ui/properties_render.py @@ -123,11 +123,12 @@ class RENDER_PT_layers(RenderButtonsPanel): col.prop(rl, "solid") col.prop(rl, "halo") col.prop(rl, "ztransp") - - col = split.column() col.prop(rl, "sky") + + col = split.column() col.prop(rl, "edge") col.prop(rl, "strand") + col.prop(rl, "freestyle") layout.separator() @@ -174,6 +175,137 @@ class RENDER_PT_layers(RenderButtonsPanel): row.prop(rl, "pass_refraction_exclude", text="") +class RENDER_PT_freestyle(RenderButtonsPanel): + bl_label = "Freestyle" + COMPAT_ENGINES = {'BLENDER_RENDER'} + + def poll(self, context): + rd = context.scene.render + rl = rd.layers[rd.active_layer_index] + return rl and rl.freestyle + + def draw(self, context): + layout = self.layout + + rd = context.scene.render + rl = rd.layers[rd.active_layer_index] + freestyle = rl.freestyle_settings + + split = layout.split() + + col = split.column() + col.prop(freestyle, "mode", text="Control Mode") + + if freestyle.mode == "EDITOR": + col.label(text="Edge Detection Options:") + col.prop(freestyle, "crease_angle") + col.prop(freestyle, "sphere_radius") + sub = col.row() + sub.prop(freestyle, "dkr_epsilon") + sub.active = any(lineset.select_suggestive_contour for lineset in freestyle.linesets) + + lineset = freestyle.active_lineset + + col.label(text="Line Sets:") + row = col.row() + rows = 2 + if lineset: + rows = 5 + # FIXME: scrollbar does not work correctly + row.template_list(freestyle, "linesets", freestyle, "active_lineset_index", rows=rows) + + sub = row.column() + subsub = sub.column(align=True) + subsub.operator("scene.freestyle_lineset_add", icon='ZOOMIN', text="") + subsub.operator("scene.freestyle_lineset_remove", icon='ZOOMOUT', text="") + if lineset: + sub.separator() + subsub = sub.column(align=True) + subsub.operator("scene.freestyle_lineset_move", icon='TRIA_UP', text="").direction = 'UP' + subsub.operator("scene.freestyle_lineset_move", icon='TRIA_DOWN', text="").direction = 'DOWN' + + if lineset: + col.prop(lineset, "name") + col.prop(lineset, "select_by_visibility") + col.prop(lineset, "select_by_edge_types") + + if lineset.select_by_visibility: + col.label(text="Visibility:") + sub = col.row(align=True) + sub.prop(lineset, "visibility", expand=True) + if lineset.visibility == "RANGE": + sub = col.row(align=True) + sub.prop(lineset, "qi_start") + sub.prop(lineset, "qi_end") + + if lineset.select_by_edge_types: + col.label(text="Edge Types:") + row = col.row() + row.prop(lineset, "edge_type_negation", expand=True) + row = col.row() + row.prop(lineset, "edge_type_combination", expand=True) + + row = col.row() + sub = row.column() + sub.prop(lineset, "select_silhouette") + sub.prop(lineset, "select_border") + sub.prop(lineset, "select_crease") + sub.prop(lineset, "select_ridge") + sub.prop(lineset, "select_valley") + sub.prop(lineset, "select_suggestive_contour") + sub.prop(lineset, "select_material_boundary") + sub = row.column() + sub.prop(lineset, "select_contour") + sub.prop(lineset, "select_external_contour") + + else: # freestyle.mode == "SCRIPT" + + col.prop(freestyle, "crease_angle") + col.prop(freestyle, "sphere_radius") + col.prop(freestyle, "ridges_and_valleys") + col.prop(freestyle, "suggestive_contours") + sub = col.row() + sub.prop(freestyle, "dkr_epsilon") + sub.active = freestyle.suggestive_contours + col.prop(freestyle, "material_boundaries") + col.operator("scene.freestyle_module_add") + + for i, module in enumerate(freestyle.modules): + box = layout.box() + box.set_context_pointer("freestyle_module", module) + row = box.row(align=True) + row.prop(module, "is_displayed", text="") + row.prop(module, "module_path", text="") + row.operator("scene.freestyle_module_remove", icon='X', text="") + row.operator("scene.freestyle_module_move", icon='TRIA_UP', text="").direction = 'UP' + row.operator("scene.freestyle_module_move", icon='TRIA_DOWN', text="").direction = 'DOWN' + + +class RENDER_PT_freestyle_linestyle(RenderButtonsPanel): + bl_label = "Freestyle: Line Style" + COMPAT_ENGINES = {'BLENDER_RENDER'} + + def poll(self, context): + rd = context.scene.render + rl = rd.layers[rd.active_layer_index] + if rl and rl.freestyle: + freestyle = rl.freestyle_settings + return freestyle.mode == "EDITOR" and freestyle.active_lineset + return False + + def draw(self, context): + layout = self.layout + + rd = context.scene.render + rl = rd.layers[rd.active_layer_index] + lineset = rl.freestyle_settings.active_lineset + linestyle = lineset.linestyle + + split = layout.split() + col = split.column() + col.template_ID(lineset, "linestyle", new="scene.freestyle_linestyle_new") + + class RENDER_PT_shading(RenderButtonsPanel): bl_label = "Shading" COMPAT_ENGINES = {'BLENDER_RENDER'} @@ -286,6 +418,12 @@ class RENDER_PT_post_processing(RenderButtonsPanel): sub.prop(rd, "edge_threshold", text="Threshold", slider=True) sub.prop(rd, "edge_color", text="") + layout.separator() + + split = layout.split() + col = split.column() + col.prop(rd, "freestyle", text="Freestyle") + class RENDER_PT_output(RenderButtonsPanel): bl_label = "Output" @@ -630,12 +768,12 @@ class RENDER_PT_bake(RenderButtonsPanel): wide_ui = context.region.width > narrowui layout.operator("object.bake_image", icon='RENDER_STILL') - + if wide_ui: layout.prop(rd, "bake_type") else: layout.prop(rd, "bake_type", text="") - + if rd.bake_type == 'NORMALS': if wide_ui: layout.prop(rd, "bake_normal_space") @@ -643,19 +781,19 @@ class RENDER_PT_bake(RenderButtonsPanel): layout.prop(rd, "bake_normal_space", text="") elif rd.bake_type in ('DISPLACEMENT', 'AO'): layout.prop(rd, "bake_normalized") - + # col.prop(rd, "bake_aa_mode") # col.prop(rd, "bake_enable_aa") - + layout.separator() - + split = layout.split() col = split.column() col.prop(rd, "bake_clear") col.prop(rd, "bake_margin") col.prop(rd, "bake_quad_split", text="Split") - + if wide_ui: col = split.column() col.prop(rd, "bake_active") @@ -664,12 +802,14 @@ class RENDER_PT_bake(RenderButtonsPanel): sub.prop(rd, "bake_distance") sub.prop(rd, "bake_bias") - + classes = [ RENDER_MT_presets, RENDER_MT_ffmpeg_presets, RENDER_PT_render, RENDER_PT_layers, + RENDER_PT_freestyle, + RENDER_PT_freestyle_linestyle, RENDER_PT_dimensions, RENDER_PT_antialiasing, RENDER_PT_motion_blur, diff --git a/release/scripts/ui/space_userpref.py b/release/scripts/ui/space_userpref.py index 61f759a1d83..fba4f28e605 100644 --- a/release/scripts/ui/space_userpref.py +++ b/release/scripts/ui/space_userpref.py @@ -196,7 +196,14 @@ class USERPREF_PT_interface(bpy.types.Panel): col.prop(view, "auto_perspective") col.prop(view, "smooth_view") col.prop(view, "rotation_angle") - + + col.separator() + col.separator() + + col.label(text="2D Viewports:") + col.prop(view, "view2d_grid_minimum_spacing", text="Minimum Grid Spacing") + col.prop(view, "timecode_style") + col.separator() col.separator() diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt index 16437737302..5e1ea753ace 100644 --- a/source/blender/CMakeLists.txt +++ b/source/blender/CMakeLists.txt @@ -42,6 +42,7 @@ ADD_SUBDIRECTORY(readblenfile) ADD_SUBDIRECTORY(render) ADD_SUBDIRECTORY(blenfont) ADD_SUBDIRECTORY(ikplugin) +ADD_SUBDIRECTORY(freestyle) IF(WITH_OPENEXR) ADD_SUBDIRECTORY(imbuf/intern/openexr) diff --git a/source/blender/SConscript b/source/blender/SConscript index 98e8ad73199..834e83ec0e1 100644 --- a/source/blender/SConscript +++ b/source/blender/SConscript @@ -9,6 +9,7 @@ SConscript(['avi/SConscript', 'blenpluginapi/SConscript', 'gpu/SConscript', 'editors/SConscript', + 'freestyle/SConscript', 'imbuf/SConscript', 'imbuf/intern/cineon/SConscript', 'makesdna/SConscript', diff --git a/source/blender/blenkernel/BKE_linestyle.h b/source/blender/blenkernel/BKE_linestyle.h new file mode 100644 index 00000000000..df7808c1a2b --- /dev/null +++ b/source/blender/blenkernel/BKE_linestyle.h @@ -0,0 +1,42 @@ +/* BKE_linestyle.h + * + * + * $Id: BKE_particle.h 29187 2010-06-03 15:39:02Z kjym3 $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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 2 + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef BKE_LINESTYLE_H +#define BKE_LINESTYLE_H + +#include "DNA_freestyle_types.h" + +struct Main; + +FreestyleLineStyle *FRS_new_linestyle(char *name, struct Main *main); +void FRS_free_linestyle(FreestyleLineStyle *linestyle); + +#endif diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index d4d76b2e6e1..d576556f13c 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -78,6 +78,7 @@ typedef struct Main { ListBase particle; ListBase wm; ListBase gpencil; + ListBase linestyle; } Main; diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index bcd60154379..195dfe2ea70 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -30,7 +30,7 @@ SET(INC . ../../../intern/guardedalloc ../../../intern/memutil ../editors/include ../blenlib ../makesdna ../modifiers ../render/extern/include ../../../intern/decimation/extern ../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/opennl/extern - ../../../intern/iksolver/extern ../blenloader ../ikplugin + ../../../intern/iksolver/extern ../blenloader ../ikplugin ../freestyle ../nodes ../../../extern/glew/include ../gpu ../makesrna ../../../intern/smoke/extern ../../../intern/bsp/extern ../blenfont ../../../intern/audaspace/intern diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index a6705653769..00c6415018b 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -7,7 +7,7 @@ incs = '. #/intern/guardedalloc #/intern/memutil ../editors/include' incs += ' ../blenlib ../blenfont ../makesdna ../windowmanager' incs += ' ../render/extern/include #/intern/decimation/extern ../makesrna' incs += ' ../imbuf ../ikplugin ../avi #/intern/elbeem/extern ../nodes ../modifiers' -incs += ' #/intern/iksolver/extern ../blenloader' +incs += ' #/intern/iksolver/extern ../blenloader ../freestyle' incs += ' #/extern/bullet2/src' incs += ' #/intern/opennl/extern #/intern/bsp/extern' incs += ' ../gpu #/extern/glew/include' diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 10c2c1801cb..28eed5a27e8 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -466,6 +466,7 @@ void BKE_animdata_main_cb (Main *main, ID_AnimData_Edit_Callback func, void *use ANIMDATA_IDS_CB(main->particle.first); /* particles */ ANIMDATA_IDS_CB(main->object.first); /* objects */ ANIMDATA_IDS_CB(main->world.first); /* worlds */ + ANIMDATA_IDS_CB(main->linestyle.first); /* linestyles */ /* scenes */ for (id= main->scene.first; id; id= id->next) { @@ -542,6 +543,9 @@ void BKE_all_animdata_fix_paths_rename (char *prefix, char *oldName, char *newNa /* worlds */ RENAMEFIX_ANIM_IDS(mainptr->world.first); + /* linestyles */ + RENAMEFIX_ANIM_IDS(mainptr->linestyle.first); + /* scenes */ for (id= mainptr->scene.first; id; id= id->next) { AnimData *adt= BKE_animdata_from_id(id); @@ -1890,6 +1894,9 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) /* particles */ EVAL_ANIM_IDS(main->particle.first, ADT_RECALC_ANIM); + /* linestyles */ + EVAL_ANIM_IDS(main->linestyle.first, ADT_RECALC_ANIM); + /* objects */ /* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets * this tagged by Depsgraph on framechange. This optimisation means that objects diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 8d859a2f712..dc0be1e2e35 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -99,6 +99,7 @@ #include "BKE_particle.h" #include "BKE_gpencil.h" #include "BKE_fcurve.h" +#include "BKE_linestyle.h" #define MAX_IDPUP 60 /* was 24 */ @@ -226,6 +227,8 @@ int id_make_local(ID *id, int test) return 0; /* can't be linked */ case ID_GD: return 0; /* not implemented */ + case ID_LS: + return 0; /* not implemented */ } return 0; @@ -315,6 +318,8 @@ int id_copy(ID *id, ID **newid, int test) return 0; /* can't be copied from here */ case ID_GD: return 0; /* not implemented */ + case ID_LS: + return 0; /* not implemented */ } return 0; @@ -413,6 +418,8 @@ ListBase *which_libbase(Main *mainlib, short type) return &(mainlib->wm); case ID_GD: return &(mainlib->gpencil); + case ID_LS: + return &(mainlib->linestyle); } return 0; } @@ -493,6 +500,7 @@ int set_listbasepointers(Main *main, ListBase **lb) lb[a++]= &(main->library); lb[a++]= &(main->wm); lb[a++]= &(main->gpencil); + lb[a++]= &(main->linestyle); lb[a]= NULL; @@ -601,6 +609,9 @@ static ID *alloc_libblock_notest(short type) case ID_GD: id = MEM_callocN(sizeof(bGPdata), "Grease Pencil"); break; + case ID_LS: + id = MEM_callocN(sizeof(FreestyleLineStyle), "Freestyle Line Style"); + break; } return id; } @@ -806,6 +817,9 @@ void free_libblock(ListBase *lb, void *idv) case ID_GD: free_gpencil_data((bGPdata *)id); break; + case ID_LS: + FRS_free_linestyle((FreestyleLineStyle *)id); + break; } if (id->properties) { diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c new file mode 100644 index 00000000000..1f768fee0ec --- /dev/null +++ b/source/blender/blenkernel/intern/linestyle.c @@ -0,0 +1,63 @@ +/* linestyle.c + * + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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 2 + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "MEM_guardedalloc.h" + +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_linestyle.h" +#include "BKE_main.h" + +static void default_linestyle_settings(FreestyleLineStyle *linestyle) +{ + +} + +FreestyleLineStyle *FRS_new_linestyle(char *name, struct Main *main) +{ + FreestyleLineStyle *linestyle; + + if (!main) + main = G.main; + + linestyle = (FreestyleLineStyle *)alloc_libblock(&main->linestyle, ID_LS, name); + + default_linestyle_settings(linestyle); + + return linestyle; +} + +void FRS_free_linestyle(FreestyleLineStyle *linestyle) +{ + +} diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 11c96e9a347..05a05c157c9 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -140,6 +140,7 @@ void init_material(Material *ma) ma->tx_limit= 0.0; ma->tx_falloff= 1.0; ma->shad_alpha= 1.0f; + ma->vcol_alpha= 0; ma->gloss_mir = ma->gloss_tra= 1.0; ma->samp_gloss_mir = ma->samp_gloss_tra= 18; diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index fe52375617b..1602fd1a373 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -74,6 +74,8 @@ #include "BLI_math.h" #include "BLI_blenlib.h" +#include "FRS_freestyle_config.h" + //XXX #include "nla.h" #ifdef WIN32 @@ -233,7 +235,8 @@ Scene *copy_scene(Main *bmain, Scene *sce, int type) void free_scene(Scene *sce) { Base *base; - + SceneRenderLayer *srl; + base= sce->base.first; while(base) { base->object->id.us--; @@ -273,6 +276,10 @@ void free_scene(Scene *sce) sce->r.ffcodecdata.properties = NULL; } + for(srl= sce->r.layers.first; srl; srl= srl->next) { + FRS_free_freestyle_config(srl); + } + BLI_freelistN(&sce->markers); BLI_freelistN(&sce->transform_spaces); BLI_freelistN(&sce->r.layers); @@ -997,6 +1004,7 @@ void scene_add_render_layer(Scene *sce) srl->lay= (1<<20) -1; srl->layflag= 0x7FFF; /* solid ztra halo edge strand */ srl->passflag= SCE_PASS_COMBINED|SCE_PASS_Z; + FRS_add_freestyle_config( srl ); } /* render simplification */ diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c index 38e9a584952..30eb09c0b61 100644 --- a/source/blender/blenloader/intern/readblenentry.c +++ b/source/blender/blenloader/intern/readblenentry.c @@ -91,6 +91,7 @@ static IDType idtypes[]= { { ID_KE, "Key", "keys", 0}, { ID_LA, "Lamp", "lamps", IDTYPE_FLAGS_ISLINKABLE}, { ID_LI, "Library", "libraries", 0}, + { ID_LS, "FreestyleLineStyle", "linestyles", 0}, { ID_LT, "Lattice", "lattices", IDTYPE_FLAGS_ISLINKABLE}, { ID_MA, "Material", "materials", IDTYPE_FLAGS_ISLINKABLE}, { ID_MB, "Metaball", "metaballs", IDTYPE_FLAGS_ISLINKABLE}, diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 7b29ab2a666..86f4fa0b103 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4133,6 +4133,7 @@ static void lib_link_scene(FileData *fd, Main *main) Base *base, *next; Sequence *seq; SceneRenderLayer *srl; + FreestyleLineSet *fls; TimeMarker *marker; sce= main->scene.first; @@ -4214,6 +4215,9 @@ static void lib_link_scene(FileData *fd, Main *main) for(srl= sce->r.layers.first; srl; srl= srl->next) { srl->mat_override= newlibadr_us(fd, sce->id.lib, srl->mat_override); srl->light_override= newlibadr_us(fd, sce->id.lib, srl->light_override); + for(fls=srl->freestyleConfig.linesets.first; fls; fls= fls->next) { + fls->linestyle= newlibadr_us(fd, sce->id.lib, fls->linestyle); + } } /*Game Settings: Dome Warp Text*/ sce->gm.dome.warptext= newlibadr(fd, sce->id.lib, sce->gm.dome.warptext); @@ -4253,6 +4257,7 @@ static void direct_link_scene(FileData *fd, Scene *sce) Editing *ed; Sequence *seq; MetaStack *ms; + SceneRenderLayer *srl; sce->theDag = NULL; sce->dagisvalid = 0; @@ -4430,6 +4435,13 @@ static void direct_link_scene(FileData *fd, Scene *sce) link_list(fd, &(sce->transform_spaces)); link_list(fd, &(sce->r.layers)); + for(srl= sce->r.layers.first; srl; srl= srl->next) { + link_list(fd, &(srl->freestyleConfig.modules)); + } + for(srl= sce->r.layers.first; srl; srl= srl->next) { + link_list(fd, &(srl->freestyleConfig.linesets)); + } + sce->nodetree= newdataadr(fd, sce->nodetree); if(sce->nodetree) direct_link_nodetree(fd, sce->nodetree); @@ -5363,6 +5375,14 @@ static void lib_link_group(FileData *fd, Main *main) } } +/* ************ READ LINE STYLE ***************** */ + +static void direct_link_linestyle(FileData *fd, FreestyleLineStyle *linestyle) +{ + +} + + /* ************** GENERAL & MAIN ******************** */ @@ -5396,6 +5416,7 @@ static char *dataname(short id_code) case ID_BR: return "Data from BR"; case ID_PA: return "Data from PA"; case ID_GD: return "Data from GD"; + case ID_LS: return "Data from LS"; } return "Data from Lib Block"; @@ -5562,6 +5583,9 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID case ID_GD: direct_link_gpencil(fd, (bGPdata *)id); break; + case ID_LS: + direct_link_linestyle(fd, (FreestyleLineStyle *)id); + break; } /*link direct data of ID properties*/ @@ -12007,6 +12031,11 @@ static void expand_sound(FileData *fd, Main *mainvar, bSound *snd) expand_doit(fd, mainvar, snd->ipo); // XXX depreceated - old animation system } +static void expand_linestyle(FileData *fd, Main *mainvar, FreestyleLineStyle *linestyle) +{ + +} + static void expand_main(FileData *fd, Main *mainvar) { @@ -12087,6 +12116,10 @@ static void expand_main(FileData *fd, Main *mainvar) break; case ID_PA: expand_particlesettings(fd, mainvar, (ParticleSettings *)id); + break; + case ID_LS: + expand_linestyle(fd, mainvar, (FreestyleLineStyle *)id); + break; } doit= 1; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 82d46a84bdd..f873dca4011 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1786,6 +1786,8 @@ static void write_scenes(WriteData *wd, ListBase *scebase) TimeMarker *marker; TransformOrientation *ts; SceneRenderLayer *srl; + FreestyleModuleConfig *fmc; + FreestyleLineSet *fls; ToolSettings *tos; sce= scebase->first; @@ -1910,8 +1912,19 @@ static void write_scenes(WriteData *wd, ListBase *scebase) for(ts = sce->transform_spaces.first; ts; ts = ts->next) writestruct(wd, DATA, "TransformOrientation", 1, ts); - for(srl= sce->r.layers.first; srl; srl= srl->next) + for(srl= sce->r.layers.first; srl; srl= srl->next) { writestruct(wd, DATA, "SceneRenderLayer", 1, srl); + + for(fmc= srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) { + writestruct(wd, DATA, "FreestyleModuleConfig", 1, fmc); + } + + for(fls= srl->freestyleConfig.linesets.first; fls; fls = fls->next) { + writestruct(wd, DATA, "FreestyleLineSet", 1, fls); + writestruct(wd, DATA, "FreestyleLineStyle", 1, fls->linestyle); + } + + } if(sce->nodetree) { writestruct(wd, DATA, "bNodeTree", 1, sce->nodetree); @@ -2361,6 +2374,17 @@ static void write_scripts(WriteData *wd, ListBase *idbase) } } +static void write_linestyles(WriteData *wd, ListBase *idbase) +{ + FreestyleLineStyle *linestyle; + + for(linestyle=idbase->first; linestyle; linestyle= linestyle->id.next) { + if(linestyle->id.us>0 || wd->current) { + writestruct(wd, ID_LS, "FreestyleLineStyle", 1, linestyle); + } + } +} + /* context is usually defined by WM, two cases where no WM is available: * - for forward compatibility, curscreen has to be saved * - for undofile, curscene needs to be saved */ @@ -2450,6 +2474,7 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil write_brushes (wd, &mainvar->brush); write_scripts (wd, &mainvar->script); write_gpencils (wd, &mainvar->gpencil); + write_linestyles(wd, &mainvar->linestyle); write_libraries(wd, mainvar->next); if (write_user_block) { diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index cbe10496a72..f8e94b87ea9 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -121,6 +121,8 @@ void uiTemplateDopeSheetFilter(uiLayout *layout, bContext *C, PointerRNA *ptr) uiItemR(row, ptr, "display_armature", 0, "", 0); if (mainptr && mainptr->particle.first) uiItemR(row, ptr, "display_particle", 0, "", 0); + if (mainptr && mainptr->linestyle.first) + uiItemR(row, ptr, "display_linestyle", 0, "", 0); /* group-based filtering (only when groups are available */ if (mainptr && mainptr->group.first) { @@ -2226,7 +2228,7 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe uiBlockSetEmboss(block, UI_EMBOSS); uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, ptr, "use_textures", i, 0, 0, 0, 0, NULL); } - else if(RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer)) { + else if(RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer) || itemptr->type == &RNA_FreestyleLineSet) { uiItemL(sub, name, icon); uiBlockSetEmboss(block, UI_EMBOSS); uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "enabled", 0, 0, 0, 0, 0, NULL); diff --git a/source/blender/editors/render/CMakeLists.txt b/source/blender/editors/render/CMakeLists.txt index 2ecdc14a497..faf110c1eed 100644 --- a/source/blender/editors/render/CMakeLists.txt +++ b/source/blender/editors/render/CMakeLists.txt @@ -36,6 +36,7 @@ SET(INC ../../python ../../render/extern/include ../../windowmanager + ../../freestyle ) IF(WITH_QUICKTIME) diff --git a/source/blender/editors/render/SConscript b/source/blender/editors/render/SConscript index 2b9737557cd..5526194eab4 100644 --- a/source/blender/editors/render/SConscript +++ b/source/blender/editors/render/SConscript @@ -5,7 +5,7 @@ sources = env.Glob('*.c') incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' -incs += ' ../../gpu' +incs += ' ../../gpu ../../freestyle' incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern' incs += ' ../../blenloader' diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h index a0441155629..2f0ce71a4e5 100644 --- a/source/blender/editors/render/render_intern.h +++ b/source/blender/editors/render/render_intern.h @@ -50,6 +50,13 @@ void MATERIAL_OT_paste(struct wmOperatorType *ot); void SCENE_OT_render_layer_add(struct wmOperatorType *ot); void SCENE_OT_render_layer_remove(struct wmOperatorType *ot); +void SCENE_OT_freestyle_module_add(struct wmOperatorType *ot); +void SCENE_OT_freestyle_module_remove(struct wmOperatorType *ot); +void SCENE_OT_freestyle_module_move(struct wmOperatorType *ot); +void SCENE_OT_freestyle_lineset_add(struct wmOperatorType *ot); +void SCENE_OT_freestyle_lineset_remove(struct wmOperatorType *ot); +void SCENE_OT_freestyle_lineset_move(struct wmOperatorType *ot); +void SCENE_OT_freestyle_linestyle_new(struct wmOperatorType *ot); void TEXTURE_OT_slot_copy(struct wmOperatorType *ot); diff --git a/source/blender/editors/render/render_ops.c b/source/blender/editors/render/render_ops.c index b1cb1d9c2f1..5a228ba5242 100644 --- a/source/blender/editors/render/render_ops.c +++ b/source/blender/editors/render/render_ops.c @@ -57,6 +57,14 @@ void ED_operatortypes_render(void) WM_operatortype_append(SCENE_OT_render_layer_add); WM_operatortype_append(SCENE_OT_render_layer_remove); + WM_operatortype_append(SCENE_OT_freestyle_module_add); + WM_operatortype_append(SCENE_OT_freestyle_module_remove); + WM_operatortype_append(SCENE_OT_freestyle_module_move); + WM_operatortype_append(SCENE_OT_freestyle_lineset_add); + WM_operatortype_append(SCENE_OT_freestyle_lineset_remove); + WM_operatortype_append(SCENE_OT_freestyle_lineset_move); + WM_operatortype_append(SCENE_OT_freestyle_linestyle_new); + #if (defined(WITH_QUICKTIME) && !defined(USE_QTKIT)) WM_operatortype_append(SCENE_OT_render_data_set_quicktime_codec); #endif diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 4a947569e66..81f32c402da 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -65,6 +65,8 @@ #include "GPU_material.h" +#include "FRS_freestyle.h" + #include "RNA_access.h" #include "WM_api.h" @@ -705,6 +707,220 @@ void SCENE_OT_render_layer_remove(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } +static int freestyle_module_add_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay); + + FRS_add_module(&srl->freestyleConfig); + + WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene); + + return OPERATOR_FINISHED; +} + +void SCENE_OT_freestyle_module_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Freestyle Module"; + ot->idname= "SCENE_OT_freestyle_module_add"; + ot->description="Add a style module into the list of modules."; + + /* api callbacks */ + ot->exec= freestyle_module_add_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int freestyle_module_remove_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay); + PointerRNA ptr= CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings); + FreestyleModuleConfig *module= ptr.data; + + FRS_delete_module(&srl->freestyleConfig, module); + + WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene); + + return OPERATOR_FINISHED; +} + +void SCENE_OT_freestyle_module_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Remove Freestyle Module"; + ot->idname= "SCENE_OT_freestyle_module_remove"; + ot->description="Remove the style module from the stack."; + + /* api callbacks */ + ot->exec= freestyle_module_remove_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int freestyle_module_move_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay); + PointerRNA ptr= CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings); + FreestyleModuleConfig *module= ptr.data; + int dir= RNA_enum_get(op->ptr, "direction"); + + if (dir == 1) { + FRS_move_module_up(&srl->freestyleConfig, module); + } else { + FRS_move_module_down(&srl->freestyleConfig, module); + } + WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene); + + return OPERATOR_FINISHED; +} + +void SCENE_OT_freestyle_module_move(wmOperatorType *ot) +{ + static EnumPropertyItem direction_items[] = { + {1, "UP", 0, "Up", ""}, + {-1, "DOWN", 0, "Down", ""}, + {0, NULL, 0, NULL, NULL} + }; + + /* identifiers */ + ot->name= "Move Freestyle Module"; + ot->idname= "SCENE_OT_freestyle_module_move"; + ot->description="Change the position of the style module within in the list of style modules."; + + /* api callbacks */ + ot->exec= freestyle_module_move_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to move, UP or DOWN"); +} + +static int freestyle_lineset_add_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay); + + FRS_add_lineset(&srl->freestyleConfig); + + WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene); + + return OPERATOR_FINISHED; +} + +void SCENE_OT_freestyle_lineset_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Line Set"; + ot->idname= "SCENE_OT_freestyle_lineset_add"; + ot->description="Add a line set into the list of line sets."; + + /* api callbacks */ + ot->exec= freestyle_lineset_add_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int freestyle_lineset_remove_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay); + + FRS_delete_active_lineset(&srl->freestyleConfig); + + WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene); + + return OPERATOR_FINISHED; +} + +void SCENE_OT_freestyle_lineset_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Remove Line Set"; + ot->idname= "SCENE_OT_freestyle_lineset_remove"; + ot->description="Remove the active line set from the list of line sets."; + + /* api callbacks */ + ot->exec= freestyle_lineset_remove_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int freestyle_lineset_move_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay); + int dir= RNA_enum_get(op->ptr, "direction"); + + if (dir == 1) { + FRS_move_active_lineset_up(&srl->freestyleConfig); + } else { + FRS_move_active_lineset_down(&srl->freestyleConfig); + } + WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene); + + return OPERATOR_FINISHED; +} + +void SCENE_OT_freestyle_lineset_move(wmOperatorType *ot) +{ + static EnumPropertyItem direction_items[] = { + {1, "UP", 0, "Up", ""}, + {-1, "DOWN", 0, "Down", ""}, + {0, NULL, 0, NULL, NULL} + }; + + /* identifiers */ + ot->name= "Move Line Set"; + ot->idname= "SCENE_OT_freestyle_lineset_move"; + ot->description="Change the position of the active line set within the list of line sets."; + + /* api callbacks */ + ot->exec= freestyle_lineset_move_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to move, UP or DOWN"); +} + +static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay); + FreestyleLineSet *lineset = FRS_get_active_lineset(&srl->freestyleConfig); + + lineset->linestyle->id.us--; + lineset->linestyle = FRS_new_linestyle("LineStyle", NULL); + + WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene); + + return OPERATOR_FINISHED; +} + +void SCENE_OT_freestyle_linestyle_new(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "New Line Style"; + ot->idname= "SCENE_OT_freestyle_linestyle_new"; + ot->description="Create a new line style, reusable by multiple line sets."; + + /* api callbacks */ + ot->exec= freestyle_linestyle_new_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + static int texture_slot_move(bContext *C, wmOperator *op) { ID *id= CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data; diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c index 95e2cb920fc..60cd768de12 100644 --- a/source/blender/editors/space_outliner/outliner.c +++ b/source/blender/editors/space_outliner/outliner.c @@ -4470,11 +4470,6 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Spa int active; for(te= lb->first; te; te= te->next) { - - /* exit drawing early */ - if((*offsx) - OL_X > xmax) - break; - tselem= TREESTORE(te); /* object hierarchy always, further constrained on level */ diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index beea3c9bee4..c177f2789d0 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -556,9 +556,6 @@ int transformEvent(TransInfo *t, wmEvent *event) if (event->type == MOUSEMOVE) { - if (t->modifiers & MOD_CONSTRAINT_SELECT) - t->con.mode |= CON_SELECT; - t->mval[0] = event->x - t->ar->winrct.xmin; t->mval[1] = event->y - t->ar->winrct.ymin; @@ -1695,6 +1692,9 @@ void transformApply(const bContext *C, TransInfo *t) { if ((t->redraw & TREDRAW_HARD) || (t->draw_handle_apply == NULL && (t->redraw & TREDRAW_SOFT))) { + if (t->modifiers & MOD_CONSTRAINT_SELECT) + t->con.mode |= CON_SELECT; + selectConstraint(t); if (t->transform) { t->transform(t, t->mval); // calls recalcData() diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index e926762709d..739aac86713 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -510,7 +510,6 @@ void initTransformOrientation(bContext *C, TransInfo *t) switch(t->current_orientation) { case V3D_MANIP_GLOBAL: - unit_m3(t->spacemtx); strcpy(t->spacename, "global"); break; diff --git a/source/blender/freestyle/CMakeLists.txt b/source/blender/freestyle/CMakeLists.txt new file mode 100644 index 00000000000..18f721ccfdc --- /dev/null +++ b/source/blender/freestyle/CMakeLists.txt @@ -0,0 +1,42 @@ +# $Id: CMakeLists.txt 14444 2008-04-16 22:40:48Z hos $ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# 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 2 +# 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, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2006, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): Jacques Beaurain. +# +# ***** END GPL LICENSE BLOCK ***** + +FILE(GLOB_RECURSE SRC *.cpp) + +SET(INC + ../blenkernel ../blenloader ../blenlib ../imbuf ../makesdna ../makesrna + ../python ../python/intern + ../render/extern/include ../render/intern/include ../include ../src + ../../../extern/glew/include ../../../intern/guardedalloc ../freestyle + ${PYTHON_INC} + ${PNG_INC} +) + +IF(WIN32) + SET(INC ${INC} ${PTHREADS_INC}) +ENDIF(WIN32) + +BLENDERLIB(bf_freestyle "${SRC}" "${INC}") diff --git a/source/blender/freestyle/FRS_freestyle.h b/source/blender/freestyle/FRS_freestyle.h new file mode 100644 index 00000000000..98f7f820715 --- /dev/null +++ b/source/blender/freestyle/FRS_freestyle.h @@ -0,0 +1,47 @@ +#ifndef FRS_FREESTYLE_H +#define FRS_FREESTYLE_H + +#ifdef __cplusplus +extern "C" { +#endif + + #include "DNA_listBase.h" + #include "DNA_scene_types.h" + + #include "BKE_context.h" + + extern Scene *freestyle_scene; + extern float freestyle_viewpoint[3]; + extern float freestyle_mv[4][4]; + extern float freestyle_proj[4][4]; + extern int freestyle_viewport[4]; + + // Rendering + void FRS_initialize(); + void FRS_set_context(bContext* C); + int FRS_is_freestyle_enabled(struct SceneRenderLayer* srl); + void FRS_init_stroke_rendering(struct Render* re); + struct Render* FRS_do_stroke_rendering(struct Render* re, struct SceneRenderLayer* srl); + void FRS_composite_result(struct Render* re, struct SceneRenderLayer* srl, struct Render* freestyle_render); + void FRS_exit(); + + // Panel configuration + void FRS_add_module(FreestyleConfig *config); + void FRS_delete_module(FreestyleConfig *config, FreestyleModuleConfig *module_conf); + void FRS_move_module_up(FreestyleConfig *config, FreestyleModuleConfig *module_conf); + void FRS_move_module_down(FreestyleConfig *config, FreestyleModuleConfig *module_conf); + + void FRS_add_lineset(FreestyleConfig *config); + void FRS_delete_active_lineset(FreestyleConfig *config); + void FRS_move_active_lineset_up(FreestyleConfig *config); + void FRS_move_active_lineset_down(FreestyleConfig *config); + + FreestyleLineSet *FRS_get_active_lineset(FreestyleConfig *config); + short FRS_get_active_lineset_index(FreestyleConfig *config); + void FRS_set_active_lineset_index(FreestyleConfig *config, short index); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/blender/freestyle/FRS_freestyle_config.h b/source/blender/freestyle/FRS_freestyle_config.h new file mode 100644 index 00000000000..86a05d1aa22 --- /dev/null +++ b/source/blender/freestyle/FRS_freestyle_config.h @@ -0,0 +1,17 @@ +#ifndef FRS_FREESTYLE_CONFIG_H +#define FRS_FREESTYLE_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + + #include "DNA_scene_types.h" + + void FRS_add_freestyle_config( SceneRenderLayer* srl ); + void FRS_free_freestyle_config( SceneRenderLayer* srl ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/blender/freestyle/SConscript b/source/blender/freestyle/SConscript new file mode 100644 index 00000000000..4ad790f53e5 --- /dev/null +++ b/source/blender/freestyle/SConscript @@ -0,0 +1,82 @@ +#!/usr/bin/python +import sys +Import ('env') + +sources = [] +defs = [] +incs = '' + +incs += '../blenkernel ../blenloader ../blenlib ../imbuf ../makesdna ../makesrna' +incs += ' ../python ../python/intern' +incs += ' ../render/extern/include ../render/intern/include ../include ../src' +incs += ' #/extern/glew/include #/intern/guardedalloc ../freestyle' +incs += ' ' + env['BF_PYTHON_INC'] +incs += ' ' + env['BF_PNG_INC'] + + +if env['OURPLATFORM'] == 'linux2': + cflags='-pthread' + incs += ' ../../../extern/binreloc/include' + +if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'): + incs += ' ' + env['BF_PTHREADS_INC'] + +######################################################## +# folders sources +######################################################## + +# system +prefix = 'intern/system' +system_sources = env.Glob(prefix + '/*.cpp') + +# image +prefix = 'intern/image' +image_sources = env.Glob(prefix + '/*.cpp') + +# geometry +prefix = 'intern/geometry' +geometry_sources = env.Glob(prefix + '/*.cpp') + +# scene_graph +prefix = 'intern/scene_graph' +scene_graph_sources = env.Glob(prefix + '/*.cpp') + +# winged_edge +prefix = 'intern/winged_edge' +winged_edge_sources = env.Glob(prefix + '/*.cpp') + +# view_map +prefix = 'intern/view_map' +view_map_sources = env.Glob(prefix + '/*.cpp') + +# stroke +prefix = 'intern/stroke' +stroke_sources = env.Glob(prefix + '/*.cpp') + +# application +prefix = 'intern/application' +application_sources = env.Glob(prefix + '/*.cpp') + +# blender_interface +prefix = 'intern/blender_interface' +interface_sources = env.Glob(prefix + '/*.cpp') + +# Python +prefix = 'intern/python' +python_sources = env.Glob(prefix + '/*.cpp') \ + + env.Glob(prefix + '/*/*.cpp') \ + + env.Glob(prefix + '/*/*/*.cpp') \ + + env.Glob(prefix + '/*/*/*/*.cpp') + +sources = system_sources + image_sources + geometry_sources + scene_graph_sources \ + + winged_edge_sources + view_map_sources + stroke_sources \ + + application_sources + interface_sources + python_sources + +env.BlenderLib (libname="bf_freestyle", + sources=sources, + includes=Split(incs), + defines=defs, + libtype=['core'], + priority = [370] # bf_python is 361 + ) + diff --git a/source/blender/freestyle/intern/application/AppCanvas.cpp b/source/blender/freestyle/intern/application/AppCanvas.cpp new file mode 100755 index 00000000000..2895549a79c --- /dev/null +++ b/source/blender/freestyle/intern/application/AppCanvas.cpp @@ -0,0 +1,187 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "Controller.h" +#include "AppView.h" +#include "../image/Image.h" +#include "../system/TimeStamp.h" +#include "../stroke/StrokeRenderer.h" +#include "AppCanvas.h" +#include "AppConfig.h" + +#include "../system/StringUtils.h" + +AppCanvas::AppCanvas() +:Canvas() +{ + _pViewer = 0; + _MapsPath = StringUtils::toAscii( Config::Path::getInstance()->getMapsDir() ).c_str(); +} + +AppCanvas::AppCanvas(AppView* iViewer) +:Canvas() +{ + _pViewer = iViewer; +} + +AppCanvas::AppCanvas(const AppCanvas& iBrother) +:Canvas(iBrother) +{ + _pViewer = iBrother._pViewer; +} + +AppCanvas::~AppCanvas() +{ + _pViewer = 0; +} + +void AppCanvas::setViewer(AppView *iViewer) +{ + _pViewer = iViewer; +} + +int AppCanvas::width() const +{ + return _pViewer->width(); +} + +int AppCanvas::height() const +{ + return _pViewer->height(); +} + +BBox<Vec2i> AppCanvas::border() const +{ + return _pViewer->border(); +} + +BBox<Vec3r> AppCanvas::scene3DBBox() const +{ + return _pViewer->scene3DBBox(); +} + +void AppCanvas::preDraw() +{ + Canvas::preDraw(); +} + +void AppCanvas::init() +{ + + // static bool firsttime = true; + // if (firsttime) { + // + // _Renderer = new BlenderStrokeRenderer; + // if(!StrokeRenderer::loadTextures()) + // { + // cerr << "unable to load stroke textures" << endl; + // return; + // } + // } +} + +void AppCanvas::postDraw() +{ + Canvas::postDraw(); +} + +void AppCanvas::Erase() +{ + Canvas::Erase(); +} + +// Abstract + +void AppCanvas::readColorPixels(int x,int y,int w, int h, RGBImage& oImage) const +{ + float *rgb = new float[3*w*h]; + memset(rgb, 0, sizeof(float) * 3 * w * h); + int xsch = width(); + int ysch = height(); + if (_pass_diffuse.buf) { + int xmin = border().getMin().x(); + int ymin = border().getMin().y(); + int xmax = border().getMax().x(); + int ymax = border().getMax().y(); + int rectx = _pass_z.width; + int recty = _pass_z.height; + float xfac = ((float)rectx) / ((float)(xmax - xmin)); + float yfac = ((float)recty) / ((float)(ymax - ymin)); + //printf("readColorPixels %d x %d @ (%d, %d) in %d x %d [%d x %d] -- %d x %d @ %d%%\n", w, h, x, y, xsch, ysch, xmax - xmin, ymax - ymin, rectx, recty, (int)(xfac * 100.0f)); + int ii, jj; + for (int j = 0; j < h; j++) { + jj = (int)((y - ymin + j) * yfac); + if (jj < 0 || jj >= recty) + continue; + for (int i = 0; i < w; i++) { + ii = (int)((x - xmin + i) * xfac); + if (ii < 0 || ii >= rectx) + continue; + memcpy(rgb + (w * j + i) * 3, _pass_diffuse.buf + (rectx * jj + ii) * 3, sizeof(float) * 3); + } + } + } + oImage.setArray(rgb, xsch, ysch, w, h, x, y, false); +} + +void AppCanvas::readDepthPixels(int x,int y,int w, int h, GrayImage& oImage) const +{ + float *z = new float[w*h]; + memset(z, 0, sizeof(float) * w * h); + int xsch = width(); + int ysch = height(); + if (_pass_z.buf) { + int xmin = border().getMin().x(); + int ymin = border().getMin().y(); + int xmax = border().getMax().x(); + int ymax = border().getMax().y(); + int rectx = _pass_z.width; + int recty = _pass_z.height; + float xfac = ((float)rectx) / ((float)(xmax - xmin)); + float yfac = ((float)recty) / ((float)(ymax - ymin)); + //printf("readDepthPixels %d x %d @ (%d, %d) in %d x %d [%d x %d] -- %d x %d @ %d%%\n", w, h, x, y, xsch, ysch, xmax - xmin, ymax - ymin, rectx, recty, (int)(xfac * 100.0f)); + int ii, jj; + for (int j = 0; j < h; j++) { + jj = (int)((y - ymin + j) * yfac); + if (jj < 0 || jj >= recty) + continue; + for (int i = 0; i < w; i++) { + ii = (int)((x - xmin + i) * xfac); + if (ii < 0 || ii >= rectx) + continue; + z[w * j + i] = _pass_z.buf[rectx * jj + ii]; + } + } + } + oImage.setArray(z, xsch, ysch, w, h, x, y, false); +} + +void AppCanvas::RenderStroke(Stroke *iStroke) { + + if(_basic) + iStroke->RenderBasic(_Renderer); + else + iStroke->Render(_Renderer); +} + + +void AppCanvas::update() {} + diff --git a/source/blender/freestyle/intern/application/AppCanvas.h b/source/blender/freestyle/intern/application/AppCanvas.h new file mode 100755 index 00000000000..42b3c7fdb50 --- /dev/null +++ b/source/blender/freestyle/intern/application/AppCanvas.h @@ -0,0 +1,70 @@ +#ifndef ARTCANVAS_H +#define ARTCANVAS_H + +#include "../stroke/Canvas.h" +#include "AppView.h" + +class AppCanvas : public Canvas +{ + +public: + AppCanvas(); + AppCanvas(AppView *iViewer); + AppCanvas(const AppCanvas& iBrother); + virtual ~AppCanvas(); + + /*! operations that need to be done before a draw */ + virtual void preDraw(); + + /*! operations that need to be done after a draw */ + virtual void postDraw(); + + /*! Erases the layers and clears the canvas */ + virtual void Erase(); + + /* init the canvas */ + virtual void init(); + + /*! Reads a pixel area from the canvas */ + virtual void readColorPixels(int x,int y,int w, int h, RGBImage& oImage) const; + /*! Reads a depth pixel area from the canvas */ + virtual void readDepthPixels(int x,int y,int w, int h, GrayImage& oImage) const; + + virtual BBox<Vec3r> scene3DBBox() const ; + + // abstract + virtual void RenderStroke(Stroke*); + virtual void update(); + + + /*! accessors */ + virtual int width() const ; + virtual int height() const ; + virtual BBox<Vec2i> border() const ; + + AppView *_pViewer; + inline const AppView * viewer() const {return _pViewer;} + + /*! modifiers */ + void setViewer(AppView *iViewer) ; + + // soc + void setPassDiffuse(float *buf, int width, int height) { + _pass_diffuse.buf = buf; + _pass_diffuse.width = width; + _pass_diffuse.height = height; + } + void setPassZ(float *buf, int width, int height) { + _pass_z.buf = buf; + _pass_z.width = width; + _pass_z.height = height; + } +private: + struct { + float *buf; + int width, height; + } _pass_diffuse, _pass_z; +}; + + +#endif diff --git a/source/blender/freestyle/intern/application/AppConfig.cpp b/source/blender/freestyle/intern/application/AppConfig.cpp new file mode 100755 index 00000000000..7157d7a89aa --- /dev/null +++ b/source/blender/freestyle/intern/application/AppConfig.cpp @@ -0,0 +1,92 @@ +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "AppConfig.h" +#include <iostream> + +#include "../system/StringUtils.h" +using namespace std; + +extern "C" { + #include "BLI_path_util.h" +} + +namespace Config { +Path* Path::_pInstance = 0; +Path::Path() { + // get the root directory + //soc + setRootDir( BLI_get_folder(BLENDER_SCRIPTS, NULL) ); + + _pInstance = this; +} +void Path::setRootDir(const string& iRootDir) { + _ProjectDir = iRootDir + string(DIR_SEP.c_str()) + "freestyle"; + _ModelsPath = ""; + _PatternsPath = _ProjectDir + string(DIR_SEP.c_str()) + "data" + + string(DIR_SEP.c_str()) + "textures" + string(DIR_SEP.c_str()) + + "variation_patterns" + string(DIR_SEP.c_str()); + _BrushesPath = _ProjectDir + string(DIR_SEP.c_str()) + "data" + + string(DIR_SEP.c_str()) + "textures" + string(DIR_SEP.c_str()) + + "brushes" + string(DIR_SEP.c_str()); + _PythonPath = _ProjectDir + string(DIR_SEP.c_str()) ++ "style_modules" + string(DIR_SEP.c_str()) ; + if (getenv("PYTHONPATH")) { + _PythonPath += string(PATH_SEP.c_str()) + string(getenv("PYTHONPATH")); + } +#ifdef WIN32 + _BrowserCmd = "C:\\Program Files\\Internet Explorer\\iexplore.exe %s"; +#else + _BrowserCmd = "mozilla %s"; +#endif + _HelpIndexPath = _ProjectDir + string(DIR_SEP.c_str()) + "doc" + + string(DIR_SEP.c_str()) + "html" + string(DIR_SEP.c_str()) + + "index.html"; + _EnvMapDir = _ProjectDir + string(DIR_SEP.c_str()) + "data" + + string(DIR_SEP.c_str()) + "env_map" + string(DIR_SEP.c_str()); + _MapsDir = _ProjectDir + string(DIR_SEP.c_str()) + "data" + + string(DIR_SEP.c_str()) + "maps" + string(DIR_SEP.c_str()); +} +void Path::setHomeDir(const string& iHomeDir) { + _HomeDir = iHomeDir; +} +Path::~Path() { + _pInstance = 0; +} +Path* Path::getInstance() { + return _pInstance; +} +string Path::getEnvVar(const string& iEnvVarName) { + string value; + if (!getenv(StringUtils::toAscii(iEnvVarName).c_str() ) ) { + cerr << "Warning: You may want to set the $" + << StringUtils::toAscii(iEnvVarName) + << " environment variable to use Freestyle." << endl + << " Otherwise, the current directory will be used instead." + << endl; + value = "."; + } else { + value = getenv(StringUtils::toAscii(iEnvVarName).c_str() ); + } + return value; +} + +} // End of namepace Config + diff --git a/source/blender/freestyle/intern/application/AppConfig.h b/source/blender/freestyle/intern/application/AppConfig.h new file mode 100755 index 00000000000..59e85ca2e17 --- /dev/null +++ b/source/blender/freestyle/intern/application/AppConfig.h @@ -0,0 +1,105 @@ +// +// Filename : AppConfig.h +// Author : Emmanuel Turquin +// Purpose : Configuration file +// Date of creation : 26/02/2003 +// +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef APP_CONFIG_H +# define APP_CONFIG_H + +# include <string> +# include "../system/FreestyleConfig.h" +# include "../system/Precision.h" + +using namespace std; + +namespace Config { + + class Path{ + protected: + static Path * _pInstance; + string _ProjectDir; + string _ModelsPath; + string _PatternsPath; + string _BrushesPath; + string _PythonPath; + string _BrowserCmd; + string _HelpIndexPath; + string _EnvMapDir; + string _MapsDir; + string _HomeDir; + public: + Path(); + virtual ~Path(); + static Path* getInstance(); + + void setRootDir(const string& iRootDir) ; + void setHomeDir(const string& iHomeDir) ; + + const string& getProjectDir() const {return _ProjectDir;} + const string& getModelsPath() const {return _ModelsPath;} + const string& getPatternsPath() const {return _PatternsPath;} + const string& getBrushesPath() const {return _BrushesPath;} + const string& getPythonPath() const {return _PythonPath;} + const string& getBrowserCmd() const {return _BrowserCmd;} + const string& getHelpIndexpath() const {return _HelpIndexPath;} + const string& getEnvMapDir() const {return _EnvMapDir;} + const string& getMapsDir() const {return _MapsDir;} + const string& getHomeDir() const {return _HomeDir;} + + static string getEnvVar(const string& iEnvVarName); + + }; + + // + // Configuration, default values + // + ////////////////////////////////////////////////////////////// + + // Application + static const string APPLICATION_NAME("APPNAME"); + static const string APPLICATION_VERSION("APPVERSION"); + + // ViewMap + static const string VIEWMAP_EXTENSION("vm"); + static const string VIEWMAP_MAGIC("ViewMap File"); + static const string VIEWMAP_VERSION("1.9"); + + // Style modules + static const string STYLE_MODULE_EXTENSION("py"); + static const string STYLE_MODULES_LIST_EXTENSION("sml"); + + // Options + static const string OPTIONS_DIR("." + APPLICATION_NAME); + static const string OPTIONS_FILE("options.xml"); + static const string OPTIONS_CURRENT_DIRS_FILE("current_dirs.xml"); + static const string OPTIONS_QGLVIEWER_FILE("qglviewer.xml"); + + // Default options + static const real DEFAULT_SPHERE_RADIUS = 1.0; + static const real DEFAULT_DKR_EPSILON = 0.0; + +} // End of namepace Config + +#endif // APP_CONFIG_H diff --git a/source/blender/freestyle/intern/application/AppView.cpp b/source/blender/freestyle/intern/application/AppView.cpp new file mode 100644 index 00000000000..8541122ef0d --- /dev/null +++ b/source/blender/freestyle/intern/application/AppView.cpp @@ -0,0 +1,179 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +extern "C" { +#include "BLI_jitter.h" +} + +#include "Controller.h" +#include <iostream> +#include "../stroke/Canvas.h" +#include "AppView.h" +#include "../scene_graph/NodeLight.h" +#include "../view_map/Silhouette.h" +#include "../view_map/ViewMap.h" +#include "../scene_graph/LineRep.h" +#include "../scene_graph/NodeShape.h" +#include "../scene_graph/VertexRep.h" +#include "AppConfig.h" + +#include "../system/StringUtils.h" + +extern "C" { +#include "BLI_blenlib.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" +#if 1 // FRS_antialiasing +#include "BKE_global.h" +#include "DNA_scene_types.h" +#endif + +#include "../../FRS_freestyle.h" + +} + +AppView::AppView(const char *iName) +{ + _Fovy = 30.f * M_PI / 180.0; + _ModelRootNode = new NodeDrawingStyle; + _SilhouetteRootNode = new NodeDrawingStyle; + _DebugRootNode = new NodeDrawingStyle; + + _RootNode.AddChild(_ModelRootNode); + _SilhouetteRootNode->setStyle(DrawingStyle::LINES); + _SilhouetteRootNode->setLightingEnabled(false); + _SilhouetteRootNode->setLineWidth(2.f); + _SilhouetteRootNode->setPointSize(3.f); + + _RootNode.AddChild(_SilhouetteRootNode); + + _DebugRootNode->setStyle(DrawingStyle::LINES); + _DebugRootNode->setLightingEnabled(false); + _DebugRootNode->setLineWidth(1.f); + + _RootNode.AddChild(_DebugRootNode); + + _minBBox = __min(__min(_ModelRootNode->bbox().getMin()[0], + _ModelRootNode->bbox().getMin()[1]), + _ModelRootNode->bbox().getMin()[2]); + _maxBBox = __max(__max(_ModelRootNode->bbox().getMax()[0], + _ModelRootNode->bbox().getMax()[1]), + _ModelRootNode->bbox().getMax()[2]); + + _maxAbs = __max(rabs(_minBBox), rabs(_maxBBox)); + _minAbs = __min(rabs(_minBBox), rabs(_maxBBox)); + + _p2DSelectionNode = new NodeDrawingStyle; + _p2DSelectionNode->setLightingEnabled(false); + _p2DSelectionNode->setStyle(DrawingStyle::LINES); + _p2DSelectionNode->setLineWidth(5.f); + + _p2DNode.AddChild(_p2DSelectionNode); + + + NodeLight *light = new NodeLight; + _Light.AddChild(light); +} + +AppView::~AppView() +{ + int ref = _RootNode.destroy(); + + _Light.destroy(); + ref = _p2DNode.destroy(); + +} + +real AppView::distanceToSceneCenter() { + BBox<Vec3r> bbox = _ModelRootNode->bbox(); + + Vec3r v( freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]); + v -= 0.5 * (bbox.getMin() + bbox.getMax()); + + return v.norm(); +} + + +real AppView::znear() { + + BBox<Vec3r> bbox = _ModelRootNode->bbox(); + Vec3r u = bbox.getMin(); + Vec3r v = bbox.getMax(); + Vec3r cameraCenter( freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]); + + Vec3r w1( u[0], u[1], u[2] ); + Vec3r w2( v[0], u[1], u[2] ); + Vec3r w3( u[0], v[1], u[2] ); + Vec3r w4( v[0], v[1], u[2] ); + Vec3r w5( u[0], u[1], v[2] ); + Vec3r w6( v[0], u[1], v[2] ); + Vec3r w7( u[0], v[1], v[2] ); + Vec3r w8( v[0], v[1], v[2] ); + + real _znear = __min( (w1-cameraCenter).norm(), + __min( (w2-cameraCenter).norm(), + __min( (w3-cameraCenter).norm(), + __min( (w4-cameraCenter).norm(), + __min( (w5-cameraCenter).norm(), + __min( (w6-cameraCenter).norm(), + __min( (w7-cameraCenter).norm(), + (w8-cameraCenter).norm() ))))))); + + return __max(_znear, 0.001); + + } + + real AppView::zfar() { + + BBox<Vec3r> bbox = _ModelRootNode->bbox(); + Vec3r u = bbox.getMin(); + Vec3r v = bbox.getMax(); + Vec3r cameraCenter( freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]); + + Vec3r w1( u[0], u[1], u[2] ); + Vec3r w2( v[0], u[1], u[2] ); + Vec3r w3( u[0], v[1], u[2] ); + Vec3r w4( v[0], v[1], u[2] ); + Vec3r w5( u[0], u[1], v[2] ); + Vec3r w6( v[0], u[1], v[2] ); + Vec3r w7( u[0], v[1], v[2] ); + Vec3r w8( v[0], v[1], v[2] ); + + real _zfar = __max( (w1-cameraCenter).norm(), + __max( (w2-cameraCenter).norm(), + __max( (w3-cameraCenter).norm(), + __max( (w4-cameraCenter).norm(), + __max( (w5-cameraCenter).norm(), + __max( (w6-cameraCenter).norm(), + __max( (w7-cameraCenter).norm(), + (w8-cameraCenter).norm() ))))))); + + return _zfar; + + } + + real AppView::GetFocalLength() + { + real Near = __max(0.1,(real)(-2.f*_maxAbs+ distanceToSceneCenter() )); + return Near; + } + + diff --git a/source/blender/freestyle/intern/application/AppView.h b/source/blender/freestyle/intern/application/AppView.h new file mode 100644 index 00000000000..d23172c9f8d --- /dev/null +++ b/source/blender/freestyle/intern/application/AppView.h @@ -0,0 +1,226 @@ +#ifndef APPVIEW_H +# define APPVIEW_H + +# if !defined(WIN32) || defined(__GNUC__) +# include <algorithm> +using namespace std; +# define __min(x,y) (min(x,y)) +# define __max(x,y) (max(x,y)) +# endif // WIN32 + +# include "../geometry/Geom.h" +# include "../geometry/BBox.h" +# include "../scene_graph/NodeDrawingStyle.h" +# include "../system/Precision.h" +# include "AppConfig.h" + +using namespace Geometry; + +class AppView +{ + +public: + + AppView(const char *iName = 0); + virtual ~AppView(); + +public: + + //inherited + inline unsigned int width() { return _width; } + inline unsigned int height() { return _height; } + inline BBox<Vec2i> border() { return _border; } + inline void setWidth( unsigned int width ) { _width = width; } + inline void setHeight( unsigned int height ) { _height = height; } + inline void setBorder( int xmin, int ymin, int xmax, int ymax ) { + _border = BBox<Vec2i>(Vec2i(xmin, ymin), Vec2i(xmax, ymax)); + } + +protected: + unsigned int _width, _height; + BBox<Vec2i> _border; + +public: + + /*! Sets the model to draw in the viewer + * iModel + * The Root Node of the model + */ + inline void setModel(NodeGroup *iModel) + { + if(0 != _ModelRootNode->numberOfChildren()) + { + _ModelRootNode->DetachChildren(); + _ModelRootNode->clearBBox(); + } + + AddModel(iModel); + } + + /*! Adds a model for displaying in the viewer */ + inline void AddModel(NodeGroup *iModel) + { + _ModelRootNode->AddChild(iModel); + + _ModelRootNode->UpdateBBox(); + + _minBBox = __min(__min(_ModelRootNode->bbox().getMin()[0], + _ModelRootNode->bbox().getMin()[1]), + _ModelRootNode->bbox().getMin()[2]); + _maxBBox = __max(__max(_ModelRootNode->bbox().getMax()[0], + _ModelRootNode->bbox().getMax()[1]), + _ModelRootNode->bbox().getMax()[2]); + + _maxAbs = __max(rabs(_minBBox), rabs(_maxBBox)); + + _minAbs = __min(rabs(_minBBox), rabs(_maxBBox)); + + } + + inline void AddSilhouette(NodeGroup* iSilhouette) + { + _SilhouetteRootNode->AddChild(iSilhouette); + } + + inline void Add2DSilhouette(NodeGroup *iSilhouette) + { + //_pFENode->AddChild(iSilhouette); + } + + inline void Add2DVisibleSilhouette(NodeGroup *iVSilhouette) + { + //_pVisibleSilhouetteNode->AddChild(iVSilhouette); + } + + inline void setDebug(NodeGroup* iDebug) + { + if(0 != _DebugRootNode->numberOfChildren()) + { + _DebugRootNode->DetachChildren(); + _DebugRootNode->clearBBox(); + } + + AddDebug(iDebug); + } + + inline void AddDebug(NodeGroup* iDebug) + { + _DebugRootNode->AddChild(iDebug); + } + + inline void DetachModel(Node *iModel) + { + _ModelRootNode->DetachChild(iModel); + _ModelRootNode->UpdateBBox(); + + _minBBox = __min(__min(_ModelRootNode->bbox().getMin()[0], + _ModelRootNode->bbox().getMin()[1]), + _ModelRootNode->bbox().getMin()[2]); + _maxBBox = __max(__max(_ModelRootNode->bbox().getMax()[0], + _ModelRootNode->bbox().getMax()[1]), + _ModelRootNode->bbox().getMax()[2]); + + _maxAbs = __max(rabs(_minBBox), rabs(_maxBBox)); + _minAbs = __min(rabs(_minBBox), rabs(_maxBBox)); + } + + inline void DetachModel() + { + _ModelRootNode->DetachChildren(); + _ModelRootNode->clearBBox(); + + // 2D Scene + //_p2DNode.DetachChildren(); + //_pFENode->DetachChildren(); + //_pVisibleSilhouetteNode->DetachChildren(); + + } + + inline void DetachSilhouette() + { + _SilhouetteRootNode->DetachChildren(); + //_pFENode->DetachChildren(); + //_pVisibleSilhouetteNode->DetachChildren(); + _p2DSelectionNode->destroy(); + } + + inline void DetachVisibleSilhouette() + { + //_pVisibleSilhouetteNode->DetachChildren(); + _p2DSelectionNode->destroy(); + } + + inline void DetachDebug() + { + _DebugRootNode->DetachChildren(); + } + + + + real distanceToSceneCenter(); + real GetFocalLength(); + + inline real GetAspect() const + { + return ((real) _width/(real) _height); + } + + void setHorizontalFov( float hfov ) +{ + _Fovy = 2.0 * atan (tan(hfov / 2.0) / GetAspect()); +} + inline real GetFovyRadian() const + { + return _Fovy; + } + + inline real GetFovyDegrees() const + { + return _Fovy * 180.0 / M_PI; + } + + BBox<Vec3r> scene3DBBox() const { return _ModelRootNode->bbox(); } + + real znear(); + real zfar(); + + +public: + /*! Core scene drawing */ + void DrawScene(SceneVisitor *iRenderer); + + /*! 2D Scene Drawing */ + void Draw2DScene(SceneVisitor *iRenderer); + + +protected: + + /*! fabs or abs */ + inline int rabs(int x) {return abs(x);} + inline real rabs(real x) {return fabs(x);} + + +protected: + float _Fovy; + + //The root node container + NodeGroup _RootNode; + NodeDrawingStyle *_ModelRootNode; + NodeDrawingStyle *_SilhouetteRootNode; + NodeDrawingStyle *_DebugRootNode; + + NodeGroup _Light; + + real _minBBox; + real _maxBBox; + real _maxAbs; + real _minAbs; + + // 2D Scene + bool _Draw2DScene; + bool _Draw3DScene; NodeGroup _p2DNode; + NodeDrawingStyle *_p2DSelectionNode; + +}; + +#endif // APPVIEW_H diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp new file mode 100755 index 00000000000..5cf1b40a344 --- /dev/null +++ b/source/blender/freestyle/intern/application/Controller.cpp @@ -0,0 +1,896 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +// Must be included before any QT header, because of moc +#include "../system/PythonInterpreter.h" + +#include <string> +#include <fstream> +#include <float.h> + +#include "AppView.h" +#include "AppCanvas.h" +#include "AppConfig.h" + + +#include "../system/StringUtils.h" +#include "../scene_graph/NodeShape.h" +#include "../scene_graph/NodeTransform.h" +#include "../scene_graph/NodeDrawingStyle.h" +#include "../winged_edge/WingedEdgeBuilder.h" +#include "../winged_edge/WEdge.h" +#include "../scene_graph/VertexRep.h" +#include "../winged_edge/WXEdgeBuilder.h" +#include "../scene_graph/ScenePrettyPrinter.h" +#include "../winged_edge/WFillGrid.h" + +#include "../view_map/ViewMapTesselator.h" +#include "../stroke/StrokeTesselator.h" +#include "../view_map/ViewMapIO.h" +#include "Controller.h" +#include "../view_map/ViewMap.h" +#include "../winged_edge/Curvature.h" +#include "../image/Image.h" +#include "../view_map/SteerableViewMap.h" +#include "../stroke/PSStrokeRenderer.h" +#include "../stroke/TextStrokeRenderer.h" +#include "../stroke/StyleModule.h" + +#include "../system/StringUtils.h" + +#include "../blender_interface/BlenderFileLoader.h" +#include "../blender_interface/BlenderStrokeRenderer.h" + +#ifdef __cplusplus +extern "C" { +#endif + + #include "../../FRS_freestyle.h" + +#ifdef __cplusplus +} +#endif + + + +Controller::Controller() +{ + + const string sep(Config::DIR_SEP.c_str()); + //const string filename = Config::Path::getInstance()->getHomeDir() + sep + Config::OPTIONS_DIR + sep + Config::OPTIONS_CURRENT_DIRS_FILE; + //_current_dirs = new ConfigIO(filename, Config::APPLICATION_NAME + "CurrentDirs", true); + + _RootNode = new NodeGroup; + _RootNode->addRef(); + + _SilhouetteNode = NULL; + //_ProjectedSilhouette = NULL; + //_VisibleProjectedSilhouette = NULL; + + _DebugNode = new NodeGroup; + _DebugNode->addRef(); + + _winged_edge = NULL; + + _pView = NULL; + + _edgeTesselationNature = (Nature::SILHOUETTE | Nature::BORDER | Nature::CREASE); + + _ProgressBar = new ProgressBar; + _SceneNumFaces = 0; + _minEdgeSize = DBL_MAX; + _EPSILON = 1e-6; + _bboxDiag = 0; + + _ViewMap = 0; + + _Canvas = 0; + + _VisibilityAlgo = ViewMapBuilder::ray_casting; + //_VisibilityAlgo = ViewMapBuilder::ray_casting_fast; + + _Canvas = new AppCanvas; + + _inter = new PythonInterpreter(); + _EnableQI = true; + _ComputeRidges = true; + _ComputeSteerableViewMap = false; + _ComputeSuggestive = true; + _ComputeMaterialBoundaries = true; + _sphereRadius = 1.0; + _creaseAngle = 134.43; + + init_options(); +} + +Controller::~Controller() +{ + if(NULL != _RootNode) + { + int ref = _RootNode->destroy(); + if(0 == ref) + delete _RootNode; + } + + if(NULL != _SilhouetteNode) + { + int ref = _SilhouetteNode->destroy(); + if(0 == ref) + delete _SilhouetteNode; + } + + if(NULL != _DebugNode) + { + int ref = _DebugNode->destroy(); + if(0 == ref) + delete _DebugNode; + } + + if(_winged_edge) { + delete _winged_edge; + _winged_edge = NULL; + } + + if(0 != _ViewMap) + { + delete _ViewMap; + _ViewMap = 0; + } + + if(0 != _Canvas) + { + delete _Canvas; + _Canvas = 0; + } + + if (_inter) { + delete _inter; + _inter = NULL; + } + + //delete _current_dirs; +} + +void Controller::setView(AppView *iView) +{ + if(NULL == iView) + return; + + _pView = iView; + _Canvas->setViewer(_pView); +} + +void Controller::setPassDiffuse(float *buf, int width, int height) +{ + AppCanvas *app_canvas = dynamic_cast<AppCanvas *>(_Canvas); + assert(app_canvas != 0); + app_canvas->setPassDiffuse(buf, width, height); +} + +void Controller::setPassZ(float *buf, int width, int height) +{ + AppCanvas *app_canvas = dynamic_cast<AppCanvas *>(_Canvas); + assert(app_canvas != 0); + app_canvas->setPassZ(buf, width, height); +} + +void Controller::setContext(bContext *C) +{ + PythonInterpreter* py_inter = dynamic_cast<PythonInterpreter*>(_inter); + assert(py_inter != 0); + py_inter->setContext(C); +} + +int Controller::LoadMesh(Render *re, SceneRenderLayer* srl) +{ + + BlenderFileLoader loader(re, srl); + + _Chrono.start(); + + NodeGroup *blenderScene = loader.Load(); + + if (blenderScene == NULL) { + cout << "Cannot load scene" << endl; + return 1; + } + + if( blenderScene->numberOfChildren() < 1) { + cout << "Empty scene" << endl; + blenderScene->destroy(); + delete blenderScene; + return 1; + } + + cout << "Scene loaded" << endl; + printf("Mesh cleaning : %lf\n", _Chrono.stop()); + _SceneNumFaces += loader.numFacesRead(); + + if(loader.minEdgeSize() < _minEdgeSize) + { + _minEdgeSize = loader.minEdgeSize(); + } + + // DEBUG + // ScenePrettyPrinter spp; + // blenderScene->accept(spp); + + _RootNode->AddChild(blenderScene); + _RootNode->UpdateBBox(); // FIXME: Correct that by making a Renderer to compute the bbox + + _pView->setModel(_RootNode); + //_pView->FitBBox(); + + + _Chrono.start(); + + + WXEdgeBuilder wx_builder; + blenderScene->accept(wx_builder); + _winged_edge = wx_builder.getWingedEdge(); + + printf("WEdge building : %lf\n", _Chrono.stop()); + + _Chrono.start(); + + _Grid.clear(); + Vec3r size; + for(unsigned int i=0; i<3; i++) + { + size[i] = fabs(_RootNode->bbox().getMax()[i] - _RootNode->bbox().getMin()[i]); + size[i] += size[i]/10.0; // let make the grid 1/10 bigger to avoid numerical errors while computing triangles/cells intersections + if(size[i]==0){ + cout << "Warning: the bbox size is 0 in dimension "<<i<<endl; + } + } + _Grid.configure(Vec3r(_RootNode->bbox().getMin() - size / 20.0), size, + _SceneNumFaces); + + // Fill in the grid: + WFillGrid fillGridRenderer(&_Grid, _winged_edge); + fillGridRenderer.fillGrid(); + + printf("Grid building : %lf\n", _Chrono.stop()); + + // DEBUG + _Grid.displayDebug(); + // + // _pView->setDebug(_DebugNode); + + //delete stuff + // if(0 != ws_builder) + // { + // delete ws_builder; + // ws_builder = 0; + // } + + //soc QFileInfo qfi(iFileName); + //soc string basename((const char*)qfi.fileName().toAscii().data()); + // char cleaned[FILE_MAX]; + // BLI_strncpy(cleaned, iFileName, FILE_MAX); + // BLI_cleanup_file(NULL, cleaned); + // string basename = StringUtils::toAscii( string(cleaned) ); + + _ListOfModels.push_back("Blender_models"); + + cout << "Triangles nb : " << _SceneNumFaces << endl; + _bboxDiag = (_RootNode->bbox().getMax()-_RootNode->bbox().getMin()).norm(); + cout << "Bounding Box : " << _bboxDiag << endl; + return 0; +} + + +void Controller::CloseFile() +{ + WShape::setCurrentId(0); + _pView->DetachModel(); + _ListOfModels.clear(); + if(NULL != _RootNode) + { + int ref = _RootNode->destroy(); + if(0 == ref) + _RootNode->addRef(); + + _RootNode->clearBBox(); + } + + _pView->DetachSilhouette(); + if (NULL != _SilhouetteNode) + { + int ref = _SilhouetteNode->destroy(); + if(0 == ref) + { + delete _SilhouetteNode; + _SilhouetteNode = NULL; + } + } + // if(NULL != _ProjectedSilhouette) + // { + // int ref = _ProjectedSilhouette->destroy(); + // if(0 == ref) + // { + // delete _ProjectedSilhouette; + // _ProjectedSilhouette = NULL; + // } + // } + // if(NULL != _VisibleProjectedSilhouette) + // { + // int ref = _VisibleProjectedSilhouette->destroy(); + // if(0 == ref) + // { + // delete _VisibleProjectedSilhouette; + // _VisibleProjectedSilhouette = NULL; + // } + // } + + _pView->DetachDebug(); + if(NULL != _DebugNode) + { + int ref = _DebugNode->destroy(); + if(0 == ref) + _DebugNode->addRef(); + } + + if(_winged_edge) { + delete _winged_edge; + _winged_edge = NULL; + } + + // We deallocate the memory: + if(NULL != _ViewMap) + { + delete _ViewMap; + _ViewMap = 0; + } + + // clears the canvas + _Canvas->Erase(); + + // clears the grid + _Grid.clear(); + _SceneNumFaces = 0; + _minEdgeSize = DBL_MAX; + + // soc: reset passes + setPassDiffuse(NULL, 0, 0); + setPassZ(NULL, 0, 0); +} + + + +void Controller::ComputeViewMap() +{ + + if (!_ListOfModels.size()) + return; + + if(NULL != _ViewMap) + { + delete _ViewMap; + _ViewMap = 0; + } + + _pView->DetachDebug(); + if(NULL != _DebugNode) + { + int ref = _DebugNode->destroy(); + if(0 == ref) + _DebugNode->addRef(); + } + + + _pView->DetachSilhouette(); + if (NULL != _SilhouetteNode) + { + int ref = _SilhouetteNode->destroy(); + if(0 == ref) + delete _SilhouetteNode; + } + // if(NULL != _ProjectedSilhouette) + // { + // int ref = _ProjectedSilhouette->destroy(); + // if(0 == ref) + // delete _ProjectedSilhouette; + // } + // if(NULL != _VisibleProjectedSilhouette) + // { + // int ref = _VisibleProjectedSilhouette->destroy(); + // if(0 == ref) + // { + // delete _VisibleProjectedSilhouette; + // _VisibleProjectedSilhouette = 0; + // } + // } + + // retrieve the 3D viewpoint and transformations information + //---------------------------------------------------------- + // Save the viewpoint context at the view level in order + // to be able to restore it later: + + // Restore the context of view: + // we need to perform all these operations while the + // 3D context is on. + Vec3r vp( freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]); + + //cout << "mv" << endl; + real mv[4][4]; + for( int i= 0; i < 4; i++) { + for( int j= 0; j < 4; j++) { + mv[i][j] = freestyle_mv[i][j]; + //cout << mv[i][j] << " "; + } + // cout << endl; + } + + //cout << "\nproj" << endl; + real proj[4][4]; + for( int i= 0; i < 4; i++) { + for( int j= 0; j < 4; j++) { + proj[i][j] = freestyle_proj[i][j]; + //cout << proj[i][j] << " "; + } + //cout << endl; + } + + int viewport[4]; + for( int i= 0; i < 4; i++) + viewport[i] = freestyle_viewport[i]; + + //cout << "\nfocal:" << _pView->GetFocalLength() << endl << endl; + + + + // Flag the WXEdge structure for silhouette edge detection: + //---------------------------------------------------------- + + cout << "\n=== Detecting silhouette edges ===" << endl; + _Chrono.start(); + + edgeDetector.setViewpoint(Vec3r(vp)); + edgeDetector.enableOrthographicProjection(proj[3][3] != 0.0); + edgeDetector.enableRidgesAndValleysFlag(_ComputeRidges); + edgeDetector.enableSuggestiveContours(_ComputeSuggestive); + edgeDetector.enableMaterialBoundaries(_ComputeMaterialBoundaries); + edgeDetector.setCreaseAngle(_creaseAngle); + edgeDetector.setSphereRadius(_sphereRadius); + edgeDetector.setSuggestiveContourKrDerivativeEpsilon(_suggestiveContourKrDerivativeEpsilon); + edgeDetector.processShapes(*_winged_edge); + + real duration = _Chrono.stop(); + printf("Feature lines : %lf\n", duration); + + // Builds the view map structure from the flagged WSEdge structure: + //---------------------------------------------------------- + ViewMapBuilder vmBuilder; + vmBuilder.setEnableQI(_EnableQI); + vmBuilder.setViewpoint(Vec3r(vp)); + vmBuilder.setTransform( mv, proj,viewport, _pView->GetFocalLength(), _pView->GetAspect(), _pView->GetFovyRadian()); + vmBuilder.setFrustum(_pView->znear(), _pView->zfar()); + vmBuilder.setGrid(&_Grid); + + // Builds a tesselated form of the silhouette for display purpose: + //--------------------------------------------------------------- + ViewMapTesselator3D sTesselator3d; + //ViewMapTesselator2D sTesselator2d; + //sTesselator2d.setNature(_edgeTesselationNature); + sTesselator3d.setNature(_edgeTesselationNature); + + cout << "\n=== Building the view map ===" << endl; + _Chrono.start(); + // Build View Map + _ViewMap = vmBuilder.BuildViewMap(*_winged_edge, _VisibilityAlgo, _EPSILON); + _ViewMap->setScene3dBBox(_RootNode->bbox()); + + printf("ViewMap edge count : %i\n", _ViewMap->viewedges_size() ); + + //Tesselate the 3D edges: + _SilhouetteNode = sTesselator3d.Tesselate(_ViewMap); + _SilhouetteNode->addRef(); + + // Tesselate 2D edges + // _ProjectedSilhouette = sTesselator2d.Tesselate(_ViewMap); + // _ProjectedSilhouette->addRef(); + + duration = _Chrono.stop(); + printf("ViewMap building : %lf\n", duration); + + + _pView->AddSilhouette(_SilhouetteNode); + //_pView->AddSilhouette(_WRoot); + //_pView->Add2DSilhouette(_ProjectedSilhouette); + //_pView->Add2DVisibleSilhouette(_VisibleProjectedSilhouette); + _pView->AddDebug(_DebugNode); + + // Draw the steerable density map: + //-------------------------------- + if(_ComputeSteerableViewMap){ + ComputeSteerableViewMap(); + } + // Reset Style modules modification flags + resetModified(true); +} + +void Controller::ComputeSteerableViewMap(){ +//soc + // if((!_Canvas) || (!_ViewMap)) + // return; + // + // // Build 4 nodes containing the edges in the 4 directions + // NodeGroup *ng[Canvas::NB_STEERABLE_VIEWMAP]; + // unsigned i; + // real c = 32.f/255.f; // see SteerableViewMap::readSteerableViewMapPixel() for information about this 32. + // for(i=0; i<Canvas::NB_STEERABLE_VIEWMAP; ++i){ + // ng[i] = new NodeGroup; + // } + // NodeShape *completeNS = new NodeShape; + // completeNS->material().setDiffuse(c,c,c,1); + // ng[Canvas::NB_STEERABLE_VIEWMAP-1]->AddChild(completeNS); + // SteerableViewMap * svm = _Canvas->getSteerableViewMap(); + // svm->Reset(); + // + // ViewMap::fedges_container& fedges = _ViewMap->FEdges(); + // LineRep * fRep; + // NodeShape *ns; + // for(ViewMap::fedges_container::iterator f=fedges.begin(), fend=fedges.end(); + // f!=fend; + // ++f){ + // if((*f)->viewedge()->qi() != 0) + // continue; + // fRep = new LineRep((*f)->vertexA()->point2d(),(*f)->vertexB()->point2d()) ; + // completeNS->AddRep(fRep); // add to the complete map anyway + // double *oweights = svm->AddFEdge(*f); + // for(i=0; i<Canvas::NB_STEERABLE_VIEWMAP-1; ++i){ + // ns = new NodeShape; + // double wc = oweights[i]*c; + // if(oweights[i] == 0) + // continue; + // ns->material().setDiffuse(wc, wc, wc, 1); + // ns->AddRep(fRep); + // ng[i]->AddChild(ns); + // } + // } + // + // GrayImage *img[Canvas::NB_STEERABLE_VIEWMAP]; + // //#ifdef WIN32 + // QGLBasicWidget offscreenBuffer(_pView, "SteerableViewMap", _pView->width(), _pView->height()); + // QPixmap pm; + // QImage qimg; + // for(i=0; i<Canvas::NB_STEERABLE_VIEWMAP; ++i){ + // offscreenBuffer.AddNode(ng[i]); + // //img[i] = new GrayImage(_pView->width(), _pView->height()); + // //offscreenBuffer.readPixels(0,0,_pView->width(), _pView->height(), img[i]->getArray()); + // pm = offscreenBuffer.renderPixmap(_pView->width(), _pView->height()); + // + // if(pm.isNull()) + // cout << "BuildViewMap Warning: couldn't render the steerable ViewMap" << endl; + // //pm.save(QString("steerable")+QString::number(i)+QString(".bmp"), "BMP"); + // // FIXME!! Lost of time ! + // qimg = pm.toImage(); + // // FIXME !! again! + // img[i] = new GrayImage(_pView->width(), _pView->height()); + // for(unsigned y=0;y<img[i]->height();++y){ + // for(unsigned x=0;x<img[i]->width();++x){ + // //img[i]->setPixel(x,y,(float)qGray(qimg.pixel(x,y))/255.f); + // img[i]->setPixel(x,y,(float)qGray(qimg.pixel(x,y))); + // // float c = qGray(qimg.pixel(x,y)); + // // img[i]->setPixel(x,y,qGray(qimg.pixel(x,y))); + // } + // } + // offscreenBuffer.DetachNode(ng[i]); + // ng[i]->destroy(); + // delete ng[i]; + // // check + // // qimg = QImage(_pView->width(), _pView->height(), 32); + // // for(y=0;y<img[i]->height();++y){ + // // for(unsigned x=0;x<img[i]->width();++x){ + // // float v = img[i]->pixel(x,y); + // // qimg.setPixel(x,y,qRgb(v,v,v)); + // // } + // // } + // // qimg.save(QString("newsteerable")+QString::number(i)+QString(".bmp"), "BMP"); + // } + // + // + // svm->buildImagesPyramids(img,false,0,1.f); +} + +void Controller::saveSteerableViewMapImages(){ + SteerableViewMap * svm = _Canvas->getSteerableViewMap(); + if(!svm){ + cerr << "the Steerable ViewMap has not been computed yet" << endl; + return; + } + svm->saveSteerableViewMap(); +} + +void Controller::toggleVisibilityAlgo() +{ + if(_VisibilityAlgo == ViewMapBuilder::ray_casting) { + _VisibilityAlgo = ViewMapBuilder::ray_casting_fast; + } + else if (_VisibilityAlgo == ViewMapBuilder::ray_casting_fast) { + _VisibilityAlgo = ViewMapBuilder::ray_casting_very_fast; + } + else { + _VisibilityAlgo = ViewMapBuilder::ray_casting; + } +} + +void Controller::setQuantitativeInvisibility(bool iBool) +{ + _EnableQI = iBool; +} + +bool Controller::getQuantitativeInvisibility() const +{ + return _EnableQI; +} + +void Controller::setComputeRidgesAndValleysFlag(bool iBool){ + _ComputeRidges = iBool; +} + +bool Controller::getComputeRidgesAndValleysFlag() const { + return _ComputeRidges; +} + +void Controller::setComputeSuggestiveContoursFlag(bool b){ + _ComputeSuggestive = b; +} + +bool Controller::getComputeSuggestiveContoursFlag() const { + return _ComputeSuggestive; +} + +void Controller::setComputeMaterialBoundariesFlag(bool b){ + _ComputeMaterialBoundaries = b; +} + +bool Controller::getComputeMaterialBoundariesFlag() const { + return _ComputeMaterialBoundaries; +} + +void Controller::setComputeSteerableViewMapFlag(bool iBool){ + _ComputeSteerableViewMap = iBool; +} + +bool Controller::getComputeSteerableViewMapFlag() const { + return _ComputeSteerableViewMap; +} + +void Controller::DrawStrokes() +{ + if(_ViewMap == 0) + return; + + cout << "\n=== Stroke drawing ===" << endl; + _Chrono.start(); + _Canvas->Draw(); + real d = _Chrono.stop(); + cout << "Strokes generation : " << d << endl; + cout << "Stroke count : " << _Canvas->stroke_count << endl; + resetModified(); +} + +void Controller::ResetRenderCount() +{ + _render_count = 0; +} + +Render* Controller::RenderStrokes(Render *re) { + BlenderStrokeRenderer* blenderRenderer = new BlenderStrokeRenderer(re, ++_render_count); + _Canvas->Render( blenderRenderer ); + Render* freestyle_render = blenderRenderer->RenderScene(re); + delete blenderRenderer; + + return freestyle_render; +} + +void Controller::InsertStyleModule(unsigned index, const char *iFileName) +{ + if( !BLI_testextensie(iFileName, ".py") ) { + cerr << "Error: Cannot load \"" << StringUtils::toAscii( string(iFileName) ) + << "\", unknown extension" << endl; + return; + } + + StyleModule* sm = new StyleModule(iFileName, _inter); + _Canvas->InsertStyleModule(index, sm); + +} + +void Controller::AddStyleModule(const char *iFileName) +{ + //_pStyleWindow->Add(iFileName); +} + +void Controller::RemoveStyleModule(unsigned index) +{ + _Canvas->RemoveStyleModule(index); +} + +void Controller::Clear() +{ + _Canvas->Clear(); +} + +void Controller::ReloadStyleModule(unsigned index, const char * iFileName) +{ + StyleModule* sm = new StyleModule(iFileName, _inter); + _Canvas->ReplaceStyleModule(index, sm); +} + +void Controller::SwapStyleModules(unsigned i1, unsigned i2) +{ + _Canvas->SwapStyleModules(i1, i2); +} + + +void Controller::toggleLayer(unsigned index, bool iDisplay) +{ + _Canvas->setVisible(index, iDisplay); +} + +void Controller::setModified(unsigned index, bool iMod) +{ + //_pStyleWindow->setModified(index, iMod); + _Canvas->setModified(index, iMod); + updateCausalStyleModules(index + 1); +} + +void Controller::updateCausalStyleModules(unsigned index) { + vector<unsigned> vec; + _Canvas->causalStyleModules(vec, index); + for (vector<unsigned>::const_iterator it = vec.begin(); it != vec.end(); it++) { + //_pStyleWindow->setModified(*it, true); + _Canvas->setModified(*it, true); + } +} + +void Controller::resetModified(bool iMod) +{ + //_pStyleWindow->resetModified(iMod); + _Canvas->resetModified(iMod); +} + +NodeGroup * Controller::BuildRep(vector<ViewEdge*>::iterator vedges_begin, + vector<ViewEdge*>::iterator vedges_end) +{ + ViewMapTesselator2D tesselator2D; + FrsMaterial mat; + mat.setDiffuse(1,1,0.3,1); + tesselator2D.setFrsMaterial(mat); + + return (tesselator2D.Tesselate(vedges_begin, vedges_end)); +} + +void Controller::toggleEdgeTesselationNature(Nature::EdgeNature iNature) +{ + _edgeTesselationNature ^= (iNature); + ComputeViewMap(); +} + +void Controller::setModelsDir(const string& dir) { + //_current_dirs->setValue("models/dir", dir); +} + +string Controller::getModelsDir() const { + string dir = "."; + //_current_dirs->getValue("models/dir", dir); + return dir; +} + +void Controller::setModulesDir(const string& dir) { + //_current_dirs->setValue("modules/dir", dir); +} + +string Controller::getModulesDir() const { + string dir = "."; + //_current_dirs->getValue("modules/dir", dir); + return dir; +} + +void Controller::setHelpIndex(const string& index) { + _help_index = index; +} + +string Controller::getHelpIndex() const { + return _help_index; +} + +void Controller::setBrowserCmd(const string& cmd) { + _browser_cmd = cmd; +} + +string Controller::getBrowserCmd() const { + return _browser_cmd; +} + +void Controller::resetInterpreter() { + if (_inter) + _inter->reset(); +} + + +void Controller::displayDensityCurves(int x, int y){ + SteerableViewMap * svm = _Canvas->getSteerableViewMap(); + if(!svm) + return; + + unsigned i,j; + typedef vector<Vec3r> densityCurve; + vector<densityCurve> curves(svm->getNumberOfOrientations()+1); + vector<densityCurve> curvesDirection(svm->getNumberOfPyramidLevels()); + + // collect the curves values + unsigned nbCurves = svm->getNumberOfOrientations()+1; + unsigned nbPoints = svm->getNumberOfPyramidLevels(); + if(!nbPoints) + return; + + // build the density/nbLevels curves for each orientation + for(i=0;i<nbCurves; ++i){ + for(j=0; j<nbPoints; ++j){ + curves[i].push_back(Vec3r(j, svm->readSteerableViewMapPixel(i, j, x, y), 0)); + } + } + // build the density/nbOrientations curves for each level + for(i=0;i<nbPoints; ++i){ + for(j=0; j<nbCurves; ++j){ + curvesDirection[i].push_back(Vec3r(j, svm->readSteerableViewMapPixel(j, i, x, y), 0)); + } + } + + // display the curves + // for(i=0; i<nbCurves; ++i) + // _pDensityCurvesWindow->setOrientationCurve(i, Vec2d(0,0), Vec2d(nbPoints, 1), curves[i], "scale", "density"); + // for(i=1; i<=8; ++i) + // _pDensityCurvesWindow->setLevelCurve(i, Vec2d(0,0), Vec2d(nbCurves, 1), curvesDirection[i], "orientation", "density"); + // _pDensityCurvesWindow->show(); +} + +void Controller::init_options(){ +// from AppOptionsWindow.cpp +// Default init options + + Config::Path * cpath = Config::Path::getInstance(); + + // Directories + ViewMapIO::Options::setModelsPath( StringUtils::toAscii( cpath->getModelsPath() ) ); + PythonInterpreter::Options::setPythonPath( StringUtils::toAscii( cpath->getPythonPath() ) ); + TextureManager::Options::setPatternsPath( StringUtils::toAscii( cpath->getPatternsPath() ) ); + TextureManager::Options::setBrushesPath( StringUtils::toAscii( cpath->getModelsPath() ) ); + + // ViewMap Format + ViewMapIO::Options::rmFlags(ViewMapIO::Options::FLOAT_VECTORS); + ViewMapIO::Options::rmFlags(ViewMapIO::Options::NO_OCCLUDERS); + setComputeSteerableViewMapFlag( false ); + + // Visibility + setQuantitativeInvisibility(true); + + // soc: initialize canvas + _Canvas->init(); + + // soc: initialize passes + setPassDiffuse(NULL, 0, 0); + setPassZ(NULL, 0, 0); +} diff --git a/source/blender/freestyle/intern/application/Controller.h b/source/blender/freestyle/intern/application/Controller.h new file mode 100755 index 00000000000..367b57bf6c3 --- /dev/null +++ b/source/blender/freestyle/intern/application/Controller.h @@ -0,0 +1,241 @@ +// +// Filename : Controller.h +// Author : Stephane Grabli +// Purpose : The spinal tap of the system +// Date of creation : 01/07/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef CONTROLLER_H +# define CONTROLLER_H + +# include "../view_map/ViewMapBuilder.h" +# include <string> +//# include "ConfigIO.h" +# include "../geometry/FastGrid.h" +# include "../geometry/HashGrid.h" +# include "../system/TimeUtils.h" +# include "../system/ProgressBar.h" +# include "../system/Precision.h" +# include "../system/Interpreter.h" +# include "../view_map/FEdgeXDetector.h" + +class AppView; +class NodeGroup; +class WShape; +class SShape; +class ViewMap; +class ViewEdge; +class AppCanvas; +class InteractiveShader; +class Shader; +class StrokeRenderer; + +#ifdef __cplusplus +extern "C" { +#endif + + #include "render_types.h" + #include "DNA_scene_types.h" + +#ifdef __cplusplus +} +#endif + +class Controller +{ +public: + Controller() ; + ~Controller() ; + + void setView(AppView *iView); + void setPassDiffuse(float *buf, int width, int height); + void setPassZ(float *buf, int width, int height); + void setContext(bContext *C); + + //soc + void init_options(); + + int LoadMesh( Render *re, SceneRenderLayer* srl ); + int Load3DSFile(const char *iFileName); + void CloseFile(); + void ComputeViewMap(); + void ComputeSteerableViewMap(); + void saveSteerableViewMapImages(); + void toggleEdgeTesselationNature(Nature::EdgeNature iNature); + void DrawStrokes(); + void ResetRenderCount(); + Render* RenderStrokes(Render *re); + void SwapStyleModules(unsigned i1, unsigned i2); + void InsertStyleModule(unsigned index, const char *iFileName); + void AddStyleModule(const char *iFileName); + void RemoveStyleModule(unsigned index); + void ReloadStyleModule(unsigned index, const char * iFileName); + void Clear(); + void toggleLayer(unsigned index, bool iDisplay); + void setModified(unsigned index, bool iMod); + void resetModified(bool iMod=false); + void updateCausalStyleModules(unsigned index); + void displayDensityCurves(int x, int y); + + + ViewEdge * SelectViewEdge(real x, real y); + FEdge * SelectFEdge(real x, real y); + NodeGroup* BuildRep(vector<ViewEdge*>::iterator vedges_begin, + vector<ViewEdge*>::iterator vedges_end) ; + + NodeGroup* debugNode() {return _DebugNode;} + AppView * view() {return _pView;} + NodeGroup* debugScene() {return _DebugNode;} + Grid& grid() {return _Grid;} + + void toggleVisibilityAlgo(); + + void setQuantitativeInvisibility(bool iBool); // if true, we compute quantitativeInvisibility + bool getQuantitativeInvisibility() const; + + void setComputeRidgesAndValleysFlag(bool b); + bool getComputeRidgesAndValleysFlag() const ; + void setComputeSuggestiveContoursFlag(bool b); + bool getComputeSuggestiveContoursFlag() const ; + void setComputeMaterialBoundariesFlag(bool b); + bool getComputeMaterialBoundariesFlag() const ; + + void setComputeSteerableViewMapFlag(bool iBool); + bool getComputeSteerableViewMapFlag() const; + void setCreaseAngle(real angle){_creaseAngle=angle;} + real getCreaseAngle() const {return _creaseAngle;} + void setSphereRadius(real s){_sphereRadius=s;} + real getSphereRadius() const {return _sphereRadius;} + void setSuggestiveContourKrDerivativeEpsilon(real dkr){_suggestiveContourKrDerivativeEpsilon=dkr;} + real getSuggestiveContourKrDerivativeEpsilon() const {return _suggestiveContourKrDerivativeEpsilon;} + + void setModelsDir(const string& dir); + string getModelsDir() const; + void setModulesDir(const string& dir); + string getModulesDir() const; + void setHelpIndex(const string& dir); + string getHelpIndex() const; + void setBrowserCmd(const string& cmd); + string getBrowserCmd() const; + + void resetInterpreter(); + +public: + // Viewmap data structure + ViewMap * _ViewMap; + + // Canvas + AppCanvas *_Canvas; + +private: + + // Main Window: + //AppMainWindow *_pMainWindow; + + // List of models currently loaded + vector<string> _ListOfModels; + + // Current directories + //ConfigIO* _current_dirs; + + + + //View + // 3D + AppView *_pView; + + // 2D + //Viewer2DWindow *_pView2DWindow; + //Viewer2D *_pView2D; + + //Model + // Drawing Structure + NodeGroup *_RootNode; + + // Winged-Edge structure + WingedEdge* _winged_edge; + + // Silhouette structure: + //std::vector<SShape*> _SShapes; + //NodeGroup *_SRoot; + + // Silhouette + NodeGroup *_SilhouetteNode; + NodeGroup *_ProjectedSilhouette; + NodeGroup *_VisibleProjectedSilhouette; + + // more Debug info + NodeGroup *_DebugNode; + + // debug + // NodeUser<ViewMap> *_ViewMapNode; // FIXME + + // Chronometer: + Chronometer _Chrono; + + // Progress Bar + ProgressBar *_ProgressBar; + + // edges tesselation nature + int _edgeTesselationNature; + + FastGrid _Grid; + //HashGrid _Grid; + + unsigned int _SceneNumFaces; + real _minEdgeSize; + real _EPSILON; + real _bboxDiag; + + int _render_count; + + //AppStyleWindow *_pStyleWindow; + //AppOptionsWindow *_pOptionsWindow; + //AppDensityCurvesWindow *_pDensityCurvesWindow; + + ViewMapBuilder::visibility_algo _VisibilityAlgo; + + // Script Interpreter + Interpreter* _inter; + + string _help_index; + string _browser_cmd; + + bool _EnableQI; + bool _ComputeRidges; + bool _ComputeSuggestive; + bool _ComputeMaterialBoundaries; + real _creaseAngle; + real _sphereRadius; + real _suggestiveContourKrDerivativeEpsilon; + + bool _ComputeSteerableViewMap; + + FEdgeXDetector edgeDetector; +}; + +extern Controller *g_pController; + +#endif // CONTROLLER_H diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp new file mode 100644 index 00000000000..3bf6ceb70f8 --- /dev/null +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp @@ -0,0 +1,435 @@ +#include "BlenderFileLoader.h" + +#include <assert.h> + +BlenderFileLoader::BlenderFileLoader(Render *re, SceneRenderLayer* srl) +{ + _re = re; + _srl = srl; + _Scene = NULL; + _numFacesRead = 0; + _minEdgeSize = DBL_MAX; +} + +BlenderFileLoader::~BlenderFileLoader() +{ + _Scene = NULL; +} + +NodeGroup* BlenderFileLoader::Load() +{ + ObjectInstanceRen *obi; + + cout << "\n=== Importing triangular meshes into Blender ===" << endl; + + // creation of the scene root node + _Scene = new NodeGroup; + + _viewplane_left= _re->viewplane.xmin; + _viewplane_right= _re->viewplane.xmax; + _viewplane_bottom= _re->viewplane.ymin; + _viewplane_top= _re->viewplane.ymax; + _z_near= -_re->clipsta; + _z_far= -_re->clipend; +#if 0 + cout << "frustrum: l " << _viewplane_left << " r " << _viewplane_right + << " b " << _viewplane_bottom << " t " << _viewplane_top + << " n " << _z_near << " f " << _z_far << endl; +#endif + + int id = 0; + for(obi= (ObjectInstanceRen *) _re->instancetable.first; obi; obi=obi->next) { + if (!(obi->lay & _re->scene->lay & _srl->lay)) + continue; + char *name = obi->ob->id.name; + //cout << name[0] << name[1] << ":" << (name+2) <<; + //print_m4("obi->mat", obi->mat); + + if( obi->obr->totvlak > 0) + insertShapeNode(obi, ++id); + else + cout << "Warning: " << (name+2) << " is not a vlak-based object (ignored)" << endl; + } + + //Returns the built scene. + return _Scene; +} + +#define CLIPPED_BY_NEAR -1 +#define NOT_CLIPPED 0 +#define CLIPPED_BY_FAR 1 + +// check if each vertex of a triangle (V1, V2, V3) is clipped by the near/far plane +// and calculate the number of triangles to be generated by clipping +int BlenderFileLoader::countClippedFaces(float v1[3], float v2[3], float v3[3], int clip[3]) +{ + float *v[3]; + int numClipped, sum, numTris; + + v[0] = v1; + v[1] = v2; + v[2] = v3; + numClipped = sum = 0; + for (int i = 0; i < 3; i++) { + if (v[i][2] > _z_near) { + clip[i] = CLIPPED_BY_NEAR; + numClipped++; + } else if (v[i][2] < _z_far) { + clip[i] = CLIPPED_BY_FAR; + numClipped++; + } else { + clip[i] = NOT_CLIPPED; + } +// printf("%d %s\n", i, (clip[i] == NOT_CLIPPED) ? "not" : (clip[i] == CLIPPED_BY_NEAR) ? "near" : "far"); + sum += clip[i]; + } + switch (numClipped) { + case 0: + numTris = 1; // triangle + break; + case 1: + numTris = 2; // tetragon + break; + case 2: + if (sum == 0) + numTris = 3; // pentagon + else + numTris = 1; // triangle + break; + case 3: + if (sum == 3 || sum == -3) + numTris = 0; + else + numTris = 2; // tetragon + break; + } + return numTris; +} + +// find the intersection point C between the line segment from V1 to V2 and +// a clipping plane at depth Z (i.e., the Z component of C is known, while +// the X and Y components are unknown). +void BlenderFileLoader::clipLine(float v1[3], float v2[3], float c[3], float z) +{ + double d[3]; + for (int i = 0; i < 3; i++) + d[i] = v2[i] - v1[i]; + double t = (z - v1[2]) / d[2]; + c[0] = v1[0] + t * d[0]; + c[1] = v1[1] + t * d[1]; + c[2] = z; +} + +// clip the triangle (V1, V2, V3) by the near and far clipping plane and +// obtain a set of vertices after the clipping. The number of vertices +// is at most 5. +void BlenderFileLoader::clipTriangle(int numTris, float triCoords[][3], float v1[3], float v2[3], float v3[3], int clip[3]) +{ + float *v[3]; + int i, j, k; + + v[0] = v1; + v[1] = v2; + v[2] = v3; + k = 0; + for (i = 0; i < 3; i++) { + j = (i + 1) % 3; + if (clip[i] == NOT_CLIPPED) { + copy_v3_v3(triCoords[k++], v[i]); + if (clip[j] != NOT_CLIPPED) { + clipLine(v[i], v[j], triCoords[k++], (clip[j] == CLIPPED_BY_NEAR) ? _z_near : _z_far); + } + } else if (clip[i] != clip[j]) { + if (clip[j] == NOT_CLIPPED) { + clipLine(v[i], v[j], triCoords[k++], (clip[i] == CLIPPED_BY_NEAR) ? _z_near : _z_far); + } else { + clipLine(v[i], v[j], triCoords[k++], (clip[i] == CLIPPED_BY_NEAR) ? _z_near : _z_far); + clipLine(v[i], v[j], triCoords[k++], (clip[j] == CLIPPED_BY_NEAR) ? _z_near : _z_far); + } + } + } + assert (k == 2 + numTris); +} + +void BlenderFileLoader::addTriangle(struct LoaderState *ls, float v1[3], float v2[3], float v3[3]) +{ + float v12[3], v13[3], n[3]; + float *fv[3], len; + unsigned i, j; + + // initialize the bounding box by the first vertex + if (ls->currentIndex == 0) { + copy_v3_v3(ls->minBBox, v1); + copy_v3_v3(ls->maxBBox, v1); + } + + // compute the normal of the triangle + sub_v3_v3v3(v12, v1, v2); + sub_v3_v3v3(v13, v1, v3); + cross_v3_v3v3(n, v12, v13); + normalize_v3(n); + + fv[0] = v1; + fv[1] = v2; + fv[2] = v3; + for (i = 0; i < 3; i++) { + + copy_v3_v3(ls->pv, fv[i]); + copy_v3_v3(ls->pn, n); + + // update the bounding box + for (j = 0; j < 3; j++) + { + if (ls->minBBox[j] > ls->pv[j]) + ls->minBBox[j] = ls->pv[j]; + + if (ls->maxBBox[j] < ls->pv[j]) + ls->maxBBox[j] = ls->pv[j]; + } + + len = len_v3v3(fv[i], fv[(i + 1) % 3]); + if (_minEdgeSize > len) + _minEdgeSize = len; + + *ls->pvi = ls->currentIndex; + *ls->pni = ls->currentIndex; + *ls->pmi = ls->currentMIndex; + + ls->currentIndex +=3; + ls->pv += 3; + ls->pn += 3; + + ls->pvi++; + ls->pni++; + ls->pmi++; + } +} + +void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id) +{ + ObjectRen *obr = obi->obr; + + // We parse vlak nodes and count the number of faces after the clipping by + // the near and far view planes is applied (Note: mesh vertices are in the + // camera coordinate system). + VlakRen *vlr; + unsigned numFaces = 0; + float v1[3], v2[3], v3[3], v4[3]; + int clip_1[3], clip_2[3]; + int wire_material = 0; + for(int a=0; a < obr->totvlak; a++) { + if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; + else vlr++; + if (vlr->mat->material_type == MA_TYPE_WIRE) { + wire_material = 1; + continue; + } + copy_v3_v3(v1, vlr->v1->co); + copy_v3_v3(v2, vlr->v2->co); + copy_v3_v3(v3, vlr->v3->co); + if (vlr->v4) copy_v3_v3(v4, vlr->v4->co); + if (obi->flag & R_TRANSFORMED) { + mul_m4_v3(obi->mat, v1); + mul_m4_v3(obi->mat, v2); + mul_m4_v3(obi->mat, v3); + if (vlr->v4) mul_m4_v3(obi->mat, v4); + } +// print_v3("v1", v1); +// print_v3("v2", v2); +// print_v3("v3", v3); +// if (vlr->v4) print_v3("v4", v4); + numFaces += countClippedFaces(v1, v2, v3, clip_1); + if (vlr->v4) + numFaces += countClippedFaces(v1, v3, v4, clip_2); + } + if (wire_material) + cout << "Warning: some faces have wire materials (ignored)" << endl; +// cout <<"numFaces " <<numFaces<<endl; + if (numFaces == 0) + return; + + // We allocate memory for the meshes to be imported + NodeTransform *currentMesh = new NodeTransform; + NodeShape * shape = new NodeShape; + + unsigned vSize = 3*3*numFaces; + float *vertices = new float[vSize]; + unsigned nSize = vSize; + float *normals = new float[nSize]; + unsigned *numVertexPerFaces = new unsigned[numFaces]; + vector<FrsMaterial> meshFrsMaterials; + + IndexedFaceSet::TRIANGLES_STYLE *faceStyle = new IndexedFaceSet::TRIANGLES_STYLE[numFaces]; + unsigned i; + for (i = 0; i <numFaces; i++) { + faceStyle[i] = IndexedFaceSet::TRIANGLES; + numVertexPerFaces[i] = 3; + } + + unsigned viSize = 3*numFaces; + unsigned *VIndices = new unsigned[viSize]; + unsigned niSize = viSize; + unsigned *NIndices = new unsigned[niSize]; + unsigned *MIndices = new unsigned[viSize]; // Material Indices + + struct LoaderState ls; + ls.pv = vertices; + ls.pn = normals; + ls.pvi = VIndices; + ls.pni = NIndices; + ls.pmi = MIndices; + ls.currentIndex = 0; + ls.currentMIndex = 0; + + FrsMaterial tmpMat; + + // We parse the vlak nodes again and import meshes while applying the clipping + // by the near and far view planes. + int p; + for(p=0; p < obr->totvlak; ++p) // we parse the faces of the mesh + { + // Lib3dsFace *f=&mesh->faceL[p]; + // Lib3dsMaterial *mat=0; + if((p & 255)==0) vlr = obr->vlaknodes[p>>8].vlak; + else vlr++; + copy_v3_v3(v1, vlr->v1->co); + copy_v3_v3(v2, vlr->v2->co); + copy_v3_v3(v3, vlr->v3->co); + if (vlr->v4) copy_v3_v3(v4, vlr->v4->co); + if (obi->flag & R_TRANSFORMED) { + mul_m4_v3(obi->mat, v1); + mul_m4_v3(obi->mat, v2); + mul_m4_v3(obi->mat, v3); + if (vlr->v4) mul_m4_v3(obi->mat, v4); + } + + unsigned numTris_1, numTris_2; + numTris_1 = countClippedFaces(v1, v2, v3, clip_1); + numTris_2 = (vlr->v4) ? countClippedFaces(v1, v3, v4, clip_2) : 0; + if (numTris_1 == 0 && numTris_2 == 0) + continue; + + Material *mat = vlr->mat; + + if (mat) + { + tmpMat.setDiffuse( mat->r, mat->g, mat->b, mat->alpha ); + tmpMat.setSpecular( mat->specr, mat->specg, mat->specb, mat->spectra); + float s = 1.0 * (mat->har + 1) / 4 ; // in Blender: [1;511] => in OpenGL: [0;128] + if(s > 128.f) + s = 128.f; + tmpMat.setShininess(s); + } + + if(meshFrsMaterials.empty()) + { + meshFrsMaterials.push_back(tmpMat); + shape->setFrsMaterial(tmpMat); + } else { + // find if the material is aleady in the list + unsigned i=0; + bool found = false; + + for(vector<FrsMaterial>::iterator it=meshFrsMaterials.begin(), itend=meshFrsMaterials.end(); + it!=itend; + ++it){ + if(*it == tmpMat){ + ls.currentMIndex = i; + found = true; + break; + } + ++i; + } + + if(!found){ + meshFrsMaterials.push_back(tmpMat); + ls.currentMIndex = meshFrsMaterials.size()-1; + } + } + + float triCoords[5][3]; + + if (numTris_1 > 0) { + clipTriangle(numTris_1, triCoords, v1, v2, v3, clip_1); + for (i = 0; i < numTris_1; i++) { + addTriangle(&ls, triCoords[0], triCoords[i+1], triCoords[i+2]); + _numFacesRead++; + } + } + + if (numTris_2 > 0) { + clipTriangle(numTris_2, triCoords, v1, v3, v4, clip_2); + for (i = 0; i < numTris_2; i++) { + addTriangle(&ls, triCoords[0], triCoords[i+1], triCoords[i+2]); + _numFacesRead++; + } + } + } + + // We might have several times the same vertex. We want a clean + // shape with no real-vertex. Here, we are making a cleaning + // pass. + real *cleanVertices = NULL; + unsigned cvSize; + unsigned *cleanVIndices = NULL; + + GeomCleaner::CleanIndexedVertexArray( + vertices, vSize, + VIndices, viSize, + &cleanVertices, &cvSize, + &cleanVIndices); + + real *cleanNormals = NULL; + unsigned cnSize; + unsigned *cleanNIndices = NULL; + + GeomCleaner::CleanIndexedVertexArray( + normals, nSize, + NIndices, niSize, + &cleanNormals, &cnSize, + &cleanNIndices); + + // format materials array + FrsMaterial** marray = new FrsMaterial*[meshFrsMaterials.size()]; + unsigned mindex=0; + for(vector<FrsMaterial>::iterator m=meshFrsMaterials.begin(), mend=meshFrsMaterials.end(); + m!=mend; + ++m){ + marray[mindex] = new FrsMaterial(*m); + ++mindex; + } + // deallocates memory: + delete [] vertices; + delete [] normals; + delete [] VIndices; + delete [] NIndices; + + // Create the IndexedFaceSet with the retrieved attributes + IndexedFaceSet *rep; + rep = new IndexedFaceSet(cleanVertices, cvSize, + cleanNormals, cnSize, + marray, meshFrsMaterials.size(), + 0, 0, + numFaces, numVertexPerFaces, faceStyle, + cleanVIndices, viSize, + cleanNIndices, niSize, + MIndices, viSize, + 0,0, + 0); + // sets the id of the rep + rep->setId(Id(id, 0)); + rep->setName(obi->ob->id.name+2); + + const BBox<Vec3r> bbox = BBox<Vec3r>(Vec3r(ls.minBBox[0], ls.minBBox[1], ls.minBBox[2]), + Vec3r(ls.maxBBox[0], ls.maxBBox[1], ls.maxBBox[2])); + rep->setBBox(bbox); + shape->AddRep(rep); + + Matrix44r meshMat = Matrix44r::identity(); + currentMesh->setMatrix(meshMat); + currentMesh->Translate(0,0,0); + + currentMesh->AddChild(shape); + _Scene->AddChild(currentMesh); + +} diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h new file mode 100644 index 00000000000..038f4bdd6c8 --- /dev/null +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h @@ -0,0 +1,84 @@ +#ifndef BLENDER_FILE_LOADER_H +# define BLENDER_FILE_LOADER_H + +# include <string.h> +# include <float.h> + +# include "../system/FreestyleConfig.h" +# include "../scene_graph/NodeGroup.h" +# include "../scene_graph/NodeTransform.h" +# include "../scene_graph/NodeShape.h" +# include "../scene_graph/IndexedFaceSet.h" +# include "../geometry/BBox.h" +# include "../geometry/Geom.h" +# include "../geometry/GeomCleaner.h" + +#ifdef __cplusplus +extern "C" { +#endif + + #include "DNA_material_types.h" + #include "DNA_scene_types.h" + #include "render_types.h" + #include "renderdatabase.h" + + #include "BKE_mesh.h" + #include "BKE_scene.h" + #include "BLI_math.h" + +#ifdef __cplusplus +} +#endif + + +class NodeGroup; + +struct LoaderState { + float *pv; + float *pn; + unsigned *pvi; + unsigned *pni; + unsigned *pmi; + unsigned currentIndex; + unsigned currentMIndex; + float minBBox[3]; + float maxBBox[3]; +}; + +class LIB_SCENE_GRAPH_EXPORT BlenderFileLoader +{ +public: + /*! Builds a MaxFileLoader */ + BlenderFileLoader(Render *re, SceneRenderLayer* srl); + virtual ~BlenderFileLoader(); + + /*! Loads the 3D scene and returns a pointer to the scene root node */ + NodeGroup * Load(); + + /*! Gets the number of read faces */ + inline unsigned int numFacesRead() {return _numFacesRead;} + + /*! Gets the smallest edge size read */ + inline real minEdgeSize() {return _minEdgeSize;} + +protected: + void insertShapeNode(ObjectInstanceRen *obi, int id); + int countClippedFaces(float v1[3], float v2[3], float v3[3], int clip[3]); + void clipLine(float v1[3], float v2[3], float c[3], float z); + void clipTriangle(int numTris, float triCoords[][3], float v1[3], float v2[3], float v3[3], int clip[3]); + void addTriangle(struct LoaderState *ls, float v1[3], float v2[3], float v3[3]); + +protected: + Render* _re; + SceneRenderLayer* _srl; + NodeGroup* _Scene; + unsigned _numFacesRead; + real _minEdgeSize; + float _viewplane_left; + float _viewplane_right; + float _viewplane_bottom; + float _viewplane_top; + float _z_near, _z_far; +}; + +#endif // BLENDER_FILE_LOADER_H diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp new file mode 100644 index 00000000000..4c6ea48f692 --- /dev/null +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -0,0 +1,341 @@ +# include "BlenderStrokeRenderer.h" +# include "../stroke/Canvas.h" +# include "../application/AppConfig.h" + +# include "BlenderTextureManager.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "MEM_guardedalloc.h" + +#include "DNA_camera_types.h" +#include "DNA_customdata_types.h" +#include "DNA_listBase.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_screen_types.h" + +#include "BKE_customdata.h" +#include "BKE_global.h" +#include "BKE_library.h" /* free_libblock */ +#include "BKE_material.h" +#include "BKE_main.h" /* struct Main */ +#include "BKE_object.h" +#include "BKE_scene.h" + +#include "RE_pipeline.h" + +#ifdef __cplusplus +} +#endif + + +BlenderStrokeRenderer::BlenderStrokeRenderer(Render* re, int render_count) +:StrokeRenderer(){ + + // TEMPORARY - need a texture manager + _textureManager = new BlenderTextureManager; + _textureManager->load(); + + // Scene.New("FreestyleStrokes") + old_scene = re->scene; + + ListBase lb; + char name[22]; + snprintf(name, sizeof(name), "FRS%d_%s", render_count, re->scene->id.name+2); + freestyle_scene = add_scene(name); + lb = freestyle_scene->r.layers; + freestyle_scene->r= old_scene->r; + freestyle_scene->r.layers= lb; + set_scene_bg( freestyle_scene ); + + // image dimensions + float ycor = ((float)re->r.yasp) / ((float)re->r.xasp); + float width = freestyle_scene->r.xsch; + float height = freestyle_scene->r.ysch * ycor; + + // Camera + Object* object_camera = add_object(freestyle_scene, OB_CAMERA); + + Camera* camera = (Camera *) object_camera->data; + camera->type = CAM_ORTHO; + camera->ortho_scale = max(width,height); + camera->clipsta = 0.1f; + camera->clipend = 100.0f; + + _z_delta = 0.00001f; + _z = camera->clipsta + _z_delta; + + // test + //_z = 999.90f; _z_delta = 0.01f; + + object_camera->loc[0] = 0.5 * width; + object_camera->loc[1] = 0.5 * height; + object_camera->loc[2] = 1.0; + + freestyle_scene->camera = object_camera; + + // Material + material = add_material("stroke_material"); + material->mode |= MA_VERTEXCOLP; + material->mode |= MA_TRANSP; + material->mode |= MA_SHLESS; + material->vcol_alpha = 1; +} + +BlenderStrokeRenderer::~BlenderStrokeRenderer(){ + + if(0 != _textureManager) + { + delete _textureManager; + _textureManager = 0; + } + + // The freestyle_scene object is not released here. Instead, + // the scene is released in free_all_freestyle_renders() in + // source/blender/render/intern/source/pipeline.c, after the + // compositor has finished. + + // release objects and data blocks + Base *b = (Base *)freestyle_scene->base.first; + while(b) { + Object *ob = b->object; + void *data = ob->data; + char name[24]; + strcpy(name, ob->id.name); + //cout << "removing " << name[0] << name[1] << ":" << (name+2) << endl; + switch (ob->type) { + case OB_MESH: + free_libblock( &G.main->object, ob ); + free_libblock( &G.main->mesh, data ); + break; + case OB_CAMERA: + free_libblock( &G.main->object, ob ); + free_libblock( &G.main->camera, data ); + freestyle_scene->camera = NULL; + break; + default: + cerr << "Warning: unexpected object in the scene: " << name[0] << name[1] << ":" << (name+2) << endl; + } + b = b->next; + } + BLI_freelistN( &freestyle_scene->base ); + + // release material + free_libblock( &G.main->mat, material ); + + set_scene_bg( old_scene ); +} + +float BlenderStrokeRenderer::get_stroke_vertex_z(void) const { + float z = _z; + BlenderStrokeRenderer *self = const_cast<BlenderStrokeRenderer *>(this); + if (!(_z < _z_delta * 100000.0f)) + self->_z_delta *= 10.0f; + self->_z += _z_delta; + return -z; +} + +void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const{ + RenderStrokeRepBasic(iStrokeRep); +} + +void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const{ + + //////////////////// + // Build up scene + //////////////////// + + vector<Strip*>& strips = iStrokeRep->getStrips(); + Strip::vertex_container::iterator v[3]; + StrokeVertexRep *svRep[3]; + Vec3r color[3]; + unsigned int vertex_index; + float ycor = ((float)freestyle_scene->r.yasp) / ((float)freestyle_scene->r.xasp); + float width = freestyle_scene->r.xsch; + float height = freestyle_scene->r.ysch * ycor; + Vec2r p; + + for(vector<Strip*>::iterator s=strips.begin(), send=strips.end(); + s!=send; + ++s){ + + Strip::vertex_container& strip_vertices = (*s)->vertices(); + int strip_vertex_count = (*s)->sizeStrip(); + int m, n, visible_faces, visible_segments; + bool visible; + + // iterate over all vertices and count visible faces and strip segments + // (note: a strip segment is a series of visible faces, while two strip + // segments are separated by one or more invisible faces) + v[0] = strip_vertices.begin(); + v[1] = v[0]; ++(v[1]); + v[2] = v[1]; ++(v[2]); + visible_faces = visible_segments = 0; + visible = false; + for (n = 2; n < strip_vertex_count; n++) + { + svRep[0] = *(v[0]); + svRep[1] = *(v[1]); + svRep[2] = *(v[2]); + m = 0; + for (int j = 0; j < 3; j++) { + p = svRep[j]->point2d(); + if (p[0] < 0.0 || p[0] > width || p[1] < 0.0 || p[1] > height) + m++; + } + if (m == 3) { + visible = false; + } else { + visible_faces++; + if (!visible) + visible_segments++; + visible = true; + } + ++v[0]; ++v[1]; ++v[2]; + } + if (visible_faces == 0) + continue; + + // me = Mesh.New() + Object* object_mesh = add_object(freestyle_scene, OB_MESH); + Mesh* mesh = (Mesh *) object_mesh->data; + MEM_freeN(mesh->bb); + mesh->bb= NULL; + mesh->id.us = 0; + +#if 1 + // me.materials = [mat] + mesh->mat = ( Material ** ) MEM_mallocN( 1 * sizeof( Material * ), "MaterialList" ); + mesh->mat[0] = material; + mesh->totcol = 1; + test_object_materials( (ID*) mesh ); +#else + assign_material(object_mesh, material, object_mesh->totcol+1); + object_mesh->actcol= object_mesh->totcol; +#endif + + // vertices allocation + mesh->totvert = visible_faces + visible_segments * 2; + mesh->mvert = (MVert*) CustomData_add_layer( &mesh->vdata, CD_MVERT, CD_CALLOC, NULL, mesh->totvert); + + // faces allocation + mesh->totface = visible_faces; + mesh->mface = (MFace*) CustomData_add_layer( &mesh->fdata, CD_MFACE, CD_CALLOC, NULL, mesh->totface); + + // colors allocation - me.vertexColors = True + mesh->mcol = (MCol *) CustomData_add_layer( &mesh->fdata, CD_MCOL, CD_CALLOC, NULL, mesh->totface ); + + //////////////////// + // Data copy + //////////////////// + + MVert* vertices = mesh->mvert; + MFace* faces = mesh->mface; + MCol* colors = mesh->mcol; + + v[0] = strip_vertices.begin(); + v[1] = v[0]; ++(v[1]); + v[2] = v[1]; ++(v[2]); + + vertex_index = 0; + visible = false; + + for (n = 2; n < strip_vertex_count; n++) + { + svRep[0] = *(v[0]); + svRep[1] = *(v[1]); + svRep[2] = *(v[2]); + m = 0; + for (int j = 0; j < 3; j++) { + p = svRep[j]->point2d(); + if (p[0] < 0.0 || p[0] > width || p[1] < 0.0 || p[1] > height) + m++; + } + if (m == 3) { + visible = false; + } else { + if (!visible) { + vertex_index += 2; + + // first vertex + vertices->co[0] = svRep[0]->point2d()[0]; + vertices->co[1] = svRep[0]->point2d()[1]; + vertices->co[2] = get_stroke_vertex_z(); + ++vertices; + + // second vertex + vertices->co[0] = svRep[1]->point2d()[0]; + vertices->co[1] = svRep[1]->point2d()[1]; + vertices->co[2] = get_stroke_vertex_z(); + ++vertices; + } + visible = true; + + // vertex + vertices->co[0] = svRep[2]->point2d()[0]; + vertices->co[1] = svRep[2]->point2d()[1]; + vertices->co[2] = get_stroke_vertex_z(); + + // faces + faces->v1 = vertex_index - 2; + faces->v2 = vertex_index - 1; + faces->v3 = vertex_index; + faces->v4 = 0; + + // colors + // red and blue are swapped - cf DNA_meshdata_types.h : MCol + color[0] = svRep[0]->color(); + color[1] = svRep[1]->color(); + color[2] = svRep[2]->color(); + + colors->r = (short)(255.0f*(color[0])[2]); + colors->g = (short)(255.0f*(color[0])[1]); + colors->b = (short)(255.0f*(color[0])[0]); + colors->a = (short)(255.0f*svRep[0]->alpha()); + ++colors; + + colors->r = (short)(255.0f*(color[1])[2]); + colors->g = (short)(255.0f*(color[1])[1]); + colors->b = (short)(255.0f*(color[1])[0]); + colors->a = (short)(255.0f*svRep[1]->alpha()); + ++colors; + + colors->r = (short)(255.0f*(color[2])[2]); + colors->g = (short)(255.0f*(color[2])[1]); + colors->b = (short)(255.0f*(color[2])[0]); + colors->a = (short)(255.0f*svRep[2]->alpha()); + ++colors; + + ++faces; ++vertices; ++colors; + ++vertex_index; + } + ++v[0]; ++v[1]; ++v[2]; + + } // loop over strip vertices + + } // loop over strips + +} + +Render* BlenderStrokeRenderer::RenderScene( Render *re ) { + Camera *camera = (Camera *)freestyle_scene->camera->data; + if (camera->clipend < _z) + camera->clipend = _z + _z_delta * 100.0f; + //cout << "clipsta " << camera->clipsta << ", clipend " << camera->clipend << endl; + + freestyle_scene->r.mode &= ~( R_EDGE_FRS | R_SHADOW | R_SSS | R_PANORAMA | R_ENVMAP | R_MBLUR ); + freestyle_scene->r.scemode &= ~( R_SINGLE_LAYER ); + freestyle_scene->r.planes = R_PLANES32; + freestyle_scene->r.imtype = R_PNG; + if (freestyle_scene->r.mode & R_BORDER) + freestyle_scene->r.mode |= R_CROP; + + Render *freestyle_render = RE_NewRender(freestyle_scene->id.name); + + RE_RenderFreestyleStrokes(freestyle_render, freestyle_scene); + return freestyle_render; +} diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h new file mode 100644 index 00000000000..40d87ce53a1 --- /dev/null +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h @@ -0,0 +1,44 @@ +#ifndef BLENDERSTROKERENDERER_H +# define BLENDERSTROKERENDERER_H + +# include "../stroke/StrokeRenderer.h" +# include "../system/FreestyleConfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "DNA_material_types.h" +#include "DNA_scene_types.h" + +#include "render_types.h" + +#ifdef __cplusplus +} +#endif + + + +class LIB_STROKE_EXPORT BlenderStrokeRenderer : public StrokeRenderer +{ +public: + BlenderStrokeRenderer(Render *re, int render_count); + virtual ~BlenderStrokeRenderer(); + + /*! Renders a stroke rep */ + virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const; + virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const; + + Render* RenderScene(Render *re); + +protected: + Scene* old_scene; + Scene* freestyle_scene; + Material* material; + float _z, _z_delta; + + float get_stroke_vertex_z(void) const; +}; + +#endif // BLENDERSTROKERENDERER_H + diff --git a/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.cpp b/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.cpp new file mode 100644 index 00000000000..d731af42d0e --- /dev/null +++ b/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.cpp @@ -0,0 +1,71 @@ +#include "BlenderTextureManager.h" + + +BlenderTextureManager::BlenderTextureManager () +: TextureManager() +{ + //_brushes_path = Config::getInstance()... +} + +BlenderTextureManager::~BlenderTextureManager () +{ +} + +void BlenderTextureManager::loadStandardBrushes() +{ + // getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::HUMID_MEDIUM); + // getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::HUMID_MEDIUM); + // getBrushTextureIndex(TEXTURES_DIR "/brushes/oil.bmp", Stroke::HUMID_MEDIUM); + // getBrushTextureIndex(TEXTURES_DIR "/brushes/oilnoblend.bmp", Stroke::HUMID_MEDIUM); + // getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::DRY_MEDIUM); + // getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::DRY_MEDIUM); + // getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueDryBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM); + // getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM); + //_defaultTextureId = getBrushTextureIndex("smoothAlpha.bmp", Stroke::OPAQUE_MEDIUM); +} + + +unsigned +BlenderTextureManager::loadBrush(string sname, Stroke::MediumType mediumType) +{ +// GLuint texId; +// glGenTextures(1, &texId); +// bool found = false; +// vector<string> pathnames; +// string path; //soc +// StringUtils::getPathName(TextureManager::Options::getBrushesPath(), +// sname, +// pathnames); +// for (vector<string>::const_iterator j = pathnames.begin(); j != pathnames.end(); j++) { +// path = j->c_str(); +// //soc if(QFile::exists(path)){ +// if( BLI_exists( const_cast<char *>(path.c_str()) ) ) { +// found = true; +// break; +// } +// } +// if(!found) +// return 0; +// // Brush texture +// cout << "Loading brush texture..." << endl; +// switch(mediumType){ +// case Stroke::DRY_MEDIUM: +// //soc prepareTextureLuminance((const char*)path.toAscii(), texId); +// prepareTextureLuminance(StringUtils::toAscii(path), texId); +// break; +// case Stroke::HUMID_MEDIUM: +// case Stroke::OPAQUE_MEDIUM: +// default: +// //soc prepareTextureAlpha((const char*)path.toAscii(), texId); +// prepareTextureAlpha(StringUtils::toAscii(path), texId); +// break; +// } +// cout << "Done." << endl << endl; +// +// return texId; +// + return 0; +} + + + diff --git a/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.h b/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.h new file mode 100644 index 00000000000..fac33c139e1 --- /dev/null +++ b/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.h @@ -0,0 +1,23 @@ +#ifndef BLENDERTEXTUREMANAGER_H +#define BLENDERTEXTUREMANAGER_H + +# include "../stroke/StrokeRenderer.h" +# include "../stroke/StrokeRep.h" +# include "../system/FreestyleConfig.h" + +/*! Class to load textures + */ +class LIB_RENDERING_EXPORT BlenderTextureManager : public TextureManager +{ + public: + BlenderTextureManager (); + virtual ~BlenderTextureManager (); +protected: + virtual unsigned loadBrush(string fileName, Stroke::MediumType = Stroke::OPAQUE_MEDIUM); + + protected: + virtual void loadStandardBrushes(); + +}; + +#endif // BLENDERTEXTUREMANAGER_H diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp new file mode 100644 index 00000000000..b208aa13d4f --- /dev/null +++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp @@ -0,0 +1,457 @@ +#include "../application/Controller.h" +#include "../application/AppView.h" +#include "../application/AppConfig.h" +#include "../application/AppCanvas.h" + +#include <iostream> +#include <map> +#include <set> +using namespace std; + +#ifdef __cplusplus +extern "C" { +#endif + +#include "MEM_guardedalloc.h" + +#include "DNA_camera_types.h" +#include "DNA_freestyle_types.h" + +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_linestyle.h" +#include "BKE_main.h" +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BPY_extern.h" + +#include "renderpipeline.h" +#include "pixelblending.h" + +#include "../../FRS_freestyle.h" +#include "../../FRS_freestyle_config.h" + + // Freestyle configuration + static short freestyle_is_initialized = 0; + static Config::Path *pathconfig = NULL; + static Controller *controller = NULL; + static AppView *view = NULL; + + // camera information + float freestyle_viewpoint[3]; + float freestyle_mv[4][4]; + float freestyle_proj[4][4]; + int freestyle_viewport[4]; + + // current scene + Scene *freestyle_scene; + + string default_module_path; + + //======================================================= + // Initialization + //======================================================= + + void FRS_initialize() { + + if( freestyle_is_initialized ) + return; + + pathconfig = new Config::Path; + controller = new Controller(); + view = new AppView; + controller->setView(view); + freestyle_scene = NULL; + + default_module_path = pathconfig->getProjectDir() + Config::DIR_SEP + "style_modules" + Config::DIR_SEP + "contour.py"; + + freestyle_is_initialized = 1; + } + + void FRS_set_context(bContext* C) { + cout << "FRS_set_context: context 0x" << C << " scene 0x" << CTX_data_scene(C) << endl; + controller->setContext(C); + } + + void FRS_exit() { + delete pathconfig; + delete controller; + delete view; + } + + //======================================================= + // Rendering + //======================================================= + + void init_view(Render* re){ + float ycor = ((float)re->r.yasp) / ((float)re->r.xasp); + int width = re->r.xsch; + int height = (int)(((float)re->r.ysch) * ycor); + int xmin = re->r.border.xmin * width; + int xmax = re->r.border.xmax * width; + int ymin = re->r.border.ymin * height; + int ymax = re->r.border.ymax * height; + + freestyle_viewport[0] = freestyle_viewport[1] = 0; + freestyle_viewport[2] = width; + freestyle_viewport[3] = height; + + view->setWidth( width ); + view->setHeight( height ); + view->setBorder( xmin, ymin, xmax, ymax ); + + cout << "\n=== Dimensions of the 2D image coordinate system ===" << endl; + cout << "Width : " << width << endl; + cout << "Height : " << height << endl; + if (re->r.mode & R_BORDER) + cout << "Border : (" << xmin << ", " << ymin << ") - (" << xmax << ", " << ymax << ")" << endl; + } + + void init_camera(Render* re){ + // It is assumed that imported meshes are in the camera coordinate system. + // Therefore, the view point (i.e., camera position) is at the origin, and + // the the model-view matrix is simply the identity matrix. + + freestyle_viewpoint[0] = 0.0; + freestyle_viewpoint[1] = 0.0; + freestyle_viewpoint[2] = 0.0; + + for( int i = 0; i < 4; i++ ) + for( int j = 0; j < 4; j++ ) + freestyle_mv[i][j] = (i == j) ? 1.0 : 0.0; + + for( int i = 0; i < 4; i++ ) + for( int j = 0; j < 4; j++ ) + freestyle_proj[i][j] = re->winmat[i][j]; + + //print_m4("mv", freestyle_mv); + //print_m4("proj", freestyle_proj); + } + + + void prepare(Render* re, SceneRenderLayer* srl ) { + + // clear canvas + controller->Clear(); + + // load mesh + re->i.infostr= "Freestyle: Mesh loading"; + re->stats_draw(re->sdh, &re->i); + re->i.infostr= NULL; + if( controller->LoadMesh(re, srl) ) // returns if scene cannot be loaded or if empty + return; + if( re->test_break(re->tbh) ) + return; + + // add style modules + FreestyleConfig* config = &srl->freestyleConfig; + + cout << "\n=== Rendering options ===" << endl; + cout << "Modules :"<< endl; + int layer_count = 0; + + + for( FreestyleModuleConfig* module_conf = (FreestyleModuleConfig *)config->modules.first; module_conf; module_conf = module_conf->next ) { + if( module_conf->is_displayed ) { + cout << " " << layer_count+1 << ": " << module_conf->module_path << endl; + controller->InsertStyleModule( layer_count, module_conf->module_path ); + controller->toggleLayer(layer_count, true); + layer_count++; + } + } + cout << endl; + + // set parameters + controller->setCreaseAngle( config->crease_angle ); + controller->setSphereRadius( config->sphere_radius ); + controller->setComputeRidgesAndValleysFlag( (config->flags & FREESTYLE_RIDGES_AND_VALLEYS_FLAG) ? true : false); + controller->setComputeSuggestiveContoursFlag( (config->flags & FREESTYLE_SUGGESTIVE_CONTOURS_FLAG) ? true : false); + controller->setComputeMaterialBoundariesFlag( (config->flags & FREESTYLE_MATERIAL_BOUNDARIES_FLAG) ? true : false); + controller->setSuggestiveContourKrDerivativeEpsilon( config->dkr_epsilon ) ; + + cout << "Crease angle : " << controller->getCreaseAngle() << endl; + cout << "Sphere radius : " << controller->getSphereRadius() << endl; + cout << "Redges and valleys : " << (controller->getComputeRidgesAndValleysFlag() ? "enabled" : "disabled") << endl; + cout << "Suggestive contours : " << (controller->getComputeSuggestiveContoursFlag() ? "enabled" : "disabled") << endl; + cout << "Suggestive contour dkr epsilon : " << controller->getSuggestiveContourKrDerivativeEpsilon() << endl; + cout << endl; + + // set diffuse and z depth passes + RenderLayer *rl = RE_GetRenderLayer(re->result, srl->name); + bool diffuse = false, z = false; + for (RenderPass *rpass = (RenderPass *)rl->passes.first; rpass; rpass = rpass->next) { + switch (rpass->passtype) { + case SCE_PASS_DIFFUSE: + controller->setPassDiffuse(rpass->rect, rpass->rectx, rpass->recty); + diffuse = true; + break; + case SCE_PASS_Z: + controller->setPassZ(rpass->rect, rpass->rectx, rpass->recty); + z = true; + break; + } + } + cout << "Passes :" << endl; + cout << " Diffuse = " << (diffuse ? "enabled" : "disabled") << endl; + cout << " Z = " << (z ? "enabled" : "disabled") << endl; + + // compute view map + re->i.infostr= "Freestyle: View map creation"; + re->stats_draw(re->sdh, &re->i); + re->i.infostr= NULL; + controller->ComputeViewMap(); + } + + void FRS_composite_result(Render* re, SceneRenderLayer* srl, Render* freestyle_render) + { + RenderLayer *rl; + float *src, *dest, *pixSrc, *pixDest; + int x, y, rectx, recty; + + if( freestyle_render == NULL || freestyle_render->result == NULL ) + return; + + rl = render_get_active_layer( freestyle_render, freestyle_render->result ); + if( !rl || rl->rectf == NULL) { cout << "Cannot find Freestyle result image" << endl; return; } + src = rl->rectf; + //cout << "src: " << rl->rectx << " x " << rl->recty << endl; + + rl = RE_GetRenderLayer(re->result, srl->name); + if( !rl || rl->rectf == NULL) { cout << "No layer to composite to" << endl; return; } + dest = rl->rectf; + //cout << "dest: " << rl->rectx << " x " << rl->recty << endl; + + rectx = re->rectx; + recty = re->recty; + for( y = 0; y < recty; y++) { + for( x = 0; x < rectx; x++) { + pixSrc = src + 4 * (rectx * y + x); + if( pixSrc[3] > 0.0) { + pixDest = dest + 4 * (rectx * y + x); + addAlphaOverFloat(pixDest, pixSrc); + } + } + } + } + + int displayed_layer_count( SceneRenderLayer* srl ) { + int count = 0; + + for( FreestyleModuleConfig* module_conf = (FreestyleModuleConfig *)srl->freestyleConfig.modules.first; module_conf; module_conf = module_conf->next ) { + if( module_conf->is_displayed ) + count++; + } + return count; + } + + int FRS_is_freestyle_enabled(SceneRenderLayer* srl) { + return (!(srl->layflag & SCE_LAY_DISABLE) && + srl->layflag & SCE_LAY_FRS && + displayed_layer_count(srl) > 0); + } + + void FRS_init_stroke_rendering(Render* re) { + + cout << "\n#===============================================================" << endl; + cout << "# Freestyle" << endl; + cout << "#===============================================================" << endl; + + init_view(re); + init_camera(re); + + controller->ResetRenderCount(); + } + + Render* FRS_do_stroke_rendering(Render* re, SceneRenderLayer *srl) { + + Render* freestyle_render = NULL; + + cout << "\n----------------------------------------------------------" << endl; + cout << "| " << (re->scene->id.name+2) << "|" << srl->name << endl; + cout << "----------------------------------------------------------" << endl; + + // prepare Freestyle: + // - clear canvas + // - load mesh + // - add style modules + // - set parameters + // - compute view map + prepare(re, srl); + + if( re->test_break(re->tbh) ) { + controller->CloseFile(); + return NULL; + } + + // render and composite Freestyle result + if( controller->_ViewMap ) { + + // render strokes + re->i.infostr= "Freestyle: Stroke rendering"; + re->stats_draw(re->sdh, &re->i); + re->i.infostr= NULL; + freestyle_scene = re->scene; + controller->DrawStrokes(); + freestyle_render = controller->RenderStrokes(re); + controller->CloseFile(); + freestyle_scene = NULL; + + // composite result + FRS_composite_result(re, srl, freestyle_render); + RE_FreeRenderResult(freestyle_render->result); + freestyle_render->result = NULL; + } + + return freestyle_render; + } + + //======================================================= + // Freestyle Panel Configuration + //======================================================= + + void FRS_add_freestyle_config( SceneRenderLayer* srl ) + { + FreestyleConfig* config = &srl->freestyleConfig; + + config->mode = FREESTYLE_CONTROL_SCRIPT_MODE; + + config->modules.first = config->modules.last = NULL; + config->flags = 0; + config->sphere_radius = 1.0f; + config->dkr_epsilon = 0.001f; + config->crease_angle = 134.43f; + + config->linesets.first = config->linesets.last = NULL; + } + + void FRS_free_freestyle_config( SceneRenderLayer* srl ) + { + FreestyleLineSet *lineset; + + for(lineset=(FreestyleLineSet *)srl->freestyleConfig.linesets.first; lineset; lineset=lineset->next) { + lineset->linestyle->id.us--; + lineset->linestyle = NULL; + } + BLI_freelistN( &srl->freestyleConfig.linesets ); + BLI_freelistN( &srl->freestyleConfig.modules ); + } + + void FRS_add_module(FreestyleConfig *config) + { + FreestyleModuleConfig* module_conf = (FreestyleModuleConfig*) MEM_callocN( sizeof(FreestyleModuleConfig), "style module configuration"); + BLI_addtail(&config->modules, (void*) module_conf); + + strcpy( module_conf->module_path, default_module_path.c_str() ); + module_conf->is_displayed = 1; + } + + void FRS_delete_module(FreestyleConfig *config, FreestyleModuleConfig *module_conf) + { + BLI_freelinkN(&config->modules, module_conf); + } + + void FRS_move_module_up(FreestyleConfig *config, FreestyleModuleConfig *module_conf) + { + BLI_remlink(&config->modules, module_conf); + BLI_insertlinkbefore(&config->modules, module_conf->prev, module_conf); + } + + void FRS_move_module_down(FreestyleConfig *config, FreestyleModuleConfig *module_conf) + { + BLI_remlink(&config->modules, module_conf); + BLI_insertlinkafter(&config->modules, module_conf->next, module_conf); + } + + void FRS_add_lineset(FreestyleConfig *config) + { + int lineset_index = BLI_countlist(&config->linesets); + + FreestyleLineSet *lineset = (FreestyleLineSet *) MEM_callocN( sizeof(FreestyleLineSet), "Freestyle line set"); + BLI_addtail(&config->linesets, (void *) lineset); + FRS_set_active_lineset_index(config, lineset_index); + + lineset->linestyle = FRS_new_linestyle("LineStyle", NULL); + lineset->flags |= FREESTYLE_LINESET_ENABLED; + lineset->selection = 0; + lineset->qi = FREESTYLE_QI_VISIBLE; + lineset->qi_start = 0; + lineset->qi_end = 100; + lineset->edge_types = 0; + lineset->objects.first = lineset->objects.last = NULL; + if (lineset_index > 0) + sprintf(lineset->name, "LineSet %i", lineset_index+1); + else + strcpy(lineset->name, "LineSet"); + BLI_uniquename(&config->linesets, lineset, "FreestyleLineSet", '.', offsetof(FreestyleLineSet, name), sizeof(lineset->name)); + } + + void FRS_delete_active_lineset(FreestyleConfig *config) + { + FreestyleLineSet *lineset = FRS_get_active_lineset(config); + + if (lineset) { + lineset->linestyle->id.us--; + lineset->linestyle = NULL; + BLI_remlink(&config->linesets, lineset); + MEM_freeN(lineset); + FRS_set_active_lineset_index(config, 0); + } + } + + void FRS_move_active_lineset_up(FreestyleConfig *config) + { + FreestyleLineSet *lineset = FRS_get_active_lineset(config); + + if (lineset) { + BLI_remlink(&config->linesets, lineset); + BLI_insertlinkbefore(&config->linesets, lineset->prev, lineset); + } + } + + void FRS_move_active_lineset_down(FreestyleConfig *config) + { + FreestyleLineSet *lineset = FRS_get_active_lineset(config); + + if (lineset) { + BLI_remlink(&config->linesets, lineset); + BLI_insertlinkafter(&config->linesets, lineset->next, lineset); + } + } + + FreestyleLineSet *FRS_get_active_lineset(FreestyleConfig *config) + { + FreestyleLineSet *lineset; + + for(lineset=(FreestyleLineSet *)config->linesets.first; lineset; lineset=lineset->next) + if(lineset->flags & FREESTYLE_LINESET_CURRENT) + return lineset; + return NULL; + } + + short FRS_get_active_lineset_index(FreestyleConfig *config) + { + FreestyleLineSet *lineset; + short i; + + for(lineset=(FreestyleLineSet *)config->linesets.first, i=0; lineset; lineset=lineset->next, i++) + if(lineset->flags & FREESTYLE_LINESET_CURRENT) + return i; + return 0; + } + + void FRS_set_active_lineset_index(FreestyleConfig *config, short index) + { + FreestyleLineSet *lineset; + short i; + + for(lineset=(FreestyleLineSet *)config->linesets.first, i=0; lineset; lineset=lineset->next, i++) { + if(i == index) + lineset->flags |= FREESTYLE_LINESET_CURRENT; + else + lineset->flags &= ~FREESTYLE_LINESET_CURRENT; + } + } + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/geometry/BBox.h b/source/blender/freestyle/intern/geometry/BBox.h new file mode 100755 index 00000000000..9c46d7918e2 --- /dev/null +++ b/source/blender/freestyle/intern/geometry/BBox.h @@ -0,0 +1,141 @@ +// +// Filename : BBox.h +// Author(s) : Stephane Grabli +// Purpose : A class to hold a bounding box +// Date of creation : 22/05/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef BBOX_H +# define BBOX_H + +template <class Point> +class BBox +{ + public: + + inline BBox() { + _empty = true; + } + + template <class T> + inline BBox(const T& min_in, const T& max_in) : _min(min_in), _max(max_in) { + _empty = false; + } + + template <class T> + inline BBox(const BBox<T>& b) : _min(b.getMin()), _max(b.getMax()) { + _empty = false; + } + + template <class T> + inline void extendToContain(const T& p) { + if (_empty) { + _min = p; + _max = p; + _empty = false; + return; + } + for (unsigned i = 0; i < Point::dim(); i++) { + if (p[i] < _min[i]) + _min[i] = p[i]; + else if (p[i] > _max[i]) + _max[i] = p[i]; + } + _empty = false; + } + + inline void clear() { + _empty = true; + } + + inline bool empty() const { + return _empty; + } + + inline const Point& getMin() const { + return _min; + } + + inline const Point& getMax() const { + return _max; + } + + inline BBox<Point>& operator=(const BBox<Point>& b) { + _min = b.getMin(); + _max = b.getMax(); + _empty = false; + return *this; + } + + inline BBox<Point>& operator+=(const BBox<Point>& b) { + if (_empty) { + _min = b.getMin(); + _max = b.getMax(); + _empty = false; + } + else { + for (unsigned i = 0; i < Point::dim(); i++) { + if (b.getMin()[i] < _min[i]) + _min[i] = b.getMin()[i]; + if (b.getMax()[i] > _max[i]) + _max[i] = b.getMax()[i]; + } + } + return *this; + } + + inline bool inside(const Point& p){ + if(empty()) + return false; + for (unsigned i = 0; i < Point::dim(); i++) { + if((_min[i]>p[i]) || (_max[i]<p[i])) + return false; + } + return true; + + } + +private: + + Point _min; + Point _max; + bool _empty; +}; + +template <class Point> +BBox<Point>& operator+(const BBox<Point> &b1, const BBox<Point> &b2) +{ + Point new_min; + Point new_max; + + for (unsigned i = 0; i < Point::dim(); i++) { + new_min[i] = b1.getMin()[i] < b2.getMin()[i] ? b1.getMin()[i] : b2.getMin()[i]; + new_max[i] = b1.getMax()[i] > b2.getMax()[i] ? b1.getMax()[i] : b2.getMax()[i]; + } + + return BBox<Point>(new_min, new_max); +} + +#endif // BBOX_H diff --git a/source/blender/freestyle/intern/geometry/Bezier.cpp b/source/blender/freestyle/intern/geometry/Bezier.cpp new file mode 100755 index 00000000000..8f9771f29d3 --- /dev/null +++ b/source/blender/freestyle/intern/geometry/Bezier.cpp @@ -0,0 +1,118 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "Bezier.h" +#include "FitCurve.h" + +using namespace std; + +BezierCurveSegment::BezierCurveSegment() +{ +} + +BezierCurveSegment::~BezierCurveSegment() +{ +} + +void BezierCurveSegment::AddControlPoint(const Vec2d& iPoint) +{ + _ControlPolygon.push_back(iPoint); + if(_ControlPolygon.size() == 4) + Build(); +} + +void BezierCurveSegment::Build() +{ + if(_ControlPolygon.size() != 4) + return; + + // Compute the rightmost part of the matrix: + vector<Vec2d>::const_iterator p0,p1,p2,p3; + p0 = _ControlPolygon.begin(); + p1 = p0;++p1; + p2 = p1;++p2; + p3 = p2;++p3; + float x[4], y[4]; + + x[0] = -p0->x()+3*p1->x()-3*p2->x()+p3->x(); + x[1] = 3*p0->x()-6*p1->x()+3*p2->x(); + x[2] = -3*p0->x()+3*p1->x(); + x[3] = p0->x(); + + y[0] = -p0->y()+3*p1->y()-3*p2->y()+p3->y(); + y[1] = 3*p0->y()-6*p1->y()+3*p2->y(); + y[2] = -3*p0->y()+3*p1->y(); + y[3] = p0->y(); + + int nvertices = 12; + float increment = 1.0/(float)nvertices; + float t = 0.f; + for(int i=0; i<=nvertices; ++i) + { + _Vertices.push_back(Vec2d((x[3] + t*(x[2] + t*(x[1] + t*x[0]))), + (y[3] + t*(y[2] + t*(y[1] + t*y[0]))))); + t+=increment; + } +} + +BezierCurve::BezierCurve() +{ + _currentSegment = new BezierCurveSegment; +} + +BezierCurve::BezierCurve(vector<Vec2d>& iPoints, double error) +{ + FitCurveWrapper fitcurve; + _currentSegment = new BezierCurveSegment; + vector<Vec2d> curve; + + fitcurve.FitCurve(iPoints, curve, error); + int i=0; + vector<Vec2d>::iterator v,vend; + for(v=curve.begin(),vend=curve.end(); + v!=vend; + ++v) + { + if((i == 0) || (i%4 != 0)) + AddControlPoint(*v); + ++i; + } +} + +BezierCurve::~BezierCurve() +{ + if(_currentSegment) + delete _currentSegment; +} + +void BezierCurve::AddControlPoint(const Vec2d& iPoint) +{ + _ControlPolygon.push_back(iPoint); + _currentSegment->AddControlPoint(iPoint); + if(_currentSegment->size() == 4) + { + _Segments.push_back(_currentSegment); + _currentSegment = new BezierCurveSegment; + _currentSegment->AddControlPoint(iPoint); + } +} + + diff --git a/source/blender/freestyle/intern/geometry/Bezier.h b/source/blender/freestyle/intern/geometry/Bezier.h new file mode 100755 index 00000000000..acae71bbb2c --- /dev/null +++ b/source/blender/freestyle/intern/geometry/Bezier.h @@ -0,0 +1,73 @@ +// +// Filename : Bezier.h +// Author(s) : Stephane Grabli +// Purpose : Class to define a Bezier curve of order 4. +// Date of creation : 04/06/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef BEZIER_H +# define BEZIER_H + +#include <vector> +#include "../system/FreestyleConfig.h" +#include "Geom.h" + +using namespace Geometry; + +class LIB_GEOMETRY_EXPORT BezierCurveSegment +{ +private: + std::vector<Vec2d> _ControlPolygon; + std::vector<Vec2d> _Vertices; + +public: + BezierCurveSegment(); + virtual ~BezierCurveSegment(); + + void AddControlPoint(const Vec2d& iPoint); + void Build(); + inline int size() const {return _ControlPolygon.size();} + inline std::vector<Vec2d>& vertices() {return _Vertices;} +}; + + +class LIB_GEOMETRY_EXPORT BezierCurve +{ +private: + std::vector<Vec2d> _ControlPolygon; + std::vector<BezierCurveSegment*> _Segments; + BezierCurveSegment *_currentSegment; + +public: + BezierCurve(); + BezierCurve(std::vector<Vec2d>& iPoints, double error=4.0); + virtual ~BezierCurve(); + + void AddControlPoint(const Vec2d& iPoint); + std::vector<Vec2d>& controlPolygon() {return _ControlPolygon;} + std::vector<BezierCurveSegment*>& segments() {return _Segments;} +}; + +#endif // BEZIER_H diff --git a/source/blender/freestyle/intern/geometry/FastGrid.cpp b/source/blender/freestyle/intern/geometry/FastGrid.cpp new file mode 100755 index 00000000000..325126b4b96 --- /dev/null +++ b/source/blender/freestyle/intern/geometry/FastGrid.cpp @@ -0,0 +1,62 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "FastGrid.h" + +void FastGrid::clear() { + if(!_cells) + return; + + for(unsigned i = 0; i < _cells_size; i++) + if (_cells[i]) + delete _cells[i]; + delete[] _cells; + _cells = NULL; + _cells_size = 0; + + Grid::clear(); +} + +void FastGrid::configure(const Vec3r& orig, const Vec3r& size, unsigned nb) { + Grid::configure(orig, size, nb); + _cells_size = _cells_nb[0] * _cells_nb[1] * _cells_nb[2]; + _cells = new Cell*[_cells_size]; + memset(_cells, 0, _cells_size * sizeof(*_cells)); +} + +Cell* FastGrid::getCell(const Vec3u& p) { + //cout << _cells<< " "<< p << " " <<_cells_nb[0]<<"-"<< _cells_nb[1]<<"-"<< _cells_nb[2]<< " "<<_cells_size<< endl; + assert(_cells||("_cells is a null pointer")); + assert((_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0])<_cells_size); + assert(p[0]<_cells_nb[0]); + assert(p[1]<_cells_nb[1]); + assert(p[2]<_cells_nb[2]); + return _cells[_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]]; +} + +void FastGrid::fillCell(const Vec3u& p, Cell& cell) { + assert(_cells||("_cells is a null pointer")); + assert((_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0])<_cells_size); + assert(p[0]<_cells_nb[0]); + assert(p[1]<_cells_nb[1]); + assert(p[2]<_cells_nb[2]); + _cells[_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]] = &cell; +} diff --git a/source/blender/freestyle/intern/geometry/FastGrid.h b/source/blender/freestyle/intern/geometry/FastGrid.h new file mode 100755 index 00000000000..e620ff24385 --- /dev/null +++ b/source/blender/freestyle/intern/geometry/FastGrid.h @@ -0,0 +1,85 @@ +// +// Filename : FastGrid.h +// Author(s) : Stephane Grabli +// Purpose : Class to define a cell grid surrounding the +// bounding box of the scene +// Date of creation : 30/07/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef FASTGRID_H +# define FASTGRID_H + +# include "Grid.h" +# include <cassert> +/*! Class to define a regular grid used for ray + * casting computations + * We don't use a hashtable here. The grid is + * explicitly stored for faster computations. + * However, this might result in significant + * increase in memory usage (compared to the regular grid) + */ + +class LIB_GEOMETRY_EXPORT FastGrid : public Grid +{ + public: + + FastGrid() : Grid() { + _cells = NULL; + _cells_size = 0; + } + + virtual ~FastGrid() { + clear(); + } + + /*! clears the grid + * Deletes all the cells, clears the hashtable, + * resets size, size of cell, number of cells. + */ + virtual void clear(); + + /*! Sets the different parameters of the grid + * orig + * The grid origin + * size + * The grid's dimensions + * nb + * The number of cells of the grid + */ + virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb); + + /*! returns the cell whose coordinates are pased as argument */ + Cell* getCell(const Vec3u& p) ; + + /*! Fills the case p with the cell iCell */ + virtual void fillCell(const Vec3u& p, Cell& cell); + +protected: + + Cell** _cells; + unsigned _cells_size; +}; + +#endif // FASTGRID_H diff --git a/source/blender/freestyle/intern/geometry/FitCurve.cpp b/source/blender/freestyle/intern/geometry/FitCurve.cpp new file mode 100755 index 00000000000..7754fcda32b --- /dev/null +++ b/source/blender/freestyle/intern/geometry/FitCurve.cpp @@ -0,0 +1,603 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include <cstdlib> // for malloc and free +#include <stdio.h> +#include <math.h> +#include "FitCurve.h" + +using namespace std; + +typedef Vector2 *BezierCurve; + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Forward declarations */ +static double *Reparameterize(Vector2 *d, int first, int last, double *u, BezierCurve bezCurve); +static double NewtonRaphsonRootFind(BezierCurve Q, Vector2 P, double u); +static Vector2 BezierII(int degree, Vector2 *V, double t); +static double B0(double u); +static double B1(double u); +static double B2(double u); +static double B3(double u); +static Vector2 ComputeLeftTangent(Vector2 *d, int end); +static Vector2 ComputeLeftTangent(Vector2 *d, int end); +static Vector2 ComputeLeftTangent(Vector2 *d, int end); +static double ComputeMaxError(Vector2 *d, int first, int last, BezierCurve bezCurve, double *u, int *splitPoint); +static double *ChordLengthParameterize(Vector2 *d, int first, int last); +static BezierCurve GenerateBezier(Vector2 *d, int first, int last, double *uPrime, Vector2 tHat1, Vector2 tHat2); +static Vector2 V2AddII(Vector2 a, Vector2 b); +static Vector2 V2ScaleIII(Vector2 v, double s); +static Vector2 V2SubII(Vector2 a, Vector2 b); + + +#define MAXPOINTS 1000 /* The most points you can have */ + +/* returns squared length of input vector */ +double V2SquaredLength(Vector2 *a) +{ return(((*a)[0] * (*a)[0])+((*a)[1] * (*a)[1])); +} + +/* returns length of input vector */ +double V2Length(Vector2 *a) +{ + return(sqrt(V2SquaredLength(a))); +} + +Vector2 *V2Scale(Vector2 *v, double newlen) +{ + double len = V2Length(v); + if (len != 0.0) { (*v)[0] *= newlen/len; (*v)[1] *= newlen/len; } + return(v); +} + +/* return the dot product of vectors a and b */ +double V2Dot(Vector2 *a, Vector2 *b) +{ + return(((*a)[0]*(*b)[0])+((*a)[1]*(*b)[1])); +} + +/* return the distance between two points */ +double V2DistanceBetween2Points(Vector2 *a, Vector2 *b) +{ +double dx = (*a)[0] - (*b)[0]; +double dy = (*a)[1] - (*b)[1]; + return(sqrt((dx*dx)+(dy*dy))); +} + +/* return vector sum c = a+b */ +Vector2 *V2Add(Vector2 *a, Vector2 *b, Vector2 *c) +{ + (*c)[0] = (*a)[0]+(*b)[0]; (*c)[1] = (*a)[1]+(*b)[1]; + return(c); +} + +/* normalizes the input vector and returns it */ +Vector2 *V2Normalize(Vector2 *v) +{ +double len = V2Length(v); + if (len != 0.0) { (*v)[0] /= len; (*v)[1] /= len; } + return(v); +} + +/* negates the input vector and returns it */ +Vector2 *V2Negate(Vector2 *v) +{ + (*v)[0] = -(*v)[0]; (*v)[1] = -(*v)[1]; + return(v); +} + + +/* + * GenerateBezier : + * Use least-squares method to find Bezier control points for region. + * + */ +static BezierCurve GenerateBezier(Vector2 *d, int first, int last, double *uPrime, Vector2 tHat1, Vector2 tHat2) +// Vector2 *d; /* Array of digitized points */ +// int first, last; /* Indices defining region */ +// double *uPrime; /* Parameter values for region */ +// Vector2 tHat1, tHat2; /* Unit tangents at endpoints */ +{ + int i; + Vector2 A[MAXPOINTS][2]; /* Precomputed rhs for eqn */ + int nPts; /* Number of pts in sub-curve */ + double C[2][2]; /* Matrix C */ + double X[2]; /* Matrix X */ + double det_C0_C1, /* Determinants of matrices */ + det_C0_X, + det_X_C1; + double alpha_l, /* Alpha values, left and right */ + alpha_r; + Vector2 tmp; /* Utility variable */ + BezierCurve bezCurve; /* RETURN bezier curve ctl pts */ + + bezCurve = (Vector2 *)malloc(4 * sizeof(Vector2)); + nPts = last - first + 1; + + + /* Compute the A's */ + for (i = 0; i < nPts; i++) { + Vector2 v1, v2; + v1 = tHat1; + v2 = tHat2; + V2Scale(&v1, B1(uPrime[i])); + V2Scale(&v2, B2(uPrime[i])); + A[i][0] = v1; + A[i][1] = v2; + } + + /* Create the C and X matrices */ + C[0][0] = 0.0; + C[0][1] = 0.0; + C[1][0] = 0.0; + C[1][1] = 0.0; + X[0] = 0.0; + X[1] = 0.0; + + for (i = 0; i < nPts; i++) { + C[0][0] += V2Dot(&A[i][0], &A[i][0]); + C[0][1] += V2Dot(&A[i][0], &A[i][1]); +/* C[1][0] += V2Dot(&A[i][0], &A[i][1]);*/ + C[1][0] = C[0][1]; + C[1][1] += V2Dot(&A[i][1], &A[i][1]); + + tmp = V2SubII(d[first + i], + V2AddII( + V2ScaleIII(d[first], B0(uPrime[i])), + V2AddII( + V2ScaleIII(d[first], B1(uPrime[i])), + V2AddII( + V2ScaleIII(d[last], B2(uPrime[i])), + V2ScaleIII(d[last], B3(uPrime[i])))))); + + + X[0] += V2Dot(&((A[i])[0]), &tmp); + X[1] += V2Dot(&((A[i])[1]), &tmp); + } + + /* Compute the determinants of C and X */ + det_C0_C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1]; + det_C0_X = C[0][0] * X[1] - C[0][1] * X[0]; + det_X_C1 = X[0] * C[1][1] - X[1] * C[0][1]; + + /* Finally, derive alpha values */ + if (det_C0_C1 == 0.0) { + det_C0_C1 = (C[0][0] * C[1][1]) * 10e-12; + } + alpha_l = det_X_C1 / det_C0_C1; + alpha_r = det_C0_X / det_C0_C1; + + + /* If alpha negative, use the Wu/Barsky heuristic (see text) */ + /* (if alpha is 0, you get coincident control points that lead to + * divide by zero in any subsequent NewtonRaphsonRootFind() call. */ + if (alpha_l < 1.0e-6 || alpha_r < 1.0e-6) { + double dist = V2DistanceBetween2Points(&d[last], &d[first]) / + 3.0; + + bezCurve[0] = d[first]; + bezCurve[3] = d[last]; + V2Add(&(bezCurve[0]), V2Scale(&(tHat1), dist), &(bezCurve[1])); + V2Add(&(bezCurve[3]), V2Scale(&(tHat2), dist), &(bezCurve[2])); + return (bezCurve); + } + + /* First and last control points of the Bezier curve are */ + /* positioned exactly at the first and last data points */ + /* Control points 1 and 2 are positioned an alpha distance out */ + /* on the tangent vectors, left and right, respectively */ + bezCurve[0] = d[first]; + bezCurve[3] = d[last]; + V2Add(&bezCurve[0], V2Scale(&tHat1, alpha_l), &bezCurve[1]); + V2Add(&bezCurve[3], V2Scale(&tHat2, alpha_r), &bezCurve[2]); + return (bezCurve); +} + + +/* + * Reparameterize: + * Given set of points and their parameterization, try to find + * a better parameterization. + * + */ +static double *Reparameterize(Vector2 *d, int first, int last, double *u, BezierCurve bezCurve) +// Vector2 *d; /* Array of digitized points */ +// int first, last; /* Indices defining region */ +// double *u; /* Current parameter values */ +// BezierCurve bezCurve; /* Current fitted curve */ +{ + int nPts = last-first+1; + int i; + double *uPrime; /* New parameter values */ + + uPrime = (double *)malloc(nPts * sizeof(double)); + for (i = first; i <= last; i++) { + uPrime[i-first] = NewtonRaphsonRootFind(bezCurve, d[i], u[i- + first]); + } + return (uPrime); +} + + + +/* + * NewtonRaphsonRootFind : + * Use Newton-Raphson iteration to find better root. + */ +static double NewtonRaphsonRootFind(BezierCurve Q, Vector2 P, double u) +// BezierCurve Q; /* Current fitted curve */ +// Vector2 P; /* Digitized point */ +// double u; /* Parameter value for "P" */ +{ + double numerator, denominator; + Vector2 Q1[3], Q2[2]; /* Q' and Q'' */ + Vector2 Q_u, Q1_u, Q2_u; /*u evaluated at Q, Q', & Q'' */ + double uPrime; /* Improved u */ + int i; + + /* Compute Q(u) */ + Q_u = BezierII(3, Q, u); + + /* Generate control vertices for Q' */ + for (i = 0; i <= 2; i++) { + Q1[i][0] = (Q[i+1][0] - Q[i][0]) * 3.0; + Q1[i][1] = (Q[i+1][1] - Q[i][1]) * 3.0; + } + + /* Generate control vertices for Q'' */ + for (i = 0; i <= 1; i++) { + Q2[i][0] = (Q1[i+1][0] - Q1[i][0]) * 2.0; + Q2[i][1] = (Q1[i+1][1] - Q1[i][1]) * 2.0; + } + + /* Compute Q'(u) and Q''(u) */ + Q1_u = BezierII(2, Q1, u); + Q2_u = BezierII(1, Q2, u); + + /* Compute f(u)/f'(u) */ + numerator = (Q_u[0] - P[0]) * (Q1_u[0]) + (Q_u[1] - P[1]) * (Q1_u[1]); + denominator = (Q1_u[0]) * (Q1_u[0]) + (Q1_u[1]) * (Q1_u[1]) + + (Q_u[0] - P[0]) * (Q2_u[0]) + (Q_u[1] - P[1]) * (Q2_u[1]); + + /* u = u - f(u)/f'(u) */ + if(denominator == 0) // FIXME + return u; + uPrime = u - (numerator/denominator); + return (uPrime); +} + + + +/* + * Bezier : + * Evaluate a Bezier curve at a particular parameter value + * + */ +static Vector2 BezierII(int degree, Vector2 *V, double t) +// int degree; /* The degree of the bezier curve */ +// Vector2 *V; /* Array of control points */ +// double t; /* Parametric value to find point for */ +{ + int i, j; + Vector2 Q; /* Point on curve at parameter t */ + Vector2 *Vtemp; /* Local copy of control points */ + + /* Copy array */ + Vtemp = (Vector2 *)malloc((unsigned)((degree+1) + * sizeof (Vector2))); + for (i = 0; i <= degree; i++) { + Vtemp[i] = V[i]; + } + + /* Triangle computation */ + for (i = 1; i <= degree; i++) { + for (j = 0; j <= degree-i; j++) { + Vtemp[j][0] = (1.0 - t) * Vtemp[j][0] + t * Vtemp[j+1][0]; + Vtemp[j][1] = (1.0 - t) * Vtemp[j][1] + t * Vtemp[j+1][1]; + } + } + + Q = Vtemp[0]; + free((void *)Vtemp); + return Q; +} + + +/* + * B0, B1, B2, B3 : + * Bezier multipliers + */ +static double B0(double u) +{ + double tmp = 1.0 - u; + return (tmp * tmp * tmp); +} + + +static double B1(double u) +{ + double tmp = 1.0 - u; + return (3 * u * (tmp * tmp)); +} + +static double B2(double u) +{ + double tmp = 1.0 - u; + return (3 * u * u * tmp); +} + +static double B3(double u) +{ + return (u * u * u); +} + + + +/* + * ComputeLeftTangent, ComputeRightTangent, ComputeCenterTangent : + *Approximate unit tangents at endpoints and "center" of digitized curve + */ +static Vector2 ComputeLeftTangent(Vector2 *d, int end) +// Vector2 *d; /* Digitized points*/ +// int end; /* Index to "left" end of region */ +{ + Vector2 tHat1; + tHat1 = V2SubII(d[end+1], d[end]); + tHat1 = *V2Normalize(&tHat1); + return tHat1; +} + +static Vector2 ComputeRightTangent(Vector2 *d, int end) +// Vector2 *d; /* Digitized points */ +// int end; /* Index to "right" end of region */ +{ + Vector2 tHat2; + tHat2 = V2SubII(d[end-1], d[end]); + tHat2 = *V2Normalize(&tHat2); + return tHat2; +} + +static Vector2 ComputeCenterTangent(Vector2 *d, int center) +// Vector2 *d; /* Digitized points */ +// int center; /* Index to point inside region */ +{ + Vector2 V1, V2, tHatCenter; + + V1 = V2SubII(d[center-1], d[center]); + V2 = V2SubII(d[center], d[center+1]); + tHatCenter[0] = (V1[0] + V2[0])/2.0; + tHatCenter[1] = (V1[1] + V2[1])/2.0; + tHatCenter = *V2Normalize(&tHatCenter); + return tHatCenter; +} + + +/* + * ChordLengthParameterize : + * Assign parameter values to digitized points + * using relative distances between points. + */ +static double *ChordLengthParameterize(Vector2 *d, int first, int last) +// Vector2 *d; /* Array of digitized points */ +// int first, last; /* Indices defining region */ +{ + int i; + double *u; /* Parameterization */ + + u = (double *)malloc((unsigned)(last-first+1) * sizeof(double)); + + u[0] = 0.0; + for (i = first+1; i <= last; i++) { + u[i-first] = u[i-first-1] + + V2DistanceBetween2Points(&d[i], &d[i-1]); + } + + for (i = first + 1; i <= last; i++) { + u[i-first] = u[i-first] / u[last-first]; + } + + return(u); +} + + + + +/* + * ComputeMaxError : + * Find the maximum squared distance of digitized points + * to fitted curve. +*/ +static double ComputeMaxError(Vector2 *d, int first, int last, BezierCurve bezCurve, double *u, int *splitPoint) +// Vector2 *d; /* Array of digitized points */ +// int first, last; /* Indices defining region */ +// BezierCurve bezCurve; /* Fitted Bezier curve */ +// double *u; /* Parameterization of points */ +// int *splitPoint; /* Point of maximum error */ +{ + int i; + double maxDist; /* Maximum error */ + double dist; /* Current error */ + Vector2 P; /* Point on curve */ + Vector2 v; /* Vector from point to curve */ + + *splitPoint = (last - first + 1)/2; + maxDist = 0.0; + for (i = first + 1; i < last; i++) { + P = BezierII(3, bezCurve, u[i-first]); + v = V2SubII(P, d[i]); + dist = V2SquaredLength(&v); + if (dist >= maxDist) { + maxDist = dist; + *splitPoint = i; + } + } + return (maxDist); +} +static Vector2 V2AddII(Vector2 a, Vector2 b) +{ + Vector2 c; + c[0] = a[0] + b[0]; c[1] = a[1] + b[1]; + return (c); +} +static Vector2 V2ScaleIII(Vector2 v, double s) +{ + Vector2 result; + result[0] = v[0] * s; result[1] = v[1] * s; + return (result); +} + +static Vector2 V2SubII(Vector2 a, Vector2 b) +{ + Vector2 c; + c[0] = a[0] - b[0]; c[1] = a[1] - b[1]; + return (c); +} + +#ifdef __cplusplus +} +#endif + + +//------------------------- WRAPPER -----------------------------// + +FitCurveWrapper::FitCurveWrapper() +{ +} + +FitCurveWrapper::~FitCurveWrapper() +{ + _vertices.clear(); +} + +void FitCurveWrapper::DrawBezierCurve(int n, Vector2 *curve ) +{ + for(int i=0; i<n+1; ++i) + _vertices.push_back(curve[i]); +} + +void FitCurveWrapper::FitCurve(vector<Vec2d>& data, vector<Vec2d>& oCurve, double error) +{ + int size = data.size(); + Vector2 *d = new Vector2[size]; + for(int i=0; i<size; ++i) + { + d[i][0] = data[i][0]; + d[i][1] = data[i][1]; + } + + FitCurve(d,size,error); + + // copy results + for(vector<Vector2>::iterator v=_vertices.begin(), vend=_vertices.end(); + v!=vend; + ++v) + { + oCurve.push_back(Vec2d(v->x(), v->y())) ; + } + +} + +void FitCurveWrapper::FitCurve(Vector2 *d, int nPts, double error) +{ + Vector2 tHat1, tHat2; /* Unit tangent vectors at endpoints */ + + tHat1 = ComputeLeftTangent(d, 0); + tHat2 = ComputeRightTangent(d, nPts - 1); + FitCubic(d, 0, nPts - 1, tHat1, tHat2, error); +} + +void FitCurveWrapper::FitCubic(Vector2 *d, int first, int last, Vector2 tHat1, Vector2 tHat2, double error) +{ + BezierCurve bezCurve; /*Control points of fitted Bezier curve*/ + double *u; /* Parameter values for point */ + double *uPrime; /* Improved parameter values */ + double maxError; /* Maximum fitting error */ + int splitPoint; /* Point to split point set at */ + int nPts; /* Number of points in subset */ + double iterationError; /*Error below which you try iterating */ + int maxIterations = 4; /* Max times to try iterating */ + Vector2 tHatCenter; /* Unit tangent vector at splitPoint */ + int i; + + iterationError = error * error; + nPts = last - first + 1; + + /* Use heuristic if region only has two points in it */ + if (nPts == 2) { + double dist = V2DistanceBetween2Points(&d[last], &d[first]) / 3.0; + + bezCurve = (Vector2 *)malloc(4 * sizeof(Vector2)); + bezCurve[0] = d[first]; + bezCurve[3] = d[last]; + V2Add(&bezCurve[0], V2Scale(&tHat1, dist), &bezCurve[1]); + V2Add(&bezCurve[3], V2Scale(&tHat2, dist), &bezCurve[2]); + DrawBezierCurve(3, bezCurve); + free((void *)bezCurve); + return; + } + + /* Parameterize points, and attempt to fit curve */ + u = ChordLengthParameterize(d, first, last); + bezCurve = GenerateBezier(d, first, last, u, tHat1, tHat2); + + /* Find max deviation of points to fitted curve */ + maxError = ComputeMaxError(d, first, last, bezCurve, u, &splitPoint); + if (maxError < error) { + DrawBezierCurve(3, bezCurve); + free((void *)u); + free((void *)bezCurve); + return; + } + + + /* If error not too large, try some reparameterization */ + /* and iteration */ + if (maxError < iterationError) { + for (i = 0; i < maxIterations; i++) { + uPrime = Reparameterize(d, first, last, u, bezCurve); + bezCurve = GenerateBezier(d, first, last, uPrime, tHat1, tHat2); + maxError = ComputeMaxError(d, first, last, + bezCurve, uPrime, &splitPoint); + if (maxError < error) { + DrawBezierCurve(3, bezCurve); + free((void *)u); + free((void *)bezCurve); + return; + } + free((void *)u); + u = uPrime; + } + } + + /* Fitting failed -- split at max error point and fit recursively */ + free((void *)u); + free((void *)bezCurve); + tHatCenter = ComputeCenterTangent(d, splitPoint); + FitCubic(d, first, splitPoint, tHat1, tHatCenter, error); + V2Negate(&tHatCenter); + FitCubic(d, splitPoint, last, tHatCenter, tHat2, error); + +} + diff --git a/source/blender/freestyle/intern/geometry/FitCurve.h b/source/blender/freestyle/intern/geometry/FitCurve.h new file mode 100755 index 00000000000..ed7cbe34780 --- /dev/null +++ b/source/blender/freestyle/intern/geometry/FitCurve.h @@ -0,0 +1,101 @@ +// +// Filename : FitCurve.h +// Author(s) : Stephane Grabli +// Purpose : An Algorithm for Automatically Fitting Digitized Curves +// by Philip J. Schneider +// from "Graphics Gems", Academic Press, 1990 +// Date of creation : 06/06/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef FITCURVE_H +# define FITCURVE_H + +#include <vector> +#include "../system/FreestyleConfig.h" +#include "Geom.h" + +using namespace Geometry; + +typedef struct Point2Struct { /* 2d point */ + double coordinates[2]; + Point2Struct() {coordinates[0]=0;coordinates[1]=0;} + inline double operator[](const int i) const + { + return coordinates[i]; + } + inline double& operator[](const int i) + { + return coordinates[i]; + } + inline double x() const {return coordinates[0];} + inline double y() const {return coordinates[1];} + } Point2; + +typedef Point2 Vector2; + + + +class LIB_GEOMETRY_EXPORT FitCurveWrapper +{ +private: + std::vector<Vector2> _vertices; + +public: + FitCurveWrapper(); + ~FitCurveWrapper(); + + /*! Fits a set of 2D data points to a set of Bezier Curve segments + * data + * Input data points + * oCurve + * Control points of the sets of bezier curve segments. + * Each segment is made of 4 points (polynomial degree of curve = 3) + * error + * max error tolerance between resulting curve and input data + */ + void FitCurve(std::vector<Vec2d>& data, std::vector<Vec2d>& oCurve, double error); +protected: + /* Vec2d *d; Array of digitized points */ + /* int nPts; Number of digitized points */ + /* double error; User-defined error squared */ + void FitCurve(Vector2 *d, int nPts, double error); + + /*! Draws a Bezier curve segment + * n + * degree of curve (=3) + * curve + * bezier segments control points + */ + void DrawBezierCurve(int n, Vector2 *curve); + + /* Vec2d *d; Array of digitized points */ + /* int first, last; Indices of first and last pts in region */ + /* Vec2d tHat1, tHat2; Unit tangent vectors at endpoints */ + /* double error; User-defined error squared */ + void FitCubic(Vector2 *d, int first, int last, Vector2 tHat1, Vector2 tHat2, double error); + +}; + +#endif // FITCURVE_H diff --git a/source/blender/freestyle/intern/geometry/Geom.h b/source/blender/freestyle/intern/geometry/Geom.h new file mode 100755 index 00000000000..ac94213fe98 --- /dev/null +++ b/source/blender/freestyle/intern/geometry/Geom.h @@ -0,0 +1,78 @@ +// +// Filename : Geom.h +// Author(s) : Sylvain Paris +// Emmanuel Turquin +// Stephane Grabli +// Purpose : Vectors and Matrices (useful type definitions) +// Date of creation : 20/05/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef GEOM_H +# define GEOM_H + +# include "VecMat.h" +# include "../system/Precision.h" + +namespace Geometry { + + typedef VecMat::Vec2<unsigned> Vec2u; + typedef VecMat::Vec2<int> Vec2i; + typedef VecMat::Vec2<float> Vec2f; + typedef VecMat::Vec2<double> Vec2d; + typedef VecMat::Vec2<real> Vec2r; + + typedef VecMat::Vec3<unsigned> Vec3u; + typedef VecMat::Vec3<int> Vec3i; + typedef VecMat::Vec3<float> Vec3f; + typedef VecMat::Vec3<double> Vec3d; + typedef VecMat::Vec3<real> Vec3r; + + typedef VecMat::HVec3<unsigned> HVec3u; + typedef VecMat::HVec3<int> HVec3i; + typedef VecMat::HVec3<float> HVec3f; + typedef VecMat::HVec3<double> HVec3d; + typedef VecMat::HVec3<real> HVec3r; + + typedef VecMat::SquareMatrix<unsigned, 2> Matrix22u; + typedef VecMat::SquareMatrix<int, 2> Matrix22i; + typedef VecMat::SquareMatrix<float, 2> Matrix22f; + typedef VecMat::SquareMatrix<double, 2> Matrix22d; + typedef VecMat::SquareMatrix<real, 2> Matrix22r; + + typedef VecMat::SquareMatrix<unsigned, 3> Matrix33u; + typedef VecMat::SquareMatrix<int, 3> Matrix33i; + typedef VecMat::SquareMatrix<float, 3> Matrix33f; + typedef VecMat::SquareMatrix<double, 3> Matrix33d; + typedef VecMat::SquareMatrix<real, 3> Matrix33r; + + typedef VecMat::SquareMatrix<unsigned, 4> Matrix44u; + typedef VecMat::SquareMatrix<int, 4> Matrix44i; + typedef VecMat::SquareMatrix<float, 4> Matrix44f; + typedef VecMat::SquareMatrix<double, 4> Matrix44d; + typedef VecMat::SquareMatrix<real, 4> Matrix44r; + +} // end of namespace Geometry + +#endif // GEOM_H diff --git a/source/blender/freestyle/intern/geometry/GeomCleaner.cpp b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp new file mode 100755 index 00000000000..c148c521a46 --- /dev/null +++ b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp @@ -0,0 +1,240 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +//#if defined(__GNUC__) && (__GNUC__ >= 3) +//// hash_map is not part of the C++ standard anymore; +//// hash_map.h has been kept though for backward compatibility +//# include <hash_map.h> +//#else +//# include <hash_map> +//#endif + +#include <stdio.h> +#include <list> +#include <map> +#include "../system/TimeUtils.h" +#include "GeomCleaner.h" + +using namespace std; + + +void GeomCleaner::SortIndexedVertexArray( const float *iVertices, unsigned iVSize, + const unsigned *iIndices, unsigned iISize, + real **oVertices, + unsigned **oIndices) +{ + // First, we build a list of IndexVertex: + list<IndexedVertex> indexedVertices; + unsigned i; + for(i=0; i<iVSize; i+= 3) + { + indexedVertices.push_back(IndexedVertex(Vec3r(iVertices[i], iVertices[i+1], iVertices[i+2]), i/3)); + } + + // q-sort + indexedVertices.sort(); + + // build the indices mapping array: + unsigned *mapIndices = new unsigned[iVSize/3]; + *oVertices = new real[iVSize]; + list<IndexedVertex>::iterator iv; + unsigned newIndex = 0; + unsigned vIndex = 0; + for(iv=indexedVertices.begin(); iv!=indexedVertices.end(); iv++) + { + // Build the final results: + (*oVertices)[vIndex] = iv->x(); + (*oVertices)[vIndex+1] = iv->y(); + (*oVertices)[vIndex+2] = iv->z(); + + mapIndices[iv->index()] = newIndex; + newIndex++; + vIndex+=3; + } + + + // Build the final index array: + *oIndices = new unsigned[iISize]; + for(i=0; i<iISize; i++) + { + (*oIndices)[i] = 3*mapIndices[iIndices[i]/3]; + } + + delete [] mapIndices; +} + +void GeomCleaner::CompressIndexedVertexArray(const real *iVertices, unsigned iVSize, + const unsigned *iIndices, unsigned iISize, + real **oVertices, unsigned *oVSize, + unsigned **oIndices) +{ + // First, we build a list of IndexVertex: + vector<Vec3r> vertices; + unsigned i; + for(i=0; i<iVSize; i+= 3) + { + vertices.push_back(Vec3r(iVertices[i], iVertices[i+1], iVertices[i+2])); + } + + unsigned *mapVertex = new unsigned[iVSize]; + vector<Vec3r>::iterator v = vertices.begin(); + + vector<Vec3r> compressedVertices; + Vec3r previous = *v; + mapVertex[0] = 0; + compressedVertices.push_back(vertices.front()); + + v++; + Vec3r current; + i=1; + for(; v!=vertices.end(); v++) + { + current = *v; + if(current == previous) + mapVertex[i] = compressedVertices.size()-1; + else + { + compressedVertices.push_back(current); + mapVertex[i] = compressedVertices.size()-1; + } + previous = current; + i++; + } + + // Builds the resulting vertex array: + *oVSize = 3*compressedVertices.size(); + *oVertices = new real [*oVSize]; + i=0; + for(v=compressedVertices.begin(); v!=compressedVertices.end(); v++) + { + (*oVertices)[i] = (*v)[0]; + (*oVertices)[i+1] = (*v)[1]; + (*oVertices)[i+2] = (*v)[2]; + i += 3; + } + + // Map the index array: + *oIndices = new unsigned[iISize]; + for(i=0; i<iISize; i++) + { + (*oIndices)[i] = 3*mapVertex[iIndices[i]/3]; + } + + delete [] mapVertex; +} + +void GeomCleaner::SortAndCompressIndexedVertexArray(const float *iVertices, unsigned iVSize, + const unsigned *iIndices, unsigned iISize, + real **oVertices, unsigned *oVSize, + unsigned **oIndices) +{ + + // tmp arrays used to store the sorted data: + real *tmpVertices; + unsigned *tmpIndices; + + Chronometer chrono; + // Sort data + chrono.start(); + GeomCleaner::SortIndexedVertexArray(iVertices, iVSize, + iIndices, iISize, + &tmpVertices, &tmpIndices + ); + printf("Sorting: %lf\n", chrono.stop()); + + // compress data + chrono.start(); + GeomCleaner::CompressIndexedVertexArray(tmpVertices, iVSize, + tmpIndices, iISize, + oVertices, oVSize, + oIndices); + printf("Merging: %lf\n", chrono.stop()); + + // deallocates memory: + delete [] tmpVertices; + delete [] tmpIndices; +} + +/*! Defines a hash table used for searching the Cells */ +struct GeomCleanerHasher{ +#define _MUL 950706376UL +#define _MOD 2147483647UL + inline size_t operator() (const Vec3r& p) const { + size_t res = ((unsigned long) (p[0] * _MUL)) % _MOD; + res = ((res + (unsigned long) (p[1]) * _MUL)) % _MOD; + return ((res +(unsigned long) (p[2]) * _MUL)) % _MOD; + } +}; + +void GeomCleaner::CleanIndexedVertexArray(const float *iVertices, unsigned iVSize, + const unsigned *iIndices, unsigned iISize, + real **oVertices, unsigned *oVSize, + unsigned **oIndices) +{ + typedef map<Vec3r, unsigned> cleanHashTable; + vector<Vec3r> vertices; + unsigned i; + for(i=0; i<iVSize; i+= 3) + vertices.push_back(Vec3r(iVertices[i], iVertices[i+1], iVertices[i+2])); + + cleanHashTable ht; + vector<unsigned> newIndices; + vector<Vec3r> newVertices; + + // elimination of needless points + unsigned currentIndex = 0; + vector<Vec3r>::const_iterator v = vertices.begin(); + vector<Vec3r>::const_iterator end = vertices.end(); + cleanHashTable::const_iterator found; + for(; v!=end; v++) + { + found = ht.find(*v); + if(found != ht.end()) + { + // The vertex is already in the new array. + newIndices.push_back((*found).second); + } + else + { + newVertices.push_back(*v); + newIndices.push_back(currentIndex); + ht[*v] = currentIndex; + currentIndex++; + } + } + + // creation of oVertices array: + *oVSize = 3*newVertices.size(); + *oVertices = new real[*oVSize]; + currentIndex = 0; + end = newVertices.end(); + for(v=newVertices.begin(); v!=end ; v++) + { + (*oVertices)[currentIndex++] = (*v)[0]; + (*oVertices)[currentIndex++] = (*v)[1]; + (*oVertices)[currentIndex++] = (*v)[2]; + } + + // map new indices: + *oIndices = new unsigned[iISize]; + for(i=0; i<iISize; i++) + (*oIndices)[i] = 3*newIndices[iIndices[i]/3]; +} diff --git a/source/blender/freestyle/intern/geometry/GeomCleaner.h b/source/blender/freestyle/intern/geometry/GeomCleaner.h new file mode 100755 index 00000000000..5fdfda0162a --- /dev/null +++ b/source/blender/freestyle/intern/geometry/GeomCleaner.h @@ -0,0 +1,219 @@ +// +// Filename : GeomCleaner.h +// Author : Stephane Grabli +// Purpose : Class to define a cleaner of geometry providing +// a set of useful tools +// Date of creation : 04/03/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef GEOMCLEANER_H +# define GEOMCLEANER_H + +# include "../system/FreestyleConfig.h" +# include "Geom.h" + +using namespace Geometry; + +class LIB_GEOMETRY_EXPORT GeomCleaner +{ +public: + + inline GeomCleaner() {} + inline ~GeomCleaner() {} + + /*! Sorts an array of Indexed vertices + * iVertices + * Array of vertices to sort. It is organized as a + * float series of vertex coordinates: XYZXYZXYZ... + * iVSize + * The size of iVertices array. + * iIndices + * The array containing the vertex indices (used to refer + * to the vertex coordinates in an indexed face). Each + * element is an unsignedeger multiple of 3. + * iISize + * The size of iIndices array + * oVertices + * Output of sorted vertices. A vertex v1 precedes another one + * v2 in this array if v1.x<v2.x, or v1.x=v2.x && v1.y < v2.y + * or v1.x=v2.y && v1.y=v2.y && v1.z < v2.z. + * The array is organized as a 3-float serie giving + * the vertices coordinates: XYZXYZXYZ... + * oIndices + * Output corresponding to the iIndices array but + * reorganized in order to match the sorted vertex array. + */ + + static void SortIndexedVertexArray(const float *iVertices, unsigned iVSize, + const unsigned *iIndices, unsigned iISize, + real **oVertices, + unsigned **oIndices); + + /*! Compress a SORTED indexed vertex array by eliminating + * multiple appearing occurences of a single vertex. + * iVertices + * The SORTED vertex array to compress. It is organized as a + * float series of vertex coordinates: XYZXYZXYZ... + * iVSize + * The size of iVertices array. + * iIndices + * The array containing the vertex indices (used to refer + * to the vertex coordinates in an indexed face). Each + * element is an unsignedeger multiple of 3. + * iISize + * The size of iIndices array + * oVertices + * The vertex array, result of the compression. + * The array is organized as a 3-float serie giving + * the vertices coordinates: XYZXYZXYZ... + * oVSize + * The size of oVertices. + * oIndices + * The indices array, reorganized to match the compressed + * oVertices array. + */ + + static void CompressIndexedVertexArray(const real *iVertices, unsigned iVSize, + const unsigned *iIndices, unsigned iISize, + real **oVertices, unsigned *oVSize, + unsigned **oIndices); + + /*! Sorts and compress an array of indexed vertices. + * iVertices + * The vertex array to sort then compress. It is organized as a + * float series of vertex coordinates: XYZXYZXYZ... + * iVSize + * The size of iVertices array. + * iIndices + * The array containing the vertex indices (used to refer + * to the vertex coordinates in an indexed face). Each + * element is an unsignedeger multiple of 3. + * iISize + * The size of iIndices array + * oVertices + * The vertex array, result of the sorting-compression. + * The array is organized as a 3-float serie giving + * the vertices coordinates: XYZXYZXYZ... + * oVSize + * The size of oVertices. + * oIndices + * The indices array, reorganized to match the sorted and compressed + * oVertices array. + */ + + static void SortAndCompressIndexedVertexArray(const float *iVertices, unsigned iVSize, + const unsigned *iIndices, unsigned iISize, + real **oVertices, unsigned *oVSize, + unsigned **oIndices); + + /*! Cleans an indexed vertex array. (Identical to + * SortAndCompress except that we use here a hash + * table to create the new array.) + * iVertices + * The vertex array to sort then compress. It is organized as a + * float series of vertex coordinates: XYZXYZXYZ... + * iVSize + * The size of iVertices array. + * iIndices + * The array containing the vertex indices (used to refer + * to the vertex coordinates in an indexed face). Each + * element is an unsignedeger multiple of 3. + * iISize + * The size of iIndices array + * oVertices + * The vertex array, result of the sorting-compression. + * The array is organized as a 3-float serie giving + * the vertices coordinates: XYZXYZXYZ... + * oVSize + * The size of oVertices. + * oIndices + * The indices array, reorganized to match the sorted and compressed + * oVertices array. + */ + + static void CleanIndexedVertexArray(const float *iVertices, unsigned iVSize, + const unsigned *iIndices, unsigned iISize, + real **oVertices, unsigned *oVSize, + unsigned **oIndices); +}; + + +/*! Binary operators */ +//inline bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2); + +/*! Class Indexed Vertex. Used to represent + * an indexed vertex by storing the vertex + * coordinates as well as its index + */ +class IndexedVertex +{ +public: + +private: + Vec3r _Vector; + unsigned _index; +public: + inline IndexedVertex() {} + inline IndexedVertex(Vec3r iVector, unsigned iIndex) + { + _Vector = iVector; + _index = iIndex; + } + /*! accessors */ + inline const Vec3r& vector() const {return _Vector;} + inline unsigned index() {return _index;} + inline real x() {return _Vector[0];} + inline real y() {return _Vector[1];} + inline real z() {return _Vector[2];} + + /*! modifiers */ + inline void setVector(const Vec3r& iVector) {_Vector = iVector;} + inline void setIndex(unsigned iIndex) {_index = iIndex;} + + /*! operators */ + IndexedVertex& operator=(const IndexedVertex& iv) + { + _Vector = iv._Vector; + _index = iv._index; + return *this; + } + inline real operator[](const unsigned i) {return _Vector[i];} + //friend inline bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2); + inline bool operator<(const IndexedVertex& v) const + { + return (_Vector < v._Vector); + } + inline bool operator==(const IndexedVertex& v) + { + return (_Vector == v._Vector); + } +}; + +//bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2) +//{ +// return iv1.operator<(iv2); +//} + +#endif // GEOMCLEANER_H diff --git a/source/blender/freestyle/intern/geometry/GeomUtils.cpp b/source/blender/freestyle/intern/geometry/GeomUtils.cpp new file mode 100755 index 00000000000..2169bce0364 --- /dev/null +++ b/source/blender/freestyle/intern/geometry/GeomUtils.cpp @@ -0,0 +1,753 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "GeomUtils.h" + +namespace GeomUtils { + + // This internal procedure is defined below. + bool intersect2dSegPoly(Vec2r* seg, + Vec2r* poly, + unsigned n); + + bool intersect2dSeg2dArea(const Vec2r& min, + const Vec2r& max, + const Vec2r& A, + const Vec2r& B) { + Vec2r seg[2]; + seg[0] = A; + seg[1] = B; + + Vec2r poly[5]; + poly[0][0] = min[0]; + poly[0][1] = min[1]; + poly[1][0] = max[0]; + poly[1][1] = min[1]; + poly[2][0] = max[0]; + poly[2][1] = max[1]; + poly[3][0] = min[0]; + poly[3][1] = max[1]; + poly[4][0] = min[0]; + poly[4][1] = min[1]; + + return intersect2dSegPoly(seg, poly, 4); + } + + bool include2dSeg2dArea(const Vec2r& min, + const Vec2r& max, + const Vec2r& A, + const Vec2r& B) { + if((((max[0] > A[0])&&(A[0] > min[0]))&&((max[0] > B[0])&&(B[0] > min[0]))) + && (((max[1] > A[1])&&(A[1] > min[1]))&&((max[1] > B[1])&&(B[1] > min[1])))) + return true; + return false; + } + + intersection_test intersect2dSeg2dSeg(const Vec2r& p1, + const Vec2r& p2, + const Vec2r& p3, + const Vec2r& p4, + Vec2r& res) { + real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns + real r1, r2, r3, r4; // 'Sign' values + real denom, num; // Intermediate values + + // Compute a1, b1, c1, where line joining points p1 and p2 + // is "a1 x + b1 y + c1 = 0". + a1 = p2[1] - p1[1]; + b1 = p1[0] - p2[0]; + c1 = p2[0] * p1[1] - p1[0] * p2[1]; + + // Compute r3 and r4. + r3 = a1 * p3[0] + b1 * p3[1] + c1; + r4 = a1 * p4[0] + b1 * p4[1] + c1; + + // Check signs of r3 and r4. If both point 3 and point 4 lie on + // same side of line 1, the line segments do not intersect. + if ( r3 != 0 && r4 != 0 && r3 * r4 > 0.0) + return (DONT_INTERSECT); + + // Compute a2, b2, c2 + a2 = p4[1] - p3[1]; + b2 = p3[0] - p4[0]; + c2 = p4[0] * p3[1] - p3[0] * p4[1]; + + // Compute r1 and r2 + r1 = a2 * p1[0] + b2 * p1[1] + c2; + r2 = a2 * p2[0] + b2 * p2[1] + c2; + + // Check signs of r1 and r2. If both point 1 and point 2 lie + // on same side of second line segment, the line segments do + // not intersect. + if ( r1 != 0 && r2 != 0 && r1 * r2 > 0.0) + return (DONT_INTERSECT); + + // Line segments intersect: compute intersection point. + denom = a1 * b2 - a2 * b1; + if (fabs(denom) < M_EPSILON) + return (COLINEAR); + + num = b1 * c2 - b2 * c1; + res[0] = num / denom; + + num = a2 * c1 - a1 * c2; + res[1] = num / denom; + + return (DO_INTERSECT); + } + + intersection_test intersect2dLine2dLine(const Vec2r& p1, + const Vec2r& p2, + const Vec2r& p3, + const Vec2r& p4, + Vec2r& res) { + real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns + real denom, num; // Intermediate values + + // Compute a1, b1, c1, where line joining points p1 and p2 + // is "a1 x + b1 y + c1 = 0". + a1 = p2[1] - p1[1]; + b1 = p1[0] - p2[0]; + c1 = p2[0] * p1[1] - p1[0] * p2[1]; + + // Compute a2, b2, c2 + a2 = p4[1] - p3[1]; + b2 = p3[0] - p4[0]; + c2 = p4[0] * p3[1] - p3[0] * p4[1]; + + // Line segments intersect: compute intersection point. + denom = a1 * b2 - a2 * b1; + if (fabs(denom) < M_EPSILON) + return (COLINEAR); + + num = b1 * c2 - b2 * c1; + res[0] = num / denom; + + num = a2 * c1 - a1 * c2; + res[1] = num / denom; + + return (DO_INTERSECT); + } + + intersection_test intersect2dSeg2dSegParametric(const Vec2r& p1, + const Vec2r& p2, + const Vec2r& p3, + const Vec2r& p4, + real& t, + real& u, + real epsilon) { + real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns + real r1, r2, r3, r4; // 'Sign' values + real denom, num; // Intermediate values + + // Compute a1, b1, c1, where line joining points p1 and p2 + // is "a1 x + b1 y + c1 = 0". + a1 = p2[1] - p1[1]; + b1 = p1[0] - p2[0]; + c1 = p2[0] * p1[1] - p1[0] * p2[1]; + + // Compute r3 and r4. + r3 = a1 * p3[0] + b1 * p3[1] + c1; + r4 = a1 * p4[0] + b1 * p4[1] + c1; + + // Check signs of r3 and r4. If both point 3 and point 4 lie on + // same side of line 1, the line segments do not intersect. + if ( r3 != 0 && r4 != 0 && r3 * r4 > 0.0) + return (DONT_INTERSECT); + + // Compute a2, b2, c2 + a2 = p4[1] - p3[1]; + b2 = p3[0] - p4[0]; + c2 = p4[0] * p3[1] - p3[0] * p4[1]; + + // Compute r1 and r2 + r1 = a2 * p1[0] + b2 * p1[1] + c2; + r2 = a2 * p2[0] + b2 * p2[1] + c2; + + // Check signs of r1 and r2. If both point 1 and point 2 lie + // on same side of second line segment, the line segments do + // not intersect. + if ( r1 != 0 && r2 != 0 && r1 * r2 > 0.0) + return (DONT_INTERSECT); + + // Line segments intersect: compute intersection point. + denom = a1 * b2 - a2 * b1; + if (fabs(denom) < epsilon) + return (COLINEAR); + + real d1, d2, e1; + + d1 = p1[1] - p3[1]; + d2 = p2[1] - p1[1]; + e1 = p1[0] - p3[0]; + + num = -b2 * d1 - a2 * e1; + t = num / denom; + + num = -b1 * d1 - a1 * e1; + u = num / denom; + + return (DO_INTERSECT); + } + + // AABB-triangle overlap test code + // by Tomas Akenine-Möller + // Function: int triBoxOverlap(real boxcenter[3], + // real boxhalfsize[3],real triverts[3][3]); + // History: + // 2001-03-05: released the code in its first version + // 2001-06-18: changed the order of the tests, faster + // + // Acknowledgement: Many thanks to Pierre Terdiman for + // suggestions and discussions on how to optimize code. + // Thanks to David Hunt for finding a ">="-bug! + +#define X 0 +#define Y 1 +#define Z 2 + +#define FINDMINMAX(x0, x1, x2, min, max) \ + min = max = x0; \ + if(x1<min) min=x1; \ + if(x1>max) max=x1; \ + if(x2<min) min=x2; \ + if(x2>max) max=x2; + + //======================== X-tests ========================// +#define AXISTEST_X01(a, b, fa, fb) \ + p0 = a*v0[Y] - b*v0[Z]; \ + p2 = a*v2[Y] - b*v2[Z]; \ + if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} \ + rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \ + if(min>rad || max<-rad) return 0; + +#define AXISTEST_X2(a, b, fa, fb) \ + p0 = a*v0[Y] - b*v0[Z]; \ + p1 = a*v1[Y] - b*v1[Z]; \ + if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \ + rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \ + if(min>rad || max<-rad) return 0; + + //======================== Y-tests ========================// +#define AXISTEST_Y02(a, b, fa, fb) \ + p0 = -a*v0[X] + b*v0[Z]; \ + p2 = -a*v2[X] + b*v2[Z]; \ + if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} \ + rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \ + if(min>rad || max<-rad) return 0; + +#define AXISTEST_Y1(a, b, fa, fb) \ + p0 = -a*v0[X] + b*v0[Z]; \ + p1 = -a*v1[X] + b*v1[Z]; \ + if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \ + rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \ + if(min>rad || max<-rad) return 0; + + //======================== Z-tests ========================// +#define AXISTEST_Z12(a, b, fa, fb) \ + p1 = a*v1[X] - b*v1[Y]; \ + p2 = a*v2[X] - b*v2[Y]; \ + if(p2<p1) {min=p2; max=p1;} else {min=p1; max=p2;} \ + rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \ + if(min>rad || max<-rad) return 0; + +#define AXISTEST_Z0(a, b, fa, fb) \ + p0 = a*v0[X] - b*v0[Y]; \ + p1 = a*v1[X] - b*v1[Y]; \ + if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \ + rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \ + if(min>rad || max<-rad) return 0; + + // This internal procedure is defined below. + bool overlapPlaneBox(Vec3r& normal, real d, Vec3r& maxbox); + + // Use separating axis theorem to test overlap between triangle and box + // need to test for overlap in these directions: + // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle + // we do not even need to test these) + // 2) normal of the triangle + // 3) crossproduct(edge from tri, {x,y,z}-directin) + // this gives 3x3=9 more tests + bool overlapTriangleBox(Vec3r& boxcenter, + Vec3r& boxhalfsize, + Vec3r triverts[3]) { + Vec3r v0, v1, v2, normal, e0, e1, e2; + real min, max, d, p0, p1, p2, rad, fex, fey, fez; + + // This is the fastest branch on Sun + // move everything so that the boxcenter is in (0, 0, 0) + v0 = triverts[0] - boxcenter; + v1 = triverts[1] - boxcenter; + v2 = triverts[2] - boxcenter; + + // compute triangle edges + e0 = v1 - v0; + e1 = v2 - v1; + e2 = v0 - v2; + + // Bullet 3: + // Do the 9 tests first (this was faster) + fex = fabs(e0[X]); + fey = fabs(e0[Y]); + fez = fabs(e0[Z]); + AXISTEST_X01(e0[Z], e0[Y], fez, fey); + AXISTEST_Y02(e0[Z], e0[X], fez, fex); + AXISTEST_Z12(e0[Y], e0[X], fey, fex); + + fex = fabs(e1[X]); + fey = fabs(e1[Y]); + fez = fabs(e1[Z]); + AXISTEST_X01(e1[Z], e1[Y], fez, fey); + AXISTEST_Y02(e1[Z], e1[X], fez, fex); + AXISTEST_Z0(e1[Y], e1[X], fey, fex); + + fex = fabs(e2[X]); + fey = fabs(e2[Y]); + fez = fabs(e2[Z]); + AXISTEST_X2(e2[Z], e2[Y], fez, fey); + AXISTEST_Y1(e2[Z], e2[X], fez, fex); + AXISTEST_Z12(e2[Y], e2[X], fey, fex); + + // Bullet 1: + // first test overlap in the {x,y,z}-directions + // find min, max of the triangle each direction, and test for overlap in + // that direction -- this is equivalent to testing a minimal AABB around + // the triangle against the AABB + + // test in X-direction + FINDMINMAX(v0[X], v1[X], v2[X], min, max); + if (min > boxhalfsize[X] || max < -boxhalfsize[X]) + return false; + + // test in Y-direction + FINDMINMAX(v0[Y], v1[Y], v2[Y], min, max); + if (min > boxhalfsize[Y] || max < -boxhalfsize[Y]) + return false; + + // test in Z-direction + FINDMINMAX(v0[Z], v1[Z], v2[Z], min, max); + if(min > boxhalfsize[Z] || max < -boxhalfsize[Z]) + return false; + + // Bullet 2: + // test if the box intersects the plane of the triangle + // compute plane equation of triangle: normal * x + d = 0 + normal = e0 ^ e1; + d = -(normal * v0); // plane eq: normal.x + d = 0 + if (!overlapPlaneBox(normal, d, boxhalfsize)) + return false; + + return true; // box and triangle overlaps + } + + // Fast, Minimum Storage Ray-Triangle Intersection + // + // Tomas Möller + // Prosolvia Clarus AB + // Sweden + // tompa@clarus.se + // + // Ben Trumbore + // Cornell University + // Ithaca, New York + // wbt@graphics.cornell.edu + + bool intersectRayTriangle(Vec3r& orig, Vec3r& dir, + Vec3r& v0, Vec3r& v1, Vec3r& v2, + real& t, real& u, real& v, real epsilon) { + Vec3r edge1, edge2, tvec, pvec, qvec; + real det, inv_det; + + // find vectors for two edges sharing v0 + edge1 = v1 - v0; + edge2 = v2 - v0; + + // begin calculating determinant - also used to calculate U parameter + pvec = dir ^ edge2; + + // if determinant is near zero, ray lies in plane of triangle + det = edge1 * pvec; + + // calculate distance from v0 to ray origin + tvec = orig - v0; + inv_det = 1.0 / det; + + qvec = tvec ^ edge1; + + if (det > epsilon) { + u = tvec * pvec; + if (u < 0.0 || u > det) + return false; + + // calculate V parameter and test bounds + v = dir * qvec; + if (v < 0.0 || u + v > det) + return false; + } + else if(det < -epsilon) { + // calculate U parameter and test bounds + u = tvec * pvec; + if (u > 0.0 || u < det) + return false; + + // calculate V parameter and test bounds + v = dir * qvec; + if (v > 0.0 || u + v < det) + return false; + } + else + return false; // ray is parallell to the plane of the triangle + + u *= inv_det; + v *= inv_det; + t = (edge2 * qvec) * inv_det; + + return true; + } + + // Intersection between plane and ray, adapted from Graphics Gems, Didier Badouel + intersection_test intersectRayPlane(Vec3r& orig, Vec3r& dir, + Vec3r& norm, real d, + real& t, + real epsilon) { + real denom = norm * dir; + + if(fabs(denom) <= epsilon) { // plane and ray are parallel + if(fabs((norm * orig) + d) <= epsilon) + return COINCIDENT; // plane and ray are coincident + else + return COLINEAR; + } + + t = -(d + (norm * orig)) / denom; + + if (t < 0.0f) + return DONT_INTERSECT; + + return DO_INTERSECT; + } + + bool intersectRayBBox(const Vec3r& orig, const Vec3r& dir, // ray origin and direction + const Vec3r& boxMin, const Vec3r& boxMax, // the bbox + real t0, real t1, + real& tmin, real& tmax, // I0=orig+tmin*dir is the first intersection, I1=orig+tmax*dir is the second intersection + real epsilon){ + + float tymin, tymax, tzmin, tzmax; + Vec3r inv_direction(1.0/dir[0], 1.0/dir[1], 1.0/dir[2]); + int sign[3]; + sign[0] = (inv_direction.x() < 0); + sign[1] = (inv_direction.y() < 0); + sign[2] = (inv_direction.z() < 0); + + Vec3r bounds[2]; + bounds[0] = boxMin; + bounds[1] = boxMax; + + tmin = (bounds[sign[0]].x() - orig.x()) * inv_direction.x(); + tmax = (bounds[1-sign[0]].x() - orig.x()) * inv_direction.x(); + tymin = (bounds[sign[1]].y() - orig.y()) * inv_direction.y(); + tymax = (bounds[1-sign[1]].y() - orig.y()) * inv_direction.y(); + if ( (tmin > tymax) || (tymin > tmax) ) + return false; + if (tymin > tmin) + tmin = tymin; + if (tymax < tmax) + tmax = tymax; + tzmin = (bounds[sign[2]].z() - orig.z()) * inv_direction.z(); + tzmax = (bounds[1-sign[2]].z() - orig.z()) * inv_direction.z(); + if ( (tmin > tzmax) || (tzmin > tmax) ) + return false; + if (tzmin > tmin) + tmin = tzmin; + if (tzmax < tmax) + tmax = tzmax; + return ( (tmin < t1) && (tmax > t0) ); + } + + // Checks whether 3D points p lies inside or outside of the triangle ABC + bool includePointTriangle(Vec3r& P, + Vec3r& A, + Vec3r& B, + Vec3r& C) { + Vec3r AB(B - A); + Vec3r BC(C - B); + Vec3r CA(A - C); + Vec3r AP(P - A); + Vec3r BP(P - B); + Vec3r CP(P - C); + + Vec3r N(AB ^ BC); // triangle's normal + + N.normalize(); + + Vec3r J(AB ^ AP), K(BC ^ BP), L(CA ^ CP); + J.normalize(); + K.normalize(); + L.normalize(); + + if(J * N < 0) + return false; // on the right of AB + + if(K * N < 0) + return false; // on the right of BC + + if(L * N < 0) + return false; // on the right of CA + + return true; + } + + void transformVertex(const Vec3r& vert, + const Matrix44r& matrix, + Vec3r& res) { + HVec3r hvert(vert), res_tmp; + real scale; + for (unsigned j = 0; j < 4; j++) { + scale = hvert[j]; + for (unsigned i = 0; i < 4; i++) + res_tmp[i] += matrix(i, j) * scale; + } + + res[0] = res_tmp.x(); + res[1] = res_tmp.y(); + res[2] = res_tmp.z(); + } + + void transformVertices(const vector<Vec3r>& vertices, + const Matrix44r& trans, + vector<Vec3r>& res) { + for (vector<Vec3r>::const_iterator v = vertices.begin(); + v != vertices.end(); + v++) { + Vec3r *res_tmp = new Vec3r; + transformVertex(*v, trans, *res_tmp); + res.push_back(*res_tmp); + } + } + + Vec3r rotateVector(const Matrix44r& mat, const Vec3r& v) { + Vec3r res; + for (unsigned i = 0; i < 3; i++) { + res[i] = 0; + for (unsigned j = 0; j < 3; j++) + res[i] += mat(i, j) * v[j]; + } + res.normalize(); + return res; + } + + // This internal procedure is defined below. + void fromCoordAToCoordB(const Vec3r& p, + Vec3r& q, + const real transform[4][4]); + + void fromWorldToCamera(const Vec3r& p, + Vec3r& q, + const real model_view_matrix[4][4]) { + fromCoordAToCoordB(p, q, model_view_matrix); + } + + void fromCameraToRetina(const Vec3r& p, + Vec3r& q, + const real projection_matrix[4][4]) { + fromCoordAToCoordB(p, q, projection_matrix); + } + + void fromRetinaToImage(const Vec3r& p, + Vec3r& q, + const int viewport[4]) { + // winX: + q[0] = viewport[0] + viewport[2] * (p[0] + 1.0) / 2.0; + + // winY: + q[1] = viewport[1] + viewport[3] * (p[1] + 1.0) / 2.0; + + // winZ: + q[2] = (p[2] + 1.0) / 2.0; + } + + void fromWorldToImage(const Vec3r& p, + Vec3r& q, + const real model_view_matrix[4][4], + const real projection_matrix[4][4], + const int viewport[4]) { + Vec3r p1, p2; + fromWorldToCamera(p, p1, model_view_matrix); + fromCameraToRetina(p1, p2, projection_matrix); + fromRetinaToImage(p2, q, viewport); + q[2] = p1[2]; + } + + void fromWorldToImage(const Vec3r& p, + Vec3r& q, + const real transform[4][4], + const int viewport[4]) { + fromCoordAToCoordB(p, q, transform); + + // winX: + q[0] = viewport[0] + viewport[2] * (q[0] + 1.0) / 2.0; + + //winY: + q[1] = viewport[1] + viewport[3] * (q[1] + 1.0) / 2.0; + } + + void fromImageToRetina(const Vec3r& p, + Vec3r& q, + const int viewport[4]) { + q = p; + q[0] = 2.0 * (q[0] - viewport[0]) / viewport[2] - 1; + q[1] = 2.0 * (q[1] - viewport[1]) / viewport[3] - 1; + } + + void fromRetinaToCamera(const Vec3r& p, + Vec3r& q, + real focal, + const real projection_matrix[4][4]) { + + if( projection_matrix[3][3] == 0.0 ) // perspective + { + q[0] = (-p[0] * focal) / projection_matrix[0][0]; + q[1] = (-p[1] * focal) / projection_matrix[1][1]; + q[2] = focal; + } + else // orthogonal + { + q[0] = p[0] / projection_matrix[0][0]; + q[1] = p[1] / projection_matrix[1][1]; + q[2] = focal; + } + } + + void fromCameraToWorld(const Vec3r& p, + Vec3r& q, + const real model_view_matrix[4][4]) { + + real translation[3] = { model_view_matrix[0][3], + model_view_matrix[1][3], + model_view_matrix[2][3] }; + for (unsigned i = 0; i < 3; i++) { + q[i] = 0.0; + for (unsigned short j = 0; j < 3; j++) + q[i] += model_view_matrix[j][i] * (p[j] - translation[j]); + } + } + + + // + // Internal code + // + ///////////////////////////////////////////////////////////////////////////// + + // Copyright 2001, softSurfer (www.softsurfer.com) + // This code may be freely used and modified for any purpose + // providing that this copyright notice is included with it. + // SoftSurfer makes no warranty for this code, and cannot be held + // liable for any real or imagined damage resulting from its use. + // Users of this code must verify correctness for their application. + +#define perp(u,v) ((u)[0] * (v)[1] - (u)[1] * (v)[0]) // 2D perp product + + inline bool intersect2dSegPoly(Vec2r* seg, + Vec2r* poly, + unsigned n) { + if (seg[0] == seg[1]) + return false; + + real tE = 0; // the maximum entering segment parameter + real tL = 1; // the minimum leaving segment parameter + real t, N, D; // intersect parameter t = N / D + Vec2r dseg; // the segment direction vector + dseg = seg[1] - seg[0]; + Vec2r e; // edge vector + + for (unsigned i = 0; i < n; i++) { // process polygon edge poly[i]poly[i+1] + e = poly[i+1] - poly[i]; + N = perp(e, seg[0] - poly[i]); + D = -perp(e, dseg); + if (fabs(D) < M_EPSILON) { + if (N < 0) + return false; + else + continue; + } + + t = N / D; + if (D < 0) { // segment seg is entering across this edge + if (t > tE) { // new max tE + tE = t; + if (tE > tL) // seg enters after leaving polygon + return false; + } + } + else { // segment seg is leaving across this edge + if (t < tL) { // new min tL + tL = t; + if (tL < tE) // seg leaves before entering polygon + return false; + } + } + } + + // tE <= tL implies that there is a valid intersection subsegment + return true; + } + + inline bool overlapPlaneBox(Vec3r& normal, real d, Vec3r& maxbox) { + Vec3r vmin, vmax; + + for(unsigned q = X; q <= Z; q++) { + if(normal[q] > 0.0f) { + vmin[q] = -maxbox[q]; + vmax[q] = maxbox[q]; + } + else { + vmin[q] = maxbox[q]; + vmax[q] = -maxbox[q]; + } + } + if((normal * vmin) + d > 0.0f) + return false; + if((normal * vmax) + d >= 0.0f) + return true; + return false; + } + + inline void fromCoordAToCoordB(const Vec3r&p, + Vec3r& q, + const real transform[4][4]) { + HVec3r hp(p); + HVec3r hq(0, 0, 0, 0); + + for (unsigned i = 0; i < 4; i++) + for (unsigned j = 0; j < 4; j++) + hq[i] += transform[i][j] * hp[j]; + + if(hq[3] == 0) { + q = p; + return; + } + + for (unsigned k = 0; k < 3; k++) + q[k] = hq[k] / hq[3]; + } + +} // end of namespace GeomUtils diff --git a/source/blender/freestyle/intern/geometry/GeomUtils.h b/source/blender/freestyle/intern/geometry/GeomUtils.h new file mode 100755 index 00000000000..787376108e1 --- /dev/null +++ b/source/blender/freestyle/intern/geometry/GeomUtils.h @@ -0,0 +1,310 @@ +// +// Filename : GeomUtils.h +// Author(s) : Stephane Grabli +// Purpose : Various tools for geometry +// Date of creation : 12/04/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef GEOMUTILS_H +# define GEOMUTILS_H + +# include <vector> +# include "../system/FreestyleConfig.h" +# include "Geom.h" + +using namespace std; +using namespace Geometry; + +namespace GeomUtils { + + // + // Templated procedures + // + ///////////////////////////////////////////////////////////////////////////// + + /*! Computes the distance from a point P to a segment AB */ + template<class T> + real distPointSegment( const T& P, const T& A , const T& B) { + T AB, AP, BP; + AB = B - A; + AP = P - A; + BP = P - B; + + real c1(AB * AP); + if (c1 <= 0) + return AP.norm(); + + real c2(AB * AB); + if (c2 <= c1) + return BP.norm(); + + real b = c1 / c2; + T Pb, PPb; + Pb = A + b * AB; + PPb = P - Pb; + + return PPb.norm(); + } + + // + // Non-templated procedures + // + ///////////////////////////////////////////////////////////////////////////// + + typedef enum { + DONT_INTERSECT, + DO_INTERSECT, + COLINEAR, + COINCIDENT + } intersection_test; + + LIB_GEOMETRY_EXPORT + intersection_test intersect2dSeg2dSeg(const Vec2r& p1, const Vec2r& p2, // first segment + const Vec2r& p3, const Vec2r& p4, // second segment + Vec2r& res); // found intersection point + + LIB_GEOMETRY_EXPORT + intersection_test intersect2dLine2dLine(const Vec2r& p1, const Vec2r& p2, // first segment + const Vec2r& p3, const Vec2r& p4, // second segment + Vec2r& res); // found intersection point + + LIB_GEOMETRY_EXPORT + intersection_test intersect2dSeg2dSegParametric(const Vec2r& p1, const Vec2r& p2, // first segment + const Vec2r& p3, const Vec2r& p4, // second segment + real& t, // I = P1 + t * P1P2) + real& u, // I = P3 + u * P3P4 + real epsilon = M_EPSILON); + + /*! check whether a 2D segment intersect a 2D region or not */ + LIB_GEOMETRY_EXPORT + bool intersect2dSeg2dArea(const Vec2r& min, + const Vec2r& max, + const Vec2r& A, + const Vec2r& B); + + /*! check whether a 2D segment is included in a 2D region or not */ + LIB_GEOMETRY_EXPORT + bool include2dSeg2dArea(const Vec2r& min, + const Vec2r& max, + const Vec2r& A, + const Vec2r& B); + + /*! Box-triangle overlap test, adapted from Tomas Akenine-Möller code */ + LIB_GEOMETRY_EXPORT + bool overlapTriangleBox(Vec3r& boxcenter, + Vec3r& boxhalfsize, + Vec3r triverts[3]); + + /*! Fast, Minimum Storage Ray-Triangle Intersection, + * adapted from Tomas Möller and Ben Trumbore code. + */ + LIB_GEOMETRY_EXPORT + bool intersectRayTriangle(Vec3r& orig, Vec3r& dir, + Vec3r& v0, Vec3r& v1, Vec3r& v2, + real& t, // I = orig + t * dir + real& u, real& v, // I = (1-u-v)*v0+u*v1+v*v2 + real epsilon = M_EPSILON); // the epsilon to use + + /*! Intersection between plane and ray + * adapted from Graphics Gems, Didier Badouel + */ + LIB_GEOMETRY_EXPORT + intersection_test intersectRayPlane(Vec3r& orig, Vec3r& dir, // ray origin and direction + Vec3r& norm, real d, // plane's normal and offset (plane = { P / P.N + d = 0 }) + real& t, // I = orig + t * dir + real epsilon = M_EPSILON); // the epsilon to use + + /*! Intersection Ray-Bounding box (axis aligned). + * Adapted from Williams et al, "An Efficient Robust Ray-Box Intersection Algorithm", + * JGT 10:1 (2005), pp. 49-54. + * Returns + */ + LIB_GEOMETRY_EXPORT + bool intersectRayBBox(const Vec3r& orig, const Vec3r& dir, // ray origin and direction + const Vec3r& boxMin, const Vec3r& boxMax, // the bbox + real t0, real t1, // the interval in which at least on of the intersections must happen + real& tmin, real& tmax, // Imin=orig+tmin*dir is the first intersection, Imax=orig+tmax*dir is the second intersection + real epsilon = M_EPSILON); // the epsilon to use + + + /*! Checks whether 3D point P lies inside or outside of the triangle ABC */ + LIB_GEOMETRY_EXPORT + bool includePointTriangle(Vec3r& P, + Vec3r& A, + Vec3r& B, + Vec3r& C); + + LIB_GEOMETRY_EXPORT + void transformVertex(const Vec3r& vert, + const Matrix44r& matrix, + Vec3r& res); + + LIB_GEOMETRY_EXPORT + void transformVertices(const vector<Vec3r>& vertices, + const Matrix44r& trans, + vector<Vec3r>& res); + + LIB_GEOMETRY_EXPORT + Vec3r rotateVector(const Matrix44r& mat, const Vec3r& v); + + // + // Coordinates systems changing procedures + // + ///////////////////////////////////////////////////////////////////////////// + + /*! From world to image + * p + * point's coordinates expressed in world coordinates system + * q + * vector in which the result will be stored + * model_view_matrix + * The model view matrix expressed in line major order (OpenGL + * matrices are column major ordered) + * projection_matrix + * The projection matrix expressed in line major order (OpenGL + * matrices are column major ordered) + * viewport + * The viewport: x,y coordinates followed by width and height (OpenGL like viewport) + */ + LIB_GEOMETRY_EXPORT + void fromWorldToImage(const Vec3r& p, + Vec3r& q, + const real model_view_matrix[4][4], + const real projection_matrix[4][4], + const int viewport[4]); + + /*! From world to image + * p + * point's coordinates expressed in world coordinates system + * q + * vector in which the result will be stored + * transform + * The transformation matrix (gathering model view and projection), + * expressed in line major order (OpenGL matrices are column major ordered) + * viewport + * The viewport: x,y coordinates followed by width and height (OpenGL like viewport) + */ + LIB_GEOMETRY_EXPORT + void fromWorldToImage(const Vec3r& p, + Vec3r& q, + const real transform[4][4], + const int viewport[4]); + + /*! Projects from world coordinates to camera coordinates + * Returns the point's coordinates expressed in the camera's + * coordinates system. + * p + * point's coordinates expressed in world coordinates system + * q + * vector in which the result will be stored + * model_view_matrix + * The model view matrix expressed in line major order (OpenGL + * matrices are column major ordered) + */ + LIB_GEOMETRY_EXPORT + void fromWorldToCamera(const Vec3r& p, + Vec3r& q, + const real model_view_matrix[4][4]); + + /*! Projects from World Coordinates to retina coordinates + * Returns the point's coordinates expressed in Retina system. + * p + * point's coordinates expressed in camera system + * q + * vector in which the result will be stored + * projection_matrix + * The projection matrix expressed in line major order (OpenGL + * matrices are column major ordered) + */ + LIB_GEOMETRY_EXPORT + void fromCameraToRetina(const Vec3r& p, + Vec3r& q, + const real projection_matrix[4][4]); + + /*! From retina to image. + * Returns the coordinates expressed in Image coorinates system. + * p + * point's coordinates expressed in retina system + * q + * vector in which the result will be stored + * viewport + * The viewport: x,y coordinates followed by width and height (OpenGL like viewport). + */ + LIB_GEOMETRY_EXPORT + void fromRetinaToImage(const Vec3r& p, + Vec3r& q, + const int viewport[4]); + + /*! From image to retina + * p + * point's coordinates expressed in image system + * q + * vector in which the result will be stored + * viewport + * The viewport: x,y coordinates followed by width and height (OpenGL like viewport). + */ + LIB_GEOMETRY_EXPORT + void fromImageToRetina(const Vec3r& p, + Vec3r& q, + const int viewport[4]); + + /*! computes the coordinates of q in the camera coordinates system, + * using the known z coordinates of the 3D point. + * That means that this method does not inverse any matrices, + * it only computes X and Y from x,y and Z) + * p + * point's coordinates expressed in retina system + * q + * vector in which the result will be stored + * projection_matrix + * The projection matrix expressed in line major order (OpenGL + * matrices are column major ordered) + + */ + LIB_GEOMETRY_EXPORT + void fromRetinaToCamera(const Vec3r& p, + Vec3r& q, + real z, + const real projection_matrix[4][4]); + + /*! Projects from camera coordinates to world coordinates + * Returns the point's coordinates expressed in the world's + * coordinates system. + * p + * point's coordinates expressed in the camera coordinates system + * q + * vector in which the result will be stored + * model_view_matrix + * The model view matrix expressed in line major order (OpenGL + * matrices are column major ordered) + */ + LIB_GEOMETRY_EXPORT + void fromCameraToWorld(const Vec3r& p, + Vec3r& q, + const real model_view_matrix[4][4]); + +} // end of namespace GeomUtils + +#endif // GEOMUTILS_H diff --git a/source/blender/freestyle/intern/geometry/Grid.cpp b/source/blender/freestyle/intern/geometry/Grid.cpp new file mode 100755 index 00000000000..2477227c410 --- /dev/null +++ b/source/blender/freestyle/intern/geometry/Grid.cpp @@ -0,0 +1,388 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "Grid.h" +#include "BBox.h" +#include <cassert> +#include <stdexcept> + +// Grid Visitors +///////////////// +void allOccludersGridVisitor::examineOccluder(Polygon3r *occ){ + occluders_.push_back(occ); +} + +bool inBox(const Vec3r& inter, const Vec3r& box_min, const Vec3r& box_max){ + if(((inter.x()>=box_min.x()) && (inter.x() <box_max.x())) + && ((inter.y()>=box_min.y()) && (inter.y() <box_max.y())) + && ((inter.z()>=box_min.z()) && (inter.z() <box_max.z())) + ){ + return true; + } + return false; +} +void firstIntersectionGridVisitor::examineOccluder(Polygon3r *occ){ + + // check whether the edge and the polygon plane are coincident: + //------------------------------------------------------------- + //first let us compute the plane equation. + Vec3r v1(((occ)->getVertices())[0]); + Vec3d normal((occ)->getNormal()); + //soc unused - double d = -(v1 * normal); + + double tmp_u, tmp_v, tmp_t; + if((occ)->rayIntersect(ray_org_, ray_dir_, tmp_t, tmp_u, tmp_v)){ + if (fabs(ray_dir_ * normal) > 0.0001){ + // Check whether the intersection is in the cell: + if(inBox(ray_org_+tmp_t*ray_dir_/ray_dir_.norm(), current_cell_->getOrigin(), current_cell_->getOrigin()+cell_size_)){ + + //Vec3d bboxdiag(_scene3d->bbox().getMax()-_scene3d->bbox().getMin()); + //if ((t>1.0E-06*(min(min(bboxdiag.x(),bboxdiag.y()),bboxdiag.z()))) && (t<raylength)){ + if(tmp_t < t_){ + occluder_ = occ; + u_ = tmp_u; + v_ = tmp_v; + t_ = tmp_t; + } + }else{ + occ->userdata2 = 0; + } + } + } +} + +bool firstIntersectionGridVisitor::stop(){ + if(occluder_) + return true; + return false; +} + +// Grid +///////////////// + +void Grid::clear() { + if (_occluders.size() != 0) { + for(OccludersSet::iterator it = _occluders.begin(); + it != _occluders.end(); + it++) { + delete (*it); + } + _occluders.clear(); + } + + _size = Vec3r(0, 0, 0); + _cell_size = Vec3r(0, 0, 0); + _orig = Vec3r(0, 0, 0); + _cells_nb = Vec3u(0, 0, 0); + //_ray_occluders.clear(); +} + +void Grid::configure(const Vec3r& orig, + const Vec3r& size, + unsigned nb) { + + _orig = orig; + Vec3r tmpSize=size; + // Compute the volume of the desired grid + real grid_vol = size[0] * size[1] * size[2]; + + if(grid_vol == 0){ + double min=DBL_MAX; + int index=0; + int nzeros=0; + for(int i=0;i<3;++i){ + if(size[i] == 0){ + ++nzeros; + index=i; + } + if((size[i]!=0) && (min>size[i])){ + min=size[i]; + } + } + if(nzeros>1){ + throw std::runtime_error("Warning: the 3D grid has more than one null dimension"); + } + tmpSize[index]=min; + _orig[index] = _orig[index]-min/2; + } + // Compute the desired volume of a single cell + real cell_vol = grid_vol / nb; + // The edge of such a cubic cell is cubic root of cellVolume + real edge = pow(cell_vol, 1.0 / 3.0); + + // We compute the number of cells par edge + // such as we cover at least the whole box. + unsigned i; + for (i = 0; i < 3; i++) + _cells_nb[i] = (unsigned)floor(tmpSize[i] / edge) + 1; + + _size = tmpSize; + + for(i = 0; i < 3; i++) + _cell_size[i] = _size[i] / _cells_nb[i]; +} + +void Grid::insertOccluder(Polygon3r* occluder) { + const vector<Vec3r> vertices = occluder->getVertices(); + if (vertices.size() == 0) + return; + + // add this occluder to the grid's occluders list + addOccluder(occluder); + + // find the bbox associated to this polygon + Vec3r min, max; + occluder->getBBox(min, max); + + // Retrieve the cell x, y, z cordinates associated with these min and max + Vec3u imax, imin; + getCellCoordinates(max, imax); + getCellCoordinates(min, imin); + + // We are now going to fill in the cells overlapping with the + // polygon bbox. + // If the polygon is a triangle (most of cases), we also + // check for each of these cells if it is overlapping with + // the triangle in order to only fill in the ones really overlapping + // the triangle. + + unsigned i, x, y, z; + vector<Vec3r>::const_iterator it; + Vec3u coord; + + if (vertices.size() == 3) { // Triangle case + Vec3r triverts[3]; + i = 0; + for(it = vertices.begin(); + it != vertices.end(); + it++) { + triverts[i] = Vec3r(*it); + i++; + } + + Vec3r boxmin, boxmax; + + for (z = imin[2]; z <= imax[2]; z++) + for (y = imin[1]; y <= imax[1]; y++) + for (x = imin[0]; x <= imax[0]; x++) { + coord[0] = x; + coord[1] = y; + coord[2] = z; + // We retrieve the box coordinates of the current cell + getCellBox(coord, boxmin, boxmax); + // We check whether the triangle and the box ovewrlap: + Vec3r boxcenter((boxmin + boxmax) / 2.0); + Vec3r boxhalfsize(_cell_size / 2.0); + if (GeomUtils::overlapTriangleBox(boxcenter, boxhalfsize, triverts)) { + // We must then create the Cell and add it to the cells list + // if it does not exist yet. + // We must then add the occluder to the occluders list of this cell. + Cell* cell = getCell(coord); + if (!cell) { + cell = new Cell(boxmin); + fillCell(coord, *cell); + } + cell->addOccluder(occluder); + } + } + } + else { // The polygon is not a triangle, we add all the cells overlapping the polygon bbox. + for (z = imin[2]; z <= imax[2]; z++) + for (y = imin[1]; y <= imax[1]; y++) + for (x = imin[0]; x <= imax[0]; x++) { + coord[0] = x; + coord[1] = y; + coord[2] = z; + Cell* cell = getCell(coord); + if (!cell) { + Vec3r orig; + getCellOrigin(coord, orig); + cell = new Cell(orig); + fillCell(coord, *cell); + } + cell->addOccluder(occluder); + } + } +} + +bool Grid::nextRayCell(Vec3u& current_cell, Vec3u& next_cell) { + next_cell = current_cell; + real t_min, t; + unsigned i; + + t_min = FLT_MAX; // init tmin with handle of the case where one or 2 _u[i] = 0. + unsigned coord = 0; // predominant coord(0=x, 1=y, 2=z) + + + // using a parametric equation of + // a line : B = A + t u, we find + // the tx, ty and tz respectively coresponding + // to the intersections with the plans: + // x = _cell_size[0], y = _cell_size[1], z = _cell_size[2] + for (i = 0; i < 3; i++) { + if (_ray_dir[i] == 0) + continue; + if (_ray_dir[i] > 0) + t = (_cell_size[i] - _pt[i]) / _ray_dir[i]; + else + t = -_pt[i] / _ray_dir[i]; + if (t < t_min) { + t_min = t; + coord = i; + } + } + + // We use the parametric line equation and + // the found t (tamx) to compute the + // B coordinates: + Vec3r pt_tmp(_pt); + _pt = pt_tmp + t_min * _ray_dir; + + // We express B coordinates in the next cell + // coordinates system. We just have to + // set the coordinate coord of B to 0 + // of _CellSize[coord] depending on the sign + // of _u[coord] + if (_ray_dir[coord] > 0) { + next_cell[coord]++; + _pt[coord] -= _cell_size[coord]; + // if we are out of the grid, we must stop + if (next_cell[coord] >= _cells_nb[coord]) + return false; + } + else { + int tmp = next_cell[coord] - 1; + _pt[coord] = _cell_size[coord]; + if (tmp < 0) + return false; + next_cell[coord]--; + } + + _t += t_min; + if (_t >= _t_end) + return false; + + return true; +} + +void Grid::castRay(const Vec3r& orig, + const Vec3r& end, + OccludersSet& occluders, + unsigned timestamp) { + initRay(orig, end, timestamp); + allOccludersGridVisitor visitor(occluders); + castRayInternal(visitor); +} + +void Grid::castInfiniteRay(const Vec3r& orig, + const Vec3r& dir, + OccludersSet& occluders, + unsigned timestamp) { + Vec3r end = Vec3r(orig + FLT_MAX * dir / dir.norm()); + bool inter = initInfiniteRay(orig, dir, timestamp); + if(!inter) + return; + allOccludersGridVisitor visitor(occluders); + castRayInternal(visitor); +} + +Polygon3r* Grid::castRayToFindFirstIntersection(const Vec3r& orig, + const Vec3r& dir, + double& t, + double& u, + double& v, + unsigned timestamp){ + Polygon3r *occluder = 0; + Vec3r end = Vec3r(orig + FLT_MAX * dir / dir.norm()); + bool inter = initInfiniteRay(orig, dir, timestamp); + if(!inter){ + return 0; + } + firstIntersectionGridVisitor visitor(orig,dir,_cell_size); + castRayInternal(visitor); + occluder = visitor.occluder(); + t = visitor.t_; + u = visitor.u_; + v = visitor.v_; + return occluder; +} + +void Grid::initRay (const Vec3r &orig, + const Vec3r& end, + unsigned timestamp) { + _ray_dir = end - orig; + _t_end = _ray_dir.norm(); + _t = 0; + _ray_dir.normalize(); + _timestamp = timestamp; + + for(unsigned i = 0; i < 3; i++) { + _current_cell[i] = (unsigned)floor((orig[i] - _orig[i]) / _cell_size[i]); + //soc unused - unsigned u = _current_cell[i]; + _pt[i] = orig[i] - _orig[i] - _current_cell[i] * _cell_size[i]; + } + //_ray_occluders.clear(); + +} + +bool Grid::initInfiniteRay (const Vec3r &orig, + const Vec3r& dir, + unsigned timestamp) { + _ray_dir = dir; + _t_end = FLT_MAX; + _t = 0; + _ray_dir.normalize(); + _timestamp = timestamp; + + // check whether the origin is in or out the box: + Vec3r boxMin(_orig); + Vec3r boxMax(_orig+_size); + BBox<Vec3r> box(boxMin, boxMax); + if(box.inside(orig)){ + for(unsigned i = 0; i < 3; i++) { + _current_cell[i] = (unsigned)floor((orig[i] - _orig[i]) / _cell_size[i]); + //soc unused - unsigned u = _current_cell[i]; + _pt[i] = orig[i] - _orig[i] - _current_cell[i] * _cell_size[i]; + } + }else{ + // is the ray intersecting the box? + real tmin(-1.0), tmax(-1.0); + if(GeomUtils::intersectRayBBox(orig, _ray_dir, boxMin, boxMax, 0, _t_end, tmin, tmax)){ + assert(tmin != -1.0); + Vec3r newOrig = orig + tmin*_ray_dir; + for(unsigned i = 0; i < 3; i++) { + _current_cell[i] = (unsigned)floor((newOrig[i] - _orig[i]) / _cell_size[i]); + if(_current_cell[i] == _cells_nb[i]) + _current_cell[i] = _cells_nb[i] - 1; + //soc unused - unsigned u = _current_cell[i]; + _pt[i] = newOrig[i] - _orig[i] - _current_cell[i] * _cell_size[i]; + } + + }else{ + return false; + } + } + //_ray_occluders.clear(); + + return true; + +} + diff --git a/source/blender/freestyle/intern/geometry/Grid.h b/source/blender/freestyle/intern/geometry/Grid.h new file mode 100755 index 00000000000..e54b7b4d381 --- /dev/null +++ b/source/blender/freestyle/intern/geometry/Grid.h @@ -0,0 +1,363 @@ +// +// Filename : Grid.h +// Author(s) : Stephane Grabli +// Purpose : Base class to define a cell grid surrounding +// the bounding box of the scene +// Date of creation : 30/07/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef GRID_H +# define GRID_H + +# include <cstring> // for memset +# include <float.h> +# include <vector> +# include "../system/FreestyleConfig.h" +# include "GeomUtils.h" +# include "Geom.h" +# include "Polygon.h" + +using namespace std; +using namespace Geometry; + +typedef vector<Polygon3r*> OccludersSet; + + +// +// Class to define cells used by the regular grid +// +/////////////////////////////////////////////////////////////////////////////// + +class LIB_GEOMETRY_EXPORT Cell +{ + public: + + Cell(Vec3r& orig) { + _orig = orig; + } + + virtual ~Cell() {} + + inline void addOccluder(Polygon3r* o) { + if (o) + _occluders.push_back(o); + } + + inline const Vec3r& getOrigin() { + return _orig; + } + + inline OccludersSet& getOccluders() { + return _occluders; + } + + private: + + Vec3r _orig; + OccludersSet _occluders; +}; + + +class GridVisitor{ +public: + virtual ~GridVisitor() {}; //soc + virtual void discoverCell(Cell *cell) {} + virtual void examineOccluder(Polygon3r *occ) {} + virtual void finishCell(Cell *cell) {} + virtual bool stop() {return false;} +}; + +/*! Gathers all the occluders belonging to the cells + * traversed by the ray */ +class allOccludersGridVisitor : public GridVisitor{ +public: + allOccludersGridVisitor(OccludersSet& occluders) + :GridVisitor(), occluders_(occluders){} + virtual void examineOccluder(Polygon3r *occ); + + OccludersSet& occluders() {return occluders_;} + void clear() {occluders_.clear();} + +private: + OccludersSet& occluders_; +}; + +/*! Finds the first intersection and breaks. The occluder and + * the intersection information are stored and accessible. + */ +class firstIntersectionGridVisitor : public GridVisitor { + +//soc - changed order to remove warnings +public: + double u_, v_, t_; +private: + Polygon3r *occluder_; + Vec3r ray_org_, ray_dir_, cell_size_; + Cell * current_cell_; + +public: + firstIntersectionGridVisitor(const Vec3r& ray_org, const Vec3r& ray_dir, const Vec3r& cell_size) : + GridVisitor(), u_(0),v_(0),t_(DBL_MAX), + occluder_(0), + ray_org_(ray_org), ray_dir_(ray_dir), cell_size_(cell_size), + current_cell_(0) {} + virtual ~firstIntersectionGridVisitor() {} + + virtual void discoverCell(Cell *cell) {current_cell_=cell;} + virtual void examineOccluder(Polygon3r *occ); + virtual bool stop(); + + Polygon3r * occluder() {return occluder_;} +}; + +// +// Class to define a regular grid used for ray casting computations +// +/////////////////////////////////////////////////////////////////////////////// + +class LIB_GEOMETRY_EXPORT Grid +{ +public: + + /*! Builds a Grid + * Must be followed by a call to configure() + */ + Grid() {} + + virtual ~Grid() { + clear(); + } + + /*! clears the grid + * Deletes all the cells, clears the hashtable, + * resets size, size of cell, number of cells. + */ + virtual void clear(); + + /*! Sets the different parameters of the grid + * orig + * The grid origin + * size + * The grid's dimensions + * nb + * The number of cells of the grid + */ + virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb); + + /*! returns a vector of integer containing the + * coordinates of the cell containing the point + * passed as argument + * p + * The point for which we're looking the cell + */ + inline void getCellCoordinates(const Vec3r& p, Vec3u& res) { + int tmp; + for (int i = 0; i < 3; i++) { + tmp = (int)((p[i] - _orig[i]) / _cell_size[i]); + if (tmp < 0) + res[i] = 0; + else if ((unsigned)tmp >= _cells_nb[i]) + res[i] = _cells_nb[i] - 1; + else + res[i] = tmp; + } + } + + /*! Fills the case corresponding to coord with the cell */ + virtual void fillCell(const Vec3u& coord, Cell& cell) = 0; + + /*! returns the cell whose coordinates + * are pased as argument + */ + virtual Cell* getCell(const Vec3u& coord) = 0; + + /*! returns the cell containing the point + * passed as argument. If the cell is empty + * (contains no occluder), NULL is returned + * p + * The point for which we're looking the cell + */ + inline Cell* getCell(const Vec3r& p) { + Vec3u coord; + getCellCoordinates(p, coord); + return getCell(coord); + } + + /*! Retrieves the x,y,z coordinates of the origin of the cell whose coordinates (i,j,k) + * is passed as argument + * cell_coord + * i,j,k integer coordinates for the cell + * orig + * x,y,x vector to be filled in with the cell origin's coordinates + */ + inline void getCellOrigin(const Vec3u& cell_coord, Vec3r& orig) { + for (unsigned i = 0; i < 3; i++) + orig[i] = _orig[i] + cell_coord[i] * _cell_size[i]; + } + + /*! Retrieves the box corresponding to the cell whose coordinates + * are passed as argument. + * cell_coord + * i,j,k integer coordinates for the cell + * min_out + * The min x,y,x vector of the box. Filled in by the method. + * max_out + * The max x,y,z coordinates of the box. Filled in by the method. + */ + inline void getCellBox(const Vec3u& cell_coord, Vec3r& min_out, Vec3r& max_out) { + getCellOrigin(cell_coord, min_out); + max_out = min_out + _cell_size; + } + + /*! inserts a convex polygon occluder + * This method is quite coarse insofar as it + * adds all cells intersecting the polygon bounding box + * convex_poly + * The list of 3D points constituing a convex polygon + */ + void insertOccluder(Polygon3r * convex_poly); + + /*! Adds an occluder to the list of occluders */ + void addOccluder(Polygon3r* occluder) { + _occluders.push_back(occluder); + } + + /*! Casts a ray between a starting point and an ending point + * Returns the list of occluders contained + * in the cells intersected by this ray + * Starts with a call to InitRay. + */ + void castRay(const Vec3r& orig, + const Vec3r& end, + OccludersSet& occluders, + unsigned timestamp); + + /*! Casts an infinite ray (still finishing at the end of the grid) from a starting point and in a given direction. + * Returns the list of occluders contained + * in the cells intersected by this ray + * Starts with a call to InitRay. + */ + void castInfiniteRay(const Vec3r& orig, + const Vec3r& dir, + OccludersSet& occluders, + unsigned timestamp); + + /*! Casts an infinite ray (still finishing at the end of the grid) from a starting point and in a given direction. + * Returns the first intersection (occluder,t,u,v) or null. + * Starts with a call to InitRay. + */ + Polygon3r * castRayToFindFirstIntersection(const Vec3r& orig, + const Vec3r& dir, + double& t, + double& u, + double& v, + unsigned timestamp); + + + /*! Init all structures and values for computing + * the cells intersected by this new ray + */ + void initRay (const Vec3r &orig, + const Vec3r& end, + unsigned timestamp); + + /*! Init all structures and values for computing + * the cells intersected by this infinite ray. + * Returns false if the ray doesn't intersect the + * grid. + */ + bool initInfiniteRay (const Vec3r &orig, + const Vec3r& dir, + unsigned timestamp); + + + /*! Accessors */ + inline const Vec3r& getOrigin() const { + return _orig; + } + inline Vec3r gridSize() const { + return _size; + } + inline Vec3r getCellSize() const { + return _cell_size; + } + + void displayDebug() { + cerr << "Cells nb : " << _cells_nb << endl; + cerr << "Cell size : " << _cell_size << endl; + cerr << "Origin : " << _orig << endl; + cerr << "Occluders nb : " << _occluders.size() << endl; + } + + protected: + + /*! Core of castRay and castInfiniteRay, find occluders + * along the given ray + */ + inline void castRayInternal(GridVisitor& visitor) { + Cell* current_cell = NULL; + do { + current_cell = getCell(_current_cell); + if (current_cell){ + visitor.discoverCell(current_cell); + OccludersSet& occluders = current_cell->getOccluders(); // FIXME: I had forgotten the ref & + for (OccludersSet::iterator it = occluders.begin(); + it != occluders.end(); + it++) { + if ((unsigned long)(*it)->userdata2 != _timestamp) { + (*it)->userdata2 = (void*)_timestamp; + visitor.examineOccluder(*it); + } + } + visitor.finishCell(current_cell); + } + } while ((!visitor.stop()) && (nextRayCell(_current_cell, _current_cell))); + } + + + /*! returns the cell next to the cell + * passed as argument. + */ + bool nextRayCell(Vec3u& current_cell, Vec3u& next_cell); + + unsigned _timestamp; + + Vec3u _cells_nb; // number of cells for x,y,z axis + Vec3r _cell_size; // cell x,y,z dimensions + Vec3r _size; // grid x,y,x dimensions + Vec3r _orig; // grid origin + + Vec3r _ray_dir; // direction vector for the ray + Vec3u _current_cell; // The current cell being processed (designated by its 3 coordinates) + Vec3r _pt; // Points corresponding to the incoming and outgoing intersections + // of one cell with the ray + real _t_end; // To know when we are at the end of the ray + real _t; + + //OccludersSet _ray_occluders; // Set storing the occluders contained in the cells traversed by a ray + OccludersSet _occluders; // List of all occluders inserted in the grid +}; + +#endif // GRID_H diff --git a/source/blender/freestyle/intern/geometry/HashGrid.cpp b/source/blender/freestyle/intern/geometry/HashGrid.cpp new file mode 100755 index 00000000000..3cf845d57ef --- /dev/null +++ b/source/blender/freestyle/intern/geometry/HashGrid.cpp @@ -0,0 +1,41 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "HashGrid.h" + +void HashGrid::clear() +{ + if(!_cells.empty()) { + for(GridHashTable::iterator it = _cells.begin(); + it !=_cells.end(); + it++) { + Cell* cell = (*it).second; + delete cell; + } + _cells.clear(); + } + + Grid::clear(); +} + +void HashGrid::configure(const Vec3r& orig, const Vec3r& size, unsigned nb) { + Grid::configure(orig, size, nb); +} diff --git a/source/blender/freestyle/intern/geometry/HashGrid.h b/source/blender/freestyle/intern/geometry/HashGrid.h new file mode 100755 index 00000000000..f6605957676 --- /dev/null +++ b/source/blender/freestyle/intern/geometry/HashGrid.h @@ -0,0 +1,109 @@ +// +// Filename : HashGrid.h +// Author(s) : Stephane Grabli +// Purpose : Class to define a cell grid surrounding the +// bounding box of the scene +// Date of creation : 30/07/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef HASHGRID_H +# define HASHGRID_H + +//# if defined(__GNUC__) && (__GNUC__ >= 3) +// hash_map is not part of the C++ standard anymore; +// hash_map.h has been kept though for backward compatibility +//# include <hash_map.h> +//# else +//# include <hash_map> +//# endif + +# include "Grid.h" +# include <map> +/*! Defines a hash table used for searching the Cells */ +struct GridHasher{ +#define _MUL 950706376UL +#define _MOD 2147483647UL + inline size_t operator() (const Vec3u& p) const + { + size_t res = ((unsigned long) (p[0] * _MUL)) % _MOD; + res = ((res + (unsigned long) (p[1]) * _MUL)) % _MOD; + return ((res +(unsigned long) (p[2]) * _MUL)) % _MOD; + } +}; + +/*! Class to define a regular grid used for ray + casting computations */ + +class LIB_GEOMETRY_EXPORT HashGrid : public Grid +{ + public: + + typedef map<Vec3u, Cell*> GridHashTable; + + HashGrid() : Grid() {} + + virtual ~HashGrid() { + clear(); + } + + /*! clears the grid + * Deletes all the cells, clears the hashtable, + * resets size, size of cell, number of cells. + */ + virtual void clear(); + + /*! Sets the different parameters of the grid + * orig + * The grid origin + * size + * The grid's dimensions + * nb + * The number of cells of the grid + */ + virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb); + + /*! returns the cell whose coordinates + * are pased as argument + */ + virtual Cell* getCell(const Vec3u& p) { + Cell* found_cell = NULL; + + GridHashTable::const_iterator found = _cells.find(p); + if (found != _cells.end()) + found_cell = (*found).second; + return found_cell; + } + + /*! Fills the case p with the cell iCell */ + virtual void fillCell(const Vec3u& p, Cell& cell) { + _cells[p] = &cell; + } + +protected: + + GridHashTable _cells; +}; + +#endif // HASHGRID_H diff --git a/source/blender/freestyle/intern/geometry/Noise.cpp b/source/blender/freestyle/intern/geometry/Noise.cpp new file mode 100755 index 00000000000..396fc3bbb47 --- /dev/null +++ b/source/blender/freestyle/intern/geometry/Noise.cpp @@ -0,0 +1,264 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "Noise.h" +# include <stdlib.h> +# include <stdio.h> +# include <math.h> +#include <time.h> + +#define MINX -1000000 +#define MINY MINX +#define MINZ MINX +#define SCURVE(a) ((a)*(a)*(3.0-2.0*(a))) +#define REALSCALE ( 2.0 / 65536.0 ) +#define NREALSCALE ( 2.0 / 4096.0 ) +#define HASH3D(a,b,c) hashTable[hashTable[hashTable[(a) & 0xfff] ^ ((b) & 0xfff)] ^ ((c) & 0xfff)] +#define HASH(a,b,c) (xtab[(xtab[(xtab[(a) & 0xff] ^ (b)) & 0xff] ^ (c)) & 0xff] & 0xff) +#define INCRSUM(m,s,x,y,z) ((s)*(RTable[m]*0.5 \ + + RTable[m+1]*(x) \ + + RTable[m+2]*(y) \ + + RTable[m+3]*(z))) +#define MAXSIZE 500 +#define nrand() ((float)rand()/(float)RAND_MAX) +#define seednrand(x) srand(x*RAND_MAX) + +#define BM 0xff + +#define N 0x1000 +#define NP 12 /* 2^N */ +#define NM 0xfff + +#define s_curve(t) ( t * t * (3. - 2. * t) ) + +#define lerp(t, a, b) ( a + t * (b - a) ) + +#define setup(i,b0,b1,r0,r1)\ + t = i + N;\ + b0 = ((int)t) & BM;\ + b1 = (b0+1) & BM;\ + r0 = t - (int)t;\ + r1 = r0 - 1.; + +void normalize2(float v[2]) +{ + float s; + + s = sqrt(v[0] * v[0] + v[1] * v[1]); + v[0] = v[0] / s; + v[1] = v[1] / s; +} + +void normalize3(float v[3]) +{ + float s; + + s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); + v[0] = v[0] / s; + v[1] = v[1] / s; + v[2] = v[2] / s; +} + +float Noise::turbulence1(float arg, float freq, float amp, unsigned oct) +{ + float t; + float vec; + + for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct) + { + vec = freq * arg; + t += smoothNoise1(vec) * amp; + } + return t; +} + +float Noise::turbulence2(Vec2f& v, float freq, float amp, unsigned oct) +{ + float t; + Vec2f vec; + + for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct) + { + vec.x() = freq * v.x(); + vec.y() = freq * v.y(); + t += smoothNoise2(vec) * amp; + } + return t; +} + +float Noise::turbulence3(Vec3f& v, float freq, float amp, unsigned oct) +{ + float t; + Vec3f vec; + + for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct) + { + vec.x() = freq * v.x(); + vec.y() = freq * v.y(); + vec.z() = freq * v.z(); + t += smoothNoise3(vec) * amp; + } + return t; +} + +// Noise functions over 1, 2, and 3 dimensions + +float Noise::smoothNoise1(float arg) +{ + int bx0, bx1; + float rx0, rx1, sx, t, u, v, vec; + + vec = arg; + setup(vec, bx0,bx1, rx0,rx1); + + sx = s_curve(rx0); + + u = rx0 * g1[ p[ bx0 ] ]; + v = rx1 * g1[ p[ bx1 ] ]; + + return lerp(sx, u, v); +} + +float Noise::smoothNoise2(Vec2f& vec) +{ + int bx0, bx1, by0, by1, b00, b10, b01, b11; + float rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v; + register int i, j; + + setup(vec.x(), bx0,bx1, rx0,rx1); + setup(vec.y(), by0,by1, ry0,ry1); + + i = p[ bx0 ]; + j = p[ bx1 ]; + + b00 = p[ i + by0 ]; + b10 = p[ j + by0 ]; + b01 = p[ i + by1 ]; + b11 = p[ j + by1 ]; + + sx = s_curve(rx0); + sy = s_curve(ry0); + +#define at2(rx,ry) ( rx * q[0] + ry * q[1] ) + + q = g2[ b00 ] ; u = at2(rx0,ry0); + q = g2[ b10 ] ; v = at2(rx1,ry0); + a = lerp(sx, u, v); + + q = g2[ b01 ] ; u = at2(rx0,ry1); + q = g2[ b11 ] ; v = at2(rx1,ry1); + b = lerp(sx, u, v); + + return lerp(sy, a, b); +} + +float Noise::smoothNoise3(Vec3f& vec) +{ + int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11; + float rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v; + register int i, j; + + setup(vec.x(), bx0,bx1, rx0,rx1); + setup(vec.y(), by0,by1, ry0,ry1); + setup(vec.z(), bz0,bz1, rz0,rz1); + + i = p[ bx0 ]; + j = p[ bx1 ]; + + b00 = p[ i + by0 ]; + b10 = p[ j + by0 ]; + b01 = p[ i + by1 ]; + b11 = p[ j + by1 ]; + + t = s_curve(rx0); + sy = s_curve(ry0); + sz = s_curve(rz0); + +#define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] ) + + q = g3[ b00 + bz0 ] ; + u = at3(rx0,ry0,rz0); + q = g3[ b10 + bz0 ] ; + v = at3(rx1,ry0,rz0); + a = lerp(t, u, v); + + q = g3[ b01 + bz0 ] ; + u = at3(rx0,ry1,rz0); + q = g3[ b11 + bz0 ] ; + v = at3(rx1,ry1,rz0); + b = lerp(t, u, v); + + c = lerp(sy, a, b); + + q = g3[ b00 + bz1 ] ; + u = at3(rx0,ry0,rz1); + q = g3[ b10 + bz1 ] ; + v = at3(rx1,ry0,rz1); + a = lerp(t, u, v); + + q = g3[ b01 + bz1 ] ; + u = at3(rx0,ry1,rz1); + q = g3[ b11 + bz1 ] ; + v = at3(rx1,ry1,rz1); + b = lerp(t, u, v); + + d = lerp(sy, a, b); + + return lerp(sz, c, d); +} + +Noise::Noise() +{ + int i, j, k; + + seednrand(time(NULL)); + for (i = 0 ; i < _Noise_B_ ; i++) + { + p[i] = i; + + g1[i] = (float)((rand() % (_Noise_B_ + _Noise_B_)) - _Noise_B_) / _Noise_B_; + + for (j = 0 ; j < 2 ; j++) + g2[i][j] = (float)((rand() % (_Noise_B_ + _Noise_B_)) - _Noise_B_) / _Noise_B_; + normalize2(g2[i]); + + for (j = 0 ; j < 3 ; j++) + g3[i][j] = (float)((rand() % (_Noise_B_ + _Noise_B_)) - _Noise_B_) / _Noise_B_; + normalize3(g3[i]); + } + + while (--i) + { + k = p[i]; + p[i] = p[j = rand() % _Noise_B_]; + p[j] = k; + } + + for (i = 0 ; i < _Noise_B_ + 2 ; i++) + { + p[_Noise_B_ + i] = p[i]; + g1[_Noise_B_ + i] = g1[i]; + for (j = 0 ; j < 2 ; j++) + g2[_Noise_B_ + i][j] = g2[i][j]; + for (j = 0 ; j < 3 ; j++) + g3[_Noise_B_ + i][j] = g3[i][j]; + } +} diff --git a/source/blender/freestyle/intern/geometry/Noise.h b/source/blender/freestyle/intern/geometry/Noise.h new file mode 100755 index 00000000000..00cebbb451e --- /dev/null +++ b/source/blender/freestyle/intern/geometry/Noise.h @@ -0,0 +1,77 @@ +// +// Filename : Noise.h +// Author(s) : Emmanuel Turquin +// Purpose : Class to define Perlin noise +// Date of creation : 12/01/2004 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef NOISE_H +# define NOISE_H + + +# include "../system/FreestyleConfig.h" +# include "Geom.h" + +#define _Noise_B_ 0x100 + +using namespace Geometry; +using namespace std; + +/*! Class to provide Perlin Noise functionalities */ +class LIB_GEOMETRY_EXPORT Noise +{ + public: + + /*! Builds a Noise object */ + Noise(); + /*! Destructor */ + ~Noise() {} + + /*! Returns a noise value for a 1D element */ + float turbulence1(float arg, float freq, float amp, unsigned oct = 4); + + /*! Returns a noise value for a 2D element */ + float turbulence2(Vec2f& v, float freq, float amp, unsigned oct = 4); + + /*! Returns a noise value for a 3D element */ + float turbulence3(Vec3f& v, float freq, float amp, unsigned oct = 4); + + /*! Returns a smooth noise value for a 1D element */ + float smoothNoise1(float arg); + /*! Returns a smooth noise value for a 2D element */ + float smoothNoise2(Vec2f& vec); + /*! Returns a smooth noise value for a 3D element */ + float smoothNoise3(Vec3f& vec); + + private: + + int p[ _Noise_B_ + _Noise_B_ + 2]; + float g3[ _Noise_B_ + _Noise_B_ + 2][3]; + float g2[ _Noise_B_ + _Noise_B_ + 2][2]; + float g1[ _Noise_B_ + _Noise_B_ + 2]; + int start; +}; + +#endif // NOISE_H diff --git a/source/blender/freestyle/intern/geometry/Polygon.h b/source/blender/freestyle/intern/geometry/Polygon.h new file mode 100755 index 00000000000..f9c4c78d424 --- /dev/null +++ b/source/blender/freestyle/intern/geometry/Polygon.h @@ -0,0 +1,215 @@ +// +// Filename : Polygon.h +// Author(s) : Stephane Grabli +// Purpose : Class to define a polygon +// Date of creation : 30/07/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef POLYGON_H +# define POLYGON_H + +# include <vector> +# include "Geom.h" +# include "GeomUtils.h" + +using namespace std; + +namespace Geometry { + +template <class Point> +class Polygon +{ + public: + + inline Polygon() { + _id = 0; + userdata = 0; + userdata2 = 0; + } + + inline Polygon(const vector<Point>& vertices) { + _vertices = vertices; + computeBBox(); + _id = 0; + userdata = 0; + userdata2 = 0; + } + + inline Polygon(const Polygon<Point>& poly) { + Point p; + for(typename vector<Point>::const_iterator it = poly.getVertices().begin(); + it != poly.getVertices().end(); + it++) { + p = *it; + _vertices.push_back(p); + } + + _id = poly.getId(); + poly.getBBox(_min, _max); + userdata = 0; + userdata2 = 0; + } + + virtual ~Polygon() {} + + // + // Accessors + // + ///////////////////////////////////////////////////////////////////////////// + + inline const vector<Point>& getVertices() const { + return _vertices; + } + + inline void getBBox(Point& min, Point& max) const { + min = _min; + max = _max; + } + + inline Point& getBBoxCenter() + { + Point result; + result = (_min + _max) / 2; + return result; + } + + inline Point& getCenter() { + Point result; + for (typename vector<Point>::iterator it = _vertices.begin(); + it != _vertices.end(); + it++) + result += *it; + result /= _vertices.size(); + return result; + } + + inline unsigned getId() const { + return _id; + } + + // + // Modifiers + // + ///////////////////////////////////////////////////////////////////////////// + + inline void setVertices(const vector<Point>& vertices) { + _vertices.clear(); + Point p; + for (typename vector<Point>::const_iterator it = vertices.begin(); + it != vertices.end(); + it++) { + p = *it; + _vertices.push_back(p); + } + computeBBox(); + } + + inline void setId(unsigned id) { + _id = id; + } + + // + // Other methods + // + ///////////////////////////////////////////////////////////////////////////// + + inline void computeBBox() { + if(_vertices.empty()) + return; + + _max = _vertices[0]; + _min = _vertices[0]; + + for(typename vector<Point>::iterator it = _vertices.begin(); + it != _vertices.end(); + it++) { + for(unsigned i = 0; i < Point::dim(); i++) { + if((*it)[i] > _max[i]) + _max[i] = (*it)[i]; + if((*it)[i] < _min[i]) + _min[i] = (*it)[i]; + } + } + } + + // FIXME Is it possible to get rid of userdatas ? + void* userdata; + void* userdata2; // Used during ray casting + + protected: + + vector<Point> _vertices; + Point _min; + Point _max; + unsigned _id; +}; + + +// +// Polygon3r class +// +/////////////////////////////////////////////////////////////////////////////// + +class Polygon3r : public Polygon<Vec3r> +{ + public: + + inline Polygon3r() : Polygon<Vec3r>() {} + + inline Polygon3r(const vector<Vec3r>& vertices, + const Vec3r& normal) : Polygon<Vec3r>(vertices) { + setNormal(normal); + } + + inline Polygon3r(const Polygon3r& poly) : Polygon<Vec3r>(poly) {} + + virtual ~Polygon3r() {} + + void setNormal(const Vec3r& normal) { + _normal = normal; + } + + Vec3r getNormal() const { + return _normal; + } + + /*! Check whether the Polygon intersects with the ray or not */ + inline bool rayIntersect(Vec3r& orig, Vec3r& dir, + real& t, real& u, real& v, real epsilon = M_EPSILON) { + // if (_vertices.size() < 3) + // return false; + return GeomUtils::intersectRayTriangle(orig, dir, + _vertices[0], _vertices[1], _vertices[2], + t, u, v, epsilon); + } + + private: + + Vec3r _normal; +}; + +} // end of namespace Geometry + +#endif // POLYGON_H diff --git a/source/blender/freestyle/intern/geometry/SweepLine.h b/source/blender/freestyle/intern/geometry/SweepLine.h new file mode 100755 index 00000000000..cf4c86d006d --- /dev/null +++ b/source/blender/freestyle/intern/geometry/SweepLine.h @@ -0,0 +1,336 @@ +// +// Filename : SweepLine.h +// Author(s) : Stephane Grabli +// Purpose : Class to define a Sweep Line +// Date of creation : 29/08/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef SWEEPLINE_H +# define SWEEPLINE_H + +# include <list> +# include <vector> + +/*! Class to define the intersection berween two segments*/ +template<class Edge> +class Intersection +{ +public: + + template<class EdgeClass> + Intersection(EdgeClass* eA, real ta, EdgeClass* eB, real tb) + { + EdgeA = eA; + EdgeB = eB; + tA = ta; + tB = tb; + userdata = 0; + } + + Intersection(const Intersection& iBrother) + { + EdgeA = iBrother.EdgeA; + EdgeB = iBrother.EdgeB; + tA = iBrother.tA; + tB = iBrother.tB; + userdata = 0; + } + + /*! returns the parameter giving the + * intersection, for the edge iEdge + */ + real getParameter(Edge *iEdge) + { + if(iEdge == EdgeA) + return tA; + if(iEdge == EdgeB) + return tB; + return 0; + } + +public: + void * userdata; // FIXME + + Edge *EdgeA; // first segment + Edge *EdgeB; // second segment + real tA; // parameter defining the intersection point with respect to the segment EdgeA. + real tB; // parameter defining the intersection point with respect to the segment EdgeB. +}; + + + + + + + + +template<class T, class Point> +class Segment +{ + public: + Segment() + { + } + Segment(T& s, const Point& iA, const Point& iB) + { + _edge = s; + if(iA < iB) + { + A = iA; + B = iB; + _order = true; + } + else + { + A = iB; + B = iA; + _order = false; + } + } + + Segment(Segment<T,Point>& iBrother) + { + _edge = iBrother.edge(); + A = iBrother.A; + B = iBrother.B; + _Intersections = iBrother._Intersections; + _order = iBrother._order; + } + + Segment(const Segment<T,Point>& iBrother) + { + _edge = iBrother._edge; + A = iBrother.A; + B = iBrother.B; + _Intersections = iBrother._Intersections; + _order = iBrother._order; + } + + ~Segment() { + _Intersections.clear(); + } + + inline Point operator[](const unsigned short int& i) const + { + return i%2==0 ? A : B; + } + + inline bool operator==(const Segment<T,Point>& iBrother) + { + if(_edge == iBrother._edge) + return true; + + return false; + } + + /* Adds an intersection for this segment */ + inline void AddIntersection(Intersection<Segment<T,Point> > *i) {_Intersections.push_back(i);} + + /*! Checks for a common vertex with another edge */ + inline bool CommonVertex(const Segment<T,Point>& S, Point& CP) + { + if((A == S[0]) || (A == S[1])) + { + CP = A; + return true; + } + if((B == S[0]) || (B == S[1])) + { + CP = B; + return true; + } + + return false; + } + + inline vector<Intersection<Segment<T,Point> >*>& intersections() {return _Intersections;} + inline bool order() {return _order;} + inline T& edge() {return _edge;} + + private: + T _edge; + Point A; + Point B; + std::vector<Intersection<Segment<T,Point> >*> _Intersections; // list of intersections parameters + bool _order; // true if A and B are in the same order than _edge.A and _edge.B. false otherwise. +}; + +/*! defines a binary function that can be overload + * by the user to specify at each condition + * the intersection between 2 edges must be computed + */ +template<class T1, class T2> +struct binary_rule +{ + binary_rule() {} + template<class T3,class T4> + binary_rule(const binary_rule<T3,T4>& brother) {} + virtual ~binary_rule() {} + + virtual bool operator()(T1&, T2&) + { + return true; + } +}; + + +template<class T,class Point> +class SweepLine +{ +public: + + SweepLine() {} + ~SweepLine() + { + for(typename vector<Intersection<Segment<T,Point> >*>::iterator i=_Intersections.begin(),iend=_Intersections.end(); + i!=iend; + i++) + { + delete (*i); + } + _Intersections.clear(); + + for(typename vector<Segment<T,Point>* >::iterator ie=_IntersectedEdges.begin(),ieend=_IntersectedEdges.end(); + ie!=ieend; + ie++) + { + delete (*ie); + } + _IntersectedEdges.clear(); + + _set.clear(); + } + + + inline void process(Point& p, + vector<Segment<T,Point>*>& segments, + binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule, + //binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule = binary_rule<Segment<T,Point>,Segment<T,Point> >(), + real epsilon = M_EPSILON + ) + { + // first we remove the segments that need to be removed and then + // we add the segments to add + vector<Segment<T,Point>*> toadd; + typename vector<Segment<T,Point>*>::iterator s, send; + for(s=segments.begin(), send=segments.end(); + s!=send; + s++) + { + if(p == (*(*s))[0]) + toadd.push_back((*s)); + else + remove((*s)); + } + for(s=toadd.begin(), send=toadd.end(); + s!=send; + s++) + { + add((*s), binrule, epsilon); + } + } + + inline void add(Segment<T,Point>* S, + binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule, + //binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule = binary_rule<Segment<T,Point>, Segment<T,Point> >(), + real epsilon + ) + { + real t,u; + Point CP; + Vec2r v0, v1, v2, v3; + if(true == S->order()) + { + v0[0] = ((*S)[0])[0]; + v0[1] = ((*S)[0])[1]; + v1[0] = ((*S)[1])[0]; + v1[1] = ((*S)[1])[1]; + } + else + { + v1[0] = ((*S)[0])[0]; + v1[1] = ((*S)[0])[1]; + v0[0] = ((*S)[1])[0]; + v0[1] = ((*S)[1])[1]; + } + for(typename std::list<Segment<T,Point>* >::iterator s=_set.begin(), send=_set.end(); + s!=send; + s++) + { + Segment<T,Point>* currentS = (*s); + if(true != binrule(*S, *currentS)) + continue; + + if(true == currentS->order()) + { + v2[0] = ((*currentS)[0])[0]; + v2[1] = ((*currentS)[0])[1]; + v3[0] = ((*currentS)[1])[0]; + v3[1] = ((*currentS)[1])[1]; + } + else + { + v3[0] = ((*currentS)[0])[0]; + v3[1] = ((*currentS)[0])[1]; + v2[0] = ((*currentS)[1])[0]; + v2[1] = ((*currentS)[1])[1]; + } + if(S->CommonVertex(*currentS, CP)) + continue; // the two edges have a common vertex->no need to check + + if(GeomUtils::intersect2dSeg2dSegParametric(v0, v1, v2, v3, t, u, epsilon) == GeomUtils::DO_INTERSECT) + { + // create the intersection + Intersection<Segment<T,Point> > * inter = new Intersection<Segment<T,Point> >(S,t,currentS,u); + // add it to the intersections list + _Intersections.push_back(inter); + // add this intersection to the first edge intersections list + S->AddIntersection(inter); + // add this intersection to the second edge intersections list + currentS->AddIntersection(inter); + } + } + // add the added segment to the list of active segments + _set.push_back(S); + } + + inline void remove(Segment<T,Point>* s) + { + if(s->intersections().size() > 0) + _IntersectedEdges.push_back(s); + _set.remove(s); + } + + vector<Segment<T,Point>* >& intersectedEdges() {return _IntersectedEdges;} + vector<Intersection<Segment<T,Point> >*>& intersections() {return _Intersections;} + + +private: + std::list<Segment<T,Point>* > _set; // set of active edges for a given position of the sweep line + std::vector<Segment<T,Point>* > _IntersectedEdges; // the list of intersected edges + std::vector<Intersection<Segment<T,Point> >*> _Intersections; // the list of all intersections. +}; + +#endif // SWEEPLINE_H diff --git a/source/blender/freestyle/intern/geometry/VecMat.h b/source/blender/freestyle/intern/geometry/VecMat.h new file mode 100755 index 00000000000..9bbec3b1349 --- /dev/null +++ b/source/blender/freestyle/intern/geometry/VecMat.h @@ -0,0 +1,899 @@ +// +// Filename : VecMat.h +// Author(s) : Sylvain Paris +// Emmanuel Turquin +// Stephane Grabli +// Purpose : Vectors and Matrices definition and manipulation +// Date of creation : 12/06/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef VECMAT_H +# define VECMAT_H + +# include <math.h> +# include <vector> +# include <iostream> + +namespace VecMat { + + namespace Internal { + + template <bool B> + struct is_false {}; + + template <> + struct is_false<false> { + static inline void ensure() {} + }; + + } // end of namespace Internal + + // + // Vector class + // - T: value type + // - N: dimension + // + ///////////////////////////////////////////////////////////////////////////// + + template <class T, unsigned N> + class Vec + { + public: + + typedef T value_type; + + // constructors + + inline Vec() { + for (unsigned i = 0; i < N; i++) + this->_coord[i] = 0; + } + + ~Vec() { + Internal::is_false<(N == 0)>::ensure(); + } + + template <class U> + explicit inline Vec(const U tab[N]) { + for (unsigned i = 0; i < N; i++) + this->_coord[i] = (T)tab[i]; + } + + template <class U> + explicit inline Vec(const std::vector<U>& tab) { + for (unsigned i = 0; i < N; i++) + this->_coord[i] = (T)tab[i]; + } + + template <class U> + explicit inline Vec(const Vec<U, N>& v) { + for (unsigned i = 0; i < N; i++) + this->_coord[i] = (T)v[i]; + } + + // accessors + + inline value_type operator[](const unsigned i) const { + return this->_coord[i]; + } + + inline value_type& operator[](const unsigned i) { + return this->_coord[i]; + } + + static inline unsigned dim() { + return N; + } + + // various useful methods + + inline value_type norm() const { + return (T)sqrt((float)squareNorm()); + } + + inline value_type squareNorm() const { + return (*this) * (*this); + } + + inline Vec<T, N>& normalize() { + value_type n = norm(); + for (unsigned i = 0; i < N; i++) + this->_coord[i] /= n; + return *this; + } + + inline Vec<T, N>& normalizeSafe() { + value_type n = norm(); + if (n) + for (unsigned i=0; i < N; i++) + this->_coord[i] /= n; + return *this; + } + + // classical operators + inline Vec<T, N> operator+(const Vec<T, N>& v) const{ + Vec<T, N> res(v); + res += *this; + return res; + } + + inline Vec<T, N> operator-(const Vec<T,N>& v) const{ + Vec<T, N> res(*this); + res -= v; + return res; + } + + inline Vec<T, N> operator*(const typename Vec<T,N>::value_type r) const{ + Vec<T, N> res(*this); + res *= r; + return res; + } + + inline Vec<T, N> operator/(const typename Vec<T,N>::value_type r) const{ + Vec<T, N> res(*this); + if (r) + res /= r; + return res; + } + + // dot product + inline value_type operator*(const Vec<T, N>& v) const{ + value_type sum = 0; + for (unsigned i = 0; i < N; i++) + sum += (*this)[i] * v[i]; + return sum; + } + + template <class U> + inline Vec<T, N>& operator=(const Vec<U, N>& v) { + if (this != &v) + for (unsigned i = 0; i < N; i++) + this->_coord[i] = (T)v[i]; + return *this; + } + + template <class U> + inline Vec<T, N>& operator+=(const Vec<U, N>& v) { + for (unsigned i = 0 ; i < N; i++) + this->_coord[i] += (T)v[i]; + return *this; + } + + template <class U> + inline Vec<T, N>& operator-=(const Vec<U, N>& v) { + for (unsigned i = 0 ; i < N; i++) + this->_coord[i] -= (T)v[i]; + return *this; + } + + template <class U> + inline Vec<T, N>& operator*=(const U r) { + for (unsigned i = 0 ; i < N; i++) + this->_coord[i] *= r; + return *this; + } + + template <class U> + inline Vec<T, N>& operator/=(const U r) { + if (r) + for (unsigned i = 0 ; i < N; i++) + this->_coord[i] /= r; + return *this; + } + + + inline bool operator==(const Vec<T, N>& v) const { + for(unsigned i = 0; i < N; i++) + if (this->_coord[i] != v[i]) + return false; + return true; + } + + inline bool operator!=(const Vec<T, N>& v) const { + for(unsigned i = 0; i < N; i++) + if (this->_coord[i] != v[i]) + return true; + return false; + } + + inline bool operator<(const Vec<T, N>& v) const { + for (unsigned i = 0; i<N; i++) { + if (this->_coord[i] < v[i]) + return true; + if (this->_coord[i] > v[i]) + return false; + if (this->_coord[i] == v[i]) + continue; + } + return false; + } + + inline bool operator>(const Vec<T, N>& v) const { + for (unsigned i=0; i<N; i++) { + if(this->_coord[i] > v[i]) + return true; + if(this->_coord[i] < v[i]) + return false; + if(this->_coord[i] == v[i]) + continue; + } + return false; + } + + protected: + + value_type _coord[N]; + enum { + _dim = N, + }; + }; + + + // + // Vec2 class (2D Vector) + // - T: value type + // + ///////////////////////////////////////////////////////////////////////////// + + template <class T> + class Vec2 : public Vec<T, 2> + { + public: + + typedef typename Vec<T, 2>::value_type value_type; + + inline Vec2() : Vec<T, 2>() {} + + template <class U> + explicit inline Vec2(const U tab[2]) : Vec<T, 2>(tab) {} + + template <class U> + explicit inline Vec2(const std::vector<U>& tab) : Vec<T, 2>(tab) {} + + template <class U> + inline Vec2(const Vec<U, 2>& v) : Vec<T, 2>(v) {} + + inline Vec2(const value_type x, + const value_type y = 0) : Vec<T, 2>() { + this->_coord[0] = (T)x; + this->_coord[1] = (T)y; + } + + inline value_type x() const { + return this->_coord[0]; + } + + inline value_type& x() { + return this->_coord[0]; + } + + inline value_type y() const { + return this->_coord[1]; + } + + inline value_type& y() { + return this->_coord[1]; + } + + inline void setX(const value_type v) { + this->_coord[0] = v; + } + + inline void setY(const value_type v) { + this->_coord[1] = v; + } + + // FIXME: hack swig -- no choice + inline Vec2<T> operator+(const Vec2<T>& v) const{ + Vec2<T> res(v); + res += *this; + return res; + } + + inline Vec2<T> operator-(const Vec2<T>& v) const{ + Vec2<T> res(*this); + res -= v; + return res; + } + + inline Vec2<T> operator*(const value_type r) const{ + Vec2<T> res(*this); + res *= r; + return res; + } + + inline Vec2<T> operator/(const value_type r) const{ + Vec2<T> res(*this); + if (r) + res /= r; + return res; + } + + // dot product + inline value_type operator*(const Vec2<T>& v) const{ + value_type sum = 0; + for (unsigned i = 0; i < 2; i++) + sum += (*this)[i] * v[i]; + return sum; + } + }; + + + // + // HVec3 class (3D Vector in homogeneous coordinates) + // - T: value type + // + ///////////////////////////////////////////////////////////////////////////// + + template <class T> + class HVec3 : public Vec<T, 4> + { + public: + + typedef typename Vec<T, 4>::value_type value_type; + + inline HVec3() : Vec<T, 4>() {} + + template <class U> + explicit inline HVec3(const U tab[4]) : Vec<T, 4>(tab) {} + + template <class U> + explicit inline HVec3(const std::vector<U>& tab) : Vec<T, 4>(tab) {} + + template<class U> + inline HVec3(const Vec<U, 4>& v) : Vec<T, 4>(v) {} + + inline HVec3(const value_type sx, + const value_type sy = 0, + const value_type sz = 0, + const value_type s = 1) { + this->_coord[0] = sx; + this->_coord[1] = sy; + this->_coord[2] = sz; + this->_coord[3] = s; + } + + template <class U> + inline HVec3(const Vec<U, 3>& sv, + const U s = 1) { + this->_coord[0] = (T)sv[0]; + this->_coord[1] = (T)sv[1]; + this->_coord[2] = (T)sv[2]; + this->_coord[3] = (T)s; + } + + inline value_type sx() const { + return this->_coord[0]; + } + + inline value_type& sx() { + return this->_coord[0]; + } + + inline value_type sy() const { + return this->_coord[1]; + } + + inline value_type& sy() { + return this->_coord[1]; + } + + inline value_type sz() const { + return this->_coord[2]; + } + + inline value_type& sz() { + return this->_coord[2]; + } + + inline value_type s() const { + return this->_coord[3]; + } + + inline value_type& s() { + return this->_coord[3]; + } + + // Acces to non-homogeneous coordinates in 3D + + inline value_type x() const { + return this->_coord[0] / this->_coord[3]; + } + + inline value_type y() const { + return this->_coord[1] / this->_coord[3]; + } + + inline value_type z() const { + return this->_coord[2] / this->_coord[3]; + } + }; + + + // + // Vec3 class (3D Vec) + // - T: value type + // + ///////////////////////////////////////////////////////////////////////////// + + template <class T> + class Vec3 : public Vec<T, 3> + { + public: + + typedef typename Vec<T, 3>::value_type value_type; + + inline Vec3() : Vec<T, 3>() {} + + template <class U> + explicit inline Vec3(const U tab[3]) : Vec<T, 3>(tab) {} + + template <class U> + explicit inline Vec3(const std::vector<U>& tab) : Vec<T, 3>(tab) {} + + template<class U> + inline Vec3(const Vec<U, 3>& v) : Vec<T, 3>(v) {} + + template<class U> + inline Vec3(const HVec3<U>& v) { + this->_coord[0] = (T)v.x(); + this->_coord[1] = (T)v.y(); + this->_coord[2] = (T)v.z(); + } + + inline Vec3(const value_type x, + const value_type y = 0, + const value_type z = 0) : Vec<T, 3>() { + this->_coord[0] = x; + this->_coord[1] = y; + this->_coord[2] = z; + } + + inline value_type x() const { + return this->_coord[0]; + } + + inline value_type& x() { + return this->_coord[0]; + } + + inline value_type y() const { + return this->_coord[1]; + } + + inline value_type& y() { + return this->_coord[1]; + } + + inline value_type z() const { + return this->_coord[2]; + } + + inline value_type& z() { + return this->_coord[2]; + } + + inline void setX(const value_type v) { + this->_coord[0] = v; + } + + inline void setY(const value_type v) { + this->_coord[1] = v; + } + + inline void setZ(const value_type v) { + this->_coord[2] = v; + } + + // classical operators + // FIXME: hack swig -- no choice + inline Vec3<T> operator+(const Vec3<T>& v) const{ + Vec3<T> res(v); + res += *this; + return res; + } + + inline Vec3<T> operator-(const Vec3<T>& v) const{ + Vec3<T> res(*this); + res -= v; + return res; + } + + inline Vec3<T> operator*(const value_type r) const{ + Vec3<T> res(*this); + res *= r; + return res; + } + + inline Vec3<T> operator/(const value_type r) const{ + Vec3<T> res(*this); + if (r) + res /= r; + return res; + } + + // dot product + inline value_type operator*(const Vec3<T>& v) const{ + value_type sum = 0; + for (unsigned i = 0; i < 3; i++) + sum += (*this)[i] * v[i]; + return sum; + } + + // cross product for 3D Vectors + // FIXME: hack swig -- no choice + inline Vec3<T> operator^(const Vec3<T>& v) const{ + Vec3<T> res((*this)[1] * v[2] - (*this)[2] * v[1], + (*this)[2] * v[0] - (*this)[0] * v[2], + (*this)[0] * v[1] - (*this)[1] * v[0]); + return res; + } + + // cross product for 3D Vectors + template <typename U> + inline Vec3<T> operator^(const Vec<U, 3>& v) const{ + Vec3<T> res((*this)[1] * v[2] - (*this)[2] * v[1], + (*this)[2] * v[0] - (*this)[0] * v[2], + (*this)[0] * v[1] - (*this)[1] * v[0]); + return res; + } + }; + + + // + // Matrix class + // - T: value type + // - M: rows + // - N: cols + // + ///////////////////////////////////////////////////////////////////////////// + + // Dirty, but icc under Windows needs this +# define _SIZE (M * N) + + template <class T, unsigned M, unsigned N> + class Matrix + { + public: + + typedef T value_type; + + inline Matrix() { + for (unsigned i = 0; i < _SIZE; i++) + this->_coord[i] = 0; + } + + ~Matrix() { + Internal::is_false<(M == 0)>::ensure(); + Internal::is_false<(N == 0)>::ensure(); + } + + template <class U> + explicit inline Matrix(const U tab[_SIZE]) { + for (unsigned i = 0; i < _SIZE; i++) + this->_coord[i] = tab[i]; + } + + template <class U> + explicit inline Matrix(const std::vector<U>& tab) { + for (unsigned i = 0; i < _SIZE; i++) + this->_coord[i] = tab[i]; + } + + template <class U> + inline Matrix(const Matrix<U, M, N>& m) { + for (unsigned i = 0; i < M; i++) + for (unsigned j = 0; j < N; j++) + this->_coord[i * N + j] = (T)m(i, j); + } + + inline value_type operator()(const unsigned i, const unsigned j) const { + return this->_coord[i * N + j]; + } + + inline value_type& operator()(const unsigned i, const unsigned j) { + return this->_coord[i * N + j]; + } + + static inline unsigned rows() { + return M; + } + + static inline unsigned cols() { + return N; + } + + inline Matrix<T, M, N>& transpose() const { + Matrix<T, N, M> res; + for (unsigned i = 0; i < M; i++) + for (unsigned j = 0; j < N; j++) + res(j,i) = this->_coord[i * N + j]; + return res; + } + + template <class U> + inline Matrix<T, M, N>& operator=(const Matrix<U, M, N>& m) { + if (this != &m) + for (unsigned i = 0; i < M; i++) + for (unsigned j = 0; j < N; j++) + this->_coord[i * N + j] = (T)m(i, j); + return *this; + } + + template <class U> + inline Matrix<T, M, N>& operator+=(const Matrix<U, M, N>& m) { + for (unsigned i = 0; i < M; i++) + for (unsigned j = 0; j < N; j++) + this->_coord[i * N + j] += (T)m(i, j); + return *this; + } + + template <class U> + inline Matrix<T, M, N>& operator-=(const Matrix<U, M, N>& m) { + for (unsigned i = 0; i < M; i++) + for (unsigned j = 0; j < N; j++) + this->_coord[i * N + j] -= (T)m(i, j); + return *this; + } + + template <class U> + inline Matrix<T, M, N>& operator*=(const U lambda) { + for (unsigned i = 0; i < M; i++) + for (unsigned j = 0; j < N; j++) + this->_coord[i * N + j] *= lambda; + return *this; + } + + template <class U> + inline Matrix<T, M, N>& operator/=(const U lambda) { + if (lambda) + for (unsigned i = 0; i < M; i++) + for (unsigned j = 0; j < N; j++) + this->_coord[i * N + j] /= lambda; + return *this; + } + + protected: + + value_type _coord[_SIZE]; + }; + + + // + // SquareMatrix class + // - T: value type + // - N: rows & cols + // + ///////////////////////////////////////////////////////////////////////////// + + // Dirty, but icc under Windows needs this +# define __SIZE (N * N) + + template <class T, unsigned N> + class SquareMatrix : public Matrix<T, N, N> + { + public: + + typedef T value_type; + + inline SquareMatrix() : Matrix<T, N, N>() {} + + template <class U> + explicit inline SquareMatrix(const U tab[__SIZE]) : Matrix<T, N, N>(tab) {} + + template <class U> + explicit inline SquareMatrix(const std::vector<U>& tab) : Matrix<T, N, N>(tab) {} + + template <class U> + inline SquareMatrix(const Matrix<U, N, N>& m) : Matrix<T, N, N>(m) {} + + static inline SquareMatrix<T, N> identity() { + SquareMatrix<T, N> res; + for (unsigned i = 0; i < N; i++) + res(i, i) = 1; + return res; + } + }; + + + // + // Vector external functions + // + ///////////////////////////////////////////////////////////////////////////// + + // template <class T, unsigned N> + // inline Vec<T, N> operator+(const Vec<T, N>& v1, + // const Vec<T, N>& v2) { + // Vec<T, N> res(v1); + // res += v2; + // return res; + // } + // + // template <class T, unsigned N> + // inline Vec<T, N> operator-(const Vec<T, N>& v1, + // const Vec<T, N>& v2) { + // Vec<T, N> res(v1); + // res -= v2; + // return res; + // } + // template <class T, unsigned N> + // inline Vec<T, N> operator*(const Vec<T, N>& v, + // const typename Vec<T, N>::value_type r) { + // Vec<T, N> res(v); + // res *= r; + // return res; + // } + + template <class T, unsigned N> + inline Vec<T, N> operator*(const typename Vec<T, N>::value_type r, + const Vec<T, N>& v) { + Vec<T, N> res(v); + res *= r; + return res; + } + // + // template <class T, unsigned N> + // inline Vec<T, N> operator/(const Vec<T, N>& v, + // const typename Vec<T, N>::value_type r) { + // Vec<T, N> res(v); + // if (r) + // res /= r; + // return res; + // } + // + // dot product + // template <class T, unsigned N> + // inline typename Vec<T, N>::value_type operator*(const Vec<T, N>& v1, + // const Vec<T, N>& v2) { + // typename Vec<T, N>::value_type sum = 0; + // for (unsigned i = 0; i < N; i++) + // sum += v1[i] * v2[i]; + // return sum; + // } + // + // // cross product for 3D Vectors + // template <typename T> + // inline Vec3<T> operator^(const Vec<T, 3>& v1, + // const Vec<T, 3>& v2) { + // Vec3<T> res(v1[1] * v2[2] - v1[2] * v2[1], + // v1[2] * v2[0] - v1[0] * v2[2], + // v1[0] * v2[1] - v1[1] * v2[0]); + // return res; + // } + + // stream operator + template <class T, unsigned N> + inline std::ostream& operator<<(std::ostream& s, + const Vec<T, N>& v) { + unsigned i; + s << "["; + for (i = 0; i < N - 1; i++) + s << v[i] << ", "; + s << v[i] << "]"; + return s; + } + + + // + // Matrix external functions + // + ///////////////////////////////////////////////////////////////////////////// + + template <class T, unsigned M, unsigned N> + inline Matrix<T, M, N> + operator+(const Matrix<T, M, N>& m1, + const Matrix<T, M, N>& m2) { + Matrix<T, M, N> res(m1); + res += m2; + return res; + } + + template <class T, unsigned M, unsigned N> + inline Matrix<T, M, N> + operator-(const Matrix<T, M, N>& m1, + const Matrix<T, M, N>& m2) { + Matrix<T, M, N> res(m1); + res -= m2; + return res; + } + + template <class T, unsigned M, unsigned N> + inline Matrix<T, M, N> + operator*(const Matrix<T, M, N>& m1, + const typename Matrix<T, M, N>::value_type lambda) { + Matrix<T, M, N> res(m1); + res *= lambda; + return res; + } + + template <class T, unsigned M, unsigned N> + inline Matrix<T, M, N> + operator*(const typename Matrix<T, M, N>::value_type lambda, + const Matrix<T, M, N>& m1) { + Matrix<T, M, N> res(m1); + res *= lambda; + return res; + } + + template <class T, unsigned M, unsigned N> + inline Matrix<T, M, N> + operator/(const Matrix<T, M, N>& m1, + const typename Matrix<T, M, N>::value_type lambda) { + Matrix<T, M, N> res(m1); + res /= lambda; + return res; + } + + template <class T, unsigned M, unsigned N, unsigned P> + inline Matrix<T, M, P> + operator*(const Matrix<T, M, N>& m1, + const Matrix<T, N, P>& m2) { + unsigned i, j, k; + Matrix<T, M, P> res; + typename Matrix<T, N, P>::value_type scale; + + for (j = 0; j < P; j++) { + for (k = 0; k < N; k++) { + scale = m2(k, j); + for (i = 0; i < N; i++) + res(i, j) += m1(i, k) * scale; + } + } + return res; + } + + template <class T, unsigned M, unsigned N> + inline Vec<T, M> + operator*(const Matrix<T, M, N>& m, + const Vec<T, N>& v) { + + Vec<T, M> res; + typename Matrix<T, M, N>::value_type scale; + + for (unsigned j = 0; j < M; j++) { + scale = v[j]; + for (unsigned i = 0; i < N; i++) + res[i] += m(i, j) * scale; + } + return res; + } + + // stream operator + template <class T, unsigned M, unsigned N> + inline std::ostream& operator<<(std::ostream& s, + const Matrix<T, M, N>& m) { + unsigned i, j; + for (i = 0; i < M; i++) { + s << "["; + for (j = 0; j < N - 1; j++) + s << m(i, j) << ", "; + s << m(i, j) << "]" << std::endl; + } + return s; + } + +} // end of namespace VecMat + +#endif // VECMAT_H diff --git a/source/blender/freestyle/intern/geometry/matrix_util.cpp b/source/blender/freestyle/intern/geometry/matrix_util.cpp new file mode 100755 index 00000000000..2117b06e62f --- /dev/null +++ b/source/blender/freestyle/intern/geometry/matrix_util.cpp @@ -0,0 +1,265 @@ +/* + * GXML/Graphite: Geometry and Graphics Programming Library + Utilities + * Copyright (C) 2000 Bruno Levy + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * If you modify this software, you should include a notice giving the + * name of the person performing the modification, the date of modification, + * and the reason for such modification. + * + * Contact: Bruno Levy + * + * levy@loria.fr + * + * ISA Project + * LORIA, INRIA Lorraine, + * Campus Scientifique, BP 239 + * 54506 VANDOEUVRE LES NANCY CEDEX + * FRANCE + * + * Note that the GNU General Public License does not permit incorporating + * the Software into proprietary programs. + */ + + +#include "matrix_util.h" +#include <math.h> + + + +namespace OGF { + + namespace MatrixUtil { + + static const double EPS = 0.00001 ; + static int MAX_ITER = 100 ; + + void semi_definite_symmetric_eigen( + const double *mat, int n, double *eigen_vec, double *eigen_val + ) { + double *a,*v; + double a_norm,a_normEPS,thr,thr_nn; + int nb_iter = 0; + int jj; + int i,j,k,ij,ik,l,m,lm,mq,lq,ll,mm,imv,im,iq,ilv,il,nn; + int *index; + double a_ij,a_lm,a_ll,a_mm,a_im,a_il; + double a_lm_2; + double v_ilv,v_imv; + double x; + double sinx,sinx_2,cosx,cosx_2,sincos; + double delta; + + // Number of entries in mat + + nn = (n*(n+1))/2; + + // Step 1: Copy mat to a + + a = new double[nn]; + + for( ij=0; ij<nn; ij++ ) { + a[ij] = mat[ij]; + } + + // Ugly Fortran-porting trick: indices for a are between 1 and n + a--; + + // Step 2 : Init diagonalization matrix as the unit matrix + v = new double[n*n]; + + ij = 0; + for( i=0; i<n; i++ ) { + for( j=0; j<n; j++ ) { + if( i==j ) { + v[ij++] = 1.0; + } else { + v[ij++] = 0.0; + } + } + } + + // Ugly Fortran-porting trick: indices for v are between 1 and n + v--; + + // Step 3 : compute the weight of the non diagonal terms + ij = 1 ; + a_norm = 0.0; + for( i=1; i<=n; i++ ) { + for( j=1; j<=i; j++ ) { + if( i!=j ) { + a_ij = a[ij]; + a_norm += a_ij*a_ij; + } + ij++; + } + } + + if( a_norm != 0.0 ) { + + a_normEPS = a_norm*EPS; + thr = a_norm ; + + // Step 4 : rotations + while( thr > a_normEPS && nb_iter < MAX_ITER ) { + + nb_iter++; + thr_nn = thr / nn; + + for( l=1 ; l< n; l++ ) { + for( m=l+1; m<=n; m++ ) { + + // compute sinx and cosx + + lq = (l*l-l)/2; + mq = (m*m-m)/2; + + lm = l+mq; + a_lm = a[lm]; + a_lm_2 = a_lm*a_lm; + + if( a_lm_2 < thr_nn ) { + continue ; + } + + ll = l+lq; + mm = m+mq; + a_ll = a[ll]; + a_mm = a[mm]; + + delta = a_ll - a_mm; + + if( delta == 0.0 ) { + x = - M_PI/4 ; + } else { + x = - atan( (a_lm+a_lm) / delta ) / 2.0 ; + } + + sinx = sin(x) ; + cosx = cos(x) ; + sinx_2 = sinx*sinx; + cosx_2 = cosx*cosx; + sincos = sinx*cosx; + + // rotate L and M columns + + ilv = n*(l-1); + imv = n*(m-1); + + for( i=1; i<=n;i++ ) { + if( (i!=l) && (i!=m) ) { + iq = (i*i-i)/2; + + if( i<m ) { + im = i + mq; + } else { + im = m + iq; + } + a_im = a[im]; + + if( i<l ) { + il = i + lq; + } else { + il = l + iq; + } + a_il = a[il]; + + a[il] = a_il*cosx - a_im*sinx; + a[im] = a_il*sinx + a_im*cosx; + } + + ilv++; + imv++; + + v_ilv = v[ilv]; + v_imv = v[imv]; + + v[ilv] = cosx*v_ilv - sinx*v_imv; + v[imv] = sinx*v_ilv + cosx*v_imv; + } + + x = a_lm*sincos; x+=x; + + a[ll] = a_ll*cosx_2 + a_mm*sinx_2 - x; + a[mm] = a_ll*sinx_2 + a_mm*cosx_2 + x; + a[lm] = 0.0; + + thr = fabs( thr - a_lm_2 ); + } + } + } + } + + // Step 5: index conversion and copy eigen values + + // back from Fortran to C++ + a++; + + for( i=0; i<n; i++ ) { + k = i + (i*(i+1))/2; + eigen_val[i] = a[k]; + } + + delete[] a; + + // Step 6: sort the eigen values and eigen vectors + + index = new int[n]; + for( i=0; i<n; i++ ) { + index[i] = i; + } + + for( i=0; i<(n-1); i++ ) { + x = eigen_val[i]; + k = i; + + for( j=i+1; j<n; j++ ) { + if( x < eigen_val[j] ) { + k = j; + x = eigen_val[j]; + } + } + + eigen_val[k] = eigen_val[i]; + eigen_val[i] = x; + + jj = index[k]; + index[k] = index[i]; + index[i] = jj; + } + + + // Step 7: save the eigen vectors + + v++; // back from Fortran to to C++ + + ij = 0; + for( k=0; k<n; k++ ) { + ik = index[k]*n; + for( i=0; i<n; i++ ) { + eigen_vec[ij++] = v[ik++]; + } + } + + delete[] v ; + delete[] index; + return; + } + +//_________________________________________________________ + + } +} diff --git a/source/blender/freestyle/intern/geometry/matrix_util.h b/source/blender/freestyle/intern/geometry/matrix_util.h new file mode 100755 index 00000000000..a990413c403 --- /dev/null +++ b/source/blender/freestyle/intern/geometry/matrix_util.h @@ -0,0 +1,69 @@ +/* + * GXML/Graphite: Geometry and Graphics Programming Library + Utilities + * Copyright (C) 2000 Bruno Levy + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * If you modify this software, you should include a notice giving the + * name of the person performing the modification, the date of modification, + * and the reason for such modification. + * + * Contact: Bruno Levy + * + * levy@loria.fr + * + * ISA Project + * LORIA, INRIA Lorraine, + * Campus Scientifique, BP 239 + * 54506 VANDOEUVRE LES NANCY CEDEX + * FRANCE + * + * Note that the GNU General Public License does not permit incorporating + * the Software into proprietary programs. + */ + +#ifndef __MATRIX_UTIL__ +#define __MATRIX_UTIL__ + +# include "../system/FreestyleConfig.h" + +namespace OGF { + + namespace MatrixUtil { + + /** + * computes the eigen values and eigen vectors + * of a semi definite symmetric matrix + * + * @param matrix is stored in column symmetric storage, i.e. + * matrix = { m11, m12, m22, m13, m23, m33, m14, m24, m34, m44 ... } + * size = n(n+1)/2 + * + * @param eigen_vectors (return) = { v1, v2, v3, ..., vn } + * where vk = vk0, vk1, ..., vkn + * size = n^2, must be allocated by caller + * + * @param eigen_values (return) are in decreasing order + * size = n, must be allocated by caller + */ + LIB_GEOMETRY_EXPORT + void semi_definite_symmetric_eigen( + const double *mat, int n, double *eigen_vec, double *eigen_val + ) ; + + } +} + +#endif diff --git a/source/blender/freestyle/intern/geometry/normal_cycle.cpp b/source/blender/freestyle/intern/geometry/normal_cycle.cpp new file mode 100755 index 00000000000..b456ced8331 --- /dev/null +++ b/source/blender/freestyle/intern/geometry/normal_cycle.cpp @@ -0,0 +1,103 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// +#include "normal_cycle.h" +#include "matrix_util.h" + + +namespace OGF { + +//_________________________________________________________ + + + NormalCycle::NormalCycle() { + } + + void NormalCycle::begin() { + M_[0] = M_[1] = M_[2] = M_[3] = M_[4] = M_[5] = 0 ; + } + + void NormalCycle::end() { + + double eigen_vectors[9] ; + MatrixUtil::semi_definite_symmetric_eigen(M_, 3, eigen_vectors, eigen_value_) ; + + axis_[0] = Vec3r( + eigen_vectors[0], eigen_vectors[1], eigen_vectors[2] + ) ; + + axis_[1] = Vec3r( + eigen_vectors[3], eigen_vectors[4], eigen_vectors[5] + ) ; + + axis_[2] = Vec3r( + eigen_vectors[6], eigen_vectors[7], eigen_vectors[8] + ) ; + + // Normalize the eigen vectors + + for(int i=0; i<3; i++) { + axis_[i].normalize() ; + } + + // Sort the eigen vectors + + i_[0] = 0 ; + i_[1] = 1 ; + i_[2] = 2 ; + + double l0 = ::fabs(eigen_value_[0]) ; + double l1 = ::fabs(eigen_value_[1]) ; + double l2 = ::fabs(eigen_value_[2]) ; + + if(l1 > l0) { + ogf_swap(l0 , l1 ) ; + ogf_swap(i_[0], i_[1]) ; + } + if(l2 > l1) { + ogf_swap(l1 , l2 ) ; + ogf_swap(i_[1], i_[2]) ; + } + if(l1 > l0) { + ogf_swap(l0 , l1 ) ; + ogf_swap(i_[0],i_[1]) ; + } + + } + + void NormalCycle::accumulate_dihedral_angle( + const Vec3r& edge, double beta, double neigh_area + ) { + Vec3r e = edge ; + e.normalize() ; + + double s = edge.norm() * beta * neigh_area ; + + M_[0] += s * e.x() * e.x() ; + M_[1] += s * e.x() * e.y() ; + M_[2] += s * e.y() * e.y() ; + M_[3] += s * e.x() * e.z() ; + M_[4] += s * e.y() * e.z() ; + M_[5] += s * e.z() * e.z() ; + } + +//_________________________________________________________ + +} diff --git a/source/blender/freestyle/intern/geometry/normal_cycle.h b/source/blender/freestyle/intern/geometry/normal_cycle.h new file mode 100755 index 00000000000..41fbf7b3fab --- /dev/null +++ b/source/blender/freestyle/intern/geometry/normal_cycle.h @@ -0,0 +1,97 @@ +/* + * OGF/Graphite: Geometry and Graphics Programming Library + Utilities + * Copyright (C) 2000 Bruno Levy + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * If you modify this software, you should include a notice giving the + * name of the person performing the modification, the date of modification, + * and the reason for such modification. + * + * Contact: Bruno Levy + * + * levy@loria.fr + * + * ISA Project + * LORIA, INRIA Lorraine, + * Campus Scientifique, BP 239 + * 54506 VANDOEUVRE LES NANCY CEDEX + * FRANCE + * + * Note that the GNU General Public License does not permit incorporating + * the Software into proprietary programs. + */ + +#ifndef __MESH_TOOLS_MATH_NORMAL_CYCLE__ +#define __MESH_TOOLS_MATH_NORMAL_CYCLE__ + +# include "../system/FreestyleConfig.h" +# include "Geom.h" +using namespace Geometry; + +namespace OGF { + +template <class T> inline void ogf_swap(T& x, T& y) { + T z = x ; + x = y ; + y = z ; + } + +//_________________________________________________________ + + /** + * NormalCycle evaluates the curvature tensor in function + * of a set of dihedral angles and associated vectors. + * Reference: + * Restricted Delaunay Triangulation and Normal Cycle, + * D. Cohen-Steiner and J.M. Morvan, + * SOCG 2003 + */ + class LIB_GEOMETRY_EXPORT NormalCycle { + public: + NormalCycle() ; + void begin() ; + void end() ; + /** + * Note: the specified edge vector needs to be pre-clipped + * by the neighborhood. + */ + void accumulate_dihedral_angle( + const Vec3r& edge, real angle, real neigh_area = 1.0 + ) ; + const Vec3r& eigen_vector(int i) const { return axis_[i_[i]] ; } + real eigen_value(int i) const { return eigen_value_[i_[i]] ; } + + const Vec3r& N() const { return eigen_vector(2) ; } + const Vec3r& Kmax() const { return eigen_vector(1) ; } + const Vec3r& Kmin() const { return eigen_vector(0) ; } + + real n() const { return eigen_value(2) ; } + real kmax() const { return eigen_value(1) ; } + real kmin() const { return eigen_value(0) ; } + + private: + real center_[3] ; + Vec3r axis_[3] ; + real eigen_value_[3] ; + real M_[6] ; + int i_[3] ; + } ; + +//_________________________________________________________ + +} + +#endif diff --git a/source/blender/freestyle/intern/image/GaussianFilter.cpp b/source/blender/freestyle/intern/image/GaussianFilter.cpp new file mode 100755 index 00000000000..3a79f5f9949 --- /dev/null +++ b/source/blender/freestyle/intern/image/GaussianFilter.cpp @@ -0,0 +1,96 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "GaussianFilter.h" +#include <stdlib.h> + +GaussianFilter::GaussianFilter(float iSigma ) +{ + _sigma = iSigma; + _mask = 0; + computeMask(); +} + +GaussianFilter::GaussianFilter(const GaussianFilter& iBrother) +{ + _sigma = iBrother._sigma; + _maskSize = iBrother._maskSize; + _bound = iBrother._bound; + _storedMaskSize = iBrother._storedMaskSize; + _mask = new float[_maskSize*_maskSize]; + memcpy(_mask, iBrother._mask, _maskSize*_maskSize*sizeof(float)); +} + + +GaussianFilter& GaussianFilter::operator= (const GaussianFilter& iBrother) +{ + _sigma = iBrother._sigma; + _maskSize = iBrother._maskSize; + _bound = iBrother._bound; + _storedMaskSize = iBrother._storedMaskSize; + _mask = new float[_storedMaskSize*_storedMaskSize]; + memcpy(_mask, iBrother._mask, _storedMaskSize*_storedMaskSize*sizeof(float)); + return *this; +} + + +GaussianFilter::~GaussianFilter() +{ + if(0!=_mask) + { + delete [] _mask; + } +} + +int GaussianFilter::computeMaskSize(float sigma) +{ + int maskSize = (int)floor(4*sigma)+1; + if(0 == maskSize%2) + ++maskSize; + + return maskSize; +} + +void GaussianFilter::setSigma(float sigma) +{ + _sigma = sigma; + computeMask(); +} + +void GaussianFilter::computeMask() +{ + if(0 != _mask){ + delete [] _mask; + } + + _maskSize = computeMaskSize(_sigma); + _storedMaskSize = (_maskSize+1)>>1; + _bound = _storedMaskSize-1; + + float norm = _sigma*_sigma*2.f*M_PI; + float invNorm = 1.0/norm; + _mask = new float[_storedMaskSize*_storedMaskSize*sizeof(float)]; + for(int i=0; i<_storedMaskSize; ++i) + for(int j=0; j<_storedMaskSize; ++j) + _mask[i*_storedMaskSize+j] = invNorm*exp(-(i*i + j*j)/(2.0*_sigma*_sigma)); + //_mask[i*_storedMaskSize+j] = exp(-(i*i + j*j)/(2.0*_sigma*_sigma)); +} + diff --git a/source/blender/freestyle/intern/image/GaussianFilter.h b/source/blender/freestyle/intern/image/GaussianFilter.h new file mode 100755 index 00000000000..be0e3e2bada --- /dev/null +++ b/source/blender/freestyle/intern/image/GaussianFilter.h @@ -0,0 +1,146 @@ +// +// Filename : Image.h +// Author(s) : Stephane Grabli +// Purpose : Class to perform gaussian filtering operations on an image +// Date of creation : 20/05/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef GAUSSIANFILTER_H +# define GAUSSIANFILTER_H + +#include <string.h> // for memcpy +#include <cstdlib> // for abs +#include "../system/FreestyleConfig.h" + +class LIB_IMAGE_EXPORT GaussianFilter{ +protected: + /* the mask is a symetrical 2d array (with respect + to the middle point). + Thus, M(i,j) = M(-i,j) = M(i,-j) = M(-i,-j). + For this reason, to represent a NxN array (N odd), we only store + a ((N+1)/2)x((N+1)/2) array. + */ + float _sigma; + float *_mask; + int _bound; + int _maskSize; // the real mask size (must be odd)(the size of the mask we store is ((_maskSize+1)/2)*((_maskSize+1)/2)) + int _storedMaskSize; //(_maskSize+1)/2) + +public: + GaussianFilter(float iSigma = 1.f) ; + GaussianFilter(const GaussianFilter&) ; + GaussianFilter& operator= (const GaussianFilter&) ; + virtual ~GaussianFilter() ; + + /*! Returns the value for pixel x,y of image "map" after a gaussian blur, + * made using the sigma value. + * The sigma value determines the mask size (~ 2 x sigma). + * \param map + * The image we wish to work on. The Map template must implement the + * foloowing methods: + * - float pixel(unsigned int x,unsigned int y) const; + * - unsigned width() const; + * - unsigned height() const; + * \param x + * The abscissa of the pixel where we want to evaluate the gaussian blur. + * \param y + * The ordinate of the pixel where we want to evaluate the gaussian blur. + * \param sigma + * The sigma value of the gaussian function. + */ + template<class Map> + float getSmoothedPixel(Map * map, int x, int y) ; + + /*! Compute the mask size and returns the REAL mask size ((2*_maskSize)-1) + * This method is provided for convenience. + */ + static int computeMaskSize(float sigma) ; + + /*! accessors */ + inline float sigma() const {return _sigma;} + inline int maskSize() const {return _maskSize;} + inline int getBound() {return _bound;} + + /*! modifiers */ + void setSigma(float sigma) ; + // void SetMaskSize(int size) {_maskSize = size;_storedMaskSize=(_maskSize+1)>>1;} + + +protected: + void computeMask(); +}; + +/* + + ############################################# + ############################################# + ############################################# + ###### ###### + ###### I M P L E M E N T A T I O N ###### + ###### ###### + ############################################# + ############################################# + ############################################# + +*/ + + +#include <math.h> + +#ifdef __MACH__ +#define sqrtf(x) (sqrt(x)) +#endif + +template<class Map> +float GaussianFilter::getSmoothedPixel(Map * map, int x, int y) +{ + float sum = 0.f; + float L=0.f; + int w = (int)map->width(); //soc + int h = (int)map->height(); //soc + + // Current pixel is x,y + // Sum surrounding pixels L value: + for(int i=-_bound; i<=_bound; ++i) + { + if((y+i < 0) || (y+i >= h)) + continue; + for(int j=-_bound; j<=_bound; ++j) + { + if((x+j < 0) || (x+j >= w)) + continue; + + float tmpL = map->pixel(x+j,y+i); + float m = _mask[abs(i)*_storedMaskSize+abs(j)]; + L += m*tmpL; + sum += m; + } + } + //L /= sum; + return L; +} + + +#endif // GAUSSIANFILTER diff --git a/source/blender/freestyle/intern/image/Image.h b/source/blender/freestyle/intern/image/Image.h new file mode 100755 index 00000000000..72affbc1023 --- /dev/null +++ b/source/blender/freestyle/intern/image/Image.h @@ -0,0 +1,389 @@ +// +// Filename : Image.h +// Author(s) : Stephane Grabli +// Purpose : Class to encapsulate an array of RGB or Gray level values +// Date of creation : 20/05/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef IMAGE_H +# define IMAGE_H + +# include <string.h> // for memcpy + +// +// Image base class, for all types of images +// +/////////////////////////////////////////////////////////////////////////////// + +/*! This class allows the storing of part of an image, + * while allowing a normal access to its pixel values. + * You can for example only a rectangle of sw*sh, whose + * lower-left corner is at (ox, oy), of an image of + * size w*h, and access these pixels using x,y coordinates + * specified in the whole image coordinate system. + */ +class FrsImage +{ + public: + + /*! Default constructor */ + FrsImage() { + _storedWidth = 0; + _storedHeight = 0; + _width = 0; + _height = 0; + _Ox = 0; + _Oy = 0; + } + + /*! Copy constructor */ + FrsImage(const FrsImage& brother) { + _storedWidth = brother._storedWidth; + _storedHeight = brother._storedHeight; + _width = brother._width; + _height = brother._height; + _Ox = brother._Ox; + _Oy = brother._Oy; + } + + /*! Builds an FrsImage from its width and height. + * The memory is allocated consequently. + */ + FrsImage(unsigned w, unsigned h) { + _width = w; + _height = h; + _storedWidth = w; + _storedHeight = h; + _Ox = 0; + _Oy = 0; + } + + /*! Builds a partial-storing image. + * \param w + * The width of the complete image + * \param h + * The height of the complete image + * \param sw + * The width of the rectangle that will actually + * be stored. + * \param sh + * The height of the rectangle that will actually + * be stored. + * \param ox + * The x-abscissa of the origin of the rectangle that will actually + * be stored. + * \param oy + * The x-abscissa of the origin of the rectangle that will actually + * be stored. + */ + FrsImage(unsigned w, unsigned h, unsigned sw, unsigned sh, unsigned ox, unsigned oy) { + _width = w; + _height = h; + _storedWidth = sw; + _storedHeight = sh; + _Ox = ox; + _Oy = oy; + } + + /*! Operator= */ + FrsImage& operator=(const FrsImage& brother) { + _width = brother._width; + _height = brother._height; + _storedWidth = brother._storedWidth; + _storedHeight = brother._storedHeight; + _Ox = brother._Ox; + _Oy = brother._Oy; + return* this; + } + + /*! Destructor */ + virtual ~FrsImage() {} + + /*! Returns the width of the complete image */ + inline unsigned width() const { + return _width; + } + /*! Returns the height of the complete image */ + inline unsigned height() const { + return _height; + } + + /*! Returns the grey value for pixel x,y */ + virtual float pixel(unsigned x, unsigned y) const = 0; + + /*! Sets the array. + * \param array + * The array containing the values we wish to store. + * Its size is sw*sh. + * \param width + * The width of the complete image + * \param height + * The height of the complete image + * \param sw + * The width of the rectangle that will actually + * be stored. + * \param sh + * The height of the rectangle that will actually + * be stored. + * \param ox + * The x-abscissa of the origin of the rectangle that will actually + * be stored. + * \param oy + * The x-abscissa of the origin of the rectangle that will actually + * be stored. + * \param copy + * If true, the array is copied, otherwise the pointer is + * copied + */ + virtual void setArray(float* array, unsigned width, unsigned height, unsigned sw, unsigned sh, unsigned x, unsigned y, bool copy = true) = 0; + + /*! Returns the array containing the pixels values. + * Its size is sw*sh, i.e. potentially a smaller + * rectangular part of the complete image. + */ + virtual float * getArray() = 0; + + protected: + + unsigned _width; + unsigned _height; + unsigned _storedWidth; + unsigned _storedHeight; + unsigned _Ox; // origin of the stored part + unsigned _Oy; // origin of the stored part +}; + + +// +// RGBImage +// +/////////////////////////////////////////////////////////////////////////////// + +class RGBImage : public FrsImage +{ + public: + + RGBImage() : FrsImage() { + _rgb = 0; + } + + RGBImage(const RGBImage& brother) : FrsImage(brother) { + _rgb = new float[3 * _storedWidth * _storedHeight]; + memcpy(_rgb, brother._rgb, 3 * _storedWidth * _storedHeight * sizeof(float)); + } + + RGBImage(unsigned w, unsigned h) : FrsImage(w, h) { + _rgb = new float[3 * _width * _height]; + } + + RGBImage(float* rgb, unsigned w, unsigned h) : FrsImage(w, h) { + _rgb = new float[3 * _width * _height]; + memcpy(_rgb, rgb, 3 * _width * _height * sizeof(float)); + } + + /*! Builds an RGB partial image from the useful part buffer. + * \param rgb + * The array of size 3*sw*sh containing the RGB values + * of the sw*sh pixels we need to stored. + * These sw*sh pixels constitute a rectangular part of + * a bigger RGB image containing w*h pixels. + * \param w + * The width of the complete image + * \param h + * The height of the complete image + * \param sw + * The width of the part of the image we want to store and work on + * \param sh + * The height of the part of the image we want to store and work on + */ + RGBImage(float* rgb, unsigned w, unsigned h, unsigned sw, unsigned sh, unsigned ox, unsigned oy) : FrsImage(w, h, sw, sh, ox, oy) { + _rgb = new float[3 * _storedWidth * _storedHeight]; + memcpy(_rgb, rgb, 3 * _storedWidth * _storedHeight * sizeof(float)); + } + + RGBImage& operator=(const RGBImage& brother) { + dynamic_cast<FrsImage&>(*this) = brother; + _rgb = new float[3 * _storedWidth * _storedHeight]; + memcpy(_rgb, brother._rgb, 3 * _storedWidth * _storedHeight * sizeof(float)); + return* this; + } + + virtual ~RGBImage() { + if(_rgb) + delete[] _rgb; + } + + inline float getR(unsigned x, unsigned y) const { + return _rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3]; + } + + inline float getG(unsigned x, unsigned y) const { + return _rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3 + 1]; + } + + inline float getB(unsigned x, unsigned y) const { + return _rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3 + 2]; + } + + virtual void setPixel(unsigned x, unsigned y, float r, float g, float b){ + float * tmp = &(_rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3]); + *tmp = r;++tmp; + *tmp = g;++tmp; + *tmp = b; + } + + virtual float pixel(unsigned x, unsigned y) const { + float res = 0; + float* tmp = &(_rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3]); + res += 11 * (*tmp++); + res += 16 * (*tmp++); + res += 5 * (*tmp); + return res / 32; + } + + /*! Sets the RGB array. + * copy + * If true, the array is copied, otherwise the pointer is + * copied + */ + virtual void setArray(float* rgb, unsigned width, unsigned height, unsigned sw, unsigned sh, unsigned x, unsigned y, bool copy = true) { + _width = width; + _height = height; + _storedWidth = sw; + _storedHeight = sh; + _Ox = x; + _Oy = y; + if(!copy) { + _rgb = rgb; + return; + } + + memcpy(_rgb, rgb, 3 * _storedWidth * _storedHeight* sizeof(float)); + } + + virtual float * getArray() {return _rgb;} + + protected: + + float* _rgb; +}; + + +// +// GrayImage +// +/////////////////////////////////////////////////////////////////////////////// + +class GrayImage : public FrsImage +{ + public: + + GrayImage() : FrsImage() { + _lvl = 0; + } + + GrayImage(const GrayImage& brother) : FrsImage(brother) { + _lvl = new float[_storedWidth*_storedHeight]; + memcpy(_lvl, brother._lvl, _storedWidth*_storedHeight*sizeof(*_lvl)); + } + + /*! Builds an empty gray image */ + GrayImage(unsigned w, unsigned h) : FrsImage(w, h) { + _lvl = new float[_width*_height]; + } + + GrayImage(float* lvl, unsigned w, unsigned h) : FrsImage(w, h) { + _lvl = new float[_width*_height]; + memcpy(_lvl, lvl, _width*_height*sizeof(*_lvl)); + } + + /*! Builds a partial image from the useful part buffer. + * \param lvl + * The array of size sw*sh containing the gray values + * of the sw*sh pixels we need to stored. + * These sw*sh pixels constitute a rectangular part of + * a bigger gray image containing w*h pixels. + * \param w + * The width of the complete image + * \param h + * The height of the complete image + * \param sw + * The width of the part of the image we want to store and work on + * \param sh + * The height of the part of the image we want to store and work on + */ + GrayImage(float* lvl, unsigned w, unsigned h, unsigned sw, unsigned sh, unsigned ox, unsigned oy) : FrsImage(w, h, sw, sh, ox, oy) { + _lvl = new float[_storedWidth*_storedHeight]; + memcpy(_lvl, lvl, _storedWidth*_storedHeight*sizeof(float)); + } + + GrayImage& operator=(const GrayImage& brother) { + dynamic_cast<FrsImage&>(*this) = brother; + _lvl = new float[_storedWidth * _storedHeight]; + memcpy(_lvl, brother._lvl, _storedWidth * _storedHeight * sizeof(float)); + return *this; + } + + virtual ~GrayImage() { + if(_lvl) + delete[] _lvl; + } + + inline void setPixel(unsigned x, unsigned y, float v){ + _lvl[(y-_Oy) * _storedWidth+ (x-_Ox)] = v; + } + + inline float pixel(unsigned x, unsigned y) const { + return _lvl[(y-_Oy) * _storedWidth+ (x-_Ox)]; + } + + /*! Sets the array. + * copy + * If true, the array is copie, otherwise the pounsigneder is + * copied + */ + void setArray(float *lvl, unsigned width, unsigned height, unsigned sw, unsigned sh, unsigned x, unsigned y, bool copy = true) { + _width = width; + _height = height; + _storedWidth = sw; + _storedHeight = sh; + _Ox = x; + _Oy = y; + if(!copy) { + _lvl = lvl; + return; + } + + memcpy(_lvl, lvl, _storedWidth * _storedHeight * sizeof(float)); + } + /*! Returns the array containing the gray values. */ + virtual float * getArray() {return _lvl;} + + protected: + + float *_lvl; +}; + +#endif // IMAGE_H diff --git a/source/blender/freestyle/intern/image/ImagePyramid.cpp b/source/blender/freestyle/intern/image/ImagePyramid.cpp new file mode 100755 index 00000000000..542ab7917e3 --- /dev/null +++ b/source/blender/freestyle/intern/image/ImagePyramid.cpp @@ -0,0 +1,166 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// +#include "ImagePyramid.h" +#include "Image.h" +#include "GaussianFilter.h" +#include <iostream> + +using namespace std; + +//ImagePyramid::ImagePyramid(const GrayImage& level0, unsigned nbLevels){ +// //BuildPyramid(level0,nbLevels); +//} + +ImagePyramid::ImagePyramid(const ImagePyramid& iBrother){ + if(!_levels.empty()){ + for(vector<GrayImage*>::iterator im=_levels.begin(), imend=_levels.end(); + im!=imend; + ++im){ + _levels.push_back(new GrayImage(**im)); + } + } +} +ImagePyramid::~ImagePyramid(){ + if(!_levels.empty()){ + for(vector<GrayImage*>::iterator im=_levels.begin(), imend=_levels.end(); + im!=imend; + ++im){ + delete (*im); + } + _levels.clear(); + } +} + +GrayImage * ImagePyramid::getLevel(int l){ + return _levels[l]; +} + +float ImagePyramid::pixel(int x, int y, int level){ + GrayImage *img = _levels[level]; + if(0 == level){ + return img->pixel(x,y); + } + unsigned int i = 1<<level; + unsigned int sx = x>>level; + unsigned int sy = y>>level; + if(sx >= img->width()) + sx = img->width()-1; + if(sy >= img->height()) + sy = img->height()-1; + + // bilinear interpolation + float A = i*(sx+1)-x; + float B = x-i*sx; + float C = i*(sy+1)-y; + float D = y-i*sy; + + float P1(0), P2(0); + P1 = A*img->pixel(sx,sy); + if(sx < img->width()-1){ + if(x%i != 0) + P1 += B*img->pixel(sx+1,sy); + }else{ + P1 += B*img->pixel(sx,sy); + } + if(sy<img->height()-1){ + if(y%i != 0){ + P2 = A*img->pixel(sx,sy+1); + if(sx < img->width()-1){ + if(x%i != 0) + P2 += B*img->pixel(sx+1,sy+1); + }else{ + P2 += B*img->pixel(sx,sy+1); + } + } + }else{ + P2 = P1; + } + return (1.f/(float)(1<<2*level))*(C*P1 + D*P2); +} + +int ImagePyramid::width(int level){ + return _levels[level]->width(); +} + +int ImagePyramid::height(int level){ + return _levels[level]->height(); +} + +GaussianPyramid::GaussianPyramid(const GrayImage& level0, unsigned nbLevels, float iSigma) + : ImagePyramid() +{ + _sigma = iSigma; + BuildPyramid(level0,nbLevels); +} +GaussianPyramid::GaussianPyramid(GrayImage* level0, unsigned nbLevels, float iSigma) + : ImagePyramid() +{ + _sigma = iSigma; + BuildPyramid(level0,nbLevels); +} + +GaussianPyramid::GaussianPyramid(const GaussianPyramid& iBrother) +: ImagePyramid(iBrother){ + _sigma = iBrother._sigma; +} +void GaussianPyramid::BuildPyramid(const GrayImage& level0, unsigned nbLevels){ + GrayImage *pLevel = new GrayImage(level0); + BuildPyramid(pLevel, nbLevels); +} + +void GaussianPyramid::BuildPyramid(GrayImage* level0, unsigned nbLevels){ + GrayImage *pLevel = level0; + _levels.push_back(pLevel); + GaussianFilter gf(_sigma); + // build the nbLevels: + unsigned w = pLevel->width(); + unsigned h = pLevel->height(); + if(nbLevels!=0) + { + for(unsigned i=0; i<nbLevels; ++i){ //soc + w = pLevel->width()>>1; + h = pLevel->height()>>1; + GrayImage *img = new GrayImage(w,h); + for(unsigned y=0; y<h; ++y){ + for(unsigned x=0; x<w; ++x){ + float v = gf.getSmoothedPixel<GrayImage>(pLevel, 2*x,2*y); + img->setPixel(x,y,v); + } + } + _levels.push_back(img); + pLevel = img; + } + }else{ + while((w>1) && (h>1)){ + w = pLevel->width()>>1; + h = pLevel->height()>>1; + GrayImage *img = new GrayImage(w,h); + for(unsigned y=0; y<h; ++y){ + for(unsigned x=0; x<w; ++x){ + float v = gf.getSmoothedPixel<GrayImage>(pLevel, 2*x,2*y); + img->setPixel(x,y,v); + } + } + _levels.push_back(img); + pLevel = img; + } + } +} diff --git a/source/blender/freestyle/intern/image/ImagePyramid.h b/source/blender/freestyle/intern/image/ImagePyramid.h new file mode 100755 index 00000000000..9e326757f02 --- /dev/null +++ b/source/blender/freestyle/intern/image/ImagePyramid.h @@ -0,0 +1,92 @@ +// +// Filename : ImagePyramid.h +// Author(s) : Stephane Grabli +// Purpose : Class to represent a pyramid of images +// Date of creation : 25/12/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef IMAGEPYRAMID_H +# define IMAGEPYRAMID_H + +#include "../system/FreestyleConfig.h" +#include <vector> + +class GrayImage; +class LIB_IMAGE_EXPORT ImagePyramid{ +protected: + std::vector<GrayImage*> _levels; + +public: + ImagePyramid(){} + ImagePyramid(const ImagePyramid& iBrother); + //ImagePyramid(const GrayImage& level0, unsigned nbLevels); + virtual ~ImagePyramid(); + + /*! Builds the pyramid. + * must be overloaded by inherited classes. + * if nbLevels==0, the complete pyramid is built + */ + virtual void BuildPyramid(const GrayImage& level0, unsigned nbLevels) = 0; + + /*! Builds a pyramid without copying the base level */ + virtual void BuildPyramid(GrayImage* level0, unsigned nbLevels) = 0; + + virtual GrayImage * getLevel(int l); + /*! Returns the pixel x,y using bilinear interpolation. + * \param x + * the abscissa specified in the finest level coordinate system + * \param y + * the ordinate specified in the finest level coordinate system + * \param level + * the level from which we want the pixel to be evaluated + */ + virtual float pixel(int x, int y, int level=0); + /*! Returns the width of the level-th level image */ + virtual int width(int level=0); + /*! Returns the height of the level-th level image */ + virtual int height(int level=0); + /*! Returns the number of levels in the pyramid */ + inline int getNumberOfLevels() const { return _levels.size();} +}; + +class LIB_IMAGE_EXPORT GaussianPyramid : public ImagePyramid +{ +protected: + float _sigma; +public: + GaussianPyramid(float iSigma=1.f) : ImagePyramid() {_sigma=iSigma;} + GaussianPyramid(const GrayImage& level0, unsigned nbLevels, float iSigma=1.f); + GaussianPyramid(GrayImage* level0, unsigned nbLevels, float iSigma=1.f); + GaussianPyramid(const GaussianPyramid& iBrother); + virtual ~GaussianPyramid(){} + + virtual void BuildPyramid(const GrayImage& level0, unsigned nbLevels); + virtual void BuildPyramid(GrayImage* level0, unsigned nbLevels); + /* accessors */ + inline float getSigma() const {return _sigma;} + /* modifiers */ + +}; +#endif // IMAGEPYRAMID_H diff --git a/source/blender/freestyle/intern/python/BPy_BBox.cpp b/source/blender/freestyle/intern/python/BPy_BBox.cpp new file mode 100644 index 00000000000..0acd32bad58 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_BBox.cpp @@ -0,0 +1,100 @@ +#include "BPy_BBox.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- +int BBox_Init( PyObject *module ) +{ + if( module == NULL ) + return -1; + + if( PyType_Ready( &BBox_Type ) < 0 ) + return -1; + + Py_INCREF( &BBox_Type ); + PyModule_AddObject(module, "BBox", (PyObject *)&BBox_Type); + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char BBox___doc__[] = +"Class for representing a bounding box.\n"; + +static int BBox___init__(BPy_BBox *self, PyObject *args, PyObject *kwds) +{ + if(!( PyArg_ParseTuple(args, "") )) + return -1; + self->bb = new BBox< Vec3r>(); + return 0; +} + +static void BBox___dealloc__(BPy_BBox* self) +{ + delete self->bb; + Py_TYPE(self)->tp_free((PyObject*)self); +} + + +static PyObject * BBox___repr__(BPy_BBox* self) +{ + return PyUnicode_FromFormat("BBox - address: %p", self->bb ); +} + +/*----------------------BBox instance definitions ----------------------------*/ +static PyMethodDef BPy_BBox_methods[] = { + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_BBox type definition ------------------------------*/ + +PyTypeObject BBox_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "BBox", /* tp_name */ + sizeof(BPy_BBox), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)BBox___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)BBox___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + BBox___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_BBox_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)BBox___init__, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/BPy_BBox.h b/source/blender/freestyle/intern/python/BPy_BBox.h new file mode 100644 index 00000000000..f8282187da0 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_BBox.h @@ -0,0 +1,38 @@ +#ifndef FREESTYLE_PYTHON_BBOX_H +#define FREESTYLE_PYTHON_BBOX_H + +#include <Python.h> + +#include "../geometry/BBox.h" +#include "../geometry/Geom.h" +using namespace Geometry; + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject BBox_Type; + +#define BPy_BBox_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &BBox_Type) ) + +/*---------------------------Python BPy_BBox structure definition----------*/ +typedef struct { + PyObject_HEAD + BBox<Vec3r> *bb; +} BPy_BBox; + +/*---------------------------Python BPy_BBox visible prototypes-----------*/ + +int BBox_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_BBOX_H */ diff --git a/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.cpp b/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.cpp new file mode 100644 index 00000000000..693d35b1f60 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.cpp @@ -0,0 +1,166 @@ +#include "BPy_BinaryPredicate0D.h" + +#include "BPy_Convert.h" +#include "BPy_Interface0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- +int BinaryPredicate0D_Init( PyObject *module ) +{ + if( module == NULL ) + return -1; + + if( PyType_Ready( &BinaryPredicate0D_Type ) < 0 ) + return -1; + + Py_INCREF( &BinaryPredicate0D_Type ); + PyModule_AddObject(module, "BinaryPredicate0D", (PyObject *)&BinaryPredicate0D_Type); + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char BinaryPredicate0D___doc__[] = +"Base class for binary predicates working on :class:`Interface0D`\n" +"objects. A BinaryPredicate0D is typically an ordering relation\n" +"between two Interface0D objects. The predicate evaluates a relation\n" +"between the two Interface0D instances and returns a boolean value (true\n" +"or false). It is used by invoking the __call__() method.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __call__(inter1, inter2)\n" +"\n" +" Must be overload by inherited classes. It evaluates a relation\n" +" between two Interface0D objects.\n" +"\n" +" :arg inter1: The first Interface0D object.\n" +" :type inter1: :class:`Interface0D`\n" +" :arg inter2: The second Interface0D object.\n" +" :type inter2: :class:`Interface0D`\n" +" :return: True or false.\n" +" :rtype: bool\n"; + +static int BinaryPredicate0D___init__(BPy_BinaryPredicate0D *self, PyObject *args, PyObject *kwds) +{ + if ( !PyArg_ParseTuple(args, "") ) + return -1; + self->bp0D = new BinaryPredicate0D(); + self->bp0D->py_bp0D = (PyObject *) self; + + return 0; +} + +static void BinaryPredicate0D___dealloc__(BPy_BinaryPredicate0D* self) +{ + if (self->bp0D) + delete self->bp0D; + Py_TYPE(self)->tp_free((PyObject*)self); +} + + +static PyObject * BinaryPredicate0D___repr__(BPy_BinaryPredicate0D* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->bp0D->getName().c_str(), self->bp0D ); +} + +static char BinaryPredicate0D_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the binary 0D predicate.\n" +"\n" +" :return: The name of the binary 0D predicate.\n" +" :rtype: str\n"; + +static PyObject * BinaryPredicate0D_getName( BPy_BinaryPredicate0D *self, PyObject *args) +{ + return PyUnicode_FromString( self->bp0D->getName().c_str() ); +} + +static PyObject * BinaryPredicate0D___call__( BPy_BinaryPredicate0D *self, PyObject *args, PyObject *kwds) +{ + BPy_Interface0D *obj1, *obj2; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if( !PyArg_ParseTuple(args, "O!O!", &Interface0D_Type, &obj1, &Interface0D_Type, &obj2) ) + return NULL; + + if( typeid(*(self->bp0D)) == typeid(BinaryPredicate0D) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if (self->bp0D->operator()( *(obj1->if0D) , *(obj2->if0D) ) < 0) { + if (!PyErr_Occurred()) { + string msg(self->bp0D->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + return PyBool_from_bool( self->bp0D->result ); + +} + +/*----------------------BinaryPredicate0D instance definitions ----------------------------*/ +static PyMethodDef BPy_BinaryPredicate0D_methods[] = { + {"getName", ( PyCFunction ) BinaryPredicate0D_getName, METH_NOARGS, BinaryPredicate0D_getName___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_BinaryPredicate0D type definition ------------------------------*/ + +PyTypeObject BinaryPredicate0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "BinaryPredicate0D", /* tp_name */ + sizeof(BPy_BinaryPredicate0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)BinaryPredicate0D___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)BinaryPredicate0D___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)BinaryPredicate0D___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + BinaryPredicate0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_BinaryPredicate0D_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)BinaryPredicate0D___init__, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.h b/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.h new file mode 100644 index 00000000000..6a9a0775608 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.h @@ -0,0 +1,36 @@ +#ifndef FREESTYLE_PYTHON_BINARYPREDICATE0D_H +#define FREESTYLE_PYTHON_BINARYPREDICATE0D_H + +#include <Python.h> + +#include "../stroke/Predicates0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject BinaryPredicate0D_Type; + +#define BPy_BinaryPredicate0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &BinaryPredicate0D_Type) ) + +/*---------------------------Python BPy_BinaryPredicate0D structure definition----------*/ +typedef struct { + PyObject_HEAD + BinaryPredicate0D *bp0D; +} BPy_BinaryPredicate0D; + +/*---------------------------Python BPy_BinaryPredicate0D visible prototypes-----------*/ + +int BinaryPredicate0D_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_BINARYPREDICATE0D_H */ diff --git a/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.cpp b/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.cpp new file mode 100644 index 00000000000..e690a6d51c1 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.cpp @@ -0,0 +1,193 @@ +#include "BPy_BinaryPredicate1D.h" + +#include "BPy_Convert.h" +#include "BPy_Interface1D.h" + +#include "BinaryPredicate1D/BPy_FalseBP1D.h" +#include "BinaryPredicate1D/BPy_Length2DBP1D.h" +#include "BinaryPredicate1D/BPy_SameShapeIdBP1D.h" +#include "BinaryPredicate1D/BPy_TrueBP1D.h" +#include "BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- +int BinaryPredicate1D_Init( PyObject *module ) +{ + if( module == NULL ) + return -1; + + if( PyType_Ready( &BinaryPredicate1D_Type ) < 0 ) + return -1; + Py_INCREF( &BinaryPredicate1D_Type ); + PyModule_AddObject(module, "BinaryPredicate1D", (PyObject *)&BinaryPredicate1D_Type); + + if( PyType_Ready( &FalseBP1D_Type ) < 0 ) + return -1; + Py_INCREF( &FalseBP1D_Type ); + PyModule_AddObject(module, "FalseBP1D", (PyObject *)&FalseBP1D_Type); + + if( PyType_Ready( &Length2DBP1D_Type ) < 0 ) + return -1; + Py_INCREF( &Length2DBP1D_Type ); + PyModule_AddObject(module, "Length2DBP1D", (PyObject *)&Length2DBP1D_Type); + + if( PyType_Ready( &SameShapeIdBP1D_Type ) < 0 ) + return -1; + Py_INCREF( &SameShapeIdBP1D_Type ); + PyModule_AddObject(module, "SameShapeIdBP1D", (PyObject *)&SameShapeIdBP1D_Type); + + if( PyType_Ready( &TrueBP1D_Type ) < 0 ) + return -1; + Py_INCREF( &TrueBP1D_Type ); + PyModule_AddObject(module, "TrueBP1D", (PyObject *)&TrueBP1D_Type); + + if( PyType_Ready( &ViewMapGradientNormBP1D_Type ) < 0 ) + return -1; + Py_INCREF( &ViewMapGradientNormBP1D_Type ); + PyModule_AddObject(module, "ViewMapGradientNormBP1D", (PyObject *)&ViewMapGradientNormBP1D_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char BinaryPredicate1D___doc__[] = +"Base class for binary predicates working on :class:`Interface1D`\n" +"objects. A BinaryPredicate1D is typically an ordering relation\n" +"between two Interface1D objects. The predicate evaluates a relation\n" +"between the two Interface1D instances and returns a boolean value (true\n" +"or false). It is used by invoking the __call__() method.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __call__(inter1, inter2)\n" +"\n" +" Must be overload by inherited classes. It evaluates a relation\n" +" between two Interface1D objects.\n" +"\n" +" :arg inter1: The first Interface1D object.\n" +" :type inter1: :class:`Interface1D`\n" +" :arg inter2: The second Interface1D object.\n" +" :type inter2: :class:`Interface1D`\n" +" :return: True or false.\n" +" :rtype: bool\n"; + +static int BinaryPredicate1D___init__(BPy_BinaryPredicate1D *self, PyObject *args, PyObject *kwds) +{ + if ( !PyArg_ParseTuple(args, "") ) + return -1; + self->bp1D = new BinaryPredicate1D(); + self->bp1D->py_bp1D = (PyObject *) self; + return 0; +} + +static void BinaryPredicate1D___dealloc__(BPy_BinaryPredicate1D* self) +{ + if (self->bp1D) + delete self->bp1D; + Py_TYPE(self)->tp_free((PyObject*)self); +} + +static PyObject * BinaryPredicate1D___repr__(BPy_BinaryPredicate1D* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->bp1D->getName().c_str(), self->bp1D ); +} + +static char BinaryPredicate1D_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the binary 1D predicate.\n" +"\n" +" :return: The name of the binary 1D predicate.\n" +" :rtype: str\n"; + +static PyObject *BinaryPredicate1D_getName( BPy_BinaryPredicate1D *self, PyObject *args) +{ + return PyUnicode_FromString( self->bp1D->getName().c_str() ); +} + +static PyObject *BinaryPredicate1D___call__( BPy_BinaryPredicate1D *self, PyObject *args, PyObject *kwds) +{ + BPy_Interface1D *obj1, *obj2; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if( !PyArg_ParseTuple(args, "O!O!", &Interface1D_Type, &obj1, &Interface1D_Type, &obj2) ) + return NULL; + + if( typeid(*(self->bp1D)) == typeid(BinaryPredicate1D) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if (self->bp1D->operator()( *(obj1->if1D) , *(obj2->if1D) ) < 0) { + if (!PyErr_Occurred()) { + string msg(self->bp1D->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + return PyBool_from_bool( self->bp1D->result ); +} + +/*----------------------BinaryPredicate1D instance definitions ----------------------------*/ +static PyMethodDef BPy_BinaryPredicate1D_methods[] = { + {"getName", ( PyCFunction ) BinaryPredicate1D_getName, METH_NOARGS, BinaryPredicate1D_getName___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_BinaryPredicate1D type definition ------------------------------*/ +PyTypeObject BinaryPredicate1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "BinaryPredicate1D", /* tp_name */ + sizeof(BPy_BinaryPredicate1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)BinaryPredicate1D___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)BinaryPredicate1D___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)BinaryPredicate1D___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + BinaryPredicate1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_BinaryPredicate1D_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)BinaryPredicate1D___init__, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.h b/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.h new file mode 100644 index 00000000000..5a993f84f5b --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.h @@ -0,0 +1,35 @@ +#ifndef FREESTYLE_PYTHON_BINARYPREDICATE1D_H +#define FREESTYLE_PYTHON_BINARYPREDICATE1D_H + +#include <Python.h> + +#include "../stroke/Predicates1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject BinaryPredicate1D_Type; + +#define BPy_BinaryPredicate1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &BinaryPredicate1D_Type) ) + +/*---------------------------Python BPy_BinaryPredicate1D structure definition----------*/ +typedef struct { + PyObject_HEAD + BinaryPredicate1D *bp1D; +} BPy_BinaryPredicate1D; + +/*---------------------------Python BPy_BinaryPredicate1D visible prototypes-----------*/ + +int BinaryPredicate1D_Init( PyObject *module ); + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_BINARYPREDICATE1D_H */ diff --git a/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp b/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp new file mode 100644 index 00000000000..5c824981aa3 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp @@ -0,0 +1,262 @@ +#include "BPy_ContextFunctions.h" +#include "BPy_Convert.h" + +#include "../stroke/ContextFunctions.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------ MODULE FUNCTIONS ---------------------------------- + +static char ContextFunctions_GetTimeStampCF___doc__[] = +".. function:: GetTimeStampCF()\n" +"\n" +" Returns the system time stamp.\n" +"\n" +" :return: The system time stamp.\n" +" :rtype: int\n"; + +static PyObject * +ContextFunctions_GetTimeStampCF( PyObject* self ) +{ + return PyLong_FromLong( ContextFunctions::GetTimeStampCF() ); +} + +static char ContextFunctions_GetCanvasWidthCF___doc__[] = +".. method:: GetCanvasWidthCF()\n" +"\n" +" Returns the canvas width.\n" +"\n" +" :return: The canvas width.\n" +" :rtype: int\n"; + +static PyObject * +ContextFunctions_GetCanvasWidthCF( PyObject* self ) +{ + return PyLong_FromLong( ContextFunctions::GetCanvasWidthCF() ); +} + +static char ContextFunctions_GetCanvasHeightCF___doc__[] = +".. method:: GetCanvasHeightCF()\n" +"\n" +" Returns the canvas height.\n" +"\n" +" :return: The canvas height.\n" +" :rtype: int\n"; + +static PyObject * +ContextFunctions_GetCanvasHeightCF( PyObject* self ) +{ + return PyLong_FromLong( ContextFunctions::GetCanvasHeightCF() ); +} + +static char ContextFunctions_LoadMapCF___doc__[] = +".. function:: LoadMapCF(iFileName, iMapName, iNbLevels=4, iSigma=1.0)\n" +"\n" +" Loads an image map for further reading.\n" +"\n" +" :arg iFileName: The name of the image file.\n" +" :type iFileName: str\n" +" :arg iMapName: The name that will be used to access this image.\n" +" :type iMapName: str\n" +" :arg iNbLevels: The number of levels in the map pyramid\n" +" (default = 4). If iNbLevels == 0, the complete pyramid is\n" +" built.\n" +" :type iNbLevels: int\n" +" :arg iSigma: The sigma value of the gaussian function.\n" +" :type iSigma: float\n"; + +static PyObject * +ContextFunctions_LoadMapCF( PyObject *self, PyObject *args ) +{ + char *fileName, *mapName; + unsigned nbLevels; + float sigma; + + if( !PyArg_ParseTuple(args, "ssIf", &fileName, &mapName, &nbLevels, &sigma) ) + return NULL; + + ContextFunctions::LoadMapCF(fileName, mapName, nbLevels, sigma); + + Py_RETURN_NONE; +} + +static char ContextFunctions_ReadMapPixelCF___doc__[] = +".. function:: ReadMapPixelCF(iMapName, level, x, y)\n" +"\n" +" Reads a pixel in a user-defined map.\n" +"\n" +" :arg iMapName: The name of the map.\n" +" :type iMapName: str\n" +" :arg level: The level of the pyramid in which we wish to read the\n" +" pixel.\n" +" :type level: int\n" +" :arg x: The x coordinate of the pixel we wish to read. The origin\n" +" is in the lower-left corner.\n" +" :type x: int\n" +" :arg y: The y coordinate of the pixel we wish to read. The origin\n" +" is in the lower-left corner.\n" +" :type y: int\n" +" :return: The floating-point value stored for that pixel.\n" +" :rtype: float\n"; + +static PyObject * +ContextFunctions_ReadMapPixelCF( PyObject *self, PyObject *args ) +{ + char *mapName; + int level; + unsigned x, y; + + if( !PyArg_ParseTuple(args, "siII", &mapName, &level, &x, &y) ) + return NULL; + + float f = ContextFunctions::ReadMapPixelCF(mapName, level, x, y); + + return PyFloat_FromDouble( f ); +} + +static char ContextFunctions_ReadCompleteViewMapPixelCF___doc__[] = +".. function:: ReadCompleteViewMapPixelCF(level, x, y)\n" +"\n" +" Reads a pixel in the complete view map.\n" +"\n" +" :arg level: The level of the pyramid in which we wish to read the\n" +" pixel.\n" +" :type level: int\n" +" :arg x: The x coordinate of the pixel we wish to read. The origin\n" +" is in the lower-left corner.\n" +" :type x: int\n" +" :arg y: The y coordinate of the pixel we wish to read. The origin\n" +" is in the lower-left corner.\n" +" :type y: int\n" +" :return: The floating-point value stored for that pixel.\n" +" :rtype: float\n"; + +static PyObject * +ContextFunctions_ReadCompleteViewMapPixelCF( PyObject *self, PyObject *args ) +{ + int level; + unsigned x, y; + + if( !PyArg_ParseTuple(args, "iII", &level, &x, &y) ) + return NULL; + + float f = ContextFunctions::ReadCompleteViewMapPixelCF(level, x, y); + + return PyFloat_FromDouble( f ); +} + +static char ContextFunctions_ReadDirectionalViewMapPixelCF___doc__[] = +".. function:: ReadDirectionalViewMapPixelCF(iOrientation, level, x, y)\n" +"\n" +" Reads a pixel in one of the oriented view map images.\n" +"\n" +" :arg iOrientation: The number telling which orientation we want to\n" +" check.\n" +" :type iOrientation: int\n" +" :arg level: The level of the pyramid in which we wish to read the\n" +" pixel.\n" +" :type level: int\n" +" :arg x: The x coordinate of the pixel we wish to read. The origin\n" +" is in the lower-left corner.\n" +" :type x: int\n" +" :arg y: The y coordinate of the pixel we wish to read. The origin\n" +" is in the lower-left corner.\n" +" :type y: int\n" +" :return: The floating-point value stored for that pixel.\n" +" :rtype: float\n"; + +static PyObject * +ContextFunctions_ReadDirectionalViewMapPixelCF( PyObject *self, PyObject *args ) +{ + int orientation, level; + unsigned x, y; + + if( !PyArg_ParseTuple(args, "iiII", &orientation, &level, &x, &y) ) + return NULL; + + float f = ContextFunctions::ReadDirectionalViewMapPixelCF(orientation, level, x, y); + + return PyFloat_FromDouble( f ); +} + +static char ContextFunctions_GetSelectedFEdgeCF___doc__[] = +".. function:: GetSelectedFEdgeCF()\n" +"\n" +" Returns the selected FEdge.\n" +"\n" +" :return: The selected FEdge.\n" +" :rtype: :class:`FEdge`\n"; + +static PyObject * +ContextFunctions_GetSelectedFEdgeCF( PyObject *self ) +{ + FEdge *fe = ContextFunctions::GetSelectedFEdgeCF(); + if( fe ) + return Any_BPy_FEdge_from_FEdge( *fe ); + + Py_RETURN_NONE; +} + +/*-----------------------ContextFunctions module docstring-------------------------------*/ + +static char module_docstring[] = "The Blender Freestyle.ContextFunctions submodule\n\n"; + +/*-----------------------ContextFunctions module functions definitions-------------------*/ + +static PyMethodDef module_functions[] = { + {"GetTimeStampCF", (PyCFunction)ContextFunctions_GetTimeStampCF, METH_NOARGS, ContextFunctions_GetTimeStampCF___doc__}, + {"GetCanvasWidthCF", (PyCFunction)ContextFunctions_GetCanvasWidthCF, METH_NOARGS, ContextFunctions_GetCanvasWidthCF___doc__}, + {"GetCanvasHeightCF", (PyCFunction)ContextFunctions_GetCanvasHeightCF, METH_NOARGS, ContextFunctions_GetCanvasHeightCF___doc__}, + {"LoadMapCF", (PyCFunction)ContextFunctions_LoadMapCF, METH_VARARGS, ContextFunctions_LoadMapCF___doc__}, + {"ReadMapPixelCF", (PyCFunction)ContextFunctions_ReadMapPixelCF, METH_VARARGS, ContextFunctions_ReadMapPixelCF___doc__}, + {"ReadCompleteViewMapPixelCF", (PyCFunction)ContextFunctions_ReadCompleteViewMapPixelCF, METH_VARARGS, ContextFunctions_ReadCompleteViewMapPixelCF___doc__}, + {"ReadDirectionalViewMapPixelCF", (PyCFunction)ContextFunctions_ReadDirectionalViewMapPixelCF, METH_VARARGS, ContextFunctions_ReadDirectionalViewMapPixelCF___doc__}, + {"GetSelectedFEdgeCF", (PyCFunction)ContextFunctions_GetSelectedFEdgeCF, METH_NOARGS, ContextFunctions_GetSelectedFEdgeCF___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------ContextFunctions module definition--------------------------------*/ + +static PyModuleDef module_definition = { + PyModuleDef_HEAD_INIT, + "Freestyle.ContextFunctions", + module_docstring, + -1, + module_functions +}; + +//------------------- MODULE INITIALIZATION -------------------------------- + +int ContextFunctions_Init( PyObject *module ) +{ + PyObject *m, *d, *f; + + if( module == NULL ) + return -1; + + m = PyModule_Create(&module_definition); + if (m == NULL) + return -1; + Py_INCREF(m); + PyModule_AddObject(module, "ContextFunctions", m); + + // from ContextFunctions import * + d = PyModule_GetDict(m); + for (PyMethodDef *p = module_functions; p->ml_name; p++) { + f = PyDict_GetItemString(d, p->ml_name); + Py_INCREF(f); + PyModule_AddObject(module, p->ml_name, f); + } + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/BPy_ContextFunctions.h b/source/blender/freestyle/intern/python/BPy_ContextFunctions.h new file mode 100644 index 00000000000..fafeff3e974 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_ContextFunctions.h @@ -0,0 +1,18 @@ +#ifndef FREESTYLE_PYTHON_CONTEXTFUNCTIONS_H +#define FREESTYLE_PYTHON_CONTEXTFUNCTIONS_H + +#include <Python.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------Python BPy_ContextFunctions visible prototypes-----------*/ + +int ContextFunctions_Init( PyObject *module ); + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_CONTEXTFUNCTIONS_H */ diff --git a/source/blender/freestyle/intern/python/BPy_Convert.cpp b/source/blender/freestyle/intern/python/BPy_Convert.cpp new file mode 100644 index 00000000000..e3f979fea8f --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_Convert.cpp @@ -0,0 +1,609 @@ +#include "BPy_Convert.h" + +#include "BPy_BBox.h" +#include "BPy_FrsMaterial.h" +#include "BPy_Id.h" +#include "BPy_IntegrationType.h" +#include "BPy_Interface0D.h" +#include "Interface0D/BPy_CurvePoint.h" +#include "Interface0D/CurvePoint/BPy_StrokeVertex.h" +#include "Interface0D/BPy_SVertex.h" +#include "Interface0D/BPy_ViewVertex.h" +#include "Interface0D/ViewVertex/BPy_NonTVertex.h" +#include "Interface0D/ViewVertex/BPy_TVertex.h" +#include "BPy_Interface1D.h" +#include "Interface1D/BPy_FEdge.h" +#include "Interface1D/BPy_Stroke.h" +#include "Interface1D/BPy_ViewEdge.h" +#include "Interface1D/Curve/BPy_Chain.h" +#include "Interface1D/FEdge/BPy_FEdgeSharp.h" +#include "Interface1D/FEdge/BPy_FEdgeSmooth.h" +#include "BPy_Nature.h" +#include "BPy_MediumType.h" +#include "BPy_SShape.h" +#include "BPy_StrokeAttribute.h" +#include "BPy_ViewShape.h" + +#include "Iterator/BPy_AdjacencyIterator.h" +#include "Iterator/BPy_ChainPredicateIterator.h" +#include "Iterator/BPy_ChainSilhouetteIterator.h" +#include "Iterator/BPy_ChainingIterator.h" +#include "Iterator/BPy_CurvePointIterator.h" +#include "Iterator/BPy_Interface0DIterator.h" +#include "Iterator/BPy_SVertexIterator.h" +#include "Iterator/BPy_StrokeVertexIterator.h" +#include "Iterator/BPy_ViewEdgeIterator.h" +#include "Iterator/BPy_orientedViewEdgeIterator.h" + +#include "../stroke/StrokeRep.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/////////////////////////////////////////////////////////////////////////////////////////// + +//============================== +// C++ => Python +//============================== + + +PyObject * PyBool_from_bool( bool b ){ + return PyBool_FromLong( b ? 1 : 0); +} + + +PyObject * Vector_from_Vec2f( Vec2f& vec ) { + float vec_data[2]; // because vec->_coord is protected + + vec_data[0] = vec.x(); vec_data[1] = vec.y(); + return newVectorObject( vec_data, 2, Py_NEW, NULL); +} + +PyObject * Vector_from_Vec3f( Vec3f& vec ) { + float vec_data[3]; // because vec->_coord is protected + + vec_data[0] = vec.x(); vec_data[1] = vec.y(); vec_data[2] = vec.z(); + return newVectorObject( vec_data, 3, Py_NEW, NULL); +} + +PyObject * Vector_from_Vec3r( Vec3r& vec ) { + float vec_data[3]; // because vec->_coord is protected + + vec_data[0] = vec.x(); vec_data[1] = vec.y(); vec_data[2] = vec.z(); + return newVectorObject( vec_data, 3, Py_NEW, NULL); +} + +PyObject * BPy_Id_from_Id( Id& id ) { + PyObject *py_id = Id_Type.tp_new( &Id_Type, 0, 0 ); + ((BPy_Id *) py_id)->id = new Id( id.getFirst(), id.getSecond() ); + + return py_id; +} + +PyObject * Any_BPy_Interface0D_from_Interface0D( Interface0D& if0D ) { + if (typeid(if0D) == typeid(CurvePoint)) { + return BPy_CurvePoint_from_CurvePoint(dynamic_cast<CurvePoint&>(if0D)); + } else if (typeid(if0D) == typeid(StrokeVertex)) { + return BPy_StrokeVertex_from_StrokeVertex(dynamic_cast<StrokeVertex&>(if0D)); + } else if (typeid(if0D) == typeid(SVertex)) { + return BPy_SVertex_from_SVertex(dynamic_cast<SVertex&>(if0D)); + } else if (typeid(if0D) == typeid(ViewVertex)) { + return BPy_ViewVertex_from_ViewVertex(dynamic_cast<ViewVertex&>(if0D)); + } else if (typeid(if0D) == typeid(NonTVertex)) { + return BPy_NonTVertex_from_NonTVertex(dynamic_cast<NonTVertex&>(if0D)); + } else if (typeid(if0D) == typeid(TVertex)) { + return BPy_TVertex_from_TVertex(dynamic_cast<TVertex&>(if0D)); + } else if (typeid(if0D) == typeid(Interface0D)) { + return BPy_Interface0D_from_Interface0D(if0D); + } + string msg("unexpected type: " + if0D.getExactTypeName()); + PyErr_SetString(PyExc_TypeError, msg.c_str()); + return NULL; +} + +PyObject * Any_BPy_Interface1D_from_Interface1D( Interface1D& if1D ) { + if (typeid(if1D) == typeid(ViewEdge)) { + return BPy_ViewEdge_from_ViewEdge(dynamic_cast<ViewEdge&>(if1D)); + } else if (typeid(if1D) == typeid(Chain)) { + return BPy_Chain_from_Chain(dynamic_cast<Chain&>(if1D)); + } else if (typeid(if1D) == typeid(Stroke)) { + return BPy_Stroke_from_Stroke(dynamic_cast<Stroke&>(if1D)); + } else if (typeid(if1D) == typeid(FEdgeSharp)) { + return BPy_FEdgeSharp_from_FEdgeSharp(dynamic_cast<FEdgeSharp&>(if1D)); + } else if (typeid(if1D) == typeid(FEdgeSmooth)) { + return BPy_FEdgeSmooth_from_FEdgeSmooth(dynamic_cast<FEdgeSmooth&>(if1D)); + } else if (typeid(if1D) == typeid(FEdge)) { + return BPy_FEdge_from_FEdge(dynamic_cast<FEdge&>(if1D)); + } else if (typeid(if1D) == typeid(Interface1D)) { + return BPy_Interface1D_from_Interface1D( if1D ); + } + string msg("unexpected type: " + if1D.getExactTypeName()); + PyErr_SetString(PyExc_TypeError, msg.c_str()); + return NULL; +} + +PyObject * Any_BPy_FEdge_from_FEdge( FEdge& fe ) { + if (typeid(fe) == typeid(FEdgeSharp)) { + return BPy_FEdgeSharp_from_FEdgeSharp( dynamic_cast<FEdgeSharp&>(fe) ); + } else if (typeid(fe) == typeid(FEdgeSmooth)) { + return BPy_FEdgeSmooth_from_FEdgeSmooth( dynamic_cast<FEdgeSmooth&>(fe) ); + } else if (typeid(fe) == typeid(FEdge)) { + return BPy_FEdge_from_FEdge( fe ); + } + string msg("unexpected type: " + fe.getExactTypeName()); + PyErr_SetString(PyExc_TypeError, msg.c_str()); + return NULL; +} + +PyObject * Any_BPy_ViewVertex_from_ViewVertex( ViewVertex& vv ) { + if (typeid(vv) == typeid(NonTVertex)) { + return BPy_NonTVertex_from_NonTVertex( dynamic_cast<NonTVertex&>(vv) ); + } else if (typeid(vv) == typeid(TVertex)) { + return BPy_TVertex_from_TVertex( dynamic_cast<TVertex&>(vv) ); + } else if (typeid(vv) == typeid(ViewVertex)) { + return BPy_ViewVertex_from_ViewVertex( vv ); + } + string msg("unexpected type: " + vv.getExactTypeName()); + PyErr_SetString(PyExc_TypeError, msg.c_str()); + return NULL; +} + +PyObject * BPy_Interface0D_from_Interface0D( Interface0D& if0D ) { + PyObject *py_if0D = Interface0D_Type.tp_new( &Interface0D_Type, 0, 0 ); + ((BPy_Interface0D *) py_if0D)->if0D = &if0D; + ((BPy_Interface0D *) py_if0D)->borrowed = 1; + + return py_if0D; +} + +PyObject * BPy_Interface1D_from_Interface1D( Interface1D& if1D ) { + PyObject *py_if1D = Interface1D_Type.tp_new( &Interface1D_Type, 0, 0 ); + ((BPy_Interface1D *) py_if1D)->if1D = &if1D; + ((BPy_Interface1D *) py_if1D)->borrowed = 1; + + return py_if1D; +} + +PyObject * BPy_SVertex_from_SVertex( SVertex& sv ) { + PyObject *py_sv = SVertex_Type.tp_new( &SVertex_Type, 0, 0 ); + ((BPy_SVertex *) py_sv)->sv = &sv; + ((BPy_SVertex *) py_sv)->py_if0D.if0D = ((BPy_SVertex *) py_sv)->sv; + ((BPy_SVertex *) py_sv)->py_if0D.borrowed = 1; + + return py_sv; +} + +PyObject * BPy_FEdgeSharp_from_FEdgeSharp( FEdgeSharp& fes ) { + PyObject *py_fe = FEdgeSharp_Type.tp_new( &FEdgeSharp_Type, 0, 0 ); + ((BPy_FEdgeSharp *) py_fe)->fes = &fes; + ((BPy_FEdgeSharp *) py_fe)->py_fe.fe = ((BPy_FEdgeSharp *) py_fe)->fes; + ((BPy_FEdgeSharp *) py_fe)->py_fe.py_if1D.if1D = ((BPy_FEdgeSharp *) py_fe)->fes; + ((BPy_FEdgeSharp *) py_fe)->py_fe.py_if1D.borrowed = 1; + + return py_fe; +} + +PyObject * BPy_FEdgeSmooth_from_FEdgeSmooth( FEdgeSmooth& fes ) { + PyObject *py_fe = FEdgeSmooth_Type.tp_new( &FEdgeSmooth_Type, 0, 0 ); + ((BPy_FEdgeSmooth *) py_fe)->fes = &fes; + ((BPy_FEdgeSmooth *) py_fe)->py_fe.fe = ((BPy_FEdgeSmooth *) py_fe)->fes; + ((BPy_FEdgeSmooth *) py_fe)->py_fe.py_if1D.if1D = ((BPy_FEdgeSmooth *) py_fe)->fes; + ((BPy_FEdgeSmooth *) py_fe)->py_fe.py_if1D.borrowed = 1; + + return py_fe; +} + +PyObject * BPy_FEdge_from_FEdge( FEdge& fe ) { + PyObject *py_fe = FEdge_Type.tp_new( &FEdge_Type, 0, 0 ); + ((BPy_FEdge *) py_fe)->fe = &fe; + ((BPy_FEdge *) py_fe)->py_if1D.if1D = ((BPy_FEdge *) py_fe)->fe; + ((BPy_FEdge *) py_fe)->py_if1D.borrowed = 1; + + return py_fe; +} + +PyObject * BPy_Nature_from_Nature( unsigned short n ) { + PyObject *py_n; + + PyObject *args = PyTuple_New(1); + PyTuple_SetItem( args, 0, PyLong_FromLong(n) ); + py_n = Nature_Type.tp_new(&Nature_Type, args, NULL); + Py_DECREF(args); + + return py_n; +} + +PyObject * BPy_Stroke_from_Stroke( Stroke& s ) { + PyObject *py_s = Stroke_Type.tp_new( &Stroke_Type, 0, 0 ); + ((BPy_Stroke *) py_s)->s = &s; + ((BPy_Stroke *) py_s)->py_if1D.if1D = ((BPy_Stroke *) py_s)->s; + ((BPy_Stroke *) py_s)->py_if1D.borrowed = 1; + + return py_s; +} + +PyObject * BPy_StrokeAttribute_from_StrokeAttribute( StrokeAttribute& sa ) { + PyObject *py_sa = StrokeAttribute_Type.tp_new( &StrokeAttribute_Type, 0, 0 ); + ((BPy_StrokeAttribute *) py_sa)->sa = &sa; + ((BPy_StrokeAttribute *) py_sa)->borrowed = 1; + return py_sa; +} + +PyObject * BPy_MediumType_from_MediumType( Stroke::MediumType n ) { + PyObject *py_mt; + + PyObject *args = PyTuple_New(1); + PyTuple_SetItem( args, 0, PyLong_FromLong(n) ); + py_mt = MediumType_Type.tp_new( &MediumType_Type, args, NULL ); + Py_DECREF(args); + + return py_mt; +} + +PyObject * BPy_StrokeVertex_from_StrokeVertex( StrokeVertex& sv ) { + PyObject *py_sv = StrokeVertex_Type.tp_new( &StrokeVertex_Type, 0, 0 ); + ((BPy_StrokeVertex *) py_sv)->sv = &sv; + ((BPy_StrokeVertex *) py_sv)->py_cp.cp = ((BPy_StrokeVertex *) py_sv)->sv; + ((BPy_StrokeVertex *) py_sv)->py_cp.py_if0D.if0D = ((BPy_StrokeVertex *) py_sv)->sv; + ((BPy_StrokeVertex *) py_sv)->py_cp.py_if0D.borrowed = 1; + + return py_sv; +} + +PyObject * BPy_ViewVertex_from_ViewVertex( ViewVertex& vv ) { + PyObject *py_vv = ViewVertex_Type.tp_new( &ViewVertex_Type, 0, 0 ); + ((BPy_ViewVertex *) py_vv)->vv = &vv; + ((BPy_ViewVertex *) py_vv)->py_if0D.if0D = ((BPy_ViewVertex *) py_vv)->vv; + ((BPy_ViewVertex *) py_vv)->py_if0D.borrowed = 1; + + return py_vv; +} + +PyObject * BPy_NonTVertex_from_NonTVertex( NonTVertex& ntv ) { + PyObject *py_ntv = NonTVertex_Type.tp_new( &NonTVertex_Type, 0, 0 ); + ((BPy_NonTVertex *) py_ntv)->ntv = &ntv; + ((BPy_NonTVertex *) py_ntv)->py_vv.vv = ((BPy_NonTVertex *) py_ntv)->ntv; + ((BPy_NonTVertex *) py_ntv)->py_vv.py_if0D.if0D = ((BPy_NonTVertex *) py_ntv)->ntv; + ((BPy_NonTVertex *) py_ntv)->py_vv.py_if0D.borrowed = 1; + + return py_ntv; +} + +PyObject * BPy_TVertex_from_TVertex( TVertex& tv ) { + PyObject *py_tv = TVertex_Type.tp_new( &TVertex_Type, 0, 0 ); + ((BPy_TVertex *) py_tv)->tv = &tv; + ((BPy_TVertex *) py_tv)->py_vv.vv = ((BPy_TVertex *) py_tv)->tv; + ((BPy_TVertex *) py_tv)->py_vv.py_if0D.if0D = ((BPy_TVertex *) py_tv)->tv; + ((BPy_TVertex *) py_tv)->py_vv.py_if0D.borrowed = 1; + + return py_tv; +} + +PyObject * BPy_BBox_from_BBox( BBox< Vec3r > &bb ) { + PyObject *py_bb = BBox_Type.tp_new( &BBox_Type, 0, 0 ); + ((BPy_BBox *) py_bb)->bb = new BBox< Vec3r >( bb ); + + return py_bb; +} + +PyObject * BPy_ViewEdge_from_ViewEdge( ViewEdge& ve ) { + PyObject *py_ve = ViewEdge_Type.tp_new( &ViewEdge_Type, 0, 0 ); + ((BPy_ViewEdge *) py_ve)->ve = &ve; + ((BPy_ViewEdge *) py_ve)->py_if1D.if1D = ((BPy_ViewEdge *) py_ve)->ve; + ((BPy_ViewEdge *) py_ve)->py_if1D.borrowed = 1; + + return py_ve; +} + +PyObject * BPy_Chain_from_Chain( Chain& c ) { + PyObject *py_c = Chain_Type.tp_new( &Chain_Type, 0, 0 ); + ((BPy_Chain *) py_c)->c = &c; + ((BPy_Chain *) py_c)->py_c.c = ((BPy_Chain *) py_c)->c; + ((BPy_Chain *) py_c)->py_c.py_if1D.if1D = ((BPy_Chain *) py_c)->c; + ((BPy_Chain *) py_c)->py_c.py_if1D.borrowed = 1; + return py_c; +} + +PyObject * BPy_SShape_from_SShape( SShape& ss ) { + PyObject *py_ss = SShape_Type.tp_new( &SShape_Type, 0, 0 ); + ((BPy_SShape *) py_ss)->ss = &ss; + ((BPy_SShape *) py_ss)->borrowed = 1; + + return py_ss; +} + +PyObject * BPy_ViewShape_from_ViewShape( ViewShape& vs ) { + PyObject *py_vs = ViewShape_Type.tp_new( &ViewShape_Type, 0, 0 ); + ((BPy_ViewShape *) py_vs)->vs = &vs; + ((BPy_ViewShape *) py_vs)->borrowed = 1; + + return py_vs; +} + +PyObject * BPy_FrsMaterial_from_FrsMaterial( FrsMaterial& m ){ + PyObject *py_m = FrsMaterial_Type.tp_new( &FrsMaterial_Type, 0, 0 ); + ((BPy_FrsMaterial*) py_m)->m = &m; + ((BPy_FrsMaterial*) py_m)->borrowed = 1; + + return py_m; +} + +PyObject * BPy_IntegrationType_from_IntegrationType( IntegrationType i ) { + PyObject *py_it; + + PyObject *args = PyTuple_New(1); + PyTuple_SetItem( args, 0, PyLong_FromLong(i) ); + py_it = IntegrationType_Type.tp_new( &IntegrationType_Type, args, NULL ); + Py_DECREF(args); + + return py_it; +} + +PyObject * BPy_CurvePoint_from_CurvePoint( CurvePoint& cp ) { + PyObject *py_cp = CurvePoint_Type.tp_new( &CurvePoint_Type, 0, 0 ); + ((BPy_CurvePoint*) py_cp)->cp = &cp; + ((BPy_CurvePoint*) py_cp)->py_if0D.if0D = ((BPy_CurvePoint*) py_cp)->cp; + ((BPy_CurvePoint*) py_cp)->py_if0D.borrowed = 1; + + return py_cp; +} + +PyObject * BPy_directedViewEdge_from_directedViewEdge( ViewVertex::directedViewEdge& dve ) { + PyObject *py_dve = PyTuple_New(2); + + PyTuple_SetItem( py_dve, 0, BPy_ViewEdge_from_ViewEdge(*(dve.first)) ); + PyTuple_SetItem( py_dve, 1, PyBool_from_bool(dve.second) ); + + return py_dve; +} + +//============================== +// Iterators +//============================== + +PyObject * BPy_AdjacencyIterator_from_AdjacencyIterator( AdjacencyIterator& a_it ) { + PyObject *py_a_it = AdjacencyIterator_Type.tp_new( &AdjacencyIterator_Type, 0, 0 ); + ((BPy_AdjacencyIterator *) py_a_it)->a_it = new AdjacencyIterator( a_it ); + ((BPy_AdjacencyIterator *) py_a_it)->py_it.it = ((BPy_AdjacencyIterator *) py_a_it)->a_it; + + return py_a_it; +} + +PyObject * BPy_Interface0DIterator_from_Interface0DIterator( Interface0DIterator& if0D_it, int reversed ) { + PyObject *py_if0D_it = Interface0DIterator_Type.tp_new( &Interface0DIterator_Type, 0, 0 ); + ((BPy_Interface0DIterator *) py_if0D_it)->if0D_it = new Interface0DIterator( if0D_it ); + ((BPy_Interface0DIterator *) py_if0D_it)->py_it.it = ((BPy_Interface0DIterator *) py_if0D_it)->if0D_it; + ((BPy_Interface0DIterator *) py_if0D_it)->reversed = reversed; + + return py_if0D_it; +} + +PyObject * BPy_CurvePointIterator_from_CurvePointIterator( CurveInternal::CurvePointIterator& cp_it ) { + PyObject *py_cp_it = CurvePointIterator_Type.tp_new( &CurvePointIterator_Type, 0, 0 ); + ((BPy_CurvePointIterator *) py_cp_it)->cp_it = new CurveInternal::CurvePointIterator( cp_it ); + ((BPy_CurvePointIterator *) py_cp_it)->py_it.it = ((BPy_CurvePointIterator *) py_cp_it)->cp_it; + + return py_cp_it; +} + +PyObject * BPy_StrokeVertexIterator_from_StrokeVertexIterator( StrokeInternal::StrokeVertexIterator& sv_it, int reversed) { + PyObject *py_sv_it = StrokeVertexIterator_Type.tp_new( &StrokeVertexIterator_Type, 0, 0 ); + ((BPy_StrokeVertexIterator *) py_sv_it)->sv_it = new StrokeInternal::StrokeVertexIterator( sv_it ); + ((BPy_StrokeVertexIterator *) py_sv_it)->py_it.it = ((BPy_StrokeVertexIterator *) py_sv_it)->sv_it; + ((BPy_StrokeVertexIterator *) py_sv_it)->reversed = reversed; + + return py_sv_it; +} + +PyObject * BPy_SVertexIterator_from_SVertexIterator( ViewEdgeInternal::SVertexIterator& sv_it ) { + PyObject *py_sv_it = SVertexIterator_Type.tp_new( &SVertexIterator_Type, 0, 0 ); + ((BPy_SVertexIterator *) py_sv_it)->sv_it = new ViewEdgeInternal::SVertexIterator( sv_it ); + ((BPy_SVertexIterator *) py_sv_it)->py_it.it = ((BPy_SVertexIterator *) py_sv_it)->sv_it; + + return py_sv_it; +} + + +PyObject * BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator( ViewVertexInternal::orientedViewEdgeIterator& ove_it, int reversed ) { + PyObject *py_ove_it = orientedViewEdgeIterator_Type.tp_new( &orientedViewEdgeIterator_Type, 0, 0 ); + ((BPy_orientedViewEdgeIterator *) py_ove_it)->ove_it = new ViewVertexInternal::orientedViewEdgeIterator( ove_it ); + ((BPy_orientedViewEdgeIterator *) py_ove_it)->py_it.it = ((BPy_orientedViewEdgeIterator *) py_ove_it)->ove_it; + ((BPy_orientedViewEdgeIterator *) py_ove_it)->reversed = reversed; + + return py_ove_it; +} + +PyObject * BPy_ViewEdgeIterator_from_ViewEdgeIterator( ViewEdgeInternal::ViewEdgeIterator& ve_it ) { + PyObject *py_ve_it = ViewEdgeIterator_Type.tp_new( &ViewEdgeIterator_Type, 0, 0 ); + ((BPy_ViewEdgeIterator *) py_ve_it)->ve_it = new ViewEdgeInternal::ViewEdgeIterator( ve_it ); + ((BPy_ViewEdgeIterator *) py_ve_it)->py_it.it = ((BPy_ViewEdgeIterator *) py_ve_it)->ve_it; + + return py_ve_it; +} + +PyObject * BPy_ChainingIterator_from_ChainingIterator( ChainingIterator& c_it ) { + PyObject *py_c_it = ChainingIterator_Type.tp_new( &ChainingIterator_Type, 0, 0 ); + ((BPy_ChainingIterator *) py_c_it)->c_it = new ChainingIterator( c_it ); + ((BPy_ChainingIterator *) py_c_it)->py_ve_it.py_it.it = ((BPy_ChainingIterator *) py_c_it)->c_it; + + return py_c_it; +} + +PyObject * BPy_ChainPredicateIterator_from_ChainPredicateIterator( ChainPredicateIterator& cp_it ) { + PyObject *py_cp_it = ChainPredicateIterator_Type.tp_new( &ChainPredicateIterator_Type, 0, 0 ); + ((BPy_ChainPredicateIterator *) py_cp_it)->cp_it = new ChainPredicateIterator( cp_it ); + ((BPy_ChainPredicateIterator *) py_cp_it)->py_c_it.py_ve_it.py_it.it = ((BPy_ChainPredicateIterator *) py_cp_it)->cp_it; + + return py_cp_it; +} + +PyObject * BPy_ChainSilhouetteIterator_from_ChainSilhouetteIterator( ChainSilhouetteIterator& cs_it ) { + PyObject *py_cs_it = ChainSilhouetteIterator_Type.tp_new( &ChainSilhouetteIterator_Type, 0, 0 ); + ((BPy_ChainSilhouetteIterator *) py_cs_it)->cs_it = new ChainSilhouetteIterator( cs_it ); + ((BPy_ChainSilhouetteIterator *) py_cs_it)->py_c_it.py_ve_it.py_it.it = ((BPy_ChainSilhouetteIterator *) py_cs_it)->cs_it; + + return py_cs_it; +} + + +//============================== +// Python => C++ +//============================== + +bool bool_from_PyBool( PyObject *b ) { + return PyObject_IsTrue(b) != 0; +} + +IntegrationType IntegrationType_from_BPy_IntegrationType( PyObject* obj ) { + return static_cast<IntegrationType>( PyLong_AsLong(obj) ); +} + +Stroke::MediumType MediumType_from_BPy_MediumType( PyObject* obj ) { + return static_cast<Stroke::MediumType>( PyLong_AsLong(obj) ); +} + +Nature::EdgeNature EdgeNature_from_BPy_Nature( PyObject* obj ) { + return static_cast<Nature::EdgeNature>( PyLong_AsLong(obj) ); +} + +Vec2f * Vec2f_ptr_from_PyObject( PyObject* obj ) { + Vec2f *v; + if( (v = Vec2f_ptr_from_Vector( obj )) ) + return v; + if( (v = Vec2f_ptr_from_PyList( obj )) ) + return v; + if( (v = Vec2f_ptr_from_PyTuple( obj )) ) + return v; + return NULL; +} + +Vec3f * Vec3f_ptr_from_PyObject( PyObject* obj ) { + Vec3f *v; + if( (v = Vec3f_ptr_from_Vector( obj )) ) + return v; + if( (v = Vec3f_ptr_from_PyList( obj )) ) + return v; + if( (v = Vec3f_ptr_from_PyTuple( obj )) ) + return v; + return NULL; +} + +Vec3r * Vec3r_ptr_from_PyObject( PyObject* obj ) { + Vec3r *v; + if( (v = Vec3r_ptr_from_Vector( obj )) ) + return v; + if( (v = Vec3r_ptr_from_PyList( obj )) ) + return v; + if( (v = Vec3r_ptr_from_PyTuple( obj )) ) + return v; + return NULL; +} + +Vec2f * Vec2f_ptr_from_Vector( PyObject* obj ) { + PyObject *v; + if (!VectorObject_Check(obj) || ((VectorObject *)obj)->size != 2) + return NULL; + v = PyObject_GetAttrString(obj,"x"); + float x = PyFloat_AsDouble( v ); + Py_DECREF( v ); + v = PyObject_GetAttrString(obj,"y"); + float y = PyFloat_AsDouble( v ); + Py_DECREF( v ); + + return new Vec2f(x,y); +} + +Vec3f * Vec3f_ptr_from_Vector( PyObject* obj ) { + PyObject *v; + if (!VectorObject_Check(obj) || ((VectorObject *)obj)->size != 3) + return NULL; + v = PyObject_GetAttrString(obj,"x"); + float x = PyFloat_AsDouble( v ); + Py_DECREF( v ); + v = PyObject_GetAttrString(obj,"y"); + float y = PyFloat_AsDouble( v ); + Py_DECREF( v ); + v = PyObject_GetAttrString(obj,"z"); + float z = PyFloat_AsDouble( v ); + Py_DECREF( v ); + + return new Vec3f(x,y,z); +} + +Vec3r * Vec3r_ptr_from_Vector( PyObject* obj ) { + PyObject *v; + if (!VectorObject_Check(obj) || ((VectorObject *)obj)->size != 3) + return NULL; + v = PyObject_GetAttrString(obj,"x"); + double x = PyFloat_AsDouble( v ); + Py_DECREF( v ); + v = PyObject_GetAttrString(obj,"y"); + double y = PyFloat_AsDouble( v ); + Py_DECREF( v ); + v = PyObject_GetAttrString(obj,"z"); + double z = PyFloat_AsDouble( v ); + Py_DECREF( v ); + + return new Vec3r(x,y,z); +} + +Vec2f * Vec2f_ptr_from_PyList( PyObject* obj ) { + if( !PyList_Check(obj) || PyList_Size(obj) != 2 ) + return NULL; + float x = PyFloat_AsDouble(PyList_GetItem(obj, 0)); + float y = PyFloat_AsDouble(PyList_GetItem(obj, 1)); + return new Vec2f(x,y); +} + +Vec3f * Vec3f_ptr_from_PyList( PyObject* obj ) { + if( !PyList_Check(obj) || PyList_Size(obj) != 3 ) + return NULL; + float x = PyFloat_AsDouble(PyList_GetItem(obj, 0)); + float y = PyFloat_AsDouble(PyList_GetItem(obj, 1)); + float z = PyFloat_AsDouble(PyList_GetItem(obj, 2)); + return new Vec3f(x,y,z); +} + +Vec3r * Vec3r_ptr_from_PyList( PyObject* obj ) { + if( !PyList_Check(obj) || PyList_Size(obj) != 3 ) + return NULL; + float x = PyFloat_AsDouble(PyList_GetItem(obj, 0)); + float y = PyFloat_AsDouble(PyList_GetItem(obj, 1)); + float z = PyFloat_AsDouble(PyList_GetItem(obj, 2)); + return new Vec3r(x,y,z); +} + +Vec2f * Vec2f_ptr_from_PyTuple( PyObject* obj ) { + if( !PyTuple_Check(obj) || PyTuple_Size(obj) != 2 ) + return NULL; + float x = PyFloat_AsDouble(PyTuple_GetItem(obj, 0)); + float y = PyFloat_AsDouble(PyTuple_GetItem(obj, 1)); + return new Vec2f(x,y); +} + +Vec3f * Vec3f_ptr_from_PyTuple( PyObject* obj ) { + if( !PyTuple_Check(obj) || PyTuple_Size(obj) != 3 ) + return NULL; + float x = PyFloat_AsDouble(PyTuple_GetItem(obj, 0)); + float y = PyFloat_AsDouble(PyTuple_GetItem(obj, 1)); + float z = PyFloat_AsDouble(PyTuple_GetItem(obj, 2)); + return new Vec3f(x,y,z); +} + +Vec3r * Vec3r_ptr_from_PyTuple( PyObject* obj ) { + if( !PyTuple_Check(obj) || PyTuple_Size(obj) != 3 ) + return NULL; + float x = PyFloat_AsDouble(PyTuple_GetItem(obj, 0)); + float y = PyFloat_AsDouble(PyTuple_GetItem(obj, 1)); + float z = PyFloat_AsDouble(PyTuple_GetItem(obj, 2)); + return new Vec3r(x,y,z); +} + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/BPy_Convert.h b/source/blender/freestyle/intern/python/BPy_Convert.h new file mode 100644 index 00000000000..7e4e07472d8 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_Convert.h @@ -0,0 +1,147 @@ +#ifndef FREESTYLE_PYTHON_CONVERT_H +#define FREESTYLE_PYTHON_CONVERT_H + +#include <Python.h> +#include <typeinfo> + +#include "../geometry/Geom.h" +using namespace Geometry; + +// BBox +#include "../geometry/BBox.h" + +// FEdge, FEdgeSharp, FEdgeSmooth, SShape, SVertex, FEdgeInternal::SVertexIterator +#include "../view_map/Silhouette.h" + +// Id +#include "../system/Id.h" + +// Interface0D, Interface0DIteratorNested, Interface0DIterator +#include "../view_map/Interface0D.h" + +// Interface1D +#include "../view_map/Interface1D.h" + +// FrsMaterial +#include "../scene_graph/FrsMaterial.h" + +// Nature::VertexNature, Nature::EdgeNature +#include "../winged_edge/Nature.h" + +// Stroke, StrokeAttribute, StrokeVertex +#include "../stroke/Stroke.h" + +// NonTVertex, TVertex, ViewEdge, ViewMap, ViewShape, ViewVertex +#include "../view_map/ViewMap.h" + +// CurvePoint, Curve +#include "../stroke/Curve.h" + +// Chain +#include "../stroke/Chain.h" + +//====== ITERATORS + +// AdjacencyIterator, ChainingIterator, ChainSilhouetteIterator, ChainPredicateIterator +#include "../stroke/ChainingIterators.h" + +// ViewVertexInternal::orientedViewEdgeIterator +// ViewEdgeInternal::SVertexIterator +// ViewEdgeInternal::ViewEdgeIterator +#include "../view_map/ViewMapIterators.h" + +// StrokeInternal::StrokeVertexIterator +#include "../stroke/StrokeIterators.h" + +// CurveInternal::CurvePointIterator +#include "../stroke/CurveIterators.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include "generic/mathutils.h" + +//============================== +// C++ => Python +//============================== + +PyObject * PyBool_from_bool( bool b ); +PyObject * Vector_from_Vec2f( Vec2f& v ); +PyObject * Vector_from_Vec3f( Vec3f& v ); +PyObject * Vector_from_Vec3r( Vec3r& v ); + +PyObject * Any_BPy_Interface0D_from_Interface0D( Interface0D& if0D ); +PyObject * Any_BPy_Interface1D_from_Interface1D( Interface1D& if1D ); +PyObject * Any_BPy_FEdge_from_FEdge( FEdge& fe ); +PyObject * Any_BPy_ViewVertex_from_ViewVertex( ViewVertex& vv ); + +PyObject * BPy_BBox_from_BBox( BBox< Vec3r > &bb ); +PyObject * BPy_CurvePoint_from_CurvePoint( CurvePoint& cp ); +PyObject * BPy_directedViewEdge_from_directedViewEdge( ViewVertex::directedViewEdge& dve ); +PyObject * BPy_FEdge_from_FEdge( FEdge& fe ); +PyObject * BPy_FEdgeSharp_from_FEdgeSharp( FEdgeSharp& fes ); +PyObject * BPy_FEdgeSmooth_from_FEdgeSmooth( FEdgeSmooth& fes ); +PyObject * BPy_Id_from_Id( Id& id ); +PyObject * BPy_Interface0D_from_Interface0D( Interface0D& if0D ); +PyObject * BPy_Interface1D_from_Interface1D( Interface1D& if1D ); +PyObject * BPy_IntegrationType_from_IntegrationType( IntegrationType i ); +PyObject * BPy_FrsMaterial_from_FrsMaterial( FrsMaterial& m ); +PyObject * BPy_Nature_from_Nature( unsigned short n ); +PyObject * BPy_MediumType_from_MediumType( Stroke::MediumType n ); +PyObject * BPy_SShape_from_SShape( SShape& ss ); +PyObject * BPy_Stroke_from_Stroke( Stroke& s ); +PyObject * BPy_StrokeAttribute_from_StrokeAttribute( StrokeAttribute& sa ); +PyObject * BPy_StrokeVertex_from_StrokeVertex( StrokeVertex& sv ); +PyObject * BPy_SVertex_from_SVertex( SVertex& sv ); +PyObject * BPy_ViewVertex_from_ViewVertex( ViewVertex& vv ); +PyObject * BPy_NonTVertex_from_NonTVertex( NonTVertex& ntv ); +PyObject * BPy_TVertex_from_TVertex( TVertex& tv ); +PyObject * BPy_ViewEdge_from_ViewEdge( ViewEdge& ve ); +PyObject * BPy_Chain_from_Chain( Chain& c ); +PyObject * BPy_ViewShape_from_ViewShape( ViewShape& vs ); + +PyObject * BPy_AdjacencyIterator_from_AdjacencyIterator( AdjacencyIterator& a_it ); +PyObject * BPy_Interface0DIterator_from_Interface0DIterator( Interface0DIterator& if0D_it, int reversed ); +PyObject * BPy_CurvePointIterator_from_CurvePointIterator( CurveInternal::CurvePointIterator& cp_it ); +PyObject * BPy_StrokeVertexIterator_from_StrokeVertexIterator( StrokeInternal::StrokeVertexIterator& sv_it, int reversed); +PyObject * BPy_SVertexIterator_from_SVertexIterator( ViewEdgeInternal::SVertexIterator& sv_it ); +PyObject * BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator( ViewVertexInternal::orientedViewEdgeIterator& ove_it, int reversed ); +PyObject * BPy_ViewEdgeIterator_from_ViewEdgeIterator( ViewEdgeInternal::ViewEdgeIterator& ve_it ); +PyObject * BPy_ChainingIterator_from_ChainingIterator( ChainingIterator& c_it ); +PyObject * BPy_ChainPredicateIterator_from_ChainPredicateIterator( ChainPredicateIterator& cp_it ); +PyObject * BPy_ChainSilhouetteIterator_from_ChainSilhouetteIterator( ChainSilhouetteIterator& cs_it ); + +//============================== +// Python => C++ +//============================== + +bool bool_from_PyBool( PyObject *b ); +IntegrationType IntegrationType_from_BPy_IntegrationType( PyObject* obj ); +Stroke::MediumType MediumType_from_BPy_MediumType( PyObject* obj ); +Nature::EdgeNature EdgeNature_from_BPy_Nature( PyObject* obj ); +Vec2f * Vec2f_ptr_from_PyObject( PyObject* obj ); +Vec3f * Vec3f_ptr_from_PyObject( PyObject* obj ); +Vec3r * Vec3r_ptr_from_PyObject( PyObject* obj ); +Vec2f * Vec2f_ptr_from_Vector( PyObject* obj ); +Vec3f * Vec3f_ptr_from_Vector( PyObject* obj ); +Vec3r * Vec3r_ptr_from_Vector( PyObject* obj ); +Vec2f * Vec2f_ptr_from_PyList( PyObject* obj ); +Vec3f * Vec3f_ptr_from_PyList( PyObject* obj ); +Vec3r * Vec3r_ptr_from_PyList( PyObject* obj ); +Vec2f * Vec2f_ptr_from_PyTuple( PyObject* obj ); +Vec3f * Vec3f_ptr_from_PyTuple( PyObject* obj ); +Vec3r * Vec3r_ptr_from_PyTuple( PyObject* obj ); + + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_CONVERT_H */ diff --git a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp new file mode 100644 index 00000000000..082ca32ddc7 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp @@ -0,0 +1,125 @@ +#include "BPy_Freestyle.h" + +#include "BPy_BBox.h" +#include "BPy_BinaryPredicate0D.h" +#include "BPy_BinaryPredicate1D.h" +#include "BPy_ContextFunctions.h" +#include "BPy_FrsMaterial.h" +#include "BPy_FrsNoise.h" +#include "BPy_Id.h" +#include "BPy_IntegrationType.h" +#include "BPy_Interface0D.h" +#include "BPy_Interface1D.h" +#include "BPy_Iterator.h" +#include "BPy_MediumType.h" +#include "BPy_Nature.h" +#include "BPy_Operators.h" +#include "BPy_SShape.h" +#include "BPy_StrokeAttribute.h" +#include "BPy_StrokeShader.h" +#include "BPy_UnaryFunction0D.h" +#include "BPy_UnaryFunction1D.h" +#include "BPy_UnaryPredicate0D.h" +#include "BPy_UnaryPredicate1D.h" +#include "BPy_ViewMap.h" +#include "BPy_ViewShape.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------ MODULE FUNCTIONS ---------------------------------- + +#include "FRS_freestyle.h" +#include "bpy_rna.h" /* pyrna_struct_CreatePyObject() */ + +static char Freestyle_getCurrentScene___doc__[] = +".. function:: getCurrentScene()\n" +"\n" +" Returns the current scene.\n" +"\n" +" :return: The current scene.\n" +" :rtype: :class:`bpy.types.Scene`\n"; + +static PyObject *Freestyle_getCurrentScene( PyObject *self ) +{ + if (!freestyle_scene) { + PyErr_SetString(PyExc_TypeError, "current scene not available"); + return NULL; + } + PointerRNA ptr_scene; + RNA_pointer_create(NULL, &RNA_Scene, freestyle_scene, &ptr_scene); + return pyrna_struct_CreatePyObject(&ptr_scene); +} + +/*-----------------------Freestyle module docstring----------------------------*/ + +static char module_docstring[] = "The Blender Freestyle module\n\n"; + +/*-----------------------Freestyle module method def---------------------------*/ + +static PyMethodDef module_functions[] = { + {"getCurrentScene", ( PyCFunction ) Freestyle_getCurrentScene, METH_NOARGS, Freestyle_getCurrentScene___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------Freestyle module definition---------------------------*/ + +static PyModuleDef module_definition = { + PyModuleDef_HEAD_INIT, + "Freestyle", + module_docstring, + -1, + module_functions +}; + +//-------------------MODULE INITIALIZATION-------------------------------- +PyObject *Freestyle_Init( void ) +{ + PyObject *module; + + // initialize modules + module = PyModule_Create(&module_definition); + if (!module) + return NULL; + PyDict_SetItemString(PySys_GetObject("modules"), module_definition.m_name, module); + + // attach its classes (adding the object types to the module) + + // those classes have to be initialized before the others + MediumType_Init( module ); + Nature_Init( module ); + + BBox_Init( module ); + BinaryPredicate0D_Init( module ); + BinaryPredicate1D_Init( module ); + ContextFunctions_Init( module ); + FrsMaterial_Init( module ); + FrsNoise_Init( module ); + Id_Init( module ); + IntegrationType_Init( module ); + Interface0D_Init( module ); + Interface1D_Init( module ); + Iterator_Init( module ); + Operators_Init( module ); + SShape_Init( module ); + StrokeAttribute_Init( module ); + StrokeShader_Init( module ); + UnaryFunction0D_Init( module ); + UnaryFunction1D_Init( module ); + UnaryPredicate0D_Init( module ); + UnaryPredicate1D_Init( module ); + ViewMap_Init( module ); + ViewShape_Init( module ); + + return module; +} + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/BPy_Freestyle.h b/source/blender/freestyle/intern/python/BPy_Freestyle.h new file mode 100644 index 00000000000..8ade4b5ff4d --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_Freestyle.h @@ -0,0 +1,22 @@ +#ifndef FREESTYLE_PYTHON_FREESTYLE_H +#define FREESTYLE_PYTHON_FREESTYLE_H + +#include <Python.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +/*---------------------------Python BPy_Freestyle visible prototypes-----------*/ + +PyObject *Freestyle_Init( void ); + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_FREESTYLE_H */ diff --git a/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp new file mode 100644 index 00000000000..b33a9096e81 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp @@ -0,0 +1,599 @@ +#include "BPy_FrsMaterial.h" + +#include "BPy_Convert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- +int FrsMaterial_Init( PyObject *module ) +{ + if( module == NULL ) + return -1; + + if( PyType_Ready( &FrsMaterial_Type ) < 0 ) + return -1; + + Py_INCREF( &FrsMaterial_Type ); + PyModule_AddObject(module, "Material", (PyObject *)&FrsMaterial_Type); + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char FrsMaterial___doc__[] = +"Class defining a material.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(m)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg m: A Material object.\n" +" :type m: :class:`Material`\n" +"\n" +".. method:: __init__(iDiffuse, iAmbiant, iSpecular, iEmission, iShininess)\n" +"\n" +" Builds a Material from its diffuse, ambiant, specular, emissive\n" +" colors and a shininess coefficient.\n" +"\n" +" :arg iDiffuse: The diffuse color.\n" +" :type iDiffuse: :class:`mathutils.Vector`, list of tuple of 4 float values\n" +" :arg iAmbiant: The ambiant color.\n" +" :type iAmbiant: :class:`mathutils.Vector`, list of tuple of 4 float values\n" +" :arg iSpecular: The specular color.\n" +" :type iSpecular: :class:`mathutils.Vector`, list of tuple of 4 float values\n" +" :arg iEmission: The emissive color.\n" +" :type iEmission: :class:`mathutils.Vector`, list of tuple of 4 float values\n" +" :arg iShininess: The shininess coefficient.\n" +" :type iShininess: :class:`mathutils.Vector`, list of tuple of 4 float values\n"; + +static int Vec4(PyObject *obj, float *v) +{ + if (VectorObject_Check(obj) && ((VectorObject *)obj)->size == 4) { + for (int i = 0; i < 4; i++) + v[i] = ((VectorObject *)obj)->vec[i]; + } else if( PyList_Check(obj) && PyList_Size(obj) == 4 ) { + for (int i = 0; i < 4; i++) + v[i] = PyFloat_AsDouble(PyList_GetItem(obj, i)); + } else if( PyTuple_Check(obj) && PyTuple_Size(obj) == 4 ) { + for (int i = 0; i < 4; i++) + v[i] = PyFloat_AsDouble(PyTuple_GetItem(obj, i)); + } else { + return 0; + } + return 1; +} + +static int FrsMaterial___init__(BPy_FrsMaterial *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0, *obj4 = 0; + float f1[4], f2[4], f3[4], f4[4], f5 = 0.; + + if (! PyArg_ParseTuple(args, "|OOOOf", &obj1, &obj2, &obj3, &obj4, &f5) ) + return -1; + + if( !obj1 ){ + self->m = new FrsMaterial(); + + } else if( BPy_FrsMaterial_Check(obj1) && !obj2 ) { + FrsMaterial *m = ((BPy_FrsMaterial *) obj1)->m; + if( !m ) { + PyErr_SetString(PyExc_RuntimeError, "invalid FrsMaterial object"); + return -1; + } + self->m = new FrsMaterial( *m ); + + } else if( Vec4(obj1, f1) && obj2 && Vec4(obj2, f2) && obj3 && Vec4(obj3, f3) && obj4 && Vec4(obj4, f4) ) { + self->m = new FrsMaterial(f1, f2, f3, f4, f5); + + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument(s)"); + return -1; + } + self->borrowed = 0; + + return 0; +} + +static void FrsMaterial___dealloc__( BPy_FrsMaterial* self) +{ + if( self->m && !self->borrowed ) + delete self->m; + Py_TYPE(self)->tp_free((PyObject*)self); +} + + +static PyObject * FrsMaterial___repr__( BPy_FrsMaterial* self) +{ + return PyUnicode_FromFormat("Material - address: %p", self->m ); +} + +static char FrsMaterial_diffuse___doc__[] = +".. method:: diffuse()\n" +"\n" +" Returns the diffuse color.\n" +"\n" +" :return: The diffuse color.\n" +" :rtype: Tuple of 4 float values\n"; + +static PyObject * FrsMaterial_diffuse( BPy_FrsMaterial* self) { + const float *diffuse = self->m->diffuse(); + PyObject *py_diffuse = PyTuple_New(4); + + PyTuple_SetItem( py_diffuse, 0, PyFloat_FromDouble( diffuse[0] ) ); + PyTuple_SetItem( py_diffuse, 1, PyFloat_FromDouble( diffuse[1] ) ); + PyTuple_SetItem( py_diffuse, 2, PyFloat_FromDouble( diffuse[2] ) ); + PyTuple_SetItem( py_diffuse, 3, PyFloat_FromDouble( diffuse[3] ) ); + + return py_diffuse; +} + +static char FrsMaterial_diffuseR___doc__[] = +".. method:: diffuseR()\n" +"\n" +" Returns the red component of the diffuse color.\n" +"\n" +" :return: The red component of the diffuse color.\n" +" :rtype: float\n"; + +static PyObject * FrsMaterial_diffuseR( BPy_FrsMaterial* self) { + return PyFloat_FromDouble( self->m->diffuseR() ); +} + +static char FrsMaterial_diffuseG___doc__[] = +".. method:: diffuseG()\n" +"\n" +" Returns the green component of the diffuse color.\n" +"\n" +" :return: The green component of the diffuse color.\n" +" :rtype: float\n"; + +static PyObject * FrsMaterial_diffuseG( BPy_FrsMaterial* self) { + return PyFloat_FromDouble( self->m->diffuseG() ); +} + +static char FrsMaterial_diffuseB___doc__[] = +".. method:: diffuseB()\n" +"\n" +" Returns the blue component of the diffuse color.\n" +"\n" +" :return: The blue component of the diffuse color.\n" +" :rtype: float\n"; + +static PyObject * FrsMaterial_diffuseB( BPy_FrsMaterial* self) { + return PyFloat_FromDouble( self->m->diffuseB() ); +} + +static char FrsMaterial_diffuseA___doc__[] = +".. method:: diffuseA()\n" +"\n" +" Returns the alpha component of the diffuse color.\n" +"\n" +" :return: The alpha component of the diffuse color.\n" +" :rtype: float\n"; + +static PyObject * FrsMaterial_diffuseA( BPy_FrsMaterial* self) { + return PyFloat_FromDouble( self->m->diffuseA() ); +} + +static char FrsMaterial_specular___doc__[] = +".. method:: specular()\n" +"\n" +" Returns the specular color.\n" +"\n" +" :return: The specular color.\n" +" :rtype: Tuple of 4 float values\n"; + +static PyObject * FrsMaterial_specular( BPy_FrsMaterial* self) { + const float *specular = self->m->specular(); + PyObject *py_specular = PyTuple_New(4); + + PyTuple_SetItem( py_specular, 0, PyFloat_FromDouble( specular[0] ) ); + PyTuple_SetItem( py_specular, 1, PyFloat_FromDouble( specular[1] ) ); + PyTuple_SetItem( py_specular, 2, PyFloat_FromDouble( specular[2] ) ); + PyTuple_SetItem( py_specular, 3, PyFloat_FromDouble( specular[3] ) ); + + return py_specular; +} + +static char FrsMaterial_specularR___doc__[] = +".. method:: specularR()\n" +"\n" +" Returns the red component of the specular color.\n" +"\n" +" :return: The red component of the specular color.\n" +" :rtype: float\n"; + +static PyObject * FrsMaterial_specularR( BPy_FrsMaterial* self) { + return PyFloat_FromDouble( self->m->specularR() ); +} + +static char FrsMaterial_specularG___doc__[] = +".. method:: specularG()\n" +"\n" +" Returns the green component of the specular color.\n" +"\n" +" :return: The green component of the specular color.\n" +" :rtype: float\n"; + +static PyObject * FrsMaterial_specularG( BPy_FrsMaterial* self) { + return PyFloat_FromDouble( self->m->specularG() ); +} + +static char FrsMaterial_specularB___doc__[] = +".. method:: specularB()\n" +"\n" +" Returns the blue component of the specular color.\n" +"\n" +" :return: The blue component of the specular color.\n" +" :rtype: float\n"; + +static PyObject * FrsMaterial_specularB( BPy_FrsMaterial* self) { + return PyFloat_FromDouble( self->m->specularB() ); +} + +static char FrsMaterial_specularA___doc__[] = +".. method:: specularA()\n" +"\n" +" Returns the alpha component of the specular color.\n" +"\n" +" :return: The alpha component of the specular color.\n" +" :rtype: float\n"; + +static PyObject * FrsMaterial_specularA( BPy_FrsMaterial* self) { + return PyFloat_FromDouble( self->m->specularA() ); +} + +static char FrsMaterial_ambient___doc__[] = +".. method:: ambient()\n" +"\n" +" Returns the ambiant color.\n" +"\n" +" :return: The ambiant color.\n" +" :rtype: Tuple of 4 float values\n"; + +static PyObject * FrsMaterial_ambient( BPy_FrsMaterial* self) { + const float *ambient = self->m->ambient(); + PyObject *py_ambient = PyTuple_New(4); + + PyTuple_SetItem( py_ambient, 0, PyFloat_FromDouble( ambient[0] ) ); + PyTuple_SetItem( py_ambient, 1, PyFloat_FromDouble( ambient[1] ) ); + PyTuple_SetItem( py_ambient, 2, PyFloat_FromDouble( ambient[2] ) ); + PyTuple_SetItem( py_ambient, 3, PyFloat_FromDouble( ambient[3] ) ); + + return py_ambient; +} + +static char FrsMaterial_ambientR___doc__[] = +".. method:: ambientR()\n" +"\n" +" Returns the red component of the ambiant color.\n" +"\n" +" :return: The red component of the ambiant color.\n" +" :rtype: float\n"; + +static PyObject * FrsMaterial_ambientR( BPy_FrsMaterial* self) { + return PyFloat_FromDouble( self->m->ambientR() ); +} + +static char FrsMaterial_ambientG___doc__[] = +".. method:: ambientG()\n" +"\n" +" Returns the green component of the ambiant color.\n" +"\n" +" :return: The green component of the ambiant color.\n" +" :rtype: float\n"; + +static PyObject * FrsMaterial_ambientG( BPy_FrsMaterial* self) { + return PyFloat_FromDouble( self->m->ambientG() ); +} + +static char FrsMaterial_ambientB___doc__[] = +".. method:: ambientB()\n" +"\n" +" Returns the blue component of the ambiant color.\n" +"\n" +" :return: The blue component of the ambiant color.\n" +" :rtype: float\n"; + +static PyObject * FrsMaterial_ambientB( BPy_FrsMaterial* self) { + return PyFloat_FromDouble( self->m->ambientB() ); +} + +static char FrsMaterial_ambientA___doc__[] = +".. method:: ambientA()\n" +"\n" +" Returns the alpha component of the ambiant color.\n" +"\n" +" :return: The alpha component of the ambiant color.\n" +" :rtype: float\n"; + +static PyObject * FrsMaterial_ambientA( BPy_FrsMaterial* self) { + return PyFloat_FromDouble( self->m->ambientA() ); +} + +static char FrsMaterial_emission___doc__[] = +".. method:: emission()\n" +"\n" +" Returns the emissive color.\n" +"\n" +" :return: the emissive color.\n" +" :rtype: Tuple of 4 float values\n"; + +static PyObject * FrsMaterial_emission( BPy_FrsMaterial* self) { + const float *emission = self->m->emission(); + PyObject *py_emission = PyTuple_New(4); + + PyTuple_SetItem( py_emission, 0, PyFloat_FromDouble( emission[0] ) ); + PyTuple_SetItem( py_emission, 1, PyFloat_FromDouble( emission[1] ) ); + PyTuple_SetItem( py_emission, 2, PyFloat_FromDouble( emission[2] ) ); + PyTuple_SetItem( py_emission, 3, PyFloat_FromDouble( emission[3] ) ); + + return py_emission; +} + +static char FrsMaterial_emissionR___doc__[] = +".. method:: emissionR()\n" +"\n" +" Returns the red component of the emissive color.\n" +"\n" +" :return: The red component of the emissive color.\n" +" :rtype: float\n"; + +static PyObject * FrsMaterial_emissionR( BPy_FrsMaterial* self) { + return PyFloat_FromDouble( self->m->emissionR() ); +} + +static char FrsMaterial_emissionG___doc__[] = +".. method:: emissionG()\n" +"\n" +" Returns the green component of the emissive color.\n" +"\n" +" :return: The green component of the emissive color.\n" +" :rtype: float\n"; + +static PyObject * FrsMaterial_emissionG( BPy_FrsMaterial* self) { + return PyFloat_FromDouble( self->m->emissionG() ); +} + +static char FrsMaterial_emissionB___doc__[] = +".. method:: emissionB()\n" +"\n" +" Returns the blue component of the emissive color.\n" +"\n" +" :return: The blue component of the emissive color.\n" +" :rtype: float\n"; + +static PyObject * FrsMaterial_emissionB( BPy_FrsMaterial* self) { + return PyFloat_FromDouble( self->m->emissionB() ); +} + +static char FrsMaterial_emissionA___doc__[] = +".. method:: emissionA()\n" +"\n" +" Returns the alpha component of the emissive color.\n" +"\n" +" :return: The alpha component of the emissive color.\n" +" :rtype: float\n"; + +static PyObject * FrsMaterial_emissionA( BPy_FrsMaterial* self) { + return PyFloat_FromDouble( self->m->emissionA() ); +} + +static char FrsMaterial_shininess___doc__[] = +".. method:: shininess()\n" +"\n" +" Returns the shininess coefficient.\n" +"\n" +" :return: Shininess\n" +" :rtype: float\n"; + +static PyObject * FrsMaterial_shininess( BPy_FrsMaterial* self) { + return PyFloat_FromDouble( self->m->shininess() ); +} + +static char FrsMaterial_setDiffuse___doc__[] = +".. method:: setDiffuse(r, g, b, a)\n" +"\n" +" Sets the diffuse color.\n" +"\n" +" :arg r: Red component.\n" +" :type r: float\n" +" :arg g: Green component.\n" +" :type g: float\n" +" :arg b: Blue component.\n" +" :type b: float\n" +" :arg a: Alpha component.\n" +" :type a: float\n"; + +static PyObject * FrsMaterial_setDiffuse( BPy_FrsMaterial *self, PyObject *args ) { + float f1, f2, f3, f4; + + if(!( PyArg_ParseTuple(args, "ffff", &f1, &f2, &f3, &f4) )) + return NULL; + + self->m->setDiffuse(f1, f2, f3, f4); + + Py_RETURN_NONE; +} + +static char FrsMaterial_setSpecular___doc__[] = +".. method:: setSpecular(r, g, b, a)\n" +"\n" +" Sets the specular color.\n" +"\n" +" :arg r: Red component.\n" +" :type r: float\n" +" :arg g: Green component.\n" +" :type g: float\n" +" :arg b: Blue component.\n" +" :type b: float\n" +" :arg a: Alpha component.\n" +" :type a: float\n"; + +static PyObject * FrsMaterial_setSpecular( BPy_FrsMaterial *self, PyObject *args ) { + float f1, f2, f3, f4; + + if(!( PyArg_ParseTuple(args, "ffff", &f1, &f2, &f3, &f4) )) + return NULL; + + self->m->setSpecular(f1, f2, f3, f4); + + Py_RETURN_NONE; +} + +static char FrsMaterial_setAmbient___doc__[] = +".. method:: setAmbient(r, g, b, a)\n" +"\n" +" Sets the ambiant color.\n" +"\n" +" :arg r: Red component.\n" +" :type r: float\n" +" :arg g: Green component.\n" +" :type g: float\n" +" :arg b: Blue component.\n" +" :type b: float\n" +" :arg a: Alpha component.\n" +" :type a: float\n"; + +static PyObject * FrsMaterial_setAmbient( BPy_FrsMaterial *self, PyObject *args ) { + float f1, f2, f3, f4; + + if(!( PyArg_ParseTuple(args, "ffff", &f1, &f2, &f3, &f4) )) + return NULL; + + self->m->setAmbient(f1, f2, f3, f4); + + Py_RETURN_NONE; +} + +static char FrsMaterial_setEmission___doc__[] = +".. method:: setEmission(r, g, b, a)\n" +"\n" +" Sets the emissive color.\n" +"\n" +" :arg r: Red component.\n" +" :type r: float\n" +" :arg g: Green component.\n" +" :type g: float\n" +" :arg b: Blue component.\n" +" :type b: float\n" +" :arg a: Alpha component.\n" +" :type a: float\n"; + +static PyObject * FrsMaterial_setEmission( BPy_FrsMaterial *self, PyObject *args ) { + float f1, f2, f3, f4; + + if(!( PyArg_ParseTuple(args, "ffff", &f1, &f2, &f3, &f4) )) + return NULL; + + self->m->setEmission(f1, f2, f3, f4); + + Py_RETURN_NONE; +} + +static char FrsMaterial_setShininess___doc__[] = +".. method:: setShininess(s)\n" +"\n" +" Sets the shininess.\n" +"\n" +" :arg s: Shininess.\n" +" :type s: float\n"; + +static PyObject * FrsMaterial_setShininess( BPy_FrsMaterial *self, PyObject *args ) { + float f; + + if(!( PyArg_ParseTuple(args, "f", &f) )) + return NULL; + + self->m->setShininess(f); + + Py_RETURN_NONE; +} + +/*----------------------FrsMaterial instance definitions ----------------------------*/ +static PyMethodDef BPy_FrsMaterial_methods[] = { + {"diffuse", ( PyCFunction ) FrsMaterial_diffuse, METH_NOARGS, FrsMaterial_diffuse___doc__}, + {"diffuseR", ( PyCFunction ) FrsMaterial_diffuseR, METH_NOARGS, FrsMaterial_diffuseR___doc__}, + {"diffuseG", ( PyCFunction ) FrsMaterial_diffuseG, METH_NOARGS, FrsMaterial_diffuseG___doc__}, + {"diffuseB", ( PyCFunction ) FrsMaterial_diffuseB, METH_NOARGS, FrsMaterial_diffuseB___doc__}, + {"diffuseA", ( PyCFunction ) FrsMaterial_diffuseA, METH_NOARGS, FrsMaterial_diffuseA___doc__}, + {"specular", ( PyCFunction ) FrsMaterial_specular, METH_NOARGS, FrsMaterial_specular___doc__}, + {"specularR", ( PyCFunction ) FrsMaterial_specularR, METH_NOARGS, FrsMaterial_specularR___doc__}, + {"specularG", ( PyCFunction ) FrsMaterial_specularG, METH_NOARGS, FrsMaterial_specularG___doc__}, + {"specularB", ( PyCFunction ) FrsMaterial_specularB, METH_NOARGS, FrsMaterial_specularB___doc__}, + {"specularA", ( PyCFunction ) FrsMaterial_specularA, METH_NOARGS, FrsMaterial_specularA___doc__}, + {"ambient", ( PyCFunction ) FrsMaterial_ambient, METH_NOARGS, FrsMaterial_ambient___doc__}, + {"ambientR", ( PyCFunction ) FrsMaterial_ambientR, METH_NOARGS, FrsMaterial_ambientR___doc__}, + {"ambientG", ( PyCFunction ) FrsMaterial_ambientG, METH_NOARGS, FrsMaterial_ambientG___doc__}, + {"ambientB", ( PyCFunction ) FrsMaterial_ambientB, METH_NOARGS, FrsMaterial_ambientB___doc__}, + {"ambientA", ( PyCFunction ) FrsMaterial_ambientA, METH_NOARGS, FrsMaterial_ambientA___doc__}, + {"emission", ( PyCFunction ) FrsMaterial_emission, METH_NOARGS, FrsMaterial_emission___doc__}, + {"emissionR", ( PyCFunction ) FrsMaterial_emissionR, METH_NOARGS, FrsMaterial_emissionR___doc__}, + {"emissionG", ( PyCFunction ) FrsMaterial_emissionG, METH_NOARGS, FrsMaterial_emissionG___doc__}, + {"emissionB", ( PyCFunction ) FrsMaterial_emissionB, METH_NOARGS, FrsMaterial_emissionB___doc__}, + {"emissionA", ( PyCFunction ) FrsMaterial_emissionA, METH_NOARGS, FrsMaterial_emissionA___doc__}, + {"shininess", ( PyCFunction ) FrsMaterial_shininess, METH_NOARGS, FrsMaterial_shininess___doc__}, + {"setDiffuse", ( PyCFunction ) FrsMaterial_setDiffuse, METH_NOARGS, FrsMaterial_setDiffuse___doc__}, + {"setSpecular", ( PyCFunction ) FrsMaterial_setSpecular, METH_NOARGS, FrsMaterial_setSpecular___doc__}, + {"setAmbient", ( PyCFunction ) FrsMaterial_setAmbient, METH_NOARGS, FrsMaterial_setAmbient___doc__}, + {"setEmission", ( PyCFunction ) FrsMaterial_setEmission, METH_NOARGS, FrsMaterial_setEmission___doc__}, + {"setShininess", ( PyCFunction ) FrsMaterial_setShininess, METH_NOARGS, FrsMaterial_setShininess___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_FrsMaterial type definition ------------------------------*/ + +PyTypeObject FrsMaterial_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "Material", /* tp_name */ + sizeof(BPy_FrsMaterial), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)FrsMaterial___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)FrsMaterial___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + FrsMaterial___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_FrsMaterial_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)FrsMaterial___init__, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/BPy_FrsMaterial.h b/source/blender/freestyle/intern/python/BPy_FrsMaterial.h new file mode 100644 index 00000000000..f541e1bb529 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_FrsMaterial.h @@ -0,0 +1,37 @@ +#ifndef FREESTYLE_PYTHON_FRSMATERIAL_H +#define FREESTYLE_PYTHON_FRSMATERIAL_H + +#include <Python.h> + +#include "../scene_graph/FrsMaterial.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject FrsMaterial_Type; + +#define BPy_FrsMaterial_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FrsMaterial_Type) ) + +/*---------------------------Python BPy_FrsMaterial structure definition----------*/ +typedef struct { + PyObject_HEAD + FrsMaterial *m; + int borrowed; /* non-zero if *m is a borrowed object */ +} BPy_FrsMaterial; + +/*---------------------------Python BPy_FrsMaterial visible prototypes-----------*/ + +int FrsMaterial_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_FRSMATERIAL_H */ diff --git a/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp new file mode 100644 index 00000000000..bd2b5a4dad0 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp @@ -0,0 +1,274 @@ +#include "BPy_FrsNoise.h" +#include "BPy_Convert.h" + +#include <sstream> + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- +int FrsNoise_Init( PyObject *module ) +{ + if( module == NULL ) + return -1; + + if( PyType_Ready( &FrsNoise_Type ) < 0 ) + return -1; + + Py_INCREF( &FrsNoise_Type ); + PyModule_AddObject(module, "Noise", (PyObject *)&FrsNoise_Type); + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char FrsNoise___doc__[] = +"Class to provide Perlin noise functionalities.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Builds a Noise object.\n"; + +static int FrsNoise___init__(BPy_FrsNoise *self, PyObject *args, PyObject *kwds) +{ + if(!( PyArg_ParseTuple(args, "") )) + return -1; + self->n = new Noise(); + return 0; +} + +static void FrsNoise___dealloc__(BPy_FrsNoise* self) +{ + delete self->n; + Py_TYPE(self)->tp_free((PyObject*)self); +} + + +static PyObject * FrsNoise___repr__(BPy_FrsNoise* self) +{ + return PyUnicode_FromFormat("Noise - address: %p", self->n ); +} + +static char FrsNoise_turbulence1___doc__[] = +".. method:: turbulence1(v, freq, amp, oct=4)\n" +"\n" +" Returns a noise value for a 1D element.\n" +"\n" +" :arg v: One-dimensional sample point.\n" +" :type v: float\n" +" :arg freq: Noise frequency.\n" +" :type freq: float\n" +" :arg amp: Amplitude.\n" +" :type amp: float\n" +" :arg oct: Number of octaves.\n" +" :type oct: int\n" +" :return: A noise value.\n" +" :rtype: float\n"; + +static PyObject * FrsNoise_turbulence1( BPy_FrsNoise *self , PyObject *args) { + float f1, f2, f3; + unsigned int i = 4; + + if(!( PyArg_ParseTuple(args, "fff|I", &f1, &f2, &f3, &i) )) + return NULL; + + return PyFloat_FromDouble( self->n->turbulence1(f1, f2, f3, i) ); +} + +static char FrsNoise_turbulence2___doc__[] = +".. method:: turbulence2(v, freq, amp, oct=4)\n" +"\n" +" Returns a noise value for a 2D element.\n" +"\n" +" :arg v: Two-dimensional sample point.\n" +" :type v: :class:`mathutils.Vector`, list or tuple of 2 real numbers\n" +" :arg freq: Noise frequency.\n" +" :type freq: float\n" +" :arg amp: Amplitude.\n" +" :type amp: float\n" +" :arg oct: Number of octaves.\n" +" :type oct: int\n" +" :return: A noise value.\n" +" :rtype: float\n"; + +static PyObject * FrsNoise_turbulence2( BPy_FrsNoise *self , PyObject *args) { + PyObject *obj1; + float f2, f3; + unsigned int i = 4; + + if(!( PyArg_ParseTuple(args, "Off|I", &obj1, &f2, &f3, &i) )) + return NULL; + Vec2f *v = Vec2f_ptr_from_PyObject(obj1); + if( !v ) { + PyErr_SetString(PyExc_TypeError, "argument 1 must be a 2D vector (either a list of 2 elements or Vector)"); + return NULL; + } + float t = self->n->turbulence2(*v, f2, f3, i); + delete v; + return PyFloat_FromDouble( t ); +} + +static char FrsNoise_turbulence3___doc__[] = +".. method:: turbulence3(v, freq, amp, oct=4)\n" +"\n" +" Returns a noise value for a 3D element.\n" +"\n" +" :arg v: Three-dimensional sample point.\n" +" :type v: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n" +" :arg freq: Noise frequency.\n" +" :type freq: float\n" +" :arg amp: Amplitude.\n" +" :type amp: float\n" +" :arg oct: Number of octaves.\n" +" :type oct: int\n" +" :return: A noise value.\n" +" :rtype: float\n"; + +static PyObject * FrsNoise_turbulence3( BPy_FrsNoise *self , PyObject *args) { + PyObject *obj1; + float f2, f3; + unsigned int i = 4; + + if(!( PyArg_ParseTuple(args, "Off|I", &obj1, &f2, &f3, &i) )) + return NULL; + Vec3f *v = Vec3f_ptr_from_PyObject(obj1); + if( !v ) { + PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)"); + return NULL; + } + float t = self->n->turbulence3(*v, f2, f3, i); + delete v; + return PyFloat_FromDouble( t ); +} + +static char FrsNoise_smoothNoise1___doc__[] = +".. method:: smoothNoise1(v)\n" +"\n" +" Returns a smooth noise value for a 1D element.\n" +"\n" +" :arg v: One-dimensional sample point.\n" +" :type v: float\n" +" :return: A smooth noise value.\n" +" :rtype: float\n"; + +static PyObject * FrsNoise_smoothNoise1( BPy_FrsNoise *self , PyObject *args) { + float f; + + if(!( PyArg_ParseTuple(args, "f", &f) )) + return NULL; + + return PyFloat_FromDouble( self->n->smoothNoise1(f) ); +} + +static char FrsNoise_smoothNoise2___doc__[] = +".. method:: smoothNoise2(v)\n" +"\n" +" Returns a smooth noise value for a 2D element.\n" +"\n" +" :arg v: Two-dimensional sample point.\n" +" :type v: :class:`mathutils.Vector`, list or tuple of 2 real numbers\n" +" :return: A smooth noise value.\n" +" :rtype: float\n"; + +static PyObject * FrsNoise_smoothNoise2( BPy_FrsNoise *self , PyObject *args) { + PyObject *obj; + + if(!( PyArg_ParseTuple(args, "O", &obj) )) + return NULL; + Vec2f *v = Vec2f_ptr_from_PyObject(obj); + if( !v ) { + PyErr_SetString(PyExc_TypeError, "argument 1 must be a 2D vector (either a list of 2 elements or Vector)"); + return NULL; + } + float t = self->n->smoothNoise2(*v); + delete v; + return PyFloat_FromDouble( t ); +} + +static char FrsNoise_smoothNoise3___doc__[] = +".. method:: smoothNoise3(v)\n" +"\n" +" Returns a smooth noise value for a 3D element.\n" +"\n" +" :arg v: Three-dimensional sample point.\n" +" :type v: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n" +" :return: A smooth noise value.\n" +" :rtype: float\n"; + +static PyObject * FrsNoise_smoothNoise3( BPy_FrsNoise *self , PyObject *args) { + PyObject *obj; + + if(!( PyArg_ParseTuple(args, "O", &obj) )) + return NULL; + Vec3f *v = Vec3f_ptr_from_PyObject(obj); + if( !v ) { + PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)"); + return NULL; + } + float t = self->n->smoothNoise3(*v); + delete v; + return PyFloat_FromDouble( t ); +} + +/*----------------------FrsNoise instance definitions ----------------------------*/ +static PyMethodDef BPy_FrsNoise_methods[] = { + {"turbulence1", ( PyCFunction ) FrsNoise_turbulence1, METH_VARARGS, FrsNoise_turbulence1___doc__}, + {"turbulence2", ( PyCFunction ) FrsNoise_turbulence2, METH_VARARGS, FrsNoise_turbulence2___doc__}, + {"turbulence3", ( PyCFunction ) FrsNoise_turbulence3, METH_VARARGS, FrsNoise_turbulence3___doc__}, + {"smoothNoise1", ( PyCFunction ) FrsNoise_smoothNoise1, METH_VARARGS, FrsNoise_smoothNoise1___doc__}, + {"smoothNoise2", ( PyCFunction ) FrsNoise_smoothNoise2, METH_VARARGS, FrsNoise_smoothNoise2___doc__}, + {"smoothNoise3", ( PyCFunction ) FrsNoise_smoothNoise3, METH_VARARGS, FrsNoise_smoothNoise3___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_FrsNoise type definition ------------------------------*/ + +PyTypeObject FrsNoise_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "Noise", /* tp_name */ + sizeof(BPy_FrsNoise), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)FrsNoise___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)FrsNoise___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + FrsNoise___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_FrsNoise_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)FrsNoise___init__, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/BPy_FrsNoise.h b/source/blender/freestyle/intern/python/BPy_FrsNoise.h new file mode 100644 index 00000000000..00b4f3375bc --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_FrsNoise.h @@ -0,0 +1,36 @@ +#ifndef FREESTYLE_PYTHON_FRSNOISE_H +#define FREESTYLE_PYTHON_FRSNOISE_H + +#include <Python.h> + +#include "../geometry/Noise.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject FrsNoise_Type; + +#define BPy_FrsNoise_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FrsNoise_Type) ) + +/*---------------------------Python BPy_FrsNoise structure definition----------*/ +typedef struct { + PyObject_HEAD + Noise *n; +} BPy_FrsNoise; + +/*---------------------------Python BPy_FrsNoise visible prototypes-----------*/ + +int FrsNoise_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_FRSNOISE_H */ diff --git a/source/blender/freestyle/intern/python/BPy_Id.cpp b/source/blender/freestyle/intern/python/BPy_Id.cpp new file mode 100644 index 00000000000..9254badd95d --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_Id.cpp @@ -0,0 +1,222 @@ +#include "BPy_Id.h" + +#include "BPy_Convert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- +int Id_Init( PyObject *module ) +{ + if( module == NULL ) + return -1; + + if( PyType_Ready( &Id_Type ) < 0 ) + return -1; + + Py_INCREF( &Id_Type ); + PyModule_AddObject(module, "Id", (PyObject *)&Id_Type); + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char Id___doc__[] = +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: An Id object.\n" +" :type iBrother: :class:`Id`\n" +"\n" +".. method:: __init__(iFirst)\n" +"\n" +" Builds an Id from an integer. The second number is set to 0.\n" +"\n" +" :arg iFirst: The first Id number.\n" +" :type iFirst: int\n" +"\n" +".. method:: __init__(iFirst, iSecond)\n" +"\n" +" Builds the Id from the two numbers.\n" +"\n" +" :arg iFirst: The first Id number.\n" +" :type iFirst: int\n" +" :arg iSecond: The second Id number.\n" +" :type iSecond: int\n"; + +static int Id___init__(BPy_Id *self, PyObject *args, PyObject *kwds) +{ + int first = 0, second = 0; + static char *kwlist[] = {"first", "second", NULL}; + + if (! PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwlist, &first, &second) ) + return -1; + + self->id = new Id( first, second ); + + return 0; +} + +static void Id___dealloc__(BPy_Id* self) +{ + delete self->id; + Py_TYPE(self)->tp_free((PyObject*)self); +} + +static PyObject * Id___repr__(BPy_Id* self) +{ + return PyUnicode_FromFormat("[ first: %i, second: %i ](BPy_Id)", self->id->getFirst(), self->id->getSecond() ); +} + +static char Id_getFirst___doc__[] = +".. method:: getFirst()\n" +"\n" +" Returns the first Id number.\n" +"\n" +" :return: The first Id number.\n" +" :rtype: int\n"; + +static PyObject *Id_getFirst( BPy_Id *self ) { + return PyLong_FromLong( self->id->getFirst() ); +} + +static char Id_getSecond___doc__[] = +".. method:: getSecond()\n" +"\n" +" Returns the second Id number.\n" +"\n" +" :return: The second Id number.\n" +" :rtype: int\n"; + +static PyObject *Id_getSecond( BPy_Id *self) { + return PyLong_FromLong( self->id->getSecond() ); +} + +static char Id_setFirst___doc__[] = +".. method:: setFirst(iFirst)\n" +"\n" +" Sets the first number constituting the Id.\n" +"\n" +" :arg iFirst: The first number constituting the Id.\n" +" :type iFirst: int\n"; + +static PyObject *Id_setFirst( BPy_Id *self , PyObject *args) { + unsigned int i; + + if( !PyArg_ParseTuple(args, "i", &i) ) + return NULL; + + self->id->setFirst( i ); + + Py_RETURN_NONE; +} + +static char Id_setSecond___doc__[] = +".. method:: setSecond(iSecond)\n" +"\n" +" Sets the second number constituting the Id.\n" +"\n" +" :arg iSecond: The second number constituting the Id.\n" +" :type iSecond: int\n"; + +static PyObject *Id_setSecond( BPy_Id *self , PyObject *args) { + unsigned int i; + + if( !PyArg_ParseTuple(args, "i", &i) ) + return NULL; + + self->id->setSecond( i ); + + Py_RETURN_NONE; +} + +static PyObject * Id_RichCompare(BPy_Id *o1, BPy_Id *o2, int opid) { + switch(opid){ + case Py_LT: + return PyBool_from_bool( o1->id->operator<(*(o2->id)) ); + break; + case Py_LE: + return PyBool_from_bool( o1->id->operator<(*(o2->id)) || o1->id->operator<(*(o2->id)) ); + break; + case Py_EQ: + return PyBool_from_bool( o1->id->operator==(*(o2->id)) ); + break; + case Py_NE: + return PyBool_from_bool( o1->id->operator!=(*(o2->id)) ); + break; + case Py_GT: + return PyBool_from_bool(!( o1->id->operator<(*(o2->id)) || o1->id->operator<(*(o2->id)) )); + break; + case Py_GE: + return PyBool_from_bool(!( o1->id->operator<(*(o2->id)) )); + break; + } + + Py_RETURN_NONE; +} + +/*----------------------Id instance definitions ----------------------------*/ +static PyMethodDef BPy_Id_methods[] = { + {"getFirst", ( PyCFunction ) Id_getFirst, METH_NOARGS, Id_getFirst___doc__}, + {"getSecond", ( PyCFunction ) Id_getSecond, METH_NOARGS, Id_getSecond___doc__}, + {"setFirst", ( PyCFunction ) Id_setFirst, METH_VARARGS, Id_setFirst___doc__}, + {"setSecond", ( PyCFunction ) Id_setSecond, METH_VARARGS, Id_setSecond___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_Id type definition ------------------------------*/ + +PyTypeObject Id_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "Id", /* tp_name */ + sizeof(BPy_Id), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)Id___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)Id___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Id___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + (richcmpfunc)Id_RichCompare, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_Id_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)Id___init__, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/BPy_Id.h b/source/blender/freestyle/intern/python/BPy_Id.h new file mode 100644 index 00000000000..10f370f8a80 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_Id.h @@ -0,0 +1,36 @@ +#ifndef FREESTYLE_PYTHON_ID_H +#define FREESTYLE_PYTHON_ID_H + +#include <Python.h> +#include <iostream> +using namespace std; + +#include "../system/Id.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject Id_Type; + +#define BPy_Id_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Id_Type) ) + +/*---------------------------Python BPy_Id structure definition----------*/ +typedef struct { + PyObject_HEAD + Id *id; +} BPy_Id; + +/*---------------------------Python BPy_Id visible prototypes-----------*/ + +int Id_Init( PyObject *module ); + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_ID_H */ diff --git a/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp b/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp new file mode 100644 index 00000000000..050f75a2668 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp @@ -0,0 +1,248 @@ +#include "BPy_IntegrationType.h" + +#include "BPy_Convert.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DFloat.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h" +#include "Iterator/BPy_Interface0DIterator.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------ MODULE FUNCTIONS ---------------------------------- + +static char Integrator_integrate___doc__[] = +".. function:: integrate(fun, it, it_end, integration_type)\n" +"\n" +" Returns a single value from a set of values evaluated at each 0D\n" +" element of this 1D element.\n" +"\n" +" :arg fun: The UnaryFunction0D used to compute a value at each\n" +" Interface0D.\n" +" :type fun: :class:`UnaryFunction0D`\n" +" :arg it: The Interface0DIterator used to iterate over the 0D\n" +" elements of this 1D element. The integration will occur over\n" +" the 0D elements starting from the one pointed by it.\n" +" :type it: :class:`Interface0DIterator`\n" +" :arg it_end: The Interface0DIterator pointing the end of the 0D\n" +" elements of the 1D element.\n" +" :type it_end: :class:`Interface0DIterator`\n" +" :arg integration_type: The integration method used to compute a\n" +" single value from a set of values.\n" +" :type integration_type: :class:`IntegrationType`\n" +" :return: The single value obtained for the 1D element. The return\n" +" value type is float if fun is of the :class:`UnaryFunction0DDouble`\n" +" or :class:`UnaryFunction0DFloat` type, and int if fun is of the\n" +" :class:`UnaryFunction0DUnsigned` type.\n" +" :rtype: int or float\n"; + +static PyObject * Integrator_integrate( PyObject *self, PyObject *args ) +{ + PyObject *obj1, *obj4 = 0; + BPy_Interface0DIterator *obj2, *obj3; + +#if 1 + if(!( PyArg_ParseTuple(args, "O!O!O!|O!", &UnaryFunction0D_Type, &obj1, + &Interface0DIterator_Type, &obj2, &Interface0DIterator_Type, &obj3, + &IntegrationType_Type, &obj4) )) + return NULL; +#else + if(!( PyArg_ParseTuple(args, "OOO|O", &obj1, &obj2, &obj3, &obj4) )) + return NULL; + if(!BPy_UnaryFunction0D_Check(obj1)) { + PyErr_SetString(PyExc_TypeError, "argument 1 must be a UnaryFunction0D object"); + return NULL; + } + if(!BPy_Interface0DIterator_Check(obj2)) { + PyErr_SetString(PyExc_TypeError, "argument 2 must be a Interface0DIterator object"); + return NULL; + } + if(!BPy_Interface0DIterator_Check(obj3)) { + PyErr_SetString(PyExc_TypeError, "argument 3 must be a Interface0DIterator object"); + return NULL; + } + if(obj4 && !BPy_IntegrationType_Check(obj4)) { + PyErr_SetString(PyExc_TypeError, "argument 4 must be a IntegrationType object"); + return NULL; + } +#endif + + Interface0DIterator it(*(obj2->if0D_it)), it_end(*(obj3->if0D_it)); + IntegrationType t = ( obj4 ) ? IntegrationType_from_BPy_IntegrationType( obj4 ) : MEAN; + + if( BPy_UnaryFunction0DDouble_Check(obj1) ) { + UnaryFunction0D<double> *fun = ((BPy_UnaryFunction0DDouble *)obj1)->uf0D_double; + double res = integrate( *fun, it, it_end, t ); + return PyFloat_FromDouble( res ); + + } else if( BPy_UnaryFunction0DFloat_Check(obj1) ) { + UnaryFunction0D<float> *fun = ((BPy_UnaryFunction0DFloat *)obj1)->uf0D_float; + float res = integrate( *fun, it, it_end, t ); + return PyFloat_FromDouble( res ); + + } else if( BPy_UnaryFunction0DUnsigned_Check(obj1) ) { + UnaryFunction0D<unsigned int> *fun = ((BPy_UnaryFunction0DUnsigned *)obj1)->uf0D_unsigned; + unsigned int res = integrate( *fun, it, it_end, t ); + return PyLong_FromLong( res ); + + } else { + string msg("unsupported function type: " + string(obj1->ob_type->tp_name)); + PyErr_SetString(PyExc_TypeError, msg.c_str()); + return NULL; + } +} + +/*-----------------------Integrator module docstring---------------------------------------*/ + +static char module_docstring[] = "The Blender Freestyle.Integrator submodule\n\n"; + +/*-----------------------Integrator module functions definitions---------------------------*/ + +static PyMethodDef module_functions[] = { + {"integrate", (PyCFunction) Integrator_integrate, METH_VARARGS, Integrator_integrate___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------Integrator module definition--------------------------------------*/ + +static PyModuleDef module_definition = { + PyModuleDef_HEAD_INIT, + "Freestyle.Integrator", + module_docstring, + -1, + module_functions +}; + +/*-----------------------BPy_IntegrationType type definition ------------------------------*/ + +static char IntegrationType___doc__[] = +"Different integration methods that can be invoked to integrate into a\n" +"single value the set of values obtained from each 0D element of an 1D\n" +"element:\n" +"\n" +"* IntegrationType.MEAN: The value computed for the 1D element is the\n" +" mean of the values obtained for the 0D elements.\n" +"* IntegrationType.MIN: The value computed for the 1D element is the\n" +" minimum of the values obtained for the 0D elements.\n" +"* IntegrationType.MAX: The value computed for the 1D element is the\n" +" maximum of the values obtained for the 0D elements.\n" +"* IntegrationType.FIRST: The value computed for the 1D element is the\n" +" first of the values obtained for the 0D elements.\n" +"* IntegrationType.LAST: The value computed for the 1D element is the\n" +" last of the values obtained for the 0D elements.\n"; + +PyTypeObject IntegrationType_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "IntegrationType", /* tp_name */ + sizeof(PyLongObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + IntegrationType___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &PyLong_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/*-----------------------BPy_IntegrationType instance definitions -------------------------*/ + +static PyLongObject _IntegrationType_MEAN = { + PyVarObject_HEAD_INIT(&IntegrationType_Type, 1) + { MEAN } +}; +static PyLongObject _IntegrationType_MIN = { + PyVarObject_HEAD_INIT(&IntegrationType_Type, 1) + { MIN } +}; +static PyLongObject _IntegrationType_MAX = { + PyVarObject_HEAD_INIT(&IntegrationType_Type, 1) + { MAX } +}; +static PyLongObject _IntegrationType_FIRST = { + PyVarObject_HEAD_INIT(&IntegrationType_Type, 1) + { FIRST } +}; +static PyLongObject _IntegrationType_LAST = { + PyVarObject_HEAD_INIT(&IntegrationType_Type, 1) + { LAST } +}; + +#define BPy_IntegrationType_MEAN ((PyObject *)&_IntegrationType_MEAN) +#define BPy_IntegrationType_MIN ((PyObject *)&_IntegrationType_MIN) +#define BPy_IntegrationType_MAX ((PyObject *)&_IntegrationType_MAX) +#define BPy_IntegrationType_FIRST ((PyObject *)&_IntegrationType_FIRST) +#define BPy_IntegrationType_LAST ((PyObject *)&_IntegrationType_LAST) + +//-------------------MODULE INITIALIZATION-------------------------------- +int IntegrationType_Init( PyObject *module ) +{ + PyObject *m, *d, *f; + + if( module == NULL ) + return -1; + + if( PyType_Ready( &IntegrationType_Type ) < 0 ) + return -1; + Py_INCREF( &IntegrationType_Type ); + PyModule_AddObject(module, "IntegrationType", (PyObject *)&IntegrationType_Type); + + PyDict_SetItemString( IntegrationType_Type.tp_dict, "MEAN", BPy_IntegrationType_MEAN); + PyDict_SetItemString( IntegrationType_Type.tp_dict, "MIN", BPy_IntegrationType_MIN); + PyDict_SetItemString( IntegrationType_Type.tp_dict, "MAX", BPy_IntegrationType_MAX); + PyDict_SetItemString( IntegrationType_Type.tp_dict, "FIRST", BPy_IntegrationType_FIRST); + PyDict_SetItemString( IntegrationType_Type.tp_dict, "LAST", BPy_IntegrationType_LAST); + + m = PyModule_Create(&module_definition); + if (m == NULL) + return -1; + Py_INCREF(m); + PyModule_AddObject(module, "Integrator", m); + + // from Integrator import * + d = PyModule_GetDict(m); + for (PyMethodDef *p = module_functions; p->ml_name; p++) { + f = PyDict_GetItemString(d, p->ml_name); + Py_INCREF(f); + PyModule_AddObject(module, p->ml_name, f); + } + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + diff --git a/source/blender/freestyle/intern/python/BPy_IntegrationType.h b/source/blender/freestyle/intern/python/BPy_IntegrationType.h new file mode 100644 index 00000000000..f15ae8309e3 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_IntegrationType.h @@ -0,0 +1,28 @@ +#ifndef FREESTYLE_PYTHON_INTEGRATIONTYPE_H +#define FREESTYLE_PYTHON_INTEGRATIONTYPE_H + +#include <Python.h> + +#include "../view_map/Interface1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject IntegrationType_Type; + +#define BPy_IntegrationType_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &IntegrationType_Type) ) + +/*---------------------------Python BPy_IntegrationType visible prototypes-----------*/ + +int IntegrationType_Init( PyObject *module ); + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_INTEGRATIONTYPE_H */ diff --git a/source/blender/freestyle/intern/python/BPy_Interface0D.cpp b/source/blender/freestyle/intern/python/BPy_Interface0D.cpp new file mode 100644 index 00000000000..11af30439cf --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_Interface0D.cpp @@ -0,0 +1,354 @@ +#include "BPy_Interface0D.h" + +#include "BPy_Convert.h" +#include "Interface0D/BPy_CurvePoint.h" +#include "Interface0D/CurvePoint/BPy_StrokeVertex.h" +#include "Interface0D/BPy_SVertex.h" +#include "Interface0D/BPy_ViewVertex.h" +#include "Interface0D/ViewVertex/BPy_NonTVertex.h" +#include "Interface0D/ViewVertex/BPy_TVertex.h" +#include "Interface1D/BPy_FEdge.h" +#include "BPy_Nature.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- +int Interface0D_Init( PyObject *module ) +{ + if( module == NULL ) + return -1; + + if( PyType_Ready( &Interface0D_Type ) < 0 ) + return -1; + Py_INCREF( &Interface0D_Type ); + PyModule_AddObject(module, "Interface0D", (PyObject *)&Interface0D_Type); + + if( PyType_Ready( &CurvePoint_Type ) < 0 ) + return -1; + Py_INCREF( &CurvePoint_Type ); + PyModule_AddObject(module, "CurvePoint", (PyObject *)&CurvePoint_Type); + + if( PyType_Ready( &SVertex_Type ) < 0 ) + return -1; + Py_INCREF( &SVertex_Type ); + PyModule_AddObject(module, "SVertex", (PyObject *)&SVertex_Type); + + if( PyType_Ready( &ViewVertex_Type ) < 0 ) + return -1; + Py_INCREF( &ViewVertex_Type ); + PyModule_AddObject(module, "ViewVertex", (PyObject *)&ViewVertex_Type); + + if( PyType_Ready( &StrokeVertex_Type ) < 0 ) + return -1; + Py_INCREF( &StrokeVertex_Type ); + PyModule_AddObject(module, "StrokeVertex", (PyObject *)&StrokeVertex_Type); + + if( PyType_Ready( &NonTVertex_Type ) < 0 ) + return -1; + Py_INCREF( &NonTVertex_Type ); + PyModule_AddObject(module, "NonTVertex", (PyObject *)&NonTVertex_Type); + + if( PyType_Ready( &TVertex_Type ) < 0 ) + return -1; + Py_INCREF( &TVertex_Type ); + PyModule_AddObject(module, "TVertex", (PyObject *)&TVertex_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char Interface0D___doc__[] = +"Base class for any 0D element.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n"; + +static int Interface0D___init__(BPy_Interface0D *self, PyObject *args, PyObject *kwds) +{ + if ( !PyArg_ParseTuple(args, "") ) + return -1; + self->if0D = new Interface0D(); + self->borrowed = 0; + return 0; +} + +static void Interface0D___dealloc__(BPy_Interface0D* self) +{ + if( self->if0D && !self->borrowed ) + delete self->if0D; + Py_TYPE(self)->tp_free((PyObject*)self); +} + +static PyObject * Interface0D___repr__(BPy_Interface0D* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->if0D->getExactTypeName().c_str(), self->if0D ); +} + +static char Interface0D_getExactTypeName___doc__[] = +".. method:: getExactTypeName()\n" +"\n" +" Returns the name of the 0D element.\n" +"\n" +" :return: Name of the interface.\n" +" :rtype: str\n"; + +static PyObject *Interface0D_getExactTypeName( BPy_Interface0D *self ) { + return PyUnicode_FromString( self->if0D->getExactTypeName().c_str() ); +} + +static char Interface0D_getX___doc__[] = +".. method:: getX()\n" +"\n" +" Returns the X coordinate of the 3D point of the 0D element.\n" +"\n" +" :return: The X coordinate of the 3D point.\n" +" :rtype: float\n"; + +static PyObject *Interface0D_getX( BPy_Interface0D *self ) { + double x = self->if0D->getX(); + if (PyErr_Occurred()) + return NULL; + return PyFloat_FromDouble( x ); +} + +static char Interface0D_getY___doc__[] = +".. method:: getY()\n" +"\n" +" Returns the Y coordinate of the 3D point of the 0D element.\n" +"\n" +" :return: The Y coordinate of the 3D point.\n" +" :rtype: float\n"; + +static PyObject *Interface0D_getY( BPy_Interface0D *self ) { + double y = self->if0D->getY(); + if (PyErr_Occurred()) + return NULL; + return PyFloat_FromDouble( y ); +} + +static char Interface0D_getZ___doc__[] = +".. method:: getZ()\n" +"\n" +" Returns the Z coordinate of the 3D point of the 0D element.\n" +"\n" +" :return: The Z coordinate of the 3D point.\n" +" :rtype: float\n"; + +static PyObject *Interface0D_getZ( BPy_Interface0D *self ) { + double z = self->if0D->getZ(); + if (PyErr_Occurred()) + return NULL; + return PyFloat_FromDouble( z ); +} + +static char Interface0D_getPoint3D___doc__[] = +".. method:: getPoint3D()\n" +"\n" +" Returns the location of the 0D element in the 3D space.\n" +"\n" +" :return: The 3D point of the 0D element.\n" +" :rtype: :class:`mathutils.Vector`\n"; + +static PyObject *Interface0D_getPoint3D( BPy_Interface0D *self ) { + Vec3f v( self->if0D->getPoint3D() ); + if (PyErr_Occurred()) + return NULL; + return Vector_from_Vec3f( v ); +} + +static char Interface0D_getProjectedX___doc__[] = +".. method:: getProjectedX()\n" +"\n" +" Returns the X coordinate of the 2D point of the 0D element.\n" +"\n" +" :return: The X coordinate of the 2D point.\n" +" :rtype: float\n"; + +static PyObject *Interface0D_getProjectedX( BPy_Interface0D *self ) { + double x = self->if0D->getProjectedX(); + if (PyErr_Occurred()) + return NULL; + return PyFloat_FromDouble( x ); +} + +static char Interface0D_getProjectedY___doc__[] = +".. method:: getProjectedY()\n" +"\n" +" Returns the Y coordinate of the 2D point of the 0D element.\n" +"\n" +" :return: The Y coordinate of the 2D point.\n" +" :rtype: float\n"; + +static PyObject *Interface0D_getProjectedY( BPy_Interface0D *self ) { + double y = self->if0D->getProjectedY(); + if (PyErr_Occurred()) + return NULL; + return PyFloat_FromDouble( y ); +} + +static char Interface0D_getProjectedZ___doc__[] = +".. method:: getProjectedZ()\n" +"\n" +" Returns the Z coordinate of the 2D point of the 0D element.\n" +"\n" +" :return: The Z coordinate of the 2D point.\n" +" :rtype: float\n"; + +static PyObject *Interface0D_getProjectedZ( BPy_Interface0D *self ) { + double z = self->if0D->getProjectedZ(); + if (PyErr_Occurred()) + return NULL; + return PyFloat_FromDouble( z ); +} + +static char Interface0D_getPoint2D___doc__[] = +".. method:: getPoint2D()\n" +"\n" +" Returns the location of the 0D element in the 2D space.\n" +"\n" +" :return: The 2D point of the 0D element.\n" +" :rtype: :class:`mathutils.Vector`\n"; + +static PyObject *Interface0D_getPoint2D( BPy_Interface0D *self ) { + Vec2f v( self->if0D->getPoint2D() ); + if (PyErr_Occurred()) + return NULL; + return Vector_from_Vec2f( v ); +} + +static char Interface0D_getFEdge___doc__[] = +".. method:: getFEdge(inter)\n" +"\n" +" Returns the FEdge that lies between this 0D element and the 0D\n" +" element given as the argument.\n" +"\n" +" :arg inter: A 0D element.\n" +" :type inter: :class:`Interface0D`\n" +" :return: The FEdge lying between the two 0D elements.\n" +" :rtype: :class:`FEdge`\n"; + +static PyObject *Interface0D_getFEdge( BPy_Interface0D *self, PyObject *args ) { + PyObject *py_if0D; + + if(!( PyArg_ParseTuple(args, "O!", &Interface0D_Type, &py_if0D) )) + return NULL; + + FEdge *fe = self->if0D->getFEdge(*( ((BPy_Interface0D *) py_if0D)->if0D )); + if (PyErr_Occurred()) + return NULL; + if( fe ) + return Any_BPy_FEdge_from_FEdge( *fe ); + + Py_RETURN_NONE; +} + +static char Interface0D_getId___doc__[] = +".. method:: getId()\n" +"\n" +" Returns the identifier of the 0D element.\n" +"\n" +" :return: The identifier of the 0D element.\n" +" :rtype: :class:`Id`\n"; + +static PyObject *Interface0D_getId( BPy_Interface0D *self ) { + Id id( self->if0D->getId() ); + if (PyErr_Occurred()) + return NULL; + return BPy_Id_from_Id( id ); +} + +static char Interface0D_getNature___doc__[] = +".. method:: getNature()\n" +"\n" +" Returns the nature of the 0D element.\n" +"\n" +" :return: The nature of the 0D element.\n" +" :rtype: :class:`Nature`\n"; + +static PyObject *Interface0D_getNature( BPy_Interface0D *self ) { + Nature::VertexNature nature = self->if0D->getNature(); + if (PyErr_Occurred()) + return NULL; + return BPy_Nature_from_Nature( nature ); +} + +/*----------------------Interface0D instance definitions ----------------------------*/ +static PyMethodDef BPy_Interface0D_methods[] = { + {"getExactTypeName", ( PyCFunction ) Interface0D_getExactTypeName, METH_NOARGS, Interface0D_getExactTypeName___doc__}, + {"getX", ( PyCFunction ) Interface0D_getX, METH_NOARGS, Interface0D_getX___doc__}, + {"getY", ( PyCFunction ) Interface0D_getY, METH_NOARGS, Interface0D_getY___doc__}, + {"getZ", ( PyCFunction ) Interface0D_getZ, METH_NOARGS, Interface0D_getZ___doc__}, + {"getPoint3D", ( PyCFunction ) Interface0D_getPoint3D, METH_NOARGS, Interface0D_getPoint3D___doc__}, + {"getProjectedX", ( PyCFunction ) Interface0D_getProjectedX, METH_NOARGS, Interface0D_getProjectedX___doc__}, + {"getProjectedY", ( PyCFunction ) Interface0D_getProjectedY, METH_NOARGS, Interface0D_getProjectedY___doc__}, + {"getProjectedZ", ( PyCFunction ) Interface0D_getProjectedZ, METH_NOARGS, Interface0D_getProjectedZ___doc__}, + {"getPoint2D", ( PyCFunction ) Interface0D_getPoint2D, METH_NOARGS, Interface0D_getPoint2D___doc__}, + {"getFEdge", ( PyCFunction ) Interface0D_getFEdge, METH_VARARGS, Interface0D_getFEdge___doc__}, + {"getId", ( PyCFunction ) Interface0D_getId, METH_NOARGS, Interface0D_getId___doc__}, + {"getNature", ( PyCFunction ) Interface0D_getNature, METH_NOARGS, Interface0D_getNature___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_Interface0D type definition ------------------------------*/ + +PyTypeObject Interface0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "Interface0D", /* tp_name */ + sizeof(BPy_Interface0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)Interface0D___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)Interface0D___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Interface0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_Interface0D_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)Interface0D___init__, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ + 0 /* tp_del */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + diff --git a/source/blender/freestyle/intern/python/BPy_Interface0D.h b/source/blender/freestyle/intern/python/BPy_Interface0D.h new file mode 100644 index 00000000000..25134db5352 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_Interface0D.h @@ -0,0 +1,35 @@ +#ifndef FREESTYLE_PYTHON_INTERFACE0D_H +#define FREESTYLE_PYTHON_INTERFACE0D_H + +#include <Python.h> + +#include "../view_map/Interface0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject Interface0D_Type; + +#define BPy_Interface0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Interface0D_Type) ) + +/*---------------------------Python BPy_Interface0D structure definition----------*/ +typedef struct { + PyObject_HEAD + Interface0D *if0D; + int borrowed; /* non-zero if *if0D is a borrowed object */ +} BPy_Interface0D; + +/*---------------------------Python BPy_Interface0D visible prototypes-----------*/ + +int Interface0D_Init( PyObject *module ); + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_INTERFACE0D_H */ diff --git a/source/blender/freestyle/intern/python/BPy_Interface1D.cpp b/source/blender/freestyle/intern/python/BPy_Interface1D.cpp new file mode 100644 index 00000000000..7b4bdddf70c --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_Interface1D.cpp @@ -0,0 +1,337 @@ +#include "BPy_Interface1D.h" + +#include "BPy_Convert.h" +#include "Interface1D/BPy_FrsCurve.h" +#include "Interface1D/Curve/BPy_Chain.h" +#include "Interface1D/BPy_FEdge.h" +#include "Interface1D/FEdge/BPy_FEdgeSharp.h" +#include "Interface1D/FEdge/BPy_FEdgeSmooth.h" +#include "Interface1D/BPy_Stroke.h" +#include "Interface1D/BPy_ViewEdge.h" + +#include "BPy_MediumType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- +int Interface1D_Init( PyObject *module ) +{ + if( module == NULL ) + return -1; + + if( PyType_Ready( &Interface1D_Type ) < 0 ) + return -1; + Py_INCREF( &Interface1D_Type ); + PyModule_AddObject(module, "Interface1D", (PyObject *)&Interface1D_Type); + + if( PyType_Ready( &FrsCurve_Type ) < 0 ) + return -1; + Py_INCREF( &FrsCurve_Type ); + PyModule_AddObject(module, "Curve", (PyObject *)&FrsCurve_Type); + + if( PyType_Ready( &Chain_Type ) < 0 ) + return -1; + Py_INCREF( &Chain_Type ); + PyModule_AddObject(module, "Chain", (PyObject *)&Chain_Type); + + if( PyType_Ready( &FEdge_Type ) < 0 ) + return -1; + Py_INCREF( &FEdge_Type ); + PyModule_AddObject(module, "FEdge", (PyObject *)&FEdge_Type); + + if( PyType_Ready( &FEdgeSharp_Type ) < 0 ) + return -1; + Py_INCREF( &FEdgeSharp_Type ); + PyModule_AddObject(module, "FEdgeSharp", (PyObject *)&FEdgeSharp_Type); + + if( PyType_Ready( &FEdgeSmooth_Type ) < 0 ) + return -1; + Py_INCREF( &FEdgeSmooth_Type ); + PyModule_AddObject(module, "FEdgeSmooth", (PyObject *)&FEdgeSmooth_Type); + + if( PyType_Ready( &Stroke_Type ) < 0 ) + return -1; + Py_INCREF( &Stroke_Type ); + PyModule_AddObject(module, "Stroke", (PyObject *)&Stroke_Type); + + PyDict_SetItemString( Stroke_Type.tp_dict, "DRY_MEDIUM", BPy_MediumType_DRY_MEDIUM ); + PyDict_SetItemString( Stroke_Type.tp_dict, "HUMID_MEDIUM", BPy_MediumType_HUMID_MEDIUM ); + PyDict_SetItemString( Stroke_Type.tp_dict, "OPAQUE_MEDIUM", BPy_MediumType_OPAQUE_MEDIUM ); + + if( PyType_Ready( &ViewEdge_Type ) < 0 ) + return -1; + Py_INCREF( &ViewEdge_Type ); + PyModule_AddObject(module, "ViewEdge", (PyObject *)&ViewEdge_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char Interface1D___doc__[] = +"Base class for any 1D element.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n"; + +static int Interface1D___init__(BPy_Interface1D *self, PyObject *args, PyObject *kwds) +{ + if ( !PyArg_ParseTuple(args, "") ) + return -1; + self->if1D = new Interface1D(); + self->borrowed = 0; + return 0; +} + +static void Interface1D___dealloc__(BPy_Interface1D* self) +{ + if( self->if1D && !self->borrowed ) + delete self->if1D; + Py_TYPE(self)->tp_free((PyObject*)self); +} + +static PyObject * Interface1D___repr__(BPy_Interface1D* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->if1D->getExactTypeName().c_str(), self->if1D ); +} + +static char Interface1D_getExactTypeName___doc__[] = +".. method:: getExactTypeName()\n" +"\n" +" Returns the string of the name of the 1D element.\n" +"\n" +" :return: The name of the 1D element.\n" +" :rtype: str\n"; + +static PyObject *Interface1D_getExactTypeName( BPy_Interface1D *self ) { + return PyUnicode_FromString( self->if1D->getExactTypeName().c_str() ); +} + +#if 0 +static PyObject *Interface1D_getVertices( BPy_Interface1D *self ) { + return PyList_New(0); +} + +static PyObject *Interface1D_getPoints( BPy_Interface1D *self ) { + return PyList_New(0); +} +#endif + +static char Interface1D_getLength2D___doc__[] = +".. method:: getLength2D()\n" +"\n" +" Returns the 2D length of the 1D element.\n" +"\n" +" :return: The 2D length of the 1D element.\n" +" :rtype: float\n"; + +static PyObject *Interface1D_getLength2D( BPy_Interface1D *self ) { + return PyFloat_FromDouble( (double) self->if1D->getLength2D() ); +} + +static char Interface1D_getId___doc__[] = +".. method:: getId()\n" +"\n" +" Returns the Id of the 1D element .\n" +"\n" +" :return: The Id of the 1D element .\n" +" :rtype: :class:`Id`\n"; + +static PyObject *Interface1D_getId( BPy_Interface1D *self ) { + Id id( self->if1D->getId() ); + return BPy_Id_from_Id( id ); +} + +static char Interface1D_getNature___doc__[] = +".. method:: getNature()\n" +"\n" +" Returns the nature of the 1D element.\n" +"\n" +" :return: The nature of the 1D element.\n" +" :rtype: :class:`Nature`\n"; + +static PyObject *Interface1D_getNature( BPy_Interface1D *self ) { + return BPy_Nature_from_Nature( self->if1D->getNature() ); +} + +static char Interface1D_getTimeStamp___doc__[] = +".. method:: getTimeStamp()\n" +"\n" +" Returns the time stamp of the 1D element. Mainly used for selection.\n" +"\n" +" :return: The time stamp of the 1D element.\n" +" :rtype: int\n"; + +static PyObject *Interface1D_getTimeStamp( BPy_Interface1D *self ) { + return PyLong_FromLong( self->if1D->getTimeStamp() ); +} + +static char Interface1D_setTimeStamp___doc__[] = +".. method:: setTimeStamp(iTimeStamp)\n" +"\n" +" Sets the time stamp for the 1D element.\n" +"\n" +" :arg iTimeStamp: A time stamp.\n" +" :type iTimeStamp: int\n"; + +static PyObject *Interface1D_setTimeStamp( BPy_Interface1D *self, PyObject *args) { + int timestamp = 0 ; + + if( !PyArg_ParseTuple(args, "i", ×tamp) ) + return NULL; + + self->if1D->setTimeStamp( timestamp ); + + Py_RETURN_NONE; +} + +static char Interface1D_verticesBegin___doc__[] = +".. method:: verticesBegin()\n" +"\n" +" Returns an iterator over the Interface1D vertices, pointing to the\n" +" first vertex.\n" +"\n" +" :return: An Interface0DIterator pointing to the first vertex.\n" +" :rtype: :class:`Interface0DIterator`\n"; + +static PyObject * Interface1D_verticesBegin( BPy_Interface1D *self ) { + Interface0DIterator if0D_it( self->if1D->verticesBegin() ); + return BPy_Interface0DIterator_from_Interface0DIterator( if0D_it, 0 ); +} + +static char Interface1D_verticesEnd___doc__[] = +".. method:: verticesEnd()\n" +"\n" +" Returns an iterator over the Interface1D vertices, pointing after\n" +" the last vertex.\n" +"\n" +" :return: An Interface0DIterator pointing after the last vertex.\n" +" :rtype: :class:`Interface0DIterator`\n"; + +static PyObject * Interface1D_verticesEnd( BPy_Interface1D *self ) { + Interface0DIterator if0D_it( self->if1D->verticesEnd() ); + return BPy_Interface0DIterator_from_Interface0DIterator( if0D_it, 1 ); +} + +static char Interface1D_pointsBegin___doc__[] = +".. method:: pointsBegin(t=0.0)\n" +"\n" +" Returns an iterator over the Interface1D points, pointing to the\n" +" first point. The difference with verticesBegin() is that here we can\n" +" iterate over points of the 1D element at a any given sampling.\n" +" Indeed, for each iteration, a virtual point is created.\n" +"\n" +" :arg t: A sampling with which we want to iterate over points of\n" +" this 1D element.\n" +" :type t: float\n" +" :return: An Interface0DIterator pointing to the first point.\n" +" :rtype: :class:`Interface0DIterator`\n"; + +static PyObject * Interface1D_pointsBegin( BPy_Interface1D *self, PyObject *args ) { + float f = 0; + + if(!( PyArg_ParseTuple(args, "|f", &f) )) + return NULL; + + Interface0DIterator if0D_it( self->if1D->pointsBegin(f) ); + return BPy_Interface0DIterator_from_Interface0DIterator( if0D_it, 0 ); +} + +static char Interface1D_pointsEnd___doc__[] = +".. method:: pointsEnd(t=0.0)\n" +"\n" +" Returns an iterator over the Interface1D points, pointing after the\n" +" last point. The difference with verticesEnd() is that here we can\n" +" iterate over points of the 1D element at a given sampling. Indeed,\n" +" for each iteration, a virtual point is created.\n" +"\n" +" :arg t: A sampling with which we want to iterate over points of\n" +" this 1D element.\n" +" :type t: float\n" +" :return: An Interface0DIterator pointing after the last point.\n" +" :rtype: :class:`Interface0DIterator`\n"; + +static PyObject * Interface1D_pointsEnd( BPy_Interface1D *self, PyObject *args ) { + float f = 0; + + if(!( PyArg_ParseTuple(args, "|f", &f) )) + return NULL; + + Interface0DIterator if0D_it( self->if1D->pointsEnd(f) ); + return BPy_Interface0DIterator_from_Interface0DIterator( if0D_it, 1 ); +} + +/*----------------------Interface1D instance definitions ----------------------------*/ +static PyMethodDef BPy_Interface1D_methods[] = { + {"getExactTypeName", ( PyCFunction ) Interface1D_getExactTypeName, METH_NOARGS, Interface1D_getExactTypeName___doc__}, +#if 0 + {"getVertices", ( PyCFunction ) Interface1D_getVertices, METH_NOARGS, "Returns the vertices"}, + {"getPoints", ( PyCFunction ) Interface1D_getPoints, METH_NOARGS, "Returns the points. The difference with getVertices() is that here we can iterate over points of the 1D element at any given sampling. At each call, a virtual point is created."}, +#endif + {"getLength2D", ( PyCFunction ) Interface1D_getLength2D, METH_NOARGS, Interface1D_getLength2D___doc__}, + {"getId", ( PyCFunction ) Interface1D_getId, METH_NOARGS, Interface1D_getId___doc__}, + {"getNature", ( PyCFunction ) Interface1D_getNature, METH_NOARGS, Interface1D_getNature___doc__}, + {"getTimeStamp", ( PyCFunction ) Interface1D_getTimeStamp, METH_NOARGS, Interface1D_getTimeStamp___doc__}, + {"setTimeStamp", ( PyCFunction ) Interface1D_setTimeStamp, METH_VARARGS, Interface1D_setTimeStamp___doc__}, + {"verticesBegin", ( PyCFunction ) Interface1D_verticesBegin, METH_NOARGS, Interface1D_verticesBegin___doc__}, + {"verticesEnd", ( PyCFunction ) Interface1D_verticesEnd, METH_NOARGS, Interface1D_verticesEnd___doc__}, + {"pointsBegin", ( PyCFunction ) Interface1D_pointsBegin, METH_VARARGS, Interface1D_pointsBegin___doc__}, + {"pointsEnd", ( PyCFunction ) Interface1D_pointsEnd, METH_VARARGS, Interface1D_pointsEnd___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_Interface1D type definition ------------------------------*/ + +PyTypeObject Interface1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "Interface1D", /* tp_name */ + sizeof(BPy_Interface1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)Interface1D___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)Interface1D___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Interface1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_Interface1D_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)Interface1D___init__, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + diff --git a/source/blender/freestyle/intern/python/BPy_Interface1D.h b/source/blender/freestyle/intern/python/BPy_Interface1D.h new file mode 100644 index 00000000000..75eefa1836f --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_Interface1D.h @@ -0,0 +1,36 @@ +#ifndef FREESTYLE_PYTHON_INTERFACE1D_H +#define FREESTYLE_PYTHON_INTERFACE1D_H + +#include <Python.h> + +#include "../view_map/Interface1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject Interface1D_Type; + +#define BPy_Interface1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Interface1D_Type) ) + +/*---------------------------Python BPy_Interface1D structure definition----------*/ +typedef struct { + PyObject_HEAD + Interface1D *if1D; + int borrowed; /* non-zero if *if1D is a borrowed object */ +} BPy_Interface1D; + +/*---------------------------Python BPy_Interface1D visible prototypes-----------*/ + +int Interface1D_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_INTERFACE1D_H */ diff --git a/source/blender/freestyle/intern/python/BPy_Iterator.cpp b/source/blender/freestyle/intern/python/BPy_Iterator.cpp new file mode 100644 index 00000000000..dd7d3783d81 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_Iterator.cpp @@ -0,0 +1,229 @@ +#include "BPy_Iterator.h" + +#include "BPy_Convert.h" +#include "Iterator/BPy_AdjacencyIterator.h" +#include "Iterator/BPy_Interface0DIterator.h" +#include "Iterator/BPy_CurvePointIterator.h" +#include "Iterator/BPy_StrokeVertexIterator.h" +#include "Iterator/BPy_SVertexIterator.h" +#include "Iterator/BPy_orientedViewEdgeIterator.h" +#include "Iterator/BPy_ViewEdgeIterator.h" +#include "Iterator/BPy_ChainingIterator.h" +#include "Iterator/BPy_ChainPredicateIterator.h" +#include "Iterator/BPy_ChainSilhouetteIterator.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- +int Iterator_Init( PyObject *module ) +{ + if( module == NULL ) + return -1; + + if( PyType_Ready( &Iterator_Type ) < 0 ) + return -1; + Py_INCREF( &Iterator_Type ); + PyModule_AddObject(module, "Iterator", (PyObject *)&Iterator_Type); + + if( PyType_Ready( &AdjacencyIterator_Type ) < 0 ) + return -1; + Py_INCREF( &AdjacencyIterator_Type ); + PyModule_AddObject(module, "AdjacencyIterator", (PyObject *)&AdjacencyIterator_Type); + + if( PyType_Ready( &Interface0DIterator_Type ) < 0 ) + return -1; + Py_INCREF( &Interface0DIterator_Type ); + PyModule_AddObject(module, "Interface0DIterator", (PyObject *)&Interface0DIterator_Type); + + if( PyType_Ready( &CurvePointIterator_Type ) < 0 ) + return -1; + Py_INCREF( &CurvePointIterator_Type ); + PyModule_AddObject(module, "CurvePointIterator", (PyObject *)&CurvePointIterator_Type); + + if( PyType_Ready( &StrokeVertexIterator_Type ) < 0 ) + return -1; + Py_INCREF( &StrokeVertexIterator_Type ); + PyModule_AddObject(module, "StrokeVertexIterator", (PyObject *)&StrokeVertexIterator_Type); + + if( PyType_Ready( &SVertexIterator_Type ) < 0 ) + return -1; + Py_INCREF( &SVertexIterator_Type ); + PyModule_AddObject(module, "SVertexIterator", (PyObject *)&SVertexIterator_Type); + + if( PyType_Ready( &orientedViewEdgeIterator_Type ) < 0 ) + return -1; + Py_INCREF( &orientedViewEdgeIterator_Type ); + PyModule_AddObject(module, "orientedViewEdgeIterator", (PyObject *)&orientedViewEdgeIterator_Type); + + if( PyType_Ready( &ViewEdgeIterator_Type ) < 0 ) + return -1; + Py_INCREF( &ViewEdgeIterator_Type ); + PyModule_AddObject(module, "ViewEdgeIterator", (PyObject *)&ViewEdgeIterator_Type); + + if( PyType_Ready( &ChainingIterator_Type ) < 0 ) + return -1; + Py_INCREF( &ChainingIterator_Type ); + PyModule_AddObject(module, "ChainingIterator", (PyObject *)&ChainingIterator_Type); + + if( PyType_Ready( &ChainPredicateIterator_Type ) < 0 ) + return -1; + Py_INCREF( &ChainPredicateIterator_Type ); + PyModule_AddObject(module, "ChainPredicateIterator", (PyObject *)&ChainPredicateIterator_Type); + + if( PyType_Ready( &ChainSilhouetteIterator_Type ) < 0 ) + return -1; + Py_INCREF( &ChainSilhouetteIterator_Type ); + PyModule_AddObject(module, "ChainSilhouetteIterator", (PyObject *)&ChainSilhouetteIterator_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char Iterator___doc__[] = +"Base class to define iterators.\n"; + +static void Iterator___dealloc__(BPy_Iterator* self) +{ + if (self->it) + delete self->it; + Py_TYPE(self)->tp_free((PyObject*)self); +} + +static PyObject * Iterator___repr__(BPy_Iterator* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->it->getExactTypeName().c_str(), self->it ); +} + +static char Iterator_getExactTypeName___doc__[] = +".. method:: getExactTypeName()\n" +"\n" +" Returns the name of the iterator.\n" +"\n" +" :return: The name of the iterator.\n" +" :rtype: str\n"; + +static PyObject * Iterator_getExactTypeName(BPy_Iterator* self) { + return PyUnicode_FromString( self->it->getExactTypeName().c_str() ); +} + +static char Iterator_increment___doc__[] = +".. method:: increment()\n" +"\n" +" Makes the iterator point the next element.\n"; + +static PyObject * Iterator_increment(BPy_Iterator* self) { + if (self->it->isEnd()) { + PyErr_SetString(PyExc_RuntimeError , "cannot increment any more"); + return NULL; + } + self->it->increment(); + + Py_RETURN_NONE; +} + +static char Iterator_decrement___doc__[] = +".. method:: decrement()\n" +"\n" +" Makes the iterator point the previous element.\n"; + +static PyObject * Iterator_decrement(BPy_Iterator* self) { + if (self->it->isBegin()) { + PyErr_SetString(PyExc_RuntimeError , "cannot decrement any more"); + return NULL; + } + self->it->decrement(); + + Py_RETURN_NONE; +} + +static char Iterator_isBegin___doc__[] = +".. method:: isBegin()\n" +"\n" +" Returns true if the interator points the first element.\n" +"\n" +" :return: True if the interator points the first element.\n" +" :rtype: bool\n"; + +static PyObject * Iterator_isBegin(BPy_Iterator* self) { + return PyBool_from_bool( self->it->isBegin() ); +} + +static char Iterator_isEnd___doc__[] = +".. method:: isEnd()\n" +"\n" +" Returns true if the interator points the last element.\n" +"\n" +" :return: True if the interator points the last element.\n" +" :rtype: bool\n"; + +static PyObject * Iterator_isEnd(BPy_Iterator* self) { + return PyBool_from_bool( self->it->isEnd() ); +} + +/*----------------------Iterator instance definitions ----------------------------*/ +static PyMethodDef BPy_Iterator_methods[] = { + {"getExactTypeName", ( PyCFunction ) Iterator_getExactTypeName, METH_NOARGS, Iterator_getExactTypeName___doc__}, + {"increment", ( PyCFunction ) Iterator_increment, METH_NOARGS, Iterator_increment___doc__}, + {"decrement", ( PyCFunction ) Iterator_decrement, METH_NOARGS, Iterator_decrement___doc__}, + {"isBegin", ( PyCFunction ) Iterator_isBegin, METH_NOARGS, Iterator_isBegin___doc__}, + {"isEnd", ( PyCFunction ) Iterator_isEnd, METH_NOARGS, Iterator_isEnd___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_Iterator type definition ------------------------------*/ + +PyTypeObject Iterator_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "Iterator", /* tp_name */ + sizeof(BPy_Iterator), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)Iterator___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)Iterator___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Iterator___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_Iterator_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + diff --git a/source/blender/freestyle/intern/python/BPy_Iterator.h b/source/blender/freestyle/intern/python/BPy_Iterator.h new file mode 100644 index 00000000000..0bdb52ef9a5 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_Iterator.h @@ -0,0 +1,35 @@ +#ifndef FREESTYLE_PYTHON_ITERATOR_H +#define FREESTYLE_PYTHON_ITERATOR_H + +#include <Python.h> + +#include "../system/Iterator.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject Iterator_Type; + +#define BPy_Iterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Iterator_Type) ) + +/*---------------------------Python BPy_Iterator structure definition----------*/ +typedef struct { + PyObject_HEAD + Iterator *it; +} BPy_Iterator; + +/*---------------------------Python BPy_Iterator visible prototypes-----------*/ + +int Iterator_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_ITERATOR_H */ diff --git a/source/blender/freestyle/intern/python/BPy_MediumType.cpp b/source/blender/freestyle/intern/python/BPy_MediumType.cpp new file mode 100644 index 00000000000..63a889e4786 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_MediumType.cpp @@ -0,0 +1,97 @@ +#include "BPy_MediumType.h" + +#include "BPy_Convert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +/*-----------------------BPy_MediumType type definition ------------------------------*/ + +static char MediumType___doc__[] = +"The different blending modes available to similate the interaction\n" +"media-medium:\n" +"\n" +"* Stroke.DRY_MEDIUM: To simulate a dry medium such as Pencil or Charcoal.\n" +"* Stroke.HUMID_MEDIUM: To simulate ink painting (color substraction blending).\n" +"* Stroke.OPAQUE_MEDIUM: To simulate an opaque medium (oil, spray...).\n"; + +PyTypeObject MediumType_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "MediumType", /* tp_name */ + sizeof(PyLongObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + MediumType___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &PyLong_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/*-----------------------BPy_IntegrationType instance definitions -------------------------*/ + +PyLongObject _BPy_MediumType_DRY_MEDIUM = { + PyVarObject_HEAD_INIT(&MediumType_Type, 1) + { Stroke::DRY_MEDIUM } +}; +PyLongObject _BPy_MediumType_HUMID_MEDIUM = { + PyVarObject_HEAD_INIT(&MediumType_Type, 1) + { Stroke::HUMID_MEDIUM } +}; +PyLongObject _BPy_MediumType_OPAQUE_MEDIUM = { + PyVarObject_HEAD_INIT(&MediumType_Type, 1) + { Stroke::OPAQUE_MEDIUM } +}; + +//-------------------MODULE INITIALIZATION-------------------------------- + +int MediumType_Init( PyObject *module ) +{ + if( module == NULL ) + return -1; + + if( PyType_Ready( &MediumType_Type ) < 0 ) + return -1; + Py_INCREF( &MediumType_Type ); + PyModule_AddObject(module, "MediumType", (PyObject *)&MediumType_Type); + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + diff --git a/source/blender/freestyle/intern/python/BPy_MediumType.h b/source/blender/freestyle/intern/python/BPy_MediumType.h new file mode 100644 index 00000000000..3bc50477295 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_MediumType.h @@ -0,0 +1,42 @@ +#ifndef FREESTYLE_PYTHON_MEDIUMTYPE_H +#define FREESTYLE_PYTHON_MEDIUMTYPE_H + +#include <Python.h> + +#include "../stroke/Stroke.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject MediumType_Type; + +#define BPy_MediumType_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &MediumType_Type) ) + +/*---------------------------Python BPy_MediumType structure definition----------*/ +typedef struct { + PyLongObject i; +} BPy_MediumType; + +/*---------------------------Python BPy_MediumType visible prototypes-----------*/ + +int MediumType_Init( PyObject *module ); + +// internal constants +extern PyLongObject _BPy_MediumType_DRY_MEDIUM; +extern PyLongObject _BPy_MediumType_HUMID_MEDIUM; +extern PyLongObject _BPy_MediumType_OPAQUE_MEDIUM; +// public constants +#define BPy_MediumType_DRY_MEDIUM ((PyObject *)&_BPy_MediumType_DRY_MEDIUM) +#define BPy_MediumType_HUMID_MEDIUM ((PyObject *)&_BPy_MediumType_HUMID_MEDIUM) +#define BPy_MediumType_OPAQUE_MEDIUM ((PyObject *)&_BPy_MediumType_OPAQUE_MEDIUM) + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_MEDIUMTYPE_H */ diff --git a/source/blender/freestyle/intern/python/BPy_Nature.cpp b/source/blender/freestyle/intern/python/BPy_Nature.cpp new file mode 100644 index 00000000000..bfbd612c0a5 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_Nature.cpp @@ -0,0 +1,303 @@ +#include "BPy_Nature.h" + +#include "BPy_Convert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +static PyObject *BPy_Nature___and__(PyObject *a, PyObject *b); +static PyObject *BPy_Nature___xor__(PyObject *a, PyObject *b); +static PyObject *BPy_Nature___or__(PyObject *a, PyObject *b); +static int BPy_Nature_bool(PyObject *v); + +/*-----------------------BPy_Nature number method definitions --------------------*/ + +PyNumberMethods nature_as_number = { + 0, /* binaryfunc nb_add */ + 0, /* binaryfunc nb_subtract */ + 0, /* binaryfunc nb_multiply */ + 0, /* binaryfunc nb_remainder */ + 0, /* binaryfunc nb_divmod */ + 0, /* ternaryfunc nb_power */ + 0, /* unaryfunc nb_negative */ + 0, /* unaryfunc nb_positive */ + 0, /* unaryfunc nb_absolute */ + (inquiry)BPy_Nature_bool, /* inquiry nb_bool */ + 0, /* unaryfunc nb_invert */ + 0, /* binaryfunc nb_lshift */ + 0, /* binaryfunc nb_rshift */ + (binaryfunc)BPy_Nature___and__, /* binaryfunc nb_and */ + (binaryfunc)BPy_Nature___xor__, /* binaryfunc nb_xor */ + (binaryfunc)BPy_Nature___or__, /* binaryfunc nb_or */ + 0, /* unaryfunc nb_int */ + 0, /* void *nb_reserved */ + 0, /* unaryfunc nb_float */ + 0, /* binaryfunc nb_inplace_add */ + 0, /* binaryfunc nb_inplace_subtract */ + 0, /* binaryfunc nb_inplace_multiply */ + 0, /* binaryfunc nb_inplace_remainder */ + 0, /* ternaryfunc nb_inplace_power */ + 0, /* binaryfunc nb_inplace_lshift */ + 0, /* binaryfunc nb_inplace_rshift */ + 0, /* binaryfunc nb_inplace_and */ + 0, /* binaryfunc nb_inplace_xor */ + 0, /* binaryfunc nb_inplace_or */ + 0, /* binaryfunc nb_floor_divide */ + 0, /* binaryfunc nb_true_divide */ + 0, /* binaryfunc nb_inplace_floor_divide */ + 0, /* binaryfunc nb_inplace_true_divide */ + 0, /* unaryfunc nb_index */ +}; + +/*-----------------------BPy_Nature docstring ------------------------------------*/ + +static char Nature___doc__[] = +"Different possible natures of 0D and 1D elements of the ViewMap.\n" +"\n" +"Vertex natures:\n" +"\n" +"* Nature.POINT: True for any 0D element.\n" +"* Nature.S_VERTEX: True for SVertex.\n" +"* Nature.VIEW_VERTEX: True for ViewVertex.\n" +"* Nature.NON_T_VERTEX: True for NonTVertex.\n" +"* Nature.T_VERTEX: True for TVertex.\n" +"* Nature.CUSP: True for CUSP.\n" +"\n" +"Edge natures:\n" +"\n" +"* Nature.NO_FEATURE: True for non feature edges (always false for 1D\n" +" elements of the ViewMap).\n" +"* Nature.SILHOUETTE: True for silhouettes.\n" +"* Nature.BORDER: True for borders.\n" +"* Nature.CREASE: True for creases.\n" +"* Nature.RIDGE: True for ridges.\n" +"* Nature.VALLEY: True for valleys.\n" +"* Nature.SUGGESTIVE_CONTOUR: True for suggestive contours.\n" +"* Nature.MATERIAL_BOUNDARY: True for edges at material boundaries.\n"; + +/*-----------------------BPy_Nature type definition ------------------------------*/ + +PyTypeObject Nature_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "Nature", /* tp_name */ + sizeof(PyLongObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + &nature_as_number, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + Nature___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &PyLong_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/*-----------------------BPy_Nature instance definitions ----------------------------------*/ + +static PyLongObject _Nature_POINT = { + PyVarObject_HEAD_INIT(&Nature_Type, 1) + { Nature::POINT } +}; +static PyLongObject _Nature_S_VERTEX = { + PyVarObject_HEAD_INIT(&Nature_Type, 1) + { Nature::S_VERTEX } +}; +static PyLongObject _Nature_VIEW_VERTEX = { + PyVarObject_HEAD_INIT(&Nature_Type, 1) + { Nature::VIEW_VERTEX } +}; +static PyLongObject _Nature_NON_T_VERTEX = { + PyVarObject_HEAD_INIT(&Nature_Type, 1) + { Nature::NON_T_VERTEX } +}; +static PyLongObject _Nature_T_VERTEX = { + PyVarObject_HEAD_INIT(&Nature_Type, 1) + { Nature::T_VERTEX } +}; +static PyLongObject _Nature_CUSP = { + PyVarObject_HEAD_INIT(&Nature_Type, 1) + { Nature::CUSP } +}; +static PyLongObject _Nature_NO_FEATURE = { + PyVarObject_HEAD_INIT(&Nature_Type, 1) + { Nature::NO_FEATURE } +}; +static PyLongObject _Nature_SILHOUETTE = { + PyVarObject_HEAD_INIT(&Nature_Type, 1) + { Nature::SILHOUETTE } +}; +static PyLongObject _Nature_BORDER = { + PyVarObject_HEAD_INIT(&Nature_Type, 1) + { Nature::BORDER } +}; +static PyLongObject _Nature_CREASE = { + PyVarObject_HEAD_INIT(&Nature_Type, 1) + { Nature::CREASE } +}; +static PyLongObject _Nature_RIDGE = { + PyVarObject_HEAD_INIT(&Nature_Type, 1) + { Nature::RIDGE } +}; +static PyLongObject _Nature_VALLEY = { + PyVarObject_HEAD_INIT(&Nature_Type, 1) + { Nature::VALLEY } +}; +static PyLongObject _Nature_SUGGESTIVE_CONTOUR = { + PyVarObject_HEAD_INIT(&Nature_Type, 1) + { Nature::SUGGESTIVE_CONTOUR } +}; +static PyLongObject _Nature_MATERIAL_BOUNDARY = { + PyVarObject_HEAD_INIT(&Nature_Type, 1) + { Nature::MATERIAL_BOUNDARY } +}; + +#define BPy_Nature_POINT ((PyObject *)&_Nature_POINT) +#define BPy_Nature_S_VERTEX ((PyObject *)&_Nature_S_VERTEX) +#define BPy_Nature_VIEW_VERTEX ((PyObject *)&_Nature_VIEW_VERTEX) +#define BPy_Nature_NON_T_VERTEX ((PyObject *)&_Nature_NON_T_VERTEX) +#define BPy_Nature_T_VERTEX ((PyObject *)&_Nature_T_VERTEX) +#define BPy_Nature_CUSP ((PyObject *)&_Nature_CUSP) +#define BPy_Nature_NO_FEATURE ((PyObject *)&_Nature_NO_FEATURE) +#define BPy_Nature_SILHOUETTE ((PyObject *)&_Nature_SILHOUETTE) +#define BPy_Nature_BORDER ((PyObject *)&_Nature_BORDER) +#define BPy_Nature_CREASE ((PyObject *)&_Nature_CREASE) +#define BPy_Nature_RIDGE ((PyObject *)&_Nature_RIDGE) +#define BPy_Nature_VALLEY ((PyObject *)&_Nature_VALLEY) +#define BPy_Nature_SUGGESTIVE_CONTOUR ((PyObject *)&_Nature_SUGGESTIVE_CONTOUR) +#define BPy_Nature_MATERIAL_BOUNDARY ((PyObject *)&_Nature_MATERIAL_BOUNDARY) + +//-------------------MODULE INITIALIZATION-------------------------------- +int Nature_Init( PyObject *module ) +{ + if( module == NULL ) + return -1; + + if( PyType_Ready( &Nature_Type ) < 0 ) + return -1; + Py_INCREF( &Nature_Type ); + PyModule_AddObject(module, "Nature", (PyObject *)&Nature_Type); + + // VertexNature + PyDict_SetItemString( Nature_Type.tp_dict, "POINT", BPy_Nature_POINT); + PyDict_SetItemString( Nature_Type.tp_dict, "S_VERTEX", BPy_Nature_S_VERTEX); + PyDict_SetItemString( Nature_Type.tp_dict, "VIEW_VERTEX", BPy_Nature_VIEW_VERTEX ); + PyDict_SetItemString( Nature_Type.tp_dict, "NON_T_VERTEX", BPy_Nature_NON_T_VERTEX ); + PyDict_SetItemString( Nature_Type.tp_dict, "T_VERTEX", BPy_Nature_T_VERTEX ); + PyDict_SetItemString( Nature_Type.tp_dict, "CUSP", BPy_Nature_CUSP ); + + // EdgeNature + PyDict_SetItemString( Nature_Type.tp_dict, "NO_FEATURE", BPy_Nature_NO_FEATURE ); + PyDict_SetItemString( Nature_Type.tp_dict, "SILHOUETTE", BPy_Nature_SILHOUETTE ); + PyDict_SetItemString( Nature_Type.tp_dict, "BORDER", BPy_Nature_BORDER ); + PyDict_SetItemString( Nature_Type.tp_dict, "CREASE", BPy_Nature_CREASE ); + PyDict_SetItemString( Nature_Type.tp_dict, "RIDGE", BPy_Nature_RIDGE ); + PyDict_SetItemString( Nature_Type.tp_dict, "VALLEY", BPy_Nature_VALLEY ); + PyDict_SetItemString( Nature_Type.tp_dict, "SUGGESTIVE_CONTOUR", BPy_Nature_SUGGESTIVE_CONTOUR ); + PyDict_SetItemString( Nature_Type.tp_dict, "MATERIAL_BOUNDARY", BPy_Nature_MATERIAL_BOUNDARY ); + + return 0; +} + +static PyObject * +BPy_Nature_bitwise(PyObject *a, int op, PyObject *b) +{ + BPy_Nature *result; + + if (!BPy_Nature_Check(a) || !BPy_Nature_Check(b)) { + PyErr_SetString(PyExc_TypeError, "operands must be a Nature object"); + return NULL; + } + if (Py_SIZE(a) != 1) { + stringstream msg; + msg << "operand 1: unexpected Nature byte length: " << Py_SIZE(a); + PyErr_SetString(PyExc_TypeError, msg.str().c_str()); + return NULL; + } + if (Py_SIZE(b) != 1) { + stringstream msg; + msg << "operand 2: unexpected Nature byte length: " << Py_SIZE(b); + PyErr_SetString(PyExc_TypeError, msg.str().c_str()); + return NULL; + } + result = PyObject_NewVar(BPy_Nature, &Nature_Type, 1); + if (!result) + return NULL; + if (Py_SIZE(result) != 1) { + stringstream msg; + msg << "unexpected Nature byte length: " << Py_SIZE(result); + PyErr_SetString(PyExc_TypeError, msg.str().c_str()); + return NULL; + } + switch (op) { + case '&': + result->i.ob_digit[0] = (((PyLongObject *)a)->ob_digit[0]) & (((PyLongObject *)b)->ob_digit)[0]; + break; + case '^': + result->i.ob_digit[0] = (((PyLongObject *)a)->ob_digit[0]) ^ (((PyLongObject *)b)->ob_digit)[0]; + break; + case '|': + result->i.ob_digit[0] = (((PyLongObject *)a)->ob_digit[0]) | (((PyLongObject *)b)->ob_digit)[0]; + break; + } + return (PyObject *)result; +} + +static PyObject * +BPy_Nature___and__(PyObject *a, PyObject *b) +{ + return BPy_Nature_bitwise(a, '&', b); +} + +static PyObject * +BPy_Nature___xor__(PyObject *a, PyObject *b) +{ + return BPy_Nature_bitwise(a, '^', b); +} + +static PyObject * +BPy_Nature___or__(PyObject *a, PyObject *b) +{ + return BPy_Nature_bitwise(a, '|', b); +} + +static int +BPy_Nature_bool(PyObject *v) +{ + return ((PyLongObject *)v)->ob_digit[0] != 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + diff --git a/source/blender/freestyle/intern/python/BPy_Nature.h b/source/blender/freestyle/intern/python/BPy_Nature.h new file mode 100644 index 00000000000..8c38415242e --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_Nature.h @@ -0,0 +1,33 @@ +#ifndef FREESTYLE_PYTHON_NATURE_H +#define FREESTYLE_PYTHON_NATURE_H + +#include <Python.h> + +#include "../winged_edge/Nature.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject Nature_Type; + +#define BPy_Nature_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Nature_Type) ) + +/*---------------------------Python BPy_Nature structure definition----------*/ +typedef struct { + PyLongObject i; +} BPy_Nature; + +/*---------------------------Python BPy_Nature visible prototypes-----------*/ + +int Nature_Init( PyObject *module ); + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_NATURE_H */ diff --git a/source/blender/freestyle/intern/python/BPy_Operators.cpp b/source/blender/freestyle/intern/python/BPy_Operators.cpp new file mode 100644 index 00000000000..79c3fb64a82 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_Operators.cpp @@ -0,0 +1,612 @@ +#include "BPy_Operators.h" + +#include "BPy_BinaryPredicate1D.h" +#include "BPy_UnaryPredicate0D.h" +#include "BPy_UnaryPredicate1D.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h" +#include "UnaryFunction1D/BPy_UnaryFunction1DVoid.h" +#include "Iterator/BPy_ViewEdgeIterator.h" +#include "Iterator/BPy_ChainingIterator.h" +#include "BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- +int Operators_Init( PyObject *module ) +{ + if( module == NULL ) + return -1; + + if( PyType_Ready( &Operators_Type ) < 0 ) + return -1; + + Py_INCREF( &Operators_Type ); + PyModule_AddObject(module, "Operators", (PyObject *)&Operators_Type); + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char Operators___doc__[] = +"Class defining the operators used in a style module. There are five\n" +"types of operators: Selection, chaining, splitting, sorting and\n" +"creation. All these operators are user controlled through functors,\n" +"predicates and shaders that are taken as arguments.\n"; + +static void Operators___dealloc__(BPy_Operators* self) +{ + Py_TYPE(self)->tp_free((PyObject*)self); +} + +static char Operators_select___doc__[] = +".. staticmethod:: select(pred)\n" +"\n" +" Selects the ViewEdges of the ViewMap verifying a specified\n" +" condition.\n" +"\n" +" :arg pred: The predicate expressing this condition.\n" +" :type pred: UnaryPredicate1D\n"; + +static PyObject * Operators_select(BPy_Operators* self, PyObject *args) +{ + PyObject *obj = 0; + + if ( !PyArg_ParseTuple(args, "O!", &UnaryPredicate1D_Type, &obj) ) + return NULL; + if ( !((BPy_UnaryPredicate1D *) obj)->up1D ) { + PyErr_SetString(PyExc_TypeError, "Operators.select(): 1st argument: invalid UnaryPredicate1D object"); + return NULL; + } + + if (Operators::select(*( ((BPy_UnaryPredicate1D *) obj)->up1D )) < 0) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_RuntimeError, "Operators.select() failed"); + return NULL; + } + + Py_RETURN_NONE; +} + +static char Operators_chain___doc__[] = +".. staticmethod:: chain(it, pred, modifier)\n" +"\n" +" Builds a set of chains from the current set of ViewEdges. Each\n" +" ViewEdge of the current list starts a new chain. The chaining\n" +" operator then iterates over the ViewEdges of the ViewMap using the\n" +" user specified iterator. This operator only iterates using the\n" +" increment operator and is therefore unidirectional.\n" +"\n" +" :arg it: The iterator on the ViewEdges of the ViewMap. It contains\n" +" the chaining rule.\n" +" :type it: :class:`ViewEdgeIterator`\n" +" :arg pred: The predicate on the ViewEdge that expresses the\n" +" stopping condition.\n" +" :type pred: :class:`UnaryPredicate1D`\n" +" :arg modifier: A function that takes a ViewEdge as argument and\n" +" that is used to modify the processed ViewEdge state (the\n" +" timestamp incrementation is a typical illustration of such a\n" +" modifier).\n" +" :type modifier: :class:`UnaryFunction1DVoid`\n" +"\n" +".. staticmethod:: chain(it, pred)\n" +"\n" +" Builds a set of chains from the current set of ViewEdges. Each\n" +" ViewEdge of the current list starts a new chain. The chaining\n" +" operator then iterates over the ViewEdges of the ViewMap using the\n" +" user specified iterator. This operator only iterates using the\n" +" increment operator and is therefore unidirectional. This chaining\n" +" operator is different from the previous one because it doesn't take\n" +" any modifier as argument. Indeed, the time stamp (insuring that a\n" +" ViewEdge is processed one time) is automatically managed in this\n" +" case.\n" +"\n" +" :arg it: The iterator on the ViewEdges of the ViewMap. It contains\n" +" the chaining rule. \n" +" :type it: :class:`ViewEdgeIterator`\n" +" :arg pred: The predicate on the ViewEdge that expresses the\n" +" stopping condition.\n" +" :type pred: :class:`UnaryPredicate1D`\n"; + +// CHANGE: first parameter is a chaining iterator, not just a view + +static PyObject * Operators_chain(BPy_Operators* self, PyObject *args) +{ + PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0; + + if ( !PyArg_ParseTuple(args, "O!O!|O!", &ChainingIterator_Type, &obj1, + &UnaryPredicate1D_Type, &obj2, + &UnaryFunction1DVoid_Type, &obj3) ) + return NULL; + if ( !((BPy_ChainingIterator *) obj1)->c_it ) { + PyErr_SetString(PyExc_TypeError, "Operators.chain(): 1st argument: invalid ChainingIterator object"); + return NULL; + } + if ( !((BPy_UnaryPredicate1D *) obj2)->up1D ) { + PyErr_SetString(PyExc_TypeError, "Operators.chain(): 2nd argument: invalid UnaryPredicate1D object"); + return NULL; + } + + if( !obj3 ) { + + if (Operators::chain( *( ((BPy_ChainingIterator *) obj1)->c_it ), + *( ((BPy_UnaryPredicate1D *) obj2)->up1D ) ) < 0) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_RuntimeError, "Operators.chain() failed"); + return NULL; + } + + } else { + + if ( !((BPy_UnaryFunction1DVoid *) obj3)->uf1D_void ) { + PyErr_SetString(PyExc_TypeError, "Operators.chain(): 3rd argument: invalid UnaryFunction1DVoid object"); + return NULL; + } + if (Operators::chain( *( ((BPy_ChainingIterator *) obj1)->c_it ), + *( ((BPy_UnaryPredicate1D *) obj2)->up1D ), + *( ((BPy_UnaryFunction1DVoid *) obj3)->uf1D_void ) ) < 0) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_RuntimeError, "Operators.chain() failed"); + return NULL; + } + + } + + Py_RETURN_NONE; +} + +static char Operators_bidirectionalChain___doc__[] = +".. staticmethod:: bidirectionalChain(it, pred)\n" +"\n" +" Builds a set of chains from the current set of ViewEdges. Each\n" +" ViewEdge of the current list potentially starts a new chain. The\n" +" chaining operator then iterates over the ViewEdges of the ViewMap\n" +" using the user specified iterator. This operator iterates both using\n" +" the increment and decrement operators and is therefore bidirectional.\n" +" This operator works with a ChainingIterator which contains the\n" +" chaining rules. It is this last one which can be told to chain only\n" +" edges that belong to the selection or not to process twice a ViewEdge\n" +" during the chaining. Each time a ViewEdge is added to a chain, its\n" +" chaining time stamp is incremented. This allows you to keep track of\n" +" the number of chains to which a ViewEdge belongs to.\n" +"\n" +" :arg it: The ChainingIterator on the ViewEdges of the ViewMap. It\n" +" contains the chaining rule.\n" +" :type it: :class:`ChainingIterator`\n" +" :arg pred: The predicate on the ViewEdge that expresses the\n" +" stopping condition.\n" +" :type pred: :class:`UnaryPredicate1D`\n" +"\n" +".. staticmethod:: bidirectionalChain(it)\n" +"\n" +" The only difference with the above bidirectional chaining algorithm\n" +" is that we don't need to pass a stopping criterion. This might be\n" +" desirable when the stopping criterion is already contained in the\n" +" iterator definition. Builds a set of chains from the current set of\n" +" ViewEdges. Each ViewEdge of the current list potentially starts a new\n" +" chain. The chaining operator then iterates over the ViewEdges of the\n" +" ViewMap using the user specified iterator. This operator iterates\n" +" both using the increment and decrement operators and is therefore\n" +" bidirectional. This operator works with a ChainingIterator which\n" +" contains the chaining rules. It is this last one which can be told to\n" +" chain only edges that belong to the selection or not to process twice\n" +" a ViewEdge during the chaining. Each time a ViewEdge is added to a\n" +" chain, its chaining time stamp is incremented. This allows you to\n" +" keep track of the number of chains to which a ViewEdge belongs to.\n" +"\n" +" :arg it: The ChainingIterator on the ViewEdges of the ViewMap. It\n" +" contains the chaining rule.\n" +" :type it: :class:`ChainingIterator`\n"; + +static PyObject * Operators_bidirectionalChain(BPy_Operators* self, PyObject *args) +{ + PyObject *obj1 = 0, *obj2 = 0; + + if( !PyArg_ParseTuple(args, "O!|O!", &ChainingIterator_Type, &obj1, &UnaryPredicate1D_Type, &obj2) ) + return NULL; + if ( !((BPy_ChainingIterator *) obj1)->c_it ) { + PyErr_SetString(PyExc_TypeError, "Operators.bidirectionalChain(): 1st argument: invalid ChainingIterator object"); + return NULL; + } + + if( !obj2 ) { + + if (Operators::bidirectionalChain( *( ((BPy_ChainingIterator *) obj1)->c_it ) ) < 0) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_RuntimeError, "Operators.bidirectionalChain() failed"); + return NULL; + } + + } else { + + if ( !((BPy_UnaryPredicate1D *) obj2)->up1D ) { + PyErr_SetString(PyExc_TypeError, "Operators.bidirectionalChain(): 2nd argument: invalid UnaryPredicate1D object"); + return NULL; + } + if (Operators::bidirectionalChain( *( ((BPy_ChainingIterator *) obj1)->c_it ), + *( ((BPy_UnaryPredicate1D *) obj2)->up1D ) ) < 0) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_RuntimeError, "Operators.bidirectionalChain() failed"); + return NULL; + } + + } + + Py_RETURN_NONE; +} + +static char Operators_sequentialSplit___doc__[] = +".. staticmethod:: sequentialSplit(startingPred, stoppingPred, sampling=0.0)\n" +"\n" +" Splits each chain of the current set of chains in a sequential way.\n" +" The points of each chain are processed (with a specified sampling)\n" +" sequentially. Each time a user specified starting condition is\n" +" verified, a new chain begins and ends as soon as a user-defined\n" +" stopping predicate is verified. This allows chains overlapping rather\n" +" than chains partitioning. The first point of the initial chain is the\n" +" first point of one of the resulting chains. The splitting ends when\n" +" no more chain can start.\n" +"\n" +" :arg startingPred: The predicate on a point that expresses the\n" +" starting condition.\n" +" :type startingPred: :class:`UnaryPredicate0D`\n" +" :arg stoppingPred: The predicate on a point that expresses the\n" +" stopping condition.\n" +" :type stoppingPred: :class:`UnaryPredicate0D`\n" +" :arg sampling: The resolution used to sample the chain for the\n" +" predicates evaluation. (The chain is not actually resampled;\n" +" a virtual point only progresses along the curve using this\n" +" resolution.)\n" +" :type sampling: float\n" +"\n" +".. staticmethod:: sequentialSplit(pred, sampling=0.0)\n" +"\n" +" Splits each chain of the current set of chains in a sequential way.\n" +" The points of each chain are processed (with a specified sampling)\n" +" sequentially and each time a user specified condition is verified,\n" +" the chain is split into two chains. The resulting set of chains is a\n" +" partition of the initial chain\n" +"\n" +" :arg pred: The predicate on a point that expresses the splitting\n" +" condition.\n" +" :type pred: :class:`UnaryPredicate0D`\n" +" :arg sampling: The resolution used to sample the chain for the\n" +" predicate evaluation. (The chain is not actually resampled; a\n" +" virtual point only progresses along the curve using this\n" +" resolution.)\n" +" :type sampling: float\n"; + +static PyObject * Operators_sequentialSplit(BPy_Operators* self, PyObject *args) +{ + PyObject *obj1 = 0, *obj2 = 0; + float f = 0.0; + + if( !PyArg_ParseTuple(args, "O!|Of", &UnaryPredicate0D_Type, &obj1, &obj2, &f) ) + return NULL; + if ( !((BPy_UnaryPredicate0D *) obj1)->up0D ) { + PyErr_SetString(PyExc_TypeError, "Operators.sequentialSplit(): 1st argument: invalid UnaryPredicate0D object"); + return NULL; + } + + if( obj2 && BPy_UnaryPredicate0D_Check(obj2) ) { + + if ( !((BPy_UnaryPredicate0D *) obj2)->up0D ) { + PyErr_SetString(PyExc_TypeError, "Operators.sequentialSplit(): 2nd argument: invalid UnaryPredicate0D object"); + return NULL; + } + if (Operators::sequentialSplit( *( ((BPy_UnaryPredicate0D *) obj1)->up0D ), + *( ((BPy_UnaryPredicate0D *) obj2)->up0D ), + f ) < 0) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_RuntimeError, "Operators.sequentialSplit() failed"); + return NULL; + } + + } else { + + if ( obj2 ) { + if ( !PyFloat_Check(obj2) ) { + PyErr_SetString(PyExc_TypeError, "Operators.sequentialSplit(): invalid 2nd argument"); + return NULL; + } + f = PyFloat_AsDouble(obj2); + } + if (Operators::sequentialSplit( *( ((BPy_UnaryPredicate0D *) obj1)->up0D ), f ) < 0) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_RuntimeError, "Operators.sequentialSplit() failed"); + return NULL; + } + + } + + Py_RETURN_NONE; +} + +static char Operators_recursiveSplit___doc__[] = +".. staticmethod:: recursiveSplit(func, pred, sampling=0.0)\n" +"\n" +" Splits the current set of chains in a recursive way. We process the\n" +" points of each chain (with a specified sampling) to find the point\n" +" minimizing a specified function. The chain is split in two at this\n" +" point and the two new chains are processed in the same way. The\n" +" recursivity level is controlled through a predicate 1D that expresses\n" +" a stopping condition on the chain that is about to be processed.\n" +"\n" +" :arg func: The Unary Function evaluated at each point of the chain.\n" +" The splitting point is the point minimizing this function.\n" +" :type func: :class:`UnaryFunction0DDouble`\n" +" :arg pred: The Unary Predicate expressing the recursivity stopping\n" +" condition. This predicate is evaluated for each curve before it\n" +" actually gets split. If pred(chain) is true, the curve won't be\n" +" split anymore.\n" +" :type pred: :class:`UnaryPredicate1D`\n" +" :arg sampling: The resolution used to sample the chain for the\n" +" predicates evaluation. (The chain is not actually resampled, a\n" +" virtual point only progresses along the curve using this\n" +" resolution.)\n" +" :type sampling: float\n" +"\n" +".. staticmethod:: recursiveSplit(func, pred0d, pred, sampling=0.0)\n" +"\n" +" Splits the current set of chains in a recursive way. We process the\n" +" points of each chain (with a specified sampling) to find the point\n" +" minimizing a specified function. The chain is split in two at this\n" +" point and the two new chains are processed in the same way. The user\n" +" can specify a 0D predicate to make a first selection on the points\n" +" that can potentially be split. A point that doesn't verify the 0D\n" +" predicate won't be candidate in realizing the min. The recursivity\n" +" level is controlled through a predicate 1D that expresses a stopping\n" +" condition on the chain that is about to be processed.\n" +"\n" +" :arg func: The Unary Function evaluated at each point of the chain.\n" +" The splitting point is the point minimizing this function.\n" +" :type func: :class:`UnaryFunction0DDouble`\n" +" :arg pred0d: The Unary Predicate 0D used to select the candidate\n" +" points where the split can occur. For example, it is very likely\n" +" that would rather have your chain splitting around its middle\n" +" point than around one of its extremities. A 0D predicate working\n" +" on the curvilinear abscissa allows to add this kind of constraints.\n" +" :type pred0d: :class:`UnaryPredicate0D`\n" +" :arg pred: The Unary Predicate expressing the recursivity stopping\n" +" condition. This predicate is evaluated for each curve before it\n" +" actually gets split. If pred(chain) is true, the curve won't be\n" +" split anymore.\n" +" :type pred: :class:`UnaryPredicate1D`\n" +" :arg sampling: The resolution used to sample the chain for the\n" +" predicates evaluation. (The chain is not actually resampled; a\n" +" virtual point only progresses along the curve using this\n" +" resolution.)\n" +" :type sampling: float\n"; + +static PyObject * Operators_recursiveSplit(BPy_Operators* self, PyObject *args) +{ + PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0; + float f = 0.0; + + if ( !PyArg_ParseTuple(args, "O!O|Of", &UnaryFunction0DDouble_Type, &obj1, &obj2, &obj3, &f) ) + return NULL; + if ( !((BPy_UnaryFunction0DDouble *) obj1)->uf0D_double ) { + PyErr_SetString(PyExc_TypeError, "Operators.recursiveSplit(): 1st argument: invalid UnaryFunction0DDouble object"); + return NULL; + } + + if ( BPy_UnaryPredicate1D_Check(obj2) ) { + + if ( !((BPy_UnaryPredicate1D *) obj2)->up1D ) { + PyErr_SetString(PyExc_TypeError, "Operators.recursiveSplit(): 2nd argument: invalid UnaryPredicate1D object"); + return NULL; + } + if ( obj3 ) { + if ( !PyFloat_Check(obj3) ) { + PyErr_SetString(PyExc_TypeError, "Operators.recursiveSplit(): invalid 3rd argument"); + return NULL; + } + f = PyFloat_AsDouble(obj3); + } + if (Operators::recursiveSplit( *( ((BPy_UnaryFunction0DDouble *) obj1)->uf0D_double ), + *( ((BPy_UnaryPredicate1D *) obj2)->up1D ), + f ) < 0) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_RuntimeError, "Operators.recursiveSplit() failed"); + return NULL; + } + + } else { + + if ( !BPy_UnaryPredicate0D_Check(obj2) || !((BPy_UnaryPredicate0D *) obj2)->up0D ) { + PyErr_SetString(PyExc_TypeError, "Operators.recursiveSplit(): invalid 2nd argument"); + return NULL; + } + if ( !BPy_UnaryPredicate1D_Check(obj3) || !((BPy_UnaryPredicate1D *) obj3)->up1D ) { + PyErr_SetString(PyExc_TypeError, "Operators.recursiveSplit(): invalid 3rd argument"); + return NULL; + } + if (Operators::recursiveSplit( *( ((BPy_UnaryFunction0DDouble *) obj1)->uf0D_double ), + *( ((BPy_UnaryPredicate0D *) obj2)->up0D ), + *( ((BPy_UnaryPredicate1D *) obj3)->up1D ), + f ) < 0) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_RuntimeError, "Operators.recursiveSplit() failed"); + return NULL; + } + + } + + Py_RETURN_NONE; +} + +static char Operators_sort___doc__[] = +".. staticmethod:: sort(pred)\n" +"\n" +" Sorts the current set of chains (or viewedges) according to the\n" +" comparison predicate given as argument.\n" +"\n" +" :arg pred: The binary predicate used for the comparison.\n" +" :type pred: BinaryPredicate1D\n"; + +static PyObject * Operators_sort(BPy_Operators* self, PyObject *args) +{ + PyObject *obj = 0; + + if ( !PyArg_ParseTuple(args, "O!", &BinaryPredicate1D_Type, &obj) ) + return NULL; + if ( !((BPy_BinaryPredicate1D *) obj)->bp1D ) { + PyErr_SetString(PyExc_TypeError, "Operators.sort(): 1st argument: invalid BinaryPredicate1D object"); + return NULL; + } + + if (Operators::sort(*( ((BPy_BinaryPredicate1D *) obj)->bp1D )) < 0) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_RuntimeError, "Operators.sort() failed"); + return NULL; + } + Py_RETURN_NONE; +} + +static char Operators_create___doc__[] = +".. staticmethod:: create(pred, shaders)\n" +"\n" +" Creates and shades the strokes from the current set of chains. A\n" +" predicate can be specified to make a selection pass on the chains.\n" +"\n" +" :arg pred: The predicate that a chain must verify in order to be\n" +" transform as a stroke.\n" +" :type pred: :class:`UnaryPredicate1D`\n" +" :arg shaders: The list of shaders used to shade the strokes.\n" +" :type shaders: List of StrokeShader objects\n"; + +static PyObject * Operators_create(BPy_Operators* self, PyObject *args) +{ + PyObject *obj1 = 0, *obj2 = 0; + + if ( !PyArg_ParseTuple(args, "O!O!", &UnaryPredicate1D_Type, &obj1, &PyList_Type, &obj2) ) + return NULL; + if ( !((BPy_UnaryPredicate1D *) obj1)->up1D ) { + PyErr_SetString(PyExc_TypeError, "Operators.create(): 1st argument: invalid UnaryPredicate1D object"); + return NULL; + } + + vector<StrokeShader *> shaders; + for( int i = 0; i < PyList_Size(obj2); i++) { + PyObject *py_ss = PyList_GetItem(obj2,i); + + if ( !BPy_StrokeShader_Check(py_ss) ) { + PyErr_SetString(PyExc_TypeError, "Operators.create() 2nd argument must be a list of StrokeShader objects"); + return NULL; + } + shaders.push_back( ((BPy_StrokeShader *) py_ss)->ss ); + } + + if (Operators::create( *( ((BPy_UnaryPredicate1D *) obj1)->up1D ), shaders) < 0) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_RuntimeError, "Operators.create() failed"); + return NULL; + } + + Py_RETURN_NONE; +} + +static char Operators_getViewEdgesSize___doc__[] = +".. staticmethod:: getViewEdgesSize()\n" +"\n" +" Returns the number of ViewEdges.\n" +"\n" +" :return: The number of ViewEdges.\n" +" :rtype: int\n"; + +static PyObject * Operators_getViewEdgesSize( BPy_Operators* self) { + return PyLong_FromLong( Operators::getViewEdgesSize() ); +} + +static char Operators_getChainsSize___doc__[] = +".. staticmethod:: getChainsSize()\n" +"\n" +" Returns the number of Chains.\n" +"\n" +" :return: The number of Chains.\n" +" :rtype: int\n"; + +static PyObject * Operators_getChainsSize( BPy_Operators* self ) { + return PyLong_FromLong( Operators::getChainsSize() ); +} + +static char Operators_getStrokesSize___doc__[] = +".. staticmethod:: getStrokesSize()\n" +"\n" +" Returns the number of Strokes.\n" +"\n" +" :return: The number of Strokes.\n" +" :rtype: int\n"; + +static PyObject * Operators_getStrokesSize( BPy_Operators* self) { + return PyLong_FromLong( Operators::getStrokesSize() ); +} + +/*----------------------Operators instance definitions ----------------------------*/ +static PyMethodDef BPy_Operators_methods[] = { + {"select", ( PyCFunction ) Operators_select, METH_VARARGS | METH_STATIC, Operators_select___doc__}, + {"chain", ( PyCFunction ) Operators_chain, METH_VARARGS | METH_STATIC, Operators_chain___doc__}, + {"bidirectionalChain", ( PyCFunction ) Operators_bidirectionalChain, METH_VARARGS | METH_STATIC, Operators_bidirectionalChain___doc__}, + {"sequentialSplit", ( PyCFunction ) Operators_sequentialSplit, METH_VARARGS | METH_STATIC, Operators_sequentialSplit___doc__}, + {"recursiveSplit", ( PyCFunction ) Operators_recursiveSplit, METH_VARARGS | METH_STATIC, Operators_recursiveSplit___doc__}, + {"sort", ( PyCFunction ) Operators_sort, METH_VARARGS | METH_STATIC, Operators_sort___doc__}, + {"create", ( PyCFunction ) Operators_create, METH_VARARGS | METH_STATIC, Operators_create___doc__}, + {"getViewEdgesSize", ( PyCFunction ) Operators_getViewEdgesSize, METH_NOARGS | METH_STATIC, Operators_getViewEdgesSize___doc__}, + {"getChainsSize", ( PyCFunction ) Operators_getChainsSize, METH_NOARGS | METH_STATIC, Operators_getChainsSize___doc__}, + {"getStrokesSize", ( PyCFunction ) Operators_getStrokesSize, METH_NOARGS | METH_STATIC, Operators_getStrokesSize___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_Operators type definition ------------------------------*/ + +PyTypeObject Operators_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "Operators", /* tp_name */ + sizeof(BPy_Operators), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)Operators___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + Operators___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_Operators_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + diff --git a/source/blender/freestyle/intern/python/BPy_Operators.h b/source/blender/freestyle/intern/python/BPy_Operators.h new file mode 100644 index 00000000000..5e01d6bb1fe --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_Operators.h @@ -0,0 +1,34 @@ +#ifndef FREESTYLE_PYTHON_OPERATORS_H +#define FREESTYLE_PYTHON_OPERATORS_H + +#include <Python.h> + +#include "../stroke/Operators.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject Operators_Type; + +#define BPy_Operators_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Operators_Type) ) + +/*---------------------------Python BPy_Operators structure definition----------*/ +typedef struct { + PyObject_HEAD +} BPy_Operators; + +/*---------------------------Python BPy_Operators visible prototypes-----------*/ + +int Operators_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_OPERATORS_H */ diff --git a/source/blender/freestyle/intern/python/BPy_SShape.cpp b/source/blender/freestyle/intern/python/BPy_SShape.cpp new file mode 100644 index 00000000000..65951182f10 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_SShape.cpp @@ -0,0 +1,330 @@ +#include "BPy_SShape.h" + +#include "BPy_Convert.h" +#include "BPy_BBox.h" +#include "BPy_Id.h" +#include "Interface0D/BPy_SVertex.h" +#include "Interface1D/BPy_FEdge.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- +int SShape_Init( PyObject *module ) +{ + if( module == NULL ) + return -1; + + if( PyType_Ready( &SShape_Type ) < 0 ) + return -1; + + Py_INCREF( &SShape_Type ); + PyModule_AddObject(module, "SShape", (PyObject *)&SShape_Type); + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char SShape___doc__[] = +"Class to define a feature shape. It is the gathering of feature\n" +"elements from an identified input shape.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: An SShape object.\n" +" :type iBrother: :class:`SShape`\n"; + +static int SShape___init__(BPy_SShape *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj = NULL; + + if (! PyArg_ParseTuple(args, "|O!", &SShape_Type, &obj) ) + return -1; + + if( !obj ) { + self->ss = new SShape(); + + } else { + self->ss = new SShape(*( ((BPy_SShape *) obj)->ss )); + } + self->borrowed = 0; + + return 0; +} + +static void SShape___dealloc__(BPy_SShape *self) +{ + if( self->ss && !self->borrowed ) + delete self->ss; + Py_TYPE(self)->tp_free((PyObject*)self); +} + +static PyObject * SShape___repr__(BPy_SShape *self) +{ + return PyUnicode_FromFormat("SShape - address: %p", self->ss ); +} + +static char SShape_AddEdge___doc__[] = +".. method:: AddEdge(iEdge)\n" +"\n" +" Adds an FEdge to the list of FEdges.\n" +"\n" +" :arg iEdge: An FEdge object.\n" +" :type iEdge: :class:`FEdge`\n"; + +static PyObject * SShape_AddEdge( BPy_SShape *self , PyObject *args) { + PyObject *py_fe = 0; + + if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) )) + return NULL; + + self->ss->AddEdge( ((BPy_FEdge *) py_fe)->fe ); + + Py_RETURN_NONE; +} + +static char SShape_AddNewVertex___doc__[] = +".. method:: AddNewVertex(iv)\n" +"\n" +" Adds an SVertex to the list of SVertex of this Shape. The SShape\n" +" attribute of the SVertex is also set to this SShape.\n" +"\n" +" :arg iv: An SVertex object.\n" +" :type iv: :class:`SVertex`\n"; + +static PyObject * SShape_AddNewVertex( BPy_SShape *self , PyObject *args) { + PyObject *py_sv = 0; + + if(!( PyArg_ParseTuple(args, "O!", &SVertex_Type, &py_sv) )) + return NULL; + + self->ss->AddNewVertex( ((BPy_SVertex *) py_sv)->sv ); + + Py_RETURN_NONE; +} + +static char SShape_setBBox___doc__[] = +".. method:: setBBox(iBBox)\n" +"\n" +" Sets the bounding box of the SShape.\n" +"\n" +" :arg iBBox: The bounding box of the SShape.\n" +" :type iBBox: :class:`BBox`\n"; + +static PyObject * SShape_setBBox( BPy_SShape *self , PyObject *args) { + PyObject *py_bb = 0; + + if(!( PyArg_ParseTuple(args, "O!", &BBox_Type, &py_bb) )) + return NULL; + + self->ss->setBBox(*( ((BPy_BBox*) py_bb)->bb )); + + Py_RETURN_NONE; +} + +static char SShape_ComputeBBox___doc__[] = +".. method:: ComputeBBox()\n" +"\n" +" Compute the bbox of the SShape.\n"; + +static PyObject * SShape_ComputeBBox( BPy_SShape *self ) { + self->ss->ComputeBBox(); + + Py_RETURN_NONE; +} + +static char SShape_bbox___doc__[] = +".. method:: bbox()\n" +"\n" +" Returns the bounding box of the SShape.\n" +"\n" +" :return: the bounding box of the SShape.\n" +" :rtype: :class:`BBox`\n"; + +static PyObject * SShape_bbox( BPy_SShape *self ) { + BBox<Vec3r> bb( self->ss->bbox() ); + return BPy_BBox_from_BBox( bb ); +} + +static char SShape_getVertexList___doc__[] = +".. method:: getVertexList()\n" +"\n" +" Returns the list of vertices of the SShape.\n" +"\n" +" :return: The list of vertices objects.\n" +" :rtype: List of :class:`SVertex` objects\n"; + +static PyObject * SShape_getVertexList( BPy_SShape *self ) { + PyObject *py_vertices = PyList_New(0); + + vector< SVertex * > vertices = self->ss->getVertexList(); + vector< SVertex * >::iterator it; + + for( it = vertices.begin(); it != vertices.end(); it++ ) { + PyList_Append( py_vertices, BPy_SVertex_from_SVertex(*( *it )) ); + } + + return py_vertices; +} + +static char SShape_getEdgeList___doc__[] = +".. method:: getEdgeList()\n" +"\n" +" Returns the list of edges of the SShape.\n" +"\n" +" :return: The list of edges of the SShape.\n" +" :rtype: List of :class:`FEdge` objects\n"; + +static PyObject * SShape_getEdgeList( BPy_SShape *self ) { + PyObject *py_edges = PyList_New(0); + + vector< FEdge * > edges = self->ss->getEdgeList(); + vector< FEdge * >::iterator it; + + for( it = edges.begin(); it != edges.end(); it++ ) { + PyList_Append( py_edges, Any_BPy_FEdge_from_FEdge(*( *it )) ); + } + + return py_edges; +} + +static char SShape_getId___doc__[] = +".. method:: getId()\n" +"\n" +" Returns the Id of the SShape.\n" +"\n" +" :return: The Id of the SShape.\n" +" :rtype: :class:`Id`\n"; + +static PyObject * SShape_getId( BPy_SShape *self ) { + Id id( self->ss->getId() ); + return BPy_Id_from_Id( id ); +} + +static char SShape_setId___doc__[] = +".. method:: setId(id)\n" +"\n" +" Sets the Id of the SShape.\n" +"\n" +" :arg id: The Id of the SShape.\n" +" :type id: :class:`Id`\n"; + +static PyObject * SShape_setId( BPy_SShape *self , PyObject *args) { + PyObject *py_id; + + if(!( PyArg_ParseTuple(args, "O!", &Id_Type, &py_id) )) + return NULL; + + self->ss->setId(*( ((BPy_Id *) py_id)->id )); + + Py_RETURN_NONE; +} + +static char SShape_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the SShape.\n" +"\n" +" :return: The name string.\n" +" :rtype: str\n"; + +static PyObject * SShape_getName( BPy_SShape *self ) { + return PyUnicode_FromString( self->ss->getName().c_str() ); +} + +static char SShape_setName___doc__[] = +".. method:: setName(name)\n" +"\n" +" Sets the name of the SShape.\n" +"\n" +" :arg name: A name string.\n" +" :type name: str\n"; + +static PyObject * SShape_setName( BPy_SShape *self , PyObject *args) { + char *s; + + if(!( PyArg_ParseTuple(args, "s", &s) )) + return NULL; + + self->ss->setName(s); + + Py_RETURN_NONE; +} + +// const Material & material (unsigned i) const +// const vector< Material > & materials () const +// void SetMaterials (const vector< Material > &iMaterials) + +/*----------------------SShape instance definitions ----------------------------*/ +static PyMethodDef BPy_SShape_methods[] = { + {"AddEdge", ( PyCFunction ) SShape_AddEdge, METH_VARARGS, SShape_AddEdge___doc__}, + {"AddNewVertex", ( PyCFunction ) SShape_AddNewVertex, METH_VARARGS, SShape_AddNewVertex___doc__}, + {"setBBox", ( PyCFunction ) SShape_setBBox, METH_VARARGS, SShape_setBBox___doc__}, + {"ComputeBBox", ( PyCFunction ) SShape_ComputeBBox, METH_NOARGS, SShape_ComputeBBox___doc__}, + {"bbox", ( PyCFunction ) SShape_bbox, METH_NOARGS, SShape_bbox___doc__}, + {"getVertexList", ( PyCFunction ) SShape_getVertexList, METH_NOARGS, SShape_getVertexList___doc__}, + {"getEdgeList", ( PyCFunction ) SShape_getEdgeList, METH_NOARGS, SShape_getEdgeList___doc__}, + {"getId", ( PyCFunction ) SShape_getId, METH_NOARGS, SShape_getId___doc__}, + {"setId", ( PyCFunction ) SShape_setId, METH_VARARGS, SShape_setId___doc__}, + {"getName", ( PyCFunction ) SShape_getName, METH_NOARGS, SShape_getName___doc__}, + {"setName", ( PyCFunction ) SShape_setName, METH_VARARGS, SShape_setName___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_SShape type definition ------------------------------*/ + +PyTypeObject SShape_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "SShape", /* tp_name */ + sizeof(BPy_SShape), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)SShape___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)SShape___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + SShape___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_SShape_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)SShape___init__, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/BPy_SShape.h b/source/blender/freestyle/intern/python/BPy_SShape.h new file mode 100644 index 00000000000..e8d631f0538 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_SShape.h @@ -0,0 +1,35 @@ +#ifndef FREESTYLE_PYTHON_SSHAPE_H +#define FREESTYLE_PYTHON_SSHAPE_H + +#include <Python.h> + +#include "../view_map/Silhouette.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject SShape_Type; + +#define BPy_SShape_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SShape_Type) ) + +/*---------------------------Python BPy_SShape structure definition----------*/ +typedef struct { + PyObject_HEAD + SShape *ss; + int borrowed; /* non-zero if *ss is a borrowed object */ +} BPy_SShape; + +/*---------------------------Python BPy_SShape visible prototypes-----------*/ + +int SShape_Init( PyObject *module ); + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_SSHAPE_H */ diff --git a/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp new file mode 100644 index 00000000000..e68cc3fd28b --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp @@ -0,0 +1,658 @@ +#include "BPy_StrokeAttribute.h" + +#include "BPy_Convert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- +int StrokeAttribute_Init( PyObject *module ) +{ + if( module == NULL ) + return -1; + + if( PyType_Ready( &StrokeAttribute_Type ) < 0 ) + return -1; + Py_INCREF( &StrokeAttribute_Type ); + PyModule_AddObject(module, "StrokeAttribute", (PyObject *)&StrokeAttribute_Type); + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char StrokeAttribute___doc__[] = +"Class to define a set of attributes associated with a :class:`StrokeVertex`.\n" +"The attribute set stores the color, alpha and thickness values for a Stroke\n" +"Vertex.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: A StrokeAttribute object.\n" +" :type iBrother: :class:`StrokeAttribute`\n" +"\n" +".. method:: __init__(iRColor, iGColor, iBColor, iAlpha, iRThickness, iLThickness)\n" +"\n" +" Builds a stroke vertex attribute from a set of parameters.\n" +"\n" +" :arg iRColor: Red component of a stroke color.\n" +" :type iRColor: float\n" +" :arg iGColor: Green component of a stroke color.\n" +" :type iGColor: float\n" +" :arg iBColor: Blue component of a stroke color.\n" +" :type iBColor: float\n" +" :arg iAlpha: Alpha component of a stroke color.\n" +" :type iAlpha: float\n" +" :arg iRThickness: Stroke thickness on the right.\n" +" :type iRThickness: float\n" +" :arg iLThickness: Stroke thickness on the left.\n" +" :type iLThickness: float\n" +"\n" +".. method:: __init__(a1, a2, t)\n" +"\n" +" Interpolation constructor. Builds a StrokeAttribute from two\n" +" StrokeAttribute objects and an interpolation parameter.\n" +"\n" +" :arg a1: The first StrokeAttribute object.\n" +" :type a1: :class:`StrokeAttribute`\n" +" :arg a2: The second StrokeAttribute object.\n" +" :type a2: :class:`StrokeAttribute`\n" +" :arg t: The interpolation parameter.\n" +" :type t: float\n"; + +static int StrokeAttribute___init__(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds) +{ + + PyObject *obj1 = 0, *obj2 = 0 , *obj3 = 0, *obj4 = 0, *obj5 = 0 , *obj6 = 0; + + if (! PyArg_ParseTuple(args, "|OOOOOO", &obj1, &obj2, &obj3, &obj4, &obj5, &obj6) ) + return -1; + + if( !obj1 || !obj2 || !obj3 ){ + + self->sa = new StrokeAttribute(); + + } else if( BPy_StrokeAttribute_Check(obj1) && + BPy_StrokeAttribute_Check(obj2) && + PyFloat_Check(obj3) ) { + + self->sa = new StrokeAttribute( *( ((BPy_StrokeAttribute *) obj1)->sa ), + *( ((BPy_StrokeAttribute *) obj2)->sa ), + PyFloat_AsDouble( obj3 ) ); + + } else if( obj4 && obj5 && obj6 ) { + + self->sa = new StrokeAttribute( PyFloat_AsDouble( obj1 ), + PyFloat_AsDouble( obj2 ), + PyFloat_AsDouble( obj3 ), + PyFloat_AsDouble( obj4 ), + PyFloat_AsDouble( obj5 ), + PyFloat_AsDouble( obj6 ) ); + + } else { + PyErr_SetString(PyExc_TypeError, "invalid arguments"); + return -1; + } + + self->borrowed = 0; + + return 0; + +} + +static void StrokeAttribute___dealloc__(BPy_StrokeAttribute* self) +{ + if( self->sa && !self->borrowed ) + delete self->sa; + Py_TYPE(self)->tp_free((PyObject*)self); +} + +static PyObject * StrokeAttribute___repr__(BPy_StrokeAttribute* self) +{ + stringstream repr("StrokeAttribute:"); + repr << " r: " << self->sa->getColorR() + << " g: " << self->sa->getColorG() + << " b: " << self->sa->getColorB() + << " a: " << self->sa->getAlpha() + << " - R: " << self->sa->getThicknessR() + << " L: " << self->sa->getThicknessL(); + + return PyUnicode_FromString( repr.str().c_str() ); +} + + +static char StrokeAttribute_getColorR___doc__[] = +".. method:: getColorR()\n" +"\n" +" Returns the red component of the stroke color.\n" +"\n" +" :return: Red component of the stroke color.\n" +" :rtype: float\n"; + +static PyObject *StrokeAttribute_getColorR( BPy_StrokeAttribute *self ) { + return PyFloat_FromDouble( self->sa->getColorR() ); +} + +static char StrokeAttribute_getColorG___doc__[] = +".. method:: getColorG()\n" +"\n" +" Returns the green component of the stroke color.\n" +"\n" +" :return: Green component of the stroke color.\n" +" :rtype: float\n"; + +static PyObject *StrokeAttribute_getColorG( BPy_StrokeAttribute *self ) { + return PyFloat_FromDouble( self->sa->getColorG() ); +} + +static char StrokeAttribute_getColorB___doc__[] = +".. method:: getColorB()\n" +"\n" +" Returns the blue component of the stroke color.\n" +"\n" +" :return: Blue component of the stroke color.\n" +" :rtype: float\n"; + +static PyObject *StrokeAttribute_getColorB( BPy_StrokeAttribute *self ) { + return PyFloat_FromDouble( self->sa->getColorB() ); +} + +static char StrokeAttribute_getColorRGB___doc__[] = +".. method:: getColorRGB()\n" +"\n" +" Returns the RGB components of the stroke color.\n" +"\n" +" :return: RGB components of the stroke color.\n" +" :rtype: :class:`mathutils.Vector`\n"; + +static PyObject *StrokeAttribute_getColorRGB( BPy_StrokeAttribute *self ) { + Vec3f v( self->sa->getColorRGB() ); + return Vector_from_Vec3f( v ); +} + +static char StrokeAttribute_getAlpha___doc__[] = +".. method:: getAlpha()\n" +"\n" +" Returns the alpha component of the stroke color.\n" +"\n" +" :return: Alpha component of the stroke color.\n" +" :rtype: float\n"; + +static PyObject *StrokeAttribute_getAlpha( BPy_StrokeAttribute *self ) { + return PyFloat_FromDouble( self->sa->getAlpha() ); +} + +static char StrokeAttribute_getThicknessR___doc__[] = +".. method:: getThicknessR()\n" +"\n" +" Returns the thickness on the right of the vertex when following\n" +" the stroke.\n" +"\n" +" :return: The thickness on the right of the vertex.\n" +" :rtype: float\n"; + +static PyObject *StrokeAttribute_getThicknessR( BPy_StrokeAttribute *self ) { + return PyFloat_FromDouble( self->sa->getThicknessR() ); +} + +static char StrokeAttribute_getThicknessL___doc__[] = +".. method:: getThicknessL()\n" +"\n" +" Returns the thickness on the left of the vertex when following\n" +" the stroke.\n" +"\n" +" :return: The thickness on the left of the vertex.\n" +" :rtype: float\n"; + +static PyObject *StrokeAttribute_getThicknessL( BPy_StrokeAttribute *self ) { + return PyFloat_FromDouble( self->sa->getThicknessL() ); +} + +static char StrokeAttribute_getThicknessRL___doc__[] = +".. method:: getThicknessRL()\n" +"\n" +" Returns the thickness on the right and on the left of the vertex\n" +" when following the stroke.\n" +"\n" +" :return: A two-dimensional vector. The first value is the\n" +" thickness on the right of the vertex when following the stroke,\n" +" and the second one is the thickness on the left.\n" +" :rtype: :class:`mathutils.Vector`\n"; + +static PyObject *StrokeAttribute_getThicknessRL( BPy_StrokeAttribute *self ) { + Vec2f v( self->sa->getThicknessRL() ); + return Vector_from_Vec2f( v ); +} + +static char StrokeAttribute_isVisible___doc__[] = +".. method:: isVisible()\n" +"\n" +" Returns true if the StrokeVertex is visible, false otherwise.\n" +"\n" +" :return: True if the StrokeVertex is visible, false otherwise.\n" +" :rtype: bool\n"; + +static PyObject *StrokeAttribute_isVisible( BPy_StrokeAttribute *self ) { + return PyBool_from_bool( self->sa->isVisible() ); +} + +static char StrokeAttribute_getAttributeReal___doc__[] = +".. method:: getAttributeReal(iName)\n" +"\n" +" Returns an attribute of float type.\n" +"\n" +" :arg iName: The name of the attribute.\n" +" :type iName: str\n" +" :return: The attribute value.\n" +" :rtype: float\n"; + +static PyObject *StrokeAttribute_getAttributeReal( BPy_StrokeAttribute *self, PyObject *args ) { + char *attr; + + if(!( PyArg_ParseTuple(args, "s", &attr) )) + return NULL; + + double a = self->sa->getAttributeReal( attr ); + return PyFloat_FromDouble( a ); +} + +static char StrokeAttribute_getAttributeVec2f___doc__[] = +".. method:: getAttributeVec2f(iName)\n" +"\n" +" Returns an attribute of two-dimensional vector type.\n" +"\n" +" :arg iName: The name of the attribute.\n" +" :type iName: str\n" +" :return: The attribute value.\n" +" :rtype: :class:`mathutils.Vector`\n"; + +static PyObject *StrokeAttribute_getAttributeVec2f( BPy_StrokeAttribute *self, PyObject *args ) { + char *attr; + + if(!( PyArg_ParseTuple(args, "s", &attr) )) + return NULL; + + Vec2f a = self->sa->getAttributeVec2f( attr ); + return Vector_from_Vec2f( a ); +} + +static char StrokeAttribute_getAttributeVec3f___doc__[] = +".. method:: getAttributeVec3f(iName)\n" +"\n" +" Returns an attribute of three-dimensional vector type.\n" +"\n" +" :arg iName: The name of the attribute.\n" +" :type iName: str\n" +" :return: The attribute value.\n" +" :rtype: :class:`mathutils.Vector`\n"; + +static PyObject *StrokeAttribute_getAttributeVec3f( BPy_StrokeAttribute *self, PyObject *args ) { + char *attr; + + if(!( PyArg_ParseTuple(args, "s", &attr) )) + return NULL; + + Vec3f a = self->sa->getAttributeVec3f( attr ); + return Vector_from_Vec3f( a ); +} + +static char StrokeAttribute_isAttributeAvailableReal___doc__[] = +".. method:: isAttributeAvailableReal(iName)\n" +"\n" +" Checks whether the attribute iName of float type is available.\n" +"\n" +" :arg iName: The name of the attribute.\n" +" :type iName: str\n" +" :return: True if the attribute is availbale.\n" +" :rtype: bool\n"; + +static PyObject *StrokeAttribute_isAttributeAvailableReal( BPy_StrokeAttribute *self, PyObject *args ) { + char *attr; + + if(!( PyArg_ParseTuple(args, "s", &attr) )) + return NULL; + + return PyBool_from_bool( self->sa->isAttributeAvailableReal( attr ) ); +} + +static char StrokeAttribute_isAttributeAvailableVec2f___doc__[] = +".. method:: isAttributeAvailableVec2f(iName)\n" +"\n" +" Checks whether the attribute iName of two-dimensional vector type\n" +" is available.\n" +"\n" +" :arg iName: The name of the attribute.\n" +" :type iName: str\n" +" :return: True if the attribute is availbale.\n" +" :rtype: bool\n"; + +static PyObject *StrokeAttribute_isAttributeAvailableVec2f( BPy_StrokeAttribute *self, PyObject *args ) { + char *attr; + + if(!( PyArg_ParseTuple(args, "s", &attr) )) + return NULL; + + return PyBool_from_bool( self->sa->isAttributeAvailableVec2f( attr ) ); +} + +static char StrokeAttribute_isAttributeAvailableVec3f___doc__[] = +".. method:: isAttributeAvailableVec3f(iName)\n" +"\n" +" Checks whether the attribute iName of three-dimensional vector\n" +" type is available.\n" +"\n" +" :arg iName: The name of the attribute.\n" +" :type iName: str\n" +" :return: True if the attribute is availbale.\n" +" :rtype: bool\n"; + +static PyObject *StrokeAttribute_isAttributeAvailableVec3f( BPy_StrokeAttribute *self, PyObject *args ) { + char *attr; + + if(!( PyArg_ParseTuple(args, "s", &attr) )) + return NULL; + + return PyBool_from_bool( self->sa->isAttributeAvailableVec3f( attr ) ); +} + + +static char StrokeAttribute_setColor___doc__[] = +".. method:: setColor(r, g, b)\n" +"\n" +" Sets the stroke color.\n" +"\n" +" :arg r: Red component of the stroke color.\n" +" :type r: float\n" +" :arg g: Green component of the stroke color.\n" +" :type g: float\n" +" :arg b: Blue component of the stroke color.\n" +" :type b: float\n" +"\n" +".. method:: setColor(iRGB)\n" +"\n" +" Sets the stroke color.\n" +"\n" +" :arg iRGB: The new RGB values.\n" +" :type iRGB: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"; + +static PyObject * StrokeAttribute_setColor( BPy_StrokeAttribute *self, PyObject *args ) { + PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0 ; + + if(!( PyArg_ParseTuple(args, "O|OO", &obj1, &obj2, &obj3) )) + return NULL; + + if( obj1 && !obj2 && !obj3 ){ + + Vec3f *v = Vec3f_ptr_from_PyObject(obj1); + if( !v ) { + PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)"); + return NULL; + } + self->sa->setColor( *v ); + delete v; + + } else if( obj1 && obj2 && obj3 ){ + + self->sa->setColor( PyFloat_AsDouble(obj1), + PyFloat_AsDouble(obj2), + PyFloat_AsDouble(obj3) ); + + } else { + PyErr_SetString(PyExc_TypeError, "invalid arguments"); + return NULL; + } + + Py_RETURN_NONE; +} + +static char StrokeAttribute_setAlpha___doc__[] = +".. method:: setAlpha(alpha)\n" +"\n" +" Sets the alpha component of the stroke color.\n" +"\n" +" :arg alpha: The new alpha value.\n" +" :type alpha: float\n"; + +static PyObject * StrokeAttribute_setAlpha( BPy_StrokeAttribute *self, PyObject *args ){ + float f = 0; + + if(!( PyArg_ParseTuple(args, "f", &f) )) + return NULL; + + self->sa->setAlpha( f ); + Py_RETURN_NONE; +} + +static char StrokeAttribute_setThickness___doc__[] = +".. method:: setThickness(tr, tl)\n" +"\n" +" Sets the stroke thickness.\n" +"\n" +" :arg tr: The thickness on the right of the vertex when following\n" +" the stroke.\n" +" :type tr: float\n" +" :arg tl: The thickness on the left of the vertex when following\n" +" the stroke.\n" +" :type tl: float\n" +"\n" +".. method:: setThickness(tRL)\n" +"\n" +" Sets the stroke thickness.\n" +"\n" +" :arg tRL: The thickness on the right and on the left of the vertex\n" +" when following the stroke.\n" +" :type tRL: :class:`mathutils.Vector`, list or tuple of 2 real numbers\n"; + +static PyObject * StrokeAttribute_setThickness( BPy_StrokeAttribute *self, PyObject *args ) { + PyObject *obj1 = 0, *obj2 = 0; + + if(!( PyArg_ParseTuple(args, "O|O", &obj1, &obj2) )) + return NULL; + + if( obj1 && !obj2 ){ + + Vec2f *v = Vec2f_ptr_from_PyObject(obj1); + if( !v ) { + PyErr_SetString(PyExc_TypeError, "argument 1 must be a 2D vector (either a list of 2 elements or Vector)"); + return NULL; + } + self->sa->setThickness( *v ); + delete v; + + } else if( obj1 && obj2 ){ + + self->sa->setThickness( PyFloat_AsDouble(obj1), + PyFloat_AsDouble(obj2) ); + + } else { + PyErr_SetString(PyExc_TypeError, "invalid arguments"); + return NULL; + } + + Py_RETURN_NONE; +} + +static char StrokeAttribute_setVisible___doc__[] = +".. method:: setVisible(iVisible)\n" +"\n" +" Sets the visibility flag. True means the StrokeVertex is visible.\n" +"\n" +" :arg iVisible: True if the StrokeVertex is visible.\n" +" :type iVisible: bool\n"; + +static PyObject * StrokeAttribute_setVisible( BPy_StrokeAttribute *self, PyObject *args ) { + PyObject *py_b; + + if(!( PyArg_ParseTuple(args, "O", &py_b) )) + return NULL; + + self->sa->setVisible( bool_from_PyBool(py_b) ); + + Py_RETURN_NONE; +} + +static char StrokeAttribute_setAttributeReal___doc__[] = +".. method:: setAttributeReal(iName, att)\n" +"\n" +" Adds a user-defined attribute of float type. If there is no\n" +" attribute of the given name, it is added. Otherwise, the new value\n" +" replaces the old one.\n" +"\n" +" :arg iName: The name of the attribute.\n" +" :type iName: str\n" +" :arg att: The attribute value.\n" +" :type att: float\n"; + +static PyObject * StrokeAttribute_setAttributeReal( BPy_StrokeAttribute *self, PyObject *args ) { + char *s = 0; + double d = 0; + + if(!( PyArg_ParseTuple(args, "sd", &s, &d) )) + return NULL; + + self->sa->setAttributeReal( s, d ); + Py_RETURN_NONE; +} + +static char StrokeAttribute_setAttributeVec2f___doc__[] = +".. method:: setAttributeVec2f(iName, att)\n" +"\n" +" Adds a user-defined attribute of two-dimensional vector type. If\n" +" there is no attribute of the given name, it is added. Otherwise,\n" +" the new value replaces the old one.\n" +"\n" +" :arg iName: The name of the attribute.\n" +" :type iName: str\n" +" :arg att: The attribute value.\n" +" :type att: :class:`mathutils.Vector`, list or tuple of 2 real numbers\n"; + +static PyObject * StrokeAttribute_setAttributeVec2f( BPy_StrokeAttribute *self, PyObject *args ) { + char *s; + PyObject *obj = 0; + + if(!( PyArg_ParseTuple(args, "sO", &s, &obj) )) + return NULL; + Vec2f *v = Vec2f_ptr_from_PyObject(obj); + if( !v ) { + PyErr_SetString(PyExc_TypeError, "argument 2 must be a 2D vector (either a list of 2 elements or Vector)"); + return NULL; + } + self->sa->setAttributeVec2f( s, *v ); + delete v; + + Py_RETURN_NONE; +} + +static char StrokeAttribute_setAttributeVec3f___doc__[] = +".. method:: setAttributeVec3f(iName, att)\n" +"\n" +" Adds a user-defined attribute of three-dimensional vector type.\n" +" If there is no attribute of the given name, it is added.\n" +" Otherwise, the new value replaces the old one.\n" +"\n" +" :arg iName: The name of the attribute.\n" +" :type iName: str\n" +" :arg att: The attribute value.\n" +" :type att: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"; + +static PyObject * StrokeAttribute_setAttributeVec3f( BPy_StrokeAttribute *self, PyObject *args ) { + char *s; + PyObject *obj = 0; + + if(!( PyArg_ParseTuple(args, "sO", &s, &obj) )) + return NULL; + Vec3f *v = Vec3f_ptr_from_PyObject(obj); + if( !v ) { + PyErr_SetString(PyExc_TypeError, "argument 2 must be a 3D vector (either a list of 3 elements or Vector)"); + return NULL; + } + self->sa->setAttributeVec3f( s, *v ); + delete v; + + Py_RETURN_NONE; +} + +/*----------------------StrokeAttribute instance definitions ----------------------------*/ +static PyMethodDef BPy_StrokeAttribute_methods[] = { + {"getColorR", ( PyCFunction ) StrokeAttribute_getColorR, METH_NOARGS, StrokeAttribute_getColorR___doc__}, + {"getColorG", ( PyCFunction ) StrokeAttribute_getColorG, METH_NOARGS, StrokeAttribute_getColorG___doc__}, + {"getColorB", ( PyCFunction ) StrokeAttribute_getColorB, METH_NOARGS, StrokeAttribute_getColorB___doc__}, + {"getColorRGB", ( PyCFunction ) StrokeAttribute_getColorRGB, METH_NOARGS, StrokeAttribute_getColorRGB___doc__}, + {"getAlpha", ( PyCFunction ) StrokeAttribute_getAlpha, METH_NOARGS, StrokeAttribute_getAlpha___doc__}, + {"getThicknessR", ( PyCFunction ) StrokeAttribute_getThicknessR, METH_NOARGS, StrokeAttribute_getThicknessR___doc__}, + {"getThicknessL", ( PyCFunction ) StrokeAttribute_getThicknessL, METH_NOARGS, StrokeAttribute_getThicknessL___doc__}, + {"getThicknessRL", ( PyCFunction ) StrokeAttribute_getThicknessRL, METH_NOARGS, StrokeAttribute_getThicknessRL___doc__}, + {"isVisible", ( PyCFunction ) StrokeAttribute_isVisible, METH_NOARGS, StrokeAttribute_isVisible___doc__}, + {"getAttributeReal", ( PyCFunction ) StrokeAttribute_getAttributeReal, METH_VARARGS, StrokeAttribute_getAttributeReal___doc__}, + {"getAttributeVec2f", ( PyCFunction ) StrokeAttribute_getAttributeVec2f, METH_VARARGS, StrokeAttribute_getAttributeVec2f___doc__}, + {"getAttributeVec3f", ( PyCFunction ) StrokeAttribute_getAttributeVec3f, METH_VARARGS, StrokeAttribute_getAttributeVec3f___doc__}, + {"isAttributeAvailableReal", ( PyCFunction ) StrokeAttribute_isAttributeAvailableReal, METH_VARARGS, StrokeAttribute_isAttributeAvailableReal___doc__}, + {"isAttributeAvailableVec2f", ( PyCFunction ) StrokeAttribute_isAttributeAvailableVec2f, METH_VARARGS, StrokeAttribute_isAttributeAvailableVec2f___doc__}, + {"isAttributeAvailableVec3f", ( PyCFunction ) StrokeAttribute_isAttributeAvailableVec3f, METH_VARARGS, StrokeAttribute_isAttributeAvailableVec3f___doc__}, + {"setColor", ( PyCFunction ) StrokeAttribute_setColor, METH_VARARGS, StrokeAttribute_setColor___doc__}, + {"setAlpha", ( PyCFunction ) StrokeAttribute_setAlpha, METH_VARARGS, StrokeAttribute_setAlpha___doc__}, + {"setThickness", ( PyCFunction ) StrokeAttribute_setThickness, METH_VARARGS, StrokeAttribute_setThickness___doc__}, + {"setVisible", ( PyCFunction ) StrokeAttribute_setVisible, METH_VARARGS, StrokeAttribute_setVisible___doc__}, + {"setAttributeReal", ( PyCFunction ) StrokeAttribute_setAttributeReal, METH_VARARGS, StrokeAttribute_setAttributeReal___doc__}, + {"setAttributeVec2f", ( PyCFunction ) StrokeAttribute_setAttributeVec2f, METH_VARARGS, StrokeAttribute_setAttributeVec2f___doc__}, + {"setAttributeVec3f", ( PyCFunction ) StrokeAttribute_setAttributeVec3f, METH_VARARGS, StrokeAttribute_setAttributeVec3f___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_StrokeAttribute type definition ------------------------------*/ + +PyTypeObject StrokeAttribute_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "StrokeAttribute", /* tp_name */ + sizeof(BPy_StrokeAttribute), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)StrokeAttribute___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)StrokeAttribute___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + StrokeAttribute___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_StrokeAttribute_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)StrokeAttribute___init__, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + diff --git a/source/blender/freestyle/intern/python/BPy_StrokeAttribute.h b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.h new file mode 100644 index 00000000000..51e18c0a96f --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.h @@ -0,0 +1,35 @@ +#ifndef FREESTYLE_PYTHON_STROKEATTRIBUTE_H +#define FREESTYLE_PYTHON_STROKEATTRIBUTE_H + +#include <Python.h> + +#include "../stroke/Stroke.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject StrokeAttribute_Type; + +#define BPy_StrokeAttribute_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &StrokeAttribute_Type) ) + +/*---------------------------Python BPy_StrokeAttribute structure definition----------*/ +typedef struct { + PyObject_HEAD + StrokeAttribute *sa; + int borrowed; /* non-zero if *sa is a borrowed reference */ +} BPy_StrokeAttribute; + +/*---------------------------Python BPy_StrokeAttribute visible prototypes-----------*/ + +int StrokeAttribute_Init( PyObject *module ); + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_STROKEATTRIBUTE_H */ diff --git a/source/blender/freestyle/intern/python/BPy_StrokeShader.cpp b/source/blender/freestyle/intern/python/BPy_StrokeShader.cpp new file mode 100644 index 00000000000..202e33c3231 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_StrokeShader.cpp @@ -0,0 +1,297 @@ +#include "BPy_StrokeShader.h" + +#include "BPy_Convert.h" +#include "Interface1D/BPy_Stroke.h" + +#include "StrokeShader/BPy_BackboneStretcherShader.h" +#include "StrokeShader/BPy_BezierCurveShader.h" +#include "StrokeShader/BPy_CalligraphicShader.h" +#include "StrokeShader/BPy_ColorNoiseShader.h" +#include "StrokeShader/BPy_ColorVariationPatternShader.h" +#include "StrokeShader/BPy_ConstantColorShader.h" +#include "StrokeShader/BPy_ConstantThicknessShader.h" +#include "StrokeShader/BPy_ConstrainedIncreasingThicknessShader.h" +#include "StrokeShader/BPy_fstreamShader.h" +#include "StrokeShader/BPy_GuidingLinesShader.h" +#include "StrokeShader/BPy_IncreasingColorShader.h" +#include "StrokeShader/BPy_IncreasingThicknessShader.h" +#include "StrokeShader/BPy_PolygonalizationShader.h" +#include "StrokeShader/BPy_SamplingShader.h" +#include "StrokeShader/BPy_SmoothingShader.h" +#include "StrokeShader/BPy_SpatialNoiseShader.h" +#include "StrokeShader/BPy_streamShader.h" +#include "StrokeShader/BPy_StrokeTextureShader.h" +#include "StrokeShader/BPy_TextureAssignerShader.h" +#include "StrokeShader/BPy_ThicknessNoiseShader.h" +#include "StrokeShader/BPy_ThicknessVariationPatternShader.h" +#include "StrokeShader/BPy_TipRemoverShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- +int StrokeShader_Init( PyObject *module ) +{ + if( module == NULL ) + return -1; + + if( PyType_Ready( &StrokeShader_Type ) < 0 ) + return -1; + Py_INCREF( &StrokeShader_Type ); + PyModule_AddObject(module, "StrokeShader", (PyObject *)&StrokeShader_Type); + + if( PyType_Ready( &BackboneStretcherShader_Type ) < 0 ) + return -1; + Py_INCREF( &BackboneStretcherShader_Type ); + PyModule_AddObject(module, "BackboneStretcherShader", (PyObject *)&BackboneStretcherShader_Type); + + if( PyType_Ready( &BezierCurveShader_Type ) < 0 ) + return -1; + Py_INCREF( &BezierCurveShader_Type ); + PyModule_AddObject(module, "BezierCurveShader", (PyObject *)&BezierCurveShader_Type); + + if( PyType_Ready( &CalligraphicShader_Type ) < 0 ) + return -1; + Py_INCREF( &CalligraphicShader_Type ); + PyModule_AddObject(module, "CalligraphicShader", (PyObject *)&CalligraphicShader_Type); + + if( PyType_Ready( &ColorNoiseShader_Type ) < 0 ) + return -1; + Py_INCREF( &ColorNoiseShader_Type ); + PyModule_AddObject(module, "ColorNoiseShader", (PyObject *)&ColorNoiseShader_Type); + + if( PyType_Ready( &ColorVariationPatternShader_Type ) < 0 ) + return -1; + Py_INCREF( &ColorVariationPatternShader_Type ); + PyModule_AddObject(module, "ColorVariationPatternShader", (PyObject *)&ColorVariationPatternShader_Type); + + if( PyType_Ready( &ConstantColorShader_Type ) < 0 ) + return -1; + Py_INCREF( &ConstantColorShader_Type ); + PyModule_AddObject(module, "ConstantColorShader", (PyObject *)&ConstantColorShader_Type); + + if( PyType_Ready( &ConstantThicknessShader_Type ) < 0 ) + return -1; + Py_INCREF( &ConstantThicknessShader_Type ); + PyModule_AddObject(module, "ConstantThicknessShader", (PyObject *)&ConstantThicknessShader_Type); + + if( PyType_Ready( &ConstrainedIncreasingThicknessShader_Type ) < 0 ) + return -1; + Py_INCREF( &ConstrainedIncreasingThicknessShader_Type ); + PyModule_AddObject(module, "ConstrainedIncreasingThicknessShader", (PyObject *)&ConstrainedIncreasingThicknessShader_Type); + + if( PyType_Ready( &fstreamShader_Type ) < 0 ) + return -1; + Py_INCREF( &fstreamShader_Type ); + PyModule_AddObject(module, "fstreamShader", (PyObject *)&fstreamShader_Type); + + if( PyType_Ready( &GuidingLinesShader_Type ) < 0 ) + return -1; + Py_INCREF( &GuidingLinesShader_Type ); + PyModule_AddObject(module, "GuidingLinesShader", (PyObject *)&GuidingLinesShader_Type); + + if( PyType_Ready( &IncreasingColorShader_Type ) < 0 ) + return -1; + Py_INCREF( &IncreasingColorShader_Type ); + PyModule_AddObject(module, "IncreasingColorShader", (PyObject *)&IncreasingColorShader_Type); + + if( PyType_Ready( &IncreasingThicknessShader_Type ) < 0 ) + return -1; + Py_INCREF( &IncreasingThicknessShader_Type ); + PyModule_AddObject(module, "IncreasingThicknessShader", (PyObject *)&IncreasingThicknessShader_Type); + + if( PyType_Ready( &PolygonalizationShader_Type ) < 0 ) + return -1; + Py_INCREF( &PolygonalizationShader_Type ); + PyModule_AddObject(module, "PolygonalizationShader", (PyObject *)&PolygonalizationShader_Type); + + if( PyType_Ready( &SamplingShader_Type ) < 0 ) + return -1; + Py_INCREF( &SamplingShader_Type ); + PyModule_AddObject(module, "SamplingShader", (PyObject *)&SamplingShader_Type); + + if( PyType_Ready( &SmoothingShader_Type ) < 0 ) + return -1; + Py_INCREF( &SmoothingShader_Type ); + PyModule_AddObject(module, "SmoothingShader", (PyObject *)&SmoothingShader_Type); + + if( PyType_Ready( &SpatialNoiseShader_Type ) < 0 ) + return -1; + Py_INCREF( &SpatialNoiseShader_Type ); + PyModule_AddObject(module, "SpatialNoiseShader", (PyObject *)&SpatialNoiseShader_Type); + + if( PyType_Ready( &streamShader_Type ) < 0 ) + return -1; + Py_INCREF( &streamShader_Type ); + PyModule_AddObject(module, "streamShader", (PyObject *)&streamShader_Type); + + if( PyType_Ready( &StrokeTextureShader_Type ) < 0 ) + return -1; + Py_INCREF( &StrokeTextureShader_Type ); + PyModule_AddObject(module, "StrokeTextureShader", (PyObject *)&StrokeTextureShader_Type); + + if( PyType_Ready( &TextureAssignerShader_Type ) < 0 ) + return -1; + Py_INCREF( &TextureAssignerShader_Type ); + PyModule_AddObject(module, "TextureAssignerShader", (PyObject *)&TextureAssignerShader_Type); + + if( PyType_Ready( &ThicknessNoiseShader_Type ) < 0 ) + return -1; + Py_INCREF( &ThicknessNoiseShader_Type ); + PyModule_AddObject(module, "ThicknessNoiseShader", (PyObject *)&ThicknessNoiseShader_Type); + + if( PyType_Ready( &ThicknessVariationPatternShader_Type ) < 0 ) + return -1; + Py_INCREF( &ThicknessVariationPatternShader_Type ); + PyModule_AddObject(module, "ThicknessVariationPatternShader", (PyObject *)&ThicknessVariationPatternShader_Type); + + if( PyType_Ready( &TipRemoverShader_Type ) < 0 ) + return -1; + Py_INCREF( &TipRemoverShader_Type ); + PyModule_AddObject(module, "TipRemoverShader", (PyObject *)&TipRemoverShader_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char StrokeShader___doc__[] = +"Base class for stroke shaders. Any stroke shader must inherit from\n" +"this class and overload the shade() method. A StrokeShader is\n" +"designed to modify stroke attributes such as thickness, color,\n" +"geometry, texture, blending mode, and so on. The basic way for this\n" +"operation is to iterate over the stroke vertices of the :class:`Stroke`\n" +"and to modify the :class:`StrokeAttribute` of each vertex. Here is a\n" +"code example of such an iteration::\n" +"\n" +" it = ioStroke.strokeVerticesBegin()\n" +" while it.isEnd() == 0:\n" +" att = it.getObject().attribute()\n" +" ## perform here any attribute modification\n" +" it.increment()\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n"; + +static int StrokeShader___init__(BPy_StrokeShader *self, PyObject *args, PyObject *kwds) +{ + if ( !PyArg_ParseTuple(args, "") ) + return -1; + self->ss = new StrokeShader(); + self->ss->py_ss = (PyObject *) self; + return 0; +} + +static void StrokeShader___dealloc__(BPy_StrokeShader* self) +{ + if (self->ss) + delete self->ss; + Py_TYPE(self)->tp_free((PyObject*)self); +} + + +static PyObject * StrokeShader___repr__(BPy_StrokeShader* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->ss->getName().c_str(), self->ss ); +} + +static char StrokeShader_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of this stroke shader.\n" +"\n" +" :return: The name of this stroke shader.\n" +" :rtype: str\n"; + +static PyObject * StrokeShader_getName( BPy_StrokeShader *self, PyObject *args) +{ + return PyUnicode_FromString( self->ss->getName().c_str() ); +} + +static char StrokeShader_shade___doc__[] = +".. method:: shade(s)\n" +"\n" +" The shading method. Must be overloaded by inherited classes.\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static PyObject *StrokeShader_shade( BPy_StrokeShader *self , PyObject *args) { + PyObject *py_s = 0; + + if(!( PyArg_ParseTuple(args, "O!", &Stroke_Type, &py_s) )) + return NULL; + + if( typeid(*(self->ss)) == typeid(StrokeShader) ) { + PyErr_SetString(PyExc_TypeError, "shade method not properly overridden"); + return NULL; + } + if (self->ss->shade(*( ((BPy_Stroke *) py_s)->s )) < 0) { + if (!PyErr_Occurred()) { + string msg(self->ss->getName() + " shade method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + Py_RETURN_NONE; +} + +/*----------------------StrokeShader instance definitions ----------------------------*/ +static PyMethodDef BPy_StrokeShader_methods[] = { + {"getName", ( PyCFunction ) StrokeShader_getName, METH_NOARGS, StrokeShader_getName___doc__}, + {"shade", ( PyCFunction ) StrokeShader_shade, METH_VARARGS, StrokeShader_shade___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_StrokeShader type definition ------------------------------*/ + +PyTypeObject StrokeShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "StrokeShader", /* tp_name */ + sizeof(BPy_StrokeShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)StrokeShader___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)StrokeShader___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + StrokeShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_StrokeShader_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)StrokeShader___init__, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/BPy_StrokeShader.h b/source/blender/freestyle/intern/python/BPy_StrokeShader.h new file mode 100644 index 00000000000..baa31a3100e --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_StrokeShader.h @@ -0,0 +1,40 @@ +#ifndef FREESTYLE_PYTHON_STROKESHADER_H +#define FREESTYLE_PYTHON_STROKESHADER_H + +#include <Python.h> + +#include "../system/FreestyleConfig.h" + +using namespace std; + +#include "../stroke/StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject StrokeShader_Type; + +#define BPy_StrokeShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &StrokeShader_Type) ) + +/*---------------------------Python BPy_StrokeShader structure definition----------*/ +typedef struct { + PyObject_HEAD + StrokeShader *ss; +} BPy_StrokeShader; + +/*---------------------------Python BPy_StrokeShader visible prototypes-----------*/ + +int StrokeShader_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_STROKESHADER_H */ diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp new file mode 100644 index 00000000000..9cb855f32ae --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp @@ -0,0 +1,126 @@ +#include "BPy_UnaryFunction0D.h" + +#include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DFloat.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DId.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DMaterial.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DVec2f.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DVec3f.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DViewShape.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- +int UnaryFunction0D_Init( PyObject *module ) +{ + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryFunction0D_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryFunction0D_Type ); + PyModule_AddObject(module, "UnaryFunction0D", (PyObject *)&UnaryFunction0D_Type); + + UnaryFunction0DDouble_Init( module ); + UnaryFunction0DEdgeNature_Init( module ); + UnaryFunction0DFloat_Init( module ); + UnaryFunction0DId_Init( module ); + UnaryFunction0DMaterial_Init( module ); + UnaryFunction0DUnsigned_Init( module ); + UnaryFunction0DVec2f_Init( module ); + UnaryFunction0DVec3f_Init( module ); + UnaryFunction0DVectorViewShape_Init( module ); + UnaryFunction0DViewShape_Init( module ); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryFunction0D___doc__[] = +"Base class for Unary Functions (functors) working on\n" +":class:`Interface0DIterator`. A unary function will be used by\n" +"invoking __call__() on an Interface0DIterator. In Python, several\n" +"different subclasses of UnaryFunction0D are used depending on the\n" +"types of functors' return values. For example, you would inherit from\n" +"a :class:`UnaryFunction0DDouble` if you wish to define a function that\n" +"returns a double value. Available UnaryFunction0D subclasses are:\n" +"\n" +"* :class:`UnaryFunction0DDouble`\n" +"* :class:`UnaryFunction0DEdgeNature`\n" +"* :class:`UnaryFunction0DFloat`\n" +"* :class:`UnaryFunction0DId`\n" +"* :class:`UnaryFunction0DMaterial`\n" +"* :class:`UnaryFunction0DUnsigned`\n" +"* :class:`UnaryFunction0DVec2f`\n" +"* :class:`UnaryFunction0DVec3f`\n" +"* :class:`UnaryFunction0DVectorViewShape`\n" +"* :class:`UnaryFunction0DViewShape`\n"; + +static void UnaryFunction0D___dealloc__(BPy_UnaryFunction0D* self) +{ + Py_TYPE(self)->tp_free((PyObject*)self); +} + + +static PyObject * UnaryFunction0D___repr__(BPy_UnaryFunction0D* self) +{ + return PyUnicode_FromString("UnaryFunction0D"); +} + +/*-----------------------BPy_UnaryFunction0D type definition ------------------------------*/ + +PyTypeObject UnaryFunction0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryFunction0D", /* tp_name */ + sizeof(BPy_UnaryFunction0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryFunction0D___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryFunction0D___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryFunction0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.h b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.h new file mode 100644 index 00000000000..6d61c336662 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.h @@ -0,0 +1,34 @@ +#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0D_H +#define FREESTYLE_PYTHON_UNARYFUNCTION0D_H + +#include <Python.h> + +#include "../view_map/Functions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject UnaryFunction0D_Type; + +#define BPy_UnaryFunction0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0D_Type) ) + +/*---------------------------Python BPy_UnaryFunction0D structure definition----------*/ +typedef struct { + PyObject_HEAD + PyObject *py_uf0D; +} BPy_UnaryFunction0D; + +/*---------------------------Python BPy_UnaryFunction0D visible prototypes-----------*/ + +int UnaryFunction0D_Init( PyObject *module ); + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0D_H */ diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp new file mode 100644 index 00000000000..f4de9edb962 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp @@ -0,0 +1,117 @@ +#include "BPy_UnaryFunction1D.h" + +#include "UnaryFunction1D/BPy_UnaryFunction1DDouble.h" +#include "UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h" +#include "UnaryFunction1D/BPy_UnaryFunction1DFloat.h" +#include "UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h" +#include "UnaryFunction1D/BPy_UnaryFunction1DVec2f.h" +#include "UnaryFunction1D/BPy_UnaryFunction1DVec3f.h" +#include "UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h" +#include "UnaryFunction1D/BPy_UnaryFunction1DVoid.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- +int UnaryFunction1D_Init( PyObject *module ) +{ + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryFunction1D_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryFunction1D_Type ); + PyModule_AddObject(module, "UnaryFunction1D", (PyObject *)&UnaryFunction1D_Type); + + UnaryFunction1DDouble_Init( module ); + UnaryFunction1DEdgeNature_Init( module ); + UnaryFunction1DFloat_Init( module ); + UnaryFunction1DUnsigned_Init( module ); + UnaryFunction1DVec2f_Init( module ); + UnaryFunction1DVec3f_Init( module ); + UnaryFunction1DVectorViewShape_Init( module ); + UnaryFunction1DVoid_Init( module ); + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryFunction1D___doc__[] = +"Base class for Unary Functions (functors) working on\n" +":class:`Interface1D`. A unary function will be used by invoking\n" +"__call__() on an Interface1D. In Python, several different subclasses\n" +"of UnaryFunction1D are used depending on the types of functors' return\n" +"values. For example, you would inherit from a\n" +":class:`UnaryFunction1DDouble` if you wish to define a function that\n" +"returns a double value. Available UnaryFunction1D subclasses are:\n" +"\n" +"* :class:`UnaryFunction1DDouble`\n" +"* :class:`UnaryFunction1DEdgeNature`\n" +"* :class:`UnaryFunction1DFloat`\n" +"* :class:`UnaryFunction1DUnsigned`\n" +"* :class:`UnaryFunction1DVec2f`\n" +"* :class:`UnaryFunction1DVec3f`\n" +"* :class:`UnaryFunction1DVectorViewShape`\n" +"* :class:`UnaryFunction1DVoid`\n"; + +static void UnaryFunction1D___dealloc__(BPy_UnaryFunction1D* self) +{ + Py_TYPE(self)->tp_free((PyObject*)self); +} + +static PyObject * UnaryFunction1D___repr__(BPy_UnaryFunction1D* self) +{ + return PyUnicode_FromString("UnaryFunction1D"); +} + +/*-----------------------BPy_UnaryFunction1D type definition ------------------------------*/ + +PyTypeObject UnaryFunction1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryFunction1D", /* tp_name */ + sizeof(BPy_UnaryFunction1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryFunction1D___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryFunction1D___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryFunction1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.h b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.h new file mode 100644 index 00000000000..cb9df18ab75 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.h @@ -0,0 +1,34 @@ +#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1D_H +#define FREESTYLE_PYTHON_UNARYFUNCTION1D_H + +#include <Python.h> + +#include "../view_map/Functions1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject UnaryFunction1D_Type; + +#define BPy_UnaryFunction1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1D_Type) ) + +/*---------------------------Python BPy_UnaryFunction1D structure definition----------*/ +typedef struct { + PyObject_HEAD + PyObject *py_uf1D; +} BPy_UnaryFunction1D; + +/*---------------------------Python BPy_UnaryFunction1D visible prototypes-----------*/ + +int UnaryFunction1D_Init( PyObject *module ); + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1D_H */ diff --git a/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.cpp new file mode 100644 index 00000000000..81f39ef7ab7 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.cpp @@ -0,0 +1,184 @@ +#include "BPy_UnaryPredicate0D.h" + +#include "BPy_Convert.h" +#include "Iterator/BPy_Interface0DIterator.h" +#include "UnaryPredicate0D/BPy_FalseUP0D.h" +#include "UnaryPredicate0D/BPy_TrueUP0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- +int UnaryPredicate0D_Init( PyObject *module ) +{ + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryPredicate0D_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryPredicate0D_Type ); + PyModule_AddObject(module, "UnaryPredicate0D", (PyObject *)&UnaryPredicate0D_Type); + + if( PyType_Ready( &FalseUP0D_Type ) < 0 ) + return -1; + Py_INCREF( &FalseUP0D_Type ); + PyModule_AddObject(module, "FalseUP0D", (PyObject *)&FalseUP0D_Type); + + if( PyType_Ready( &TrueUP0D_Type ) < 0 ) + return -1; + Py_INCREF( &TrueUP0D_Type ); + PyModule_AddObject(module, "TrueUP0D", (PyObject *)&TrueUP0D_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryPredicate0D___doc__[] = +"Base class for unary predicates that work on\n" +":class:`Interface0DIterator`. A UnaryPredicate0D is a functor that\n" +"evaluates a condition on an Interface0DIterator and returns true or\n" +"false depending on whether this condition is satisfied or not. The\n" +"UnaryPredicate0D is used by invoking its __call__() method. Any\n" +"inherited class must overload the __call__() method.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Must be overload by inherited classes.\n" +"\n" +" :arg it: The Interface0DIterator pointing onto the Interface0D at\n" +" which we wish to evaluate the predicate.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: True if the condition is satisfied, false otherwise.\n" +" :rtype: bool\n"; + +static int UnaryPredicate0D___init__(BPy_UnaryPredicate0D *self, PyObject *args, PyObject *kwds) +{ + if ( !PyArg_ParseTuple(args, "") ) + return -1; + self->up0D = new UnaryPredicate0D(); + self->up0D->py_up0D = (PyObject *) self; + return 0; +} + +static void UnaryPredicate0D___dealloc__(BPy_UnaryPredicate0D* self) +{ + if (self->up0D) + delete self->up0D; + Py_TYPE(self)->tp_free((PyObject*)self); +} + +static PyObject * UnaryPredicate0D___repr__(BPy_UnaryPredicate0D* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->up0D->getName().c_str(), self->up0D ); +} + +static char UnaryPredicate0D_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the UnaryPredicate0D.\n" +"\n" +" :return: The name of the UnaryPredicate0D.\n" +" :rtype: str\n"; + +static PyObject * UnaryPredicate0D_getName( BPy_UnaryPredicate0D *self ) +{ + return PyUnicode_FromString( self->up0D->getName().c_str() ); +} + +static PyObject * UnaryPredicate0D___call__( BPy_UnaryPredicate0D *self, PyObject *args, PyObject *kwds) +{ + PyObject *py_if0D_it; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if( !PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &py_if0D_it) ) + return NULL; + + Interface0DIterator *if0D_it = ((BPy_Interface0DIterator *) py_if0D_it)->if0D_it; + + if( !if0D_it ) { + string msg(self->up0D->getName() + " has no Interface0DIterator"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + return NULL; + } + if( typeid(*(self->up0D)) == typeid(UnaryPredicate0D) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if (self->up0D->operator()(*if0D_it) < 0) { + if (!PyErr_Occurred()) { + string msg(self->up0D->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + return PyBool_from_bool( self->up0D->result ); +} + +/*----------------------UnaryPredicate0D instance definitions ----------------------------*/ +static PyMethodDef BPy_UnaryPredicate0D_methods[] = { + {"getName", ( PyCFunction ) UnaryPredicate0D_getName, METH_NOARGS, UnaryPredicate0D_getName___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_UnaryPredicate0D type definition ------------------------------*/ + +PyTypeObject UnaryPredicate0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryPredicate0D", /* tp_name */ + sizeof(BPy_UnaryPredicate0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryPredicate0D___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryPredicate0D___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)UnaryPredicate0D___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryPredicate0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_UnaryPredicate0D_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)UnaryPredicate0D___init__, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + + diff --git a/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.h b/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.h new file mode 100644 index 00000000000..9f9bb0c1003 --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.h @@ -0,0 +1,34 @@ +#ifndef FREESTYLE_PYTHON_UNARYPREDICATE0D_H +#define FREESTYLE_PYTHON_UNARYPREDICATE0D_H + +#include <Python.h> + +#include "../stroke/Predicates0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject UnaryPredicate0D_Type; + +#define BPy_UnaryPredicate0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryPredicate0D_Type) ) + +/*---------------------------Python BPy_UnaryPredicate0D structure definition----------*/ +typedef struct { + PyObject_HEAD + UnaryPredicate0D *up0D; +} BPy_UnaryPredicate0D; + +/*---------------------------Python BPy_UnaryPredicate0D visible prototypes-----------*/ + +int UnaryPredicate0D_Init( PyObject *module ); + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYPREDICATE0D_H */ diff --git a/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.cpp new file mode 100644 index 00000000000..095963fb3af --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.cpp @@ -0,0 +1,230 @@ +#include "BPy_UnaryPredicate1D.h" + +#include "BPy_Convert.h" +#include "BPy_Interface1D.h" + +#include "UnaryPredicate1D/BPy_ContourUP1D.h" +#include "UnaryPredicate1D/BPy_DensityLowerThanUP1D.h" +#include "UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.h" +#include "UnaryPredicate1D/BPy_EqualToTimeStampUP1D.h" +#include "UnaryPredicate1D/BPy_ExternalContourUP1D.h" +#include "UnaryPredicate1D/BPy_FalseUP1D.h" +#include "UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h" +#include "UnaryPredicate1D/BPy_ShapeUP1D.h" +#include "UnaryPredicate1D/BPy_TrueUP1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- +int UnaryPredicate1D_Init( PyObject *module ) +{ + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryPredicate1D_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryPredicate1D_Type ); + PyModule_AddObject(module, "UnaryPredicate1D", (PyObject *)&UnaryPredicate1D_Type); + + if( PyType_Ready( &ContourUP1D_Type ) < 0 ) + return -1; + Py_INCREF( &ContourUP1D_Type ); + PyModule_AddObject(module, "ContourUP1D", (PyObject *)&ContourUP1D_Type); + + if( PyType_Ready( &DensityLowerThanUP1D_Type ) < 0 ) + return -1; + Py_INCREF( &DensityLowerThanUP1D_Type ); + PyModule_AddObject(module, "DensityLowerThanUP1D", (PyObject *)&DensityLowerThanUP1D_Type); + + if( PyType_Ready( &EqualToChainingTimeStampUP1D_Type ) < 0 ) + return -1; + Py_INCREF( &EqualToChainingTimeStampUP1D_Type ); + PyModule_AddObject(module, "EqualToChainingTimeStampUP1D", (PyObject *)&EqualToChainingTimeStampUP1D_Type); + + if( PyType_Ready( &EqualToTimeStampUP1D_Type ) < 0 ) + return -1; + Py_INCREF( &EqualToTimeStampUP1D_Type ); + PyModule_AddObject(module, "EqualToTimeStampUP1D", (PyObject *)&EqualToTimeStampUP1D_Type); + + if( PyType_Ready( &ExternalContourUP1D_Type ) < 0 ) + return -1; + Py_INCREF( &ExternalContourUP1D_Type ); + PyModule_AddObject(module, "ExternalContourUP1D", (PyObject *)&ExternalContourUP1D_Type); + + if( PyType_Ready( &FalseUP1D_Type ) < 0 ) + return -1; + Py_INCREF( &FalseUP1D_Type ); + PyModule_AddObject(module, "FalseUP1D", (PyObject *)&FalseUP1D_Type); + + if( PyType_Ready( &QuantitativeInvisibilityUP1D_Type ) < 0 ) + return -1; + Py_INCREF( &QuantitativeInvisibilityUP1D_Type ); + PyModule_AddObject(module, "QuantitativeInvisibilityUP1D", (PyObject *)&QuantitativeInvisibilityUP1D_Type); + + if( PyType_Ready( &ShapeUP1D_Type ) < 0 ) + return -1; + Py_INCREF( &ShapeUP1D_Type ); + PyModule_AddObject(module, "ShapeUP1D", (PyObject *)&ShapeUP1D_Type); + + if( PyType_Ready( &TrueUP1D_Type ) < 0 ) + return -1; + Py_INCREF( &TrueUP1D_Type ); + PyModule_AddObject(module, "TrueUP1D", (PyObject *)&TrueUP1D_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryPredicate1D___doc__[] = +"Base class for unary predicates that work on :class:`Interface1D`. A\n" +"UnaryPredicate1D is a functor that evaluates a condition on a\n" +"Interface1D and returns true or false depending on whether this\n" +"condition is satisfied or not. The UnaryPredicate1D is used by\n" +"invoking its __call__() method. Any inherited class must overload the\n" +"__call__() method.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Must be overload by inherited classes.\n" +"\n" +" :arg inter: The Interface1D on which we wish to evaluate the predicate.\n" +" :type inter: :class:`Interface1D`\n" +" :return: True if the condition is satisfied, false otherwise.\n" +" :rtype: bool\n"; + +static int UnaryPredicate1D___init__(BPy_UnaryPredicate1D *self, PyObject *args, PyObject *kwds) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->up1D = new UnaryPredicate1D(); + self->up1D->py_up1D = (PyObject *) self; + return 0; +} + +static void UnaryPredicate1D___dealloc__(BPy_UnaryPredicate1D* self) +{ + if (self->up1D) + delete self->up1D; + Py_TYPE(self)->tp_free((PyObject*)self); +} + +static PyObject * UnaryPredicate1D___repr__(BPy_UnaryPredicate1D* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->up1D->getName().c_str(), self->up1D ); +} + +static char UnaryPredicate1D_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the string of the name of the UnaryPredicate1D.\n" +"\n" +" Reimplemented in TrueUP1D, FalseUP1D, QuantitativeInvisibilityUP1D,\n" +" ContourUP1D, ExternalContourUP1D, EqualToTimeStampUP1D,\n" +" EqualToChainingTimeStampUP1D, ShapeUP1D, and DensityLowerThanUP1D.\n" +"\n" +" :return: \n" +" :rtype: str\n"; + +static PyObject * UnaryPredicate1D_getName( BPy_UnaryPredicate1D *self, PyObject *args) +{ + return PyUnicode_FromString( self->up1D->getName().c_str() ); +} + +static PyObject * UnaryPredicate1D___call__( BPy_UnaryPredicate1D *self, PyObject *args, PyObject *kwds) +{ + PyObject *py_if1D; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &py_if1D) ) + return NULL; + + Interface1D *if1D = ((BPy_Interface1D *) py_if1D)->if1D; + + if( !if1D ) { + string msg(self->up1D->getName() + " has no Interface0DIterator"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + return NULL; + } + if( typeid(*(self->up1D)) == typeid(UnaryPredicate1D) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if( self->up1D->operator()(*if1D) < 0 ) { + if (!PyErr_Occurred()) { + string msg(self->up1D->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + return PyBool_from_bool( self->up1D->result ); +} + +/*----------------------UnaryPredicate1D instance definitions ----------------------------*/ +static PyMethodDef BPy_UnaryPredicate1D_methods[] = { + {"getName", ( PyCFunction ) UnaryPredicate1D_getName, METH_NOARGS, UnaryPredicate1D_getName___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_UnaryPredicate1D type definition ------------------------------*/ + +PyTypeObject UnaryPredicate1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryPredicate1D", /* tp_name */ + sizeof(BPy_UnaryPredicate1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryPredicate1D___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryPredicate1D___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)UnaryPredicate1D___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryPredicate1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_UnaryPredicate1D_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)UnaryPredicate1D___init__, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + + diff --git a/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.h b/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.h new file mode 100644 index 00000000000..75953e7977b --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.h @@ -0,0 +1,34 @@ +#ifndef FREESTYLE_PYTHON_UNARYPREDICATE1D_H +#define FREESTYLE_PYTHON_UNARYPREDICATE1D_H + +#include <Python.h> + +#include "../stroke/Predicates1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject UnaryPredicate1D_Type; + +#define BPy_UnaryPredicate1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryPredicate1D_Type) ) + +/*---------------------------Python BPy_UnaryPredicate1D structure definition----------*/ +typedef struct { + PyObject_HEAD + UnaryPredicate1D *up1D; +} BPy_UnaryPredicate1D; + +/*---------------------------Python BPy_UnaryPredicate1D visible prototypes-----------*/ + +int UnaryPredicate1D_Init( PyObject *module ); + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYPREDICATE1D_H */ diff --git a/source/blender/freestyle/intern/python/BPy_ViewMap.cpp b/source/blender/freestyle/intern/python/BPy_ViewMap.cpp new file mode 100644 index 00000000000..c9667103e5a --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_ViewMap.cpp @@ -0,0 +1,195 @@ +#include "BPy_ViewMap.h" + +#include "BPy_Convert.h" +#include "BPy_BBox.h" +#include "Interface1D/BPy_FEdge.h" +#include "Interface1D/BPy_ViewEdge.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- +int ViewMap_Init( PyObject *module ) +{ + if( module == NULL ) + return -1; + + if( PyType_Ready( &ViewMap_Type ) < 0 ) + return -1; + + Py_INCREF( &ViewMap_Type ); + PyModule_AddObject(module, "ViewMap", (PyObject *)&ViewMap_Type); + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ViewMap___doc__[] = +"Class defining the ViewMap.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n"; + +static int ViewMap___init__(BPy_ViewMap *self, PyObject *args, PyObject *kwds) +{ + self->vm = new ViewMap(); + return 0; +} + +static void ViewMap___dealloc__(BPy_ViewMap *self) +{ + if( self->vm ) + delete self->vm; + Py_TYPE(self)->tp_free((PyObject*)self); +} + +static PyObject * ViewMap___repr__(BPy_ViewMap *self) +{ + return PyUnicode_FromFormat("ViewMap - address: %p", self->vm ); +} + +static char ViewMap_getClosestViewEdge___doc__[] = +".. method:: getClosestViewEdge(x, y)\n" +"\n" +" Gets the ViewEdge nearest to the 2D point specified as arguments.\n" +"\n" +" :arg x: X coordinate of a 2D point.\n" +" :type x: float\n" +" :arg y: Y coordinate of a 2D point.\n" +" :type y: float\n" +" :return: The ViewEdge nearest to the specified 2D point.\n" +" :rtype: :class:`ViewEdge`\n"; + +static PyObject * ViewMap_getClosestViewEdge( BPy_ViewMap *self , PyObject *args) { + double x, y; + + if(!( PyArg_ParseTuple(args, "dd", &x, &y) )) + return NULL; + + ViewEdge *ve = const_cast<ViewEdge *>( self->vm->getClosestViewEdge(x,y) ); + if( ve ) + return BPy_ViewEdge_from_ViewEdge(*ve); + + Py_RETURN_NONE; +} + +static char ViewMap_getClosestFEdge___doc__[] = +".. method:: getClosestFEdge(x, y)\n" +"\n" +" Gets the FEdge nearest to the 2D point specified as arguments.\n" +"\n" +" :arg x: X coordinate of a 2D point.\n" +" :type x: float\n" +" :arg y: Y coordinate of a 2D point.\n" +" :type y: float\n" +" :return: The FEdge nearest to the specified 2D point.\n" +" :rtype: :class:`FEdge`\n"; + +static PyObject * ViewMap_getClosestFEdge( BPy_ViewMap *self , PyObject *args) { + double x, y; + + if(!( PyArg_ParseTuple(args, "dd", &x, &y) )) + return NULL; + + FEdge *fe = const_cast<FEdge *>( self->vm->getClosestFEdge(x,y) ); + if( fe ) + return Any_BPy_FEdge_from_FEdge(*fe); + + Py_RETURN_NONE; +} + +static char ViewMap_getScene3dBBox___doc__[] = +".. method:: getScene3dBBox()\n" +"\n" +" Returns the scene 3D bounding box.\n" +"\n" +" :return: The scene 3D bounding box.\n" +" :rtype: :class:`BBox`\n"; + +static PyObject * ViewMap_getScene3dBBox( BPy_ViewMap *self , PyObject *args) { + BBox<Vec3r> bb( self->vm->getScene3dBBox() ); + return BPy_BBox_from_BBox( bb ); +} + +static char ViewMap_setScene3dBBox___doc__[] = +".. method:: setScene3dBBox(bbox)\n" +"\n" +" Sets the scene 3D bounding box.\n" +"\n" +" :arg bbox: The scene 3D bounding box.\n" +" :type bbox: :class:`BBox`\n"; + +static PyObject * ViewMap_setScene3dBBox( BPy_ViewMap *self , PyObject *args) { + PyObject *py_bb = 0; + + if(!( PyArg_ParseTuple(args, "O!", &BBox_Type, &py_bb) )) + return NULL; + + self->vm->setScene3dBBox(*( ((BPy_BBox *) py_bb)->bb )); + + Py_RETURN_NONE; +} + +// static ViewMap *getInstance (); + +/*---------------------- BPy_ViewShape instance definitions ----------------------------*/ +static PyMethodDef BPy_ViewMap_methods[] = { + {"getClosestViewEdge", ( PyCFunction ) ViewMap_getClosestViewEdge, METH_VARARGS, ViewMap_getClosestViewEdge___doc__}, + {"getClosestFEdge", ( PyCFunction ) ViewMap_getClosestFEdge, METH_VARARGS, ViewMap_getClosestFEdge___doc__}, + {"getScene3dBBox", ( PyCFunction ) ViewMap_getScene3dBBox, METH_NOARGS, ViewMap_getScene3dBBox___doc__}, + {"setScene3dBBox", ( PyCFunction ) ViewMap_setScene3dBBox, METH_VARARGS, ViewMap_setScene3dBBox___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_ViewMap type definition ------------------------------*/ + +PyTypeObject ViewMap_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ViewMap", /* tp_name */ + sizeof(BPy_ViewMap), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)ViewMap___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)ViewMap___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ViewMap___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_ViewMap_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ViewMap___init__, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/BPy_ViewMap.h b/source/blender/freestyle/intern/python/BPy_ViewMap.h new file mode 100644 index 00000000000..943aeb718fc --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_ViewMap.h @@ -0,0 +1,34 @@ +#ifndef FREESTYLE_PYTHON_VIEWMAP_H +#define FREESTYLE_PYTHON_VIEWMAP_H + +#include <Python.h> + +#include "../view_map/ViewMap.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject ViewMap_Type; + +#define BPy_ViewMap_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ViewMap_Type) ) + +/*---------------------------Python BPy_ViewMap structure definition----------*/ +typedef struct { + PyObject_HEAD + ViewMap *vm; +} BPy_ViewMap; + +/*---------------------------Python BPy_ViewMap visible prototypes-----------*/ + +int ViewMap_Init( PyObject *module ); + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_VIEWMAP_H */ diff --git a/source/blender/freestyle/intern/python/BPy_ViewShape.cpp b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp new file mode 100644 index 00000000000..eebfa88773c --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp @@ -0,0 +1,353 @@ +#include "BPy_ViewShape.h" + +#include "BPy_Convert.h" +#include "Interface0D/BPy_ViewVertex.h" +#include "Interface1D/BPy_ViewEdge.h" +#include "BPy_SShape.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- +int ViewShape_Init( PyObject *module ) +{ + if( module == NULL ) + return -1; + + if( PyType_Ready( &ViewShape_Type ) < 0 ) + return -1; + + Py_INCREF( &ViewShape_Type ); + PyModule_AddObject(module, "ViewShape", (PyObject *)&ViewShape_Type); + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ViewShape___doc__[] = +"Class gathering the elements of the ViewMap (i.e., :class:`ViewVertex`\n" +"and :class:`ViewEdge`) that are issued from the same input shape.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: A ViewShape object.\n" +" :type iBrother: :class:`ViewShape`\n" +"\n" +".. method:: __init__(iSShape)\n" +"\n" +" Builds a ViewShape from an SShape.\n" +"\n" +" :arg iSShape: An SShape object.\n" +" :type iSShape: :class:`SShape`\n"; + +static int ViewShape___init__(BPy_ViewShape *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj; + + if (! PyArg_ParseTuple(args, "|O", &obj) ) + return -1; + + if( !obj ) { + self->vs = new ViewShape(); + + } else if( BPy_SShape_Check(obj) ) { + self->vs = new ViewShape( ((BPy_SShape *) obj)->ss ); + + } else if( BPy_ViewShape_Check(obj) ) { + self->vs = new ViewShape(*( ((BPy_ViewShape *) obj)->vs )); + + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument"); + return -1; + } + self->borrowed = 0; + + return 0; +} + +static void ViewShape___dealloc__(BPy_ViewShape *self) +{ + if( self->vs && !self->borrowed ) + delete self->vs; + Py_TYPE(self)->tp_free((PyObject*)self); +} + +static PyObject * ViewShape___repr__(BPy_ViewShape *self) +{ + return PyUnicode_FromFormat("ViewShape - address: %p", self->vs ); +} + +static char ViewShape_sshape___doc__[] = +".. method:: sshape()\n" +"\n" +" Returns the SShape on top of which this ViewShape is built.\n" +"\n" +" :return: The SShape on top of which this ViewShape is built.\n" +" :rtype: :class:`SShape`\n"; + +static PyObject * ViewShape_sshape( BPy_ViewShape *self ) { + return BPy_SShape_from_SShape( *(self->vs->sshape()) ); +} + +static char ViewShape_vertices___doc__[] = +".. method:: vertices()\n" +"\n" +" Returns the list of ViewVertex objects contained in this ViewShape.\n" +"\n" +" :return: The list of ViewVertex objects.\n" +" :rtype: List of :class:`ViewVertex` objects\n"; + +static PyObject * ViewShape_vertices( BPy_ViewShape *self ) { + PyObject *py_vertices = PyList_New(0); + + vector< ViewVertex * > vertices = self->vs->vertices(); + vector< ViewVertex * >::iterator it; + + for( it = vertices.begin(); it != vertices.end(); it++ ) { + PyList_Append( py_vertices, Any_BPy_ViewVertex_from_ViewVertex(*( *it )) ); + } + + return py_vertices; +} + +static char ViewShape_edges___doc__[] = +".. method:: edges()\n" +"\n" +" Returns the list of ViewEdge objects contained in this ViewShape.\n" +"\n" +" :return: The list of ViewEdge objects.\n" +" :rtype: List of :class:`ViewEdge` objects\n"; + +static PyObject * ViewShape_edges( BPy_ViewShape *self ) { + PyObject *py_edges = PyList_New(0); + + vector< ViewEdge * > edges = self->vs->edges(); + vector< ViewEdge * >::iterator it; + + for( it = edges.begin(); it != edges.end(); it++ ) { + PyList_Append( py_edges, BPy_ViewEdge_from_ViewEdge(*( *it )) ); + } + + return py_edges; +} + +static char ViewShape_getId___doc__[] = +".. method:: getId()\n" +"\n" +" Returns the ViewShape id.\n" +"\n" +" :return: An Id object.\n" +" :rtype: :class:`Id`\n"; + +static PyObject * ViewShape_getId( BPy_ViewShape *self ) { + Id id( self->vs->getId() ); + return BPy_Id_from_Id( id ); +} + +static char ViewShape_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the ViewShape.\n" +"\n" +" :return: The name string.\n" +" :rtype: str\n"; + +static PyObject * ViewShape_getName( BPy_ViewShape *self ) { + return PyUnicode_FromString( self->vs->getName().c_str() ); +} + +static char ViewShape_setSShape___doc__[] = +".. method:: setSShape(iSShape)\n" +"\n" +" Sets the SShape on top of which the ViewShape is built.\n" +"\n" +" :arg iSShape: An SShape object.\n" +" :type iSShape: :class:`SShape`\n"; + +static PyObject * ViewShape_setSShape( BPy_ViewShape *self , PyObject *args) { + PyObject *py_ss = 0; + + if(!( PyArg_ParseTuple(args, "O!", &SShape_Type, &py_ss) )) + return NULL; + + self->vs->setSShape( ((BPy_SShape *) py_ss)->ss ); + + Py_RETURN_NONE; +} + +static char ViewShape_setVertices___doc__[] = +".. method:: setVertices(iVertices)\n" +"\n" +" Sets the list of ViewVertex objects contained in this ViewShape.\n" +"\n" +" :arg iVertices: The list of ViewVertex objects.\n" +" :type iVertices: List of :class:`ViewVertex` objects\n"; + +static PyObject * ViewShape_setVertices( BPy_ViewShape *self , PyObject *args) { + PyObject *list = 0; + PyObject *tmp; + + if(!( PyArg_ParseTuple(args, "O!", &PyList_Type, &list) )) + return NULL; + + vector< ViewVertex *> v; + + for( int i=0; i < PyList_Size(list); i++ ) { + tmp = PyList_GetItem(list, i); + if( BPy_ViewVertex_Check(tmp) ) + v.push_back( ((BPy_ViewVertex *) tmp)->vv ); + else { + PyErr_SetString(PyExc_TypeError, "argument must be list of ViewVertex objects"); + return NULL; + } + } + + self->vs->setVertices( v ); + + Py_RETURN_NONE; +} + +static char ViewShape_setEdges___doc__[] = +".. method:: setEdges(iEdges)\n" +"\n" +" Sets the list of ViewEdge objects contained in this ViewShape.\n" +"\n" +" :arg iEdges: The list of ViewEdge objects.\n" +" :type iEdges: List of :class:`ViewEdge` objects.\n"; + +static PyObject * ViewShape_setEdges( BPy_ViewShape *self , PyObject *args) { + PyObject *list = 0; + PyObject *tmp; + + if(!( PyArg_ParseTuple(args, "O!", &PyList_Type, &list) )) + return NULL; + + vector<ViewEdge *> v; + + for( int i=0; i < PyList_Size(list); i++ ) { + tmp = PyList_GetItem(list, i); + if( BPy_ViewEdge_Check(tmp) ) + v.push_back( ((BPy_ViewEdge *) tmp)->ve ); + else { + PyErr_SetString(PyExc_TypeError, "argument must be list of ViewEdge objects"); + return NULL; + } + } + + self->vs->setEdges( v ); + + Py_RETURN_NONE; +} + +static char ViewShape_AddEdge___doc__[] = +".. method:: AddEdge(iEdge)\n" +"\n" +" Adds a ViewEdge to the list of ViewEdge objects.\n" +"\n" +" :arg iEdge: A ViewEdge object.\n" +" :type iEdge: :class:`ViewEdge`\n"; + +static PyObject * ViewShape_AddEdge( BPy_ViewShape *self , PyObject *args) { + PyObject *py_ve = 0; + + if(!( PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve) )) + return NULL; + + self->vs->AddEdge( ((BPy_ViewEdge *) py_ve)->ve ); + + Py_RETURN_NONE; +} + +static char ViewShape_AddVertex___doc__[] = +".. method:: AddVertex(iVertex)\n" +"\n" +" Adds a ViewVertex to the list of the ViewVertex objects.\n" +"\n" +" :arg iVertex: A ViewVertex object.\n" +" :type iVertex: :class:`ViewVertex`\n"; + +static PyObject * ViewShape_AddVertex( BPy_ViewShape *self , PyObject *args) { + PyObject *py_vv = 0; + + if(!( PyArg_ParseTuple(args, "O!", &ViewVertex_Type, &py_vv) )) + return NULL; + + self->vs->AddVertex( ((BPy_ViewVertex *) py_vv)->vv ); + + Py_RETURN_NONE; +} + +// virtual ViewShape * duplicate () + +/*---------------------- BPy_ViewShape instance definitions ----------------------------*/ +static PyMethodDef BPy_ViewShape_methods[] = { + {"sshape", ( PyCFunction ) ViewShape_sshape, METH_NOARGS, ViewShape_sshape___doc__}, + {"vertices", ( PyCFunction ) ViewShape_vertices, METH_NOARGS, ViewShape_vertices___doc__}, + {"edges", ( PyCFunction ) ViewShape_edges, METH_NOARGS, ViewShape_edges___doc__}, + {"getId", ( PyCFunction ) ViewShape_getId, METH_NOARGS, ViewShape_getId___doc__}, + {"getName", ( PyCFunction ) ViewShape_getName, METH_NOARGS, ViewShape_getName___doc__}, + {"setSShape", ( PyCFunction ) ViewShape_setSShape, METH_VARARGS, ViewShape_setSShape___doc__}, + {"setVertices", ( PyCFunction ) ViewShape_setVertices, METH_VARARGS, ViewShape_setVertices___doc__}, + {"setEdges", ( PyCFunction ) ViewShape_setEdges, METH_VARARGS, ViewShape_setEdges___doc__}, + {"AddEdge", ( PyCFunction ) ViewShape_AddEdge, METH_VARARGS, ViewShape_AddEdge___doc__}, + {"AddVertex", ( PyCFunction ) ViewShape_AddVertex, METH_VARARGS, ViewShape_AddVertex___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_ViewShape type definition ------------------------------*/ + +PyTypeObject ViewShape_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ViewShape", /* tp_name */ + sizeof(BPy_ViewShape), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)ViewShape___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)ViewShape___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ViewShape___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_ViewShape_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ViewShape___init__, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/BPy_ViewShape.h b/source/blender/freestyle/intern/python/BPy_ViewShape.h new file mode 100644 index 00000000000..1850ec8f13a --- /dev/null +++ b/source/blender/freestyle/intern/python/BPy_ViewShape.h @@ -0,0 +1,35 @@ +#ifndef FREESTYLE_PYTHON_VIEWSHAPE_H +#define FREESTYLE_PYTHON_VIEWSHAPE_H + +#include <Python.h> + +#include "../view_map/ViewMap.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +extern PyTypeObject ViewShape_Type; + +#define BPy_ViewShape_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ViewShape_Type) ) + +/*---------------------------Python BPy_ViewShape structure definition----------*/ +typedef struct { + PyObject_HEAD + ViewShape *vs; + int borrowed; /* non-zero if *vs a borrowed object */ +} BPy_ViewShape; + +/*---------------------------Python BPy_ViewShape visible prototypes-----------*/ + +int ViewShape_Init( PyObject *module ); + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_VIEWSHAPE_H */ diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp new file mode 100644 index 00000000000..78566d915d6 --- /dev/null +++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp @@ -0,0 +1,77 @@ +#include "BPy_FalseBP1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char FalseBP1D___doc__[] = +".. method:: __call__(inter1, inter2)\n" +"\n" +" Always returns false.\n" +"\n" +" :arg inter1: The first Interface1D object.\n" +" :type inter1: :class:`Interface1D`\n" +" :arg inter2: The second Interface1D object.\n" +" :type inter2: :class:`Interface1D`\n" +" :return: False.\n" +" :rtype: bool\n"; + +static int FalseBP1D___init__( BPy_FalseBP1D* self, PyObject *args ) +{ + if(!( PyArg_ParseTuple(args, "") )) + return -1; + self->py_bp1D.bp1D = new Predicates1D::FalseBP1D(); + return 0; +} + +/*-----------------------BPy_FalseBP1D type definition ------------------------------*/ +PyTypeObject FalseBP1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "FalseBP1D", /* tp_name */ + sizeof(BPy_FalseBP1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + FalseBP1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &BinaryPredicate1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)FalseBP1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.h b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.h new file mode 100644 index 00000000000..a8d4aad88aa --- /dev/null +++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.h @@ -0,0 +1,29 @@ +#ifndef FREESTYLE_PYTHON_FALSEBP1D_H +#define FREESTYLE_PYTHON_FALSEBP1D_H + +#include "../BPy_BinaryPredicate1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject FalseBP1D_Type; + +#define BPy_FalseBP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FalseBP1D_Type) ) + +/*---------------------------Python BPy_FalseBP1D structure definition----------*/ +typedef struct { + BPy_BinaryPredicate1D py_bp1D; +} BPy_FalseBP1D; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_FALSEBP1D_H */ diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp new file mode 100644 index 00000000000..5249e2ba6b0 --- /dev/null +++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp @@ -0,0 +1,79 @@ +#include "BPy_Length2DBP1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char Length2DBP1D___doc__[] = +".. method:: __call__(inter1, inter2)\n" +"\n" +" Returns true if the 2D length of inter1 is less than the 2D length\n" +" of inter2.\n" +"\n" +" :arg inter1: The first Interface1D object.\n" +" :type inter1: :class:`Interface1D`\n" +" :arg inter2: The second Interface1D object.\n" +" :type inter2: :class:`Interface1D`\n" +" :return: True or false.\n" +" :rtype: bool\n"; + +static int Length2DBP1D___init__( BPy_Length2DBP1D* self, PyObject *args ) +{ + if(!( PyArg_ParseTuple(args, "") )) + return -1; + self->py_bp1D.bp1D = new Predicates1D::Length2DBP1D(); + return 0; +} + +/*-----------------------BPy_Length2DBP1D type definition ------------------------------*/ + +PyTypeObject Length2DBP1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "Length2DBP1D", /* tp_name */ + sizeof(BPy_Length2DBP1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Length2DBP1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &BinaryPredicate1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)Length2DBP1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.h b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.h new file mode 100644 index 00000000000..d5bce5b150d --- /dev/null +++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.h @@ -0,0 +1,29 @@ +#ifndef FREESTYLE_PYTHON_LENGTH2DBP1D_H +#define FREESTYLE_PYTHON_LENGTH2DBP1D_H + +#include "../BPy_BinaryPredicate1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject Length2DBP1D_Type; + +#define BPy_Length2DBP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Length2DBP1D_Type) ) + +/*---------------------------Python BPy_Length2DBP1D structure definition----------*/ +typedef struct { + BPy_BinaryPredicate1D py_bp1D; +} BPy_Length2DBP1D; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_LENGTH2DBP1D_H */ diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp new file mode 100644 index 00000000000..5255752ff71 --- /dev/null +++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp @@ -0,0 +1,78 @@ +#include "BPy_SameShapeIdBP1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char SameShapeIdBP1D___doc__[] = +".. method:: __call__(inter1, inter2)\n" +"\n" +" Returns true if inter1 and inter2 belong to the same shape.\n" +"\n" +" :arg inter1: The first Interface1D object.\n" +" :type inter1: :class:`Interface1D`\n" +" :arg inter2: The second Interface1D object.\n" +" :type inter2: :class:`Interface1D`\n" +" :return: True or false.\n" +" :rtype: bool\n"; + +static int SameShapeIdBP1D___init__( BPy_SameShapeIdBP1D* self, PyObject *args ) +{ + if(!( PyArg_ParseTuple(args, "") )) + return -1; + self->py_bp1D.bp1D = new Predicates1D::SameShapeIdBP1D(); + return 0; +} + +/*-----------------------BPy_SameShapeIdBP1D type definition ------------------------------*/ + +PyTypeObject SameShapeIdBP1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "SameShapeIdBP1D", /* tp_name */ + sizeof(BPy_SameShapeIdBP1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + SameShapeIdBP1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &BinaryPredicate1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)SameShapeIdBP1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.h b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.h new file mode 100644 index 00000000000..71065d4ceeb --- /dev/null +++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.h @@ -0,0 +1,29 @@ +#ifndef FREESTYLE_PYTHON_SAMESHAPEIDBP1D_H +#define FREESTYLE_PYTHON_SAMESHAPEIDBP1D_H + +#include "../BPy_BinaryPredicate1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject SameShapeIdBP1D_Type; + +#define BPy_SameShapeIdBP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SameShapeIdBP1D_Type) ) + +/*---------------------------Python BPy_SameShapeIdBP1D structure definition----------*/ +typedef struct { + BPy_BinaryPredicate1D py_bp1D; +} BPy_SameShapeIdBP1D; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_SAMESHAPEIDBP1D_H */ diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp new file mode 100644 index 00000000000..6df906a31d5 --- /dev/null +++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp @@ -0,0 +1,78 @@ +#include "BPy_TrueBP1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char TrueBP1D___doc__[] = +".. method:: __call__(inter1, inter2)\n" +"\n" +" Always returns true.\n" +"\n" +" :arg inter1: The first Interface1D object.\n" +" :type inter1: :class:`Interface1D`\n" +" :arg inter2: The second Interface1D object.\n" +" :type inter2: :class:`Interface1D`\n" +" :return: True.\n" +" :rtype: bool\n"; + +static int TrueBP1D___init__( BPy_TrueBP1D* self, PyObject *args ) +{ + if(!( PyArg_ParseTuple(args, "") )) + return -1; + self->py_bp1D.bp1D = new Predicates1D::TrueBP1D(); + return 0; +} + +/*-----------------------BPy_TrueBP1D type definition ------------------------------*/ + +PyTypeObject TrueBP1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "TrueBP1D", /* tp_name */ + sizeof(BPy_TrueBP1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + TrueBP1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &BinaryPredicate1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)TrueBP1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.h b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.h new file mode 100644 index 00000000000..7d809e1fe65 --- /dev/null +++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.h @@ -0,0 +1,29 @@ +#ifndef FREESTYLE_PYTHON_TRUEBP1D_H +#define FREESTYLE_PYTHON_TRUEBP1D_H + +#include "../BPy_BinaryPredicate1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject TrueBP1D_Type; + +#define BPy_TrueBP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TrueBP1D_Type) ) + +/*---------------------------Python BPy_TrueBP1D structure definition----------*/ +typedef struct { + BPy_BinaryPredicate1D py_bp1D; +} BPy_TrueBP1D; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_TRUEBP1D_H */ diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp new file mode 100644 index 00000000000..5f433ae3e22 --- /dev/null +++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp @@ -0,0 +1,90 @@ +#include "BPy_ViewMapGradientNormBP1D.h" + +#include "../BPy_Convert.h" +#include "../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +//ViewMapGradientNormBP1D(int level, IntegrationType iType=MEAN, float sampling=2.0) + +static char ViewMapGradientNormBP1D___doc__[] = +".. method:: __call__(inter1, inter2)\n" +"\n" +" Returns true if the evaluation of the Gradient norm Function is\n" +" higher for inter1 than for inter2.\n" +"\n" +" :arg inter1: The first Interface1D object.\n" +" :type inter1: :class:`Interface1D`\n" +" :arg inter2: The second Interface1D object.\n" +" :type inter2: :class:`Interface1D`\n" +" :return: True or false.\n" +" :rtype: bool\n"; + +static int ViewMapGradientNormBP1D___init__( BPy_ViewMapGradientNormBP1D* self, PyObject *args ) +{ + int i; + PyObject *obj; + float f = 2.0; + + if(!( PyArg_ParseTuple(args, "i|O!f", &i, &IntegrationType_Type, &obj, &f) )) + return -1; + + IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN; + self->py_bp1D.bp1D = new Predicates1D::ViewMapGradientNormBP1D(i,t,f); + return 0; +} + +/*-----------------------BPy_ViewMapGradientNormBP1D type definition ------------------------------*/ + +PyTypeObject ViewMapGradientNormBP1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ViewMapGradientNormBP1D", /* tp_name */ + sizeof(BPy_ViewMapGradientNormBP1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ViewMapGradientNormBP1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &BinaryPredicate1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ViewMapGradientNormBP1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.h b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.h new file mode 100644 index 00000000000..23d27e118a9 --- /dev/null +++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.h @@ -0,0 +1,29 @@ +#ifndef FREESTYLE_PYTHON_VIEWMAPGRADIENTNORMBP1D_H +#define FREESTYLE_PYTHON_VIEWMAPGRADIENTNORMBP1D_H + +#include "../BPy_BinaryPredicate1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ViewMapGradientNormBP1D_Type; + +#define BPy_ViewMapGradientNormBP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ViewMapGradientNormBP1D_Type) ) + +/*---------------------------Python BPy_ViewMapGradientNormBP1D structure definition----------*/ +typedef struct { + BPy_BinaryPredicate1D py_bp1D; +} BPy_ViewMapGradientNormBP1D; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_VIEWMAPGRADIENTNORMBP1D_H */ diff --git a/source/blender/freestyle/intern/python/Director.cpp b/source/blender/freestyle/intern/python/Director.cpp new file mode 100644 index 00000000000..1948da2b6b0 --- /dev/null +++ b/source/blender/freestyle/intern/python/Director.cpp @@ -0,0 +1,304 @@ +#include "Director.h" + +#include "BPy_Convert.h" + +#include "BPy_BinaryPredicate0D.h" +#include "BPy_BinaryPredicate1D.h" +#include "BPy_FrsMaterial.h" +#include "BPy_Id.h" +#include "BPy_UnaryFunction0D.h" +#include "BPy_UnaryFunction1D.h" +#include "BPy_UnaryPredicate0D.h" +#include "BPy_UnaryPredicate1D.h" +#include "BPy_StrokeShader.h" +#include "Iterator/BPy_ChainingIterator.h" +#include "Iterator/BPy_Interface0DIterator.h" +#include "Interface1D/BPy_Stroke.h" +#include "Interface1D/BPy_ViewEdge.h" +#include "BPy_ViewShape.h" + +#include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DFloat.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DId.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DMaterial.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DVec2f.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DVec3f.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h" +#include "UnaryFunction0D/BPy_UnaryFunction0DViewShape.h" + +#include "UnaryFunction1D/BPy_UnaryFunction1DDouble.h" +#include "UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h" +#include "UnaryFunction1D/BPy_UnaryFunction1DFloat.h" +#include "UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h" +#include "UnaryFunction1D/BPy_UnaryFunction1DVec2f.h" +#include "UnaryFunction1D/BPy_UnaryFunction1DVec3f.h" +#include "UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h" + + +// BinaryPredicate0D: __call__ +int Director_BPy_BinaryPredicate0D___call__( BinaryPredicate0D *bp0D, Interface0D& i1, Interface0D& i2 ) { + if (!bp0D->py_bp0D) { // internal error + PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_bp0D) not initialized"); + return -1; + } + PyObject *arg1 = Any_BPy_Interface0D_from_Interface0D(i1); + PyObject *arg2 = Any_BPy_Interface0D_from_Interface0D(i2); + if (!arg1 || !arg2) { + Py_XDECREF(arg1); + Py_XDECREF(arg2); + return -1; + } + PyObject *result = PyObject_CallMethod( bp0D->py_bp0D, "__call__", "OO", arg1, arg2 ); + Py_DECREF(arg1); + Py_DECREF(arg2); + if (!result) + return -1; + int ret = PyObject_IsTrue(result); + Py_DECREF(result); + if (ret < 0) + return -1; + bp0D->result = ret; + return 0; +} + + +// BinaryPredicate1D: __call__ +int Director_BPy_BinaryPredicate1D___call__( BinaryPredicate1D *bp1D, Interface1D& i1, Interface1D& i2 ) { + if (!bp1D->py_bp1D) { // internal error + PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_bp1D) not initialized"); + return -1; + } + PyObject *arg1 = Any_BPy_Interface1D_from_Interface1D(i1); + PyObject *arg2 = Any_BPy_Interface1D_from_Interface1D(i2); + if (!arg1 || !arg2) { + Py_XDECREF(arg1); + Py_XDECREF(arg2); + return -1; + } + PyObject *result = PyObject_CallMethod( bp1D->py_bp1D, "__call__", "OO", arg1, arg2 ); + Py_DECREF(arg1); + Py_DECREF(arg2); + if (!result) + return -1; + int ret = PyObject_IsTrue(result); + Py_DECREF(result); + if (ret < 0) + return -1; + bp1D->result = ret; + return 0; +} + + +// UnaryPredicate0D: __call__ +int Director_BPy_UnaryPredicate0D___call__( UnaryPredicate0D *up0D, Interface0DIterator& if0D_it ) { + if (!up0D->py_up0D) { // internal error + PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_up0D) not initialized"); + return -1; + } + PyObject *arg = BPy_Interface0DIterator_from_Interface0DIterator(if0D_it, 0); + if (!arg) + return -1; + PyObject *result = PyObject_CallMethod( up0D->py_up0D, "__call__", "O", arg ); + Py_DECREF(arg); + if (!result) + return -1; + int ret = PyObject_IsTrue(result); + Py_DECREF(result); + if (ret < 0) + return -1; + up0D->result = ret; + return 0; +} + + +// UnaryPredicate1D: __call__ +int Director_BPy_UnaryPredicate1D___call__( UnaryPredicate1D *up1D, Interface1D& if1D ) { + if (!up1D->py_up1D) { // internal error + PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_up1D) not initialized"); + return -1; + } + PyObject *arg = Any_BPy_Interface1D_from_Interface1D(if1D); + if (!arg) + return -1; + PyObject *result = PyObject_CallMethod( up1D->py_up1D, "__call__", "O", arg ); + Py_DECREF(arg); + if (!result) + return -1; + int ret = PyObject_IsTrue(result); + Py_DECREF(result); + if (ret < 0) + return -1; + up1D->result = ret; + return 0; +} + + +// StrokeShader: shade +int Director_BPy_StrokeShader_shade( StrokeShader *ss, Stroke& s ) { + if (!ss->py_ss) { // internal error + PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_ss) not initialized"); + return -1; + } + PyObject *arg = BPy_Stroke_from_Stroke(s); + if (!arg) + return -1; + PyObject *result = PyObject_CallMethod( ss->py_ss, "shade", "O", arg ); + Py_DECREF(arg); + if (!result) + return -1; + Py_DECREF(result); + return 0; +} + +// ChainingIterator: init, traverse +int Director_BPy_ChainingIterator_init( ChainingIterator *c_it ) { + if (!c_it->py_c_it) { // internal error + PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_c_it) not initialized"); + return -1; + } + PyObject *result = PyObject_CallMethod( c_it->py_c_it, "init", ""); + if (!result) + return -1; + Py_DECREF(result); + return 0; +} + +int Director_BPy_ChainingIterator_traverse( ChainingIterator *c_it, AdjacencyIterator& a_it ) { + if (!c_it->py_c_it) { // internal error + PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_c_it) not initialized"); + return -1; + } + PyObject *arg = BPy_AdjacencyIterator_from_AdjacencyIterator(a_it); + if (!arg) + return -1; + PyObject *result = PyObject_CallMethod( c_it->py_c_it, "traverse", "O", arg ); + Py_DECREF(arg); + if (!result) + return -1; + if (BPy_ViewEdge_Check(result)) { + c_it->result = ((BPy_ViewEdge *) result)->ve; + } else if (result == Py_None) { + c_it->result = NULL; + } else { + PyErr_SetString(PyExc_RuntimeError, "traverse method returned a wrong value"); + Py_DECREF(result); + return -1; + } + Py_DECREF(result); + return 0; +} + + +// BPy_UnaryFunction{0D,1D}: __call__ +int Director_BPy_UnaryFunction0D___call__( void *uf0D, PyObject *obj, Interface0DIterator& if0D_it) { + + if (!obj) { // internal error + PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_uf0D) not initialized"); + return -1; + } + PyObject *arg = BPy_Interface0DIterator_from_Interface0DIterator(if0D_it, 0); + if (!arg) + return -1; + PyObject *result = PyObject_CallMethod( obj, "__call__", "O", arg ); + Py_DECREF(arg); + if (!result) + return -1; + + if( BPy_UnaryFunction0DDouble_Check(obj) ) { + ((UnaryFunction0D<double> *) uf0D)->result = PyFloat_AsDouble(result); + + } else if ( BPy_UnaryFunction0DEdgeNature_Check(obj) ) { + ((UnaryFunction0D<Nature::EdgeNature> *) uf0D)->result = EdgeNature_from_BPy_Nature(result); + + } else if ( BPy_UnaryFunction0DFloat_Check(obj) ) { + ((UnaryFunction0D<float> *) uf0D)->result = PyFloat_AsDouble(result); + + } else if ( BPy_UnaryFunction0DId_Check(obj) ) { + ((UnaryFunction0D<Id> *) uf0D)->result = *( ((BPy_Id *) result)->id ); + + } else if ( BPy_UnaryFunction0DMaterial_Check(obj) ) { + ((UnaryFunction0D<FrsMaterial> *) uf0D)->result = *( ((BPy_FrsMaterial *) result)->m ); + + } else if ( BPy_UnaryFunction0DUnsigned_Check(obj) ) { + ((UnaryFunction0D<unsigned> *) uf0D)->result = PyLong_AsLong(result); + + } else if ( BPy_UnaryFunction0DVec2f_Check(obj) ) { + Vec2f *v = Vec2f_ptr_from_Vector( result ); + ((UnaryFunction0D<Vec2f> *) uf0D)->result = *v; + delete v; + + } else if ( BPy_UnaryFunction0DVec3f_Check(obj) ) { + Vec3f *v = Vec3f_ptr_from_Vector( result ); + ((UnaryFunction0D<Vec3f> *) uf0D)->result = *v; + delete v; + + } else if ( BPy_UnaryFunction0DVectorViewShape_Check(obj) ) { + vector<ViewShape*> vec; + for( int i = 0; i < PyList_Size(result); i++) { + ViewShape *b = ( (BPy_ViewShape *) PyList_GetItem(result, i) )->vs; + vec.push_back( b ); + } + + ((UnaryFunction0D< vector<ViewShape*> > *) uf0D)->result = vec; + + } else if ( BPy_UnaryFunction0DViewShape_Check(obj) ) { + ((UnaryFunction0D<ViewShape*> *) uf0D)->result = ((BPy_ViewShape *) result)->vs; + + } + + Py_DECREF(result); + return 0; +} + +int Director_BPy_UnaryFunction1D___call__( void *uf1D, PyObject *obj, Interface1D& if1D) { + + if (!obj) { // internal error + PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_uf1D) not initialized"); + return -1; + } + PyObject *arg = Any_BPy_Interface1D_from_Interface1D(if1D); + if (!arg) + return -1; + PyObject *result = PyObject_CallMethod( obj, "__call__", "O", arg ); + Py_DECREF(arg); + if (!result) + return -1; + + if( BPy_UnaryFunction1DDouble_Check(obj) ) { + ((UnaryFunction1D<double> *) uf1D)->result = PyFloat_AsDouble(result); + + } else if ( BPy_UnaryFunction1DEdgeNature_Check(obj) ) { + ((UnaryFunction1D<Nature::EdgeNature> *) uf1D)->result = EdgeNature_from_BPy_Nature(result); + + } else if ( BPy_UnaryFunction1DFloat_Check(obj) ) { + ((UnaryFunction1D<float> *) uf1D)->result = PyFloat_AsDouble(result); + + } else if ( BPy_UnaryFunction1DUnsigned_Check(obj) ) { + ((UnaryFunction1D<unsigned> *) uf1D)->result = PyLong_AsLong(result); + + } else if ( BPy_UnaryFunction1DVec2f_Check(obj) ) { + Vec2f *v = Vec2f_ptr_from_Vector( result ); + ((UnaryFunction1D<Vec2f> *) uf1D)->result = *v; + delete v; + + } else if ( BPy_UnaryFunction1DVec3f_Check(obj) ) { + Vec3f *v = Vec3f_ptr_from_Vector( result ); + ((UnaryFunction1D<Vec3f> *) uf1D)->result = *v; + delete v; + + } else if ( BPy_UnaryFunction1DVectorViewShape_Check(obj) ) { + vector<ViewShape*> vec; + for( int i = 1; i < PyList_Size(result); i++) { + ViewShape *b = ( (BPy_ViewShape *) PyList_GetItem(result, i) )->vs; + vec.push_back( b ); + } + + ((UnaryFunction1D< vector<ViewShape*> > *) uf1D)->result = vec; + + } + + Py_DECREF(result); + return 0; +} diff --git a/source/blender/freestyle/intern/python/Director.h b/source/blender/freestyle/intern/python/Director.h new file mode 100644 index 00000000000..667d4a65942 --- /dev/null +++ b/source/blender/freestyle/intern/python/Director.h @@ -0,0 +1,49 @@ +#ifndef FREESTYLE_PYTHON_DIRECTOR +# define FREESTYLE_PYTHON_DIRECTOR + +class UnaryPredicate0D; +class UnaryPredicate1D; +class BinaryPredicate0D; +class BinaryPredicate1D; +class ChainingIterator; +class AdjacencyIterator; +class Interface0D; +class Interface1D; +class Interface0DIterator; +class Stroke; +class StrokeShader; + +#ifdef __cplusplus +extern "C" { +#endif + +#include <Python.h> + +#ifdef __cplusplus +} +#endif + +// BinaryPredicate0D: __call__ +int Director_BPy_BinaryPredicate0D___call__( BinaryPredicate0D *bp0D, Interface0D& i1, Interface0D& i2 ); + +// BinaryPredicate1D: __call__ +int Director_BPy_BinaryPredicate1D___call__( BinaryPredicate1D *bp1D, Interface1D& i1, Interface1D& i2 ); + +// UnaryFunction{0D,1D}: __call__ +int Director_BPy_UnaryFunction0D___call__( void *uf0D, PyObject *obj, Interface0DIterator& if0D_it); +int Director_BPy_UnaryFunction1D___call__( void *uf1D, PyObject *obj, Interface1D& if1D); + +// UnaryPredicate0D: __call__ +int Director_BPy_UnaryPredicate0D___call__( UnaryPredicate0D *up0D, Interface0DIterator& if0D_it ); + +// UnaryPredicate1D: __call__ +int Director_BPy_UnaryPredicate1D___call__( UnaryPredicate1D *up1D, Interface1D& if1D ); + +// StrokeShader: shade +int Director_BPy_StrokeShader_shade( StrokeShader *ss, Stroke& s ); + +// ChainingIterator: init, traverse +int Director_BPy_ChainingIterator_init( ChainingIterator *c_it ); +int Director_BPy_ChainingIterator_traverse( ChainingIterator *c_it, AdjacencyIterator& a_it ); + +#endif // FREESTYLE_PYTHON_DIRECTOR diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp new file mode 100644 index 00000000000..dd1f4a2efba --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp @@ -0,0 +1,276 @@ +#include "BPy_CurvePoint.h" + +#include "../BPy_Convert.h" +#include "../Interface0D/BPy_SVertex.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char CurvePoint___doc__[] = +"Class to represent a point of a curve. A CurvePoint can be any point\n" +"of a 1D curve (it doesn't have to be a vertex of the curve). Any\n" +":class:`Interface1D` is built upon ViewEdges, themselves built upon\n" +"FEdges. Therefore, a curve is basically a polyline made of a list of\n" +":class:`SVertex` objects. Thus, a CurvePoint is built by linearly\n" +"interpolating two :class:`SVertex` instances. CurvePoint can be used\n" +"as virtual points while querying 0D information along a curve at a\n" +"given resolution.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Defult constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: A CurvePoint object.\n" +" :type iBrother: :class:`CurvePoint`\n" +"\n" +".. method:: __init__(iA, iB, t2d)\n" +"\n" +" Builds a CurvePoint from two SVertex and an interpolation parameter.\n" +"\n" +" :arg iA: The first SVertex.\n" +" :type iA: :class:`SVertex`\n" +" :arg iB: The second SVertex.\n" +" :type iB: :class:`SVertex`\n" +" :arg t2d: A 2D interpolation parameter used to linearly interpolate\n" +" iA and iB.\n" +" :type t2d: float\n" +"\n" +".. method:: __init__(iA, iB, t2d)\n" +"\n" +" Builds a CurvePoint from two CurvePoint and an interpolation\n" +" parameter.\n" +"\n" +" :arg iA: The first CurvePoint.\n" +" :type iA: :class:`CurvePoint`\n" +" :arg iB: The second CurvePoint.\n" +" :type iB: :class:`CurvePoint`\n" +" :arg t2d: The 2D interpolation parameter used to linearly\n" +" interpolate iA and iB.\n" +" :type t2d: float\n"; + +static int CurvePoint___init__(BPy_CurvePoint *self, PyObject *args, PyObject *kwds) +{ + + PyObject *obj1 = 0, *obj2 = 0 , *obj3 = 0; + + if (! PyArg_ParseTuple(args, "|OOO!", &obj1, &obj2, &PyFloat_Type, &obj3) ) + return -1; + + if( !obj1 ){ + self->cp = new CurvePoint(); + + } else if( !obj2 && BPy_CurvePoint_Check(obj1) ) { + self->cp = new CurvePoint( *(((BPy_CurvePoint *) obj1)->cp) ); + + } else if( obj3 && BPy_SVertex_Check(obj1) && BPy_SVertex_Check(obj2) ) { + self->cp = new CurvePoint( ((BPy_SVertex *) obj1)->sv, + ((BPy_SVertex *) obj2)->sv, + PyFloat_AsDouble( obj3 ) ); + + } else if( obj3 && BPy_CurvePoint_Check(obj1) && BPy_CurvePoint_Check(obj2) ) { + CurvePoint *cp1 = ((BPy_CurvePoint *) obj1)->cp; + CurvePoint *cp2 = ((BPy_CurvePoint *) obj2)->cp; + if( !cp1 || cp1->A() == 0 || cp1->B() == 0 ) { + PyErr_SetString(PyExc_TypeError, "argument 1 is an invalid CurvePoint object"); + return -1; + } + if( !cp2 || cp2->A() == 0 || cp2->B() == 0 ) { + PyErr_SetString(PyExc_TypeError, "argument 2 is an invalid CurvePoint object"); + return -1; + } + self->cp = new CurvePoint( cp1, cp2, PyFloat_AsDouble( obj3 ) ); + + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument(s)"); + return -1; + } + + self->py_if0D.if0D = self->cp; + self->py_if0D.borrowed = 0; + + return 0; +} + +static char CurvePoint_A___doc__[] = +".. method:: A()\n" +"\n" +" Returns the first SVertex upon which the CurvePoint is built.\n" +"\n" +" :return: The first SVertex.\n" +" :rtype: :class:`SVertex`\n"; + +static PyObject * CurvePoint_A( BPy_CurvePoint *self ) { + SVertex *A = self->cp->A(); + if( A ) + return BPy_SVertex_from_SVertex( *A ); + + Py_RETURN_NONE; +} + +static char CurvePoint_B___doc__[] = +".. method:: B()\n" +"\n" +" Returns the second SVertex upon which the CurvePoint is built.\n" +"\n" +" :return: The second SVertex.\n" +" :rtype: :class:`SVertex`\n"; + +static PyObject * CurvePoint_B( BPy_CurvePoint *self ) { + SVertex *B = self->cp->B(); + if( B ) + return BPy_SVertex_from_SVertex( *B ); + + Py_RETURN_NONE; +} + +static char CurvePoint_t2d___doc__[] = +".. method:: t2d()\n" +"\n" +" Returns the 2D interpolation parameter.\n" +"\n" +" :return: The 2D interpolation parameter.\n" +" :rtype: float\n"; + +static PyObject * CurvePoint_t2d( BPy_CurvePoint *self ) { + return PyFloat_FromDouble( self->cp->t2d() ); +} + +static char CurvePoint_setA___doc__[] = +".. method:: setA(iA)\n" +"\n" +" Sets the first SVertex upon which to build the CurvePoint.\n" +"\n" +" :arg iA: The first SVertex.\n" +" :type iA: :class:`SVertex`\n"; + +static PyObject *CurvePoint_setA( BPy_CurvePoint *self , PyObject *args) { + PyObject *py_sv; + + if(!( PyArg_ParseTuple(args, "O!", &SVertex_Type, &py_sv) )) + return NULL; + + self->cp->setA( ((BPy_SVertex *) py_sv)->sv ); + + Py_RETURN_NONE; +} + +static char CurvePoint_setB___doc__[] = +".. method:: setB(iB)\n" +"\n" +" Sets the first SVertex upon which to build the CurvePoint.\n" +"\n" +" :arg iB: The second SVertex.\n" +" :type iB: :class:`SVertex`\n"; + +static PyObject *CurvePoint_setB( BPy_CurvePoint *self , PyObject *args) { + PyObject *py_sv; + + if(!( PyArg_ParseTuple(args, "O!", &SVertex_Type, &py_sv) )) + return NULL; + + self->cp->setB( ((BPy_SVertex *) py_sv)->sv ); + + Py_RETURN_NONE; +} + +static char CurvePoint_setT2d___doc__[] = +".. method:: setT2d(t)\n" +"\n" +" Sets the 2D interpolation parameter to use.\n" +"\n" +" :arg t: The 2D interpolation parameter.\n" +" :type t: float\n"; + +static PyObject *CurvePoint_setT2d( BPy_CurvePoint *self , PyObject *args) { + float t; + + if(!( PyArg_ParseTuple(args, "f", &t) )) + return NULL; + + self->cp->setT2d( t ); + + Py_RETURN_NONE; +} + +static char CurvePoint_curvatureFredo___doc__[] = +".. method:: curvatureFredo()\n" +"\n" +" Returns the angle in radians.\n" +"\n" +" :return: The angle in radians.\n" +" :rtype: float\n"; + +static PyObject *CurvePoint_curvatureFredo( BPy_CurvePoint *self , PyObject *args) { + return PyFloat_FromDouble( self->cp->curvatureFredo() ); +} + +///bool operator== (const CurvePoint &b) + +/*----------------------CurvePoint instance definitions ----------------------------*/ +static PyMethodDef BPy_CurvePoint_methods[] = { + {"A", ( PyCFunction ) CurvePoint_A, METH_NOARGS, CurvePoint_A___doc__}, + {"B", ( PyCFunction ) CurvePoint_B, METH_NOARGS, CurvePoint_B___doc__}, + {"t2d", ( PyCFunction ) CurvePoint_t2d, METH_NOARGS, CurvePoint_t2d___doc__}, + {"setA", ( PyCFunction ) CurvePoint_setA, METH_VARARGS, CurvePoint_setA___doc__}, + {"setB", ( PyCFunction ) CurvePoint_setB, METH_VARARGS, CurvePoint_setB___doc__}, + {"setT2d", ( PyCFunction ) CurvePoint_setT2d, METH_VARARGS, CurvePoint_setT2d___doc__}, + {"curvatureFredo", ( PyCFunction ) CurvePoint_curvatureFredo, METH_NOARGS, CurvePoint_curvatureFredo___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_CurvePoint type definition ------------------------------*/ +PyTypeObject CurvePoint_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "CurvePoint", /* tp_name */ + sizeof(BPy_CurvePoint), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + CurvePoint___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_CurvePoint_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &Interface0D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)CurvePoint___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h new file mode 100644 index 00000000000..b4c22645503 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_CURVEPOINT_H +#define FREESTYLE_PYTHON_CURVEPOINT_H + +#include "../BPy_Interface0D.h" +#include "../../stroke/Curve.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject CurvePoint_Type; + +#define BPy_CurvePoint_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &CurvePoint_Type) ) + +/*---------------------------Python BPy_CurvePoint structure definition----------*/ +typedef struct { + BPy_Interface0D py_if0D; + CurvePoint *cp; +} BPy_CurvePoint; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_CURVEPOINT_H */ diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp new file mode 100644 index 00000000000..bf810e6458e --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp @@ -0,0 +1,301 @@ +#include "BPy_SVertex.h" + +#include "../BPy_Convert.h" +#include "../BPy_Id.h" +#include "../Interface1D/BPy_FEdge.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +static char SVertex___doc__[] = +"Class to define a vertex of the embedding.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: A SVertex object.\n" +" :type iBrother: :class:`SVertex`\n" +"\n" +".. method:: __init__(iPoint3D, id)\n" +"\n" +" Builds a SVertex from 3D coordinates and an Id.\n" +"\n" +" :arg iPoint3D: A three-dimensional vector.\n" +" :type iPoint3D: :class:`mathutils.Vector`\n" +" :arg id: An Id object.\n" +" :type id: :class:`Id`\n"; + +//------------------------INSTANCE METHODS ---------------------------------- + +static int SVertex___init__(BPy_SVertex *self, PyObject *args, PyObject *kwds) +{ + PyObject *py_point = 0; + BPy_Id *py_id = 0; + + + if (! PyArg_ParseTuple(args, "|OO!", &py_point, &Id_Type, &py_id) ) + return -1; + + if( !py_point ) { + self->sv = new SVertex(); + + } else if( !py_id && BPy_SVertex_Check(py_point) ) { + self->sv = new SVertex( *(((BPy_SVertex *)py_point)->sv) ); + + } else if( py_point && py_id ) { + Vec3r *v = Vec3r_ptr_from_PyObject(py_point); + if( !v ) { + PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)"); + return -1; + } + self->sv = new SVertex( *v, *(py_id->id) ); + delete v; + + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument(s)"); + return -1; + } + + self->py_if0D.if0D = self->sv; + self->py_if0D.borrowed = 0; + + return 0; +} + +static char SVertex_normals___doc__[] = +".. method:: normals()\n" +"\n" +" Returns the normals for this Vertex as a list. In a smooth surface,\n" +" a vertex has exactly one normal. In a sharp surface, a vertex can\n" +" have any number of normals.\n" +"\n" +" :return: A list of normals.\n" +" :rtype: List of :class:`mathutils.Vector` objects\n"; + +static PyObject * SVertex_normals( BPy_SVertex *self ) { + PyObject *py_normals; + set< Vec3r > normals; + + py_normals = PyList_New(0); + normals = self->sv->normals(); + + for( set< Vec3r >::iterator set_iterator = normals.begin(); set_iterator != normals.end(); set_iterator++ ) { + Vec3r v( *set_iterator ); + PyList_Append( py_normals, Vector_from_Vec3r(v) ); + } + + return py_normals; +} + +static char SVertex_normalsSize___doc__[] = +".. method:: normalsSize()\n" +"\n" +" Returns the number of different normals for this vertex.\n" +"\n" +" :return: The number of normals.\n" +" :rtype: int\n"; + +static PyObject * SVertex_normalsSize( BPy_SVertex *self ) { + return PyLong_FromLong( self->sv->normalsSize() ); +} + +static char SVertex_viewvertex___doc__[] = +".. method:: viewvertex()\n" +"\n" +" If this SVertex is also a ViewVertex, this method returns the\n" +" ViewVertex. None is returned otherwise.\n" +"\n" +" :return: The ViewVertex object.\n" +" :rtype: :class:`ViewVertex`\n"; + +static PyObject * SVertex_viewvertex( BPy_SVertex *self ) { + ViewVertex *vv = self->sv->viewvertex(); + if( vv ) + return Any_BPy_ViewVertex_from_ViewVertex( *vv ); + + Py_RETURN_NONE; +} + +static char SVertex_setPoint3D___doc__[] = +".. method:: setPoint3D(p)\n" +"\n" +" Sets the 3D coordinates of the SVertex.\n" +"\n" +" :arg p: A three-dimensional vector.\n" +" :type p: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"; + +static PyObject *SVertex_setPoint3D( BPy_SVertex *self , PyObject *args) { + PyObject *py_point; + + if(!( PyArg_ParseTuple(args, "O", &py_point) )) + return NULL; + Vec3r *v = Vec3r_ptr_from_PyObject(py_point); + if( !v ) { + PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)"); + return NULL; + } + self->sv->setPoint3D( *v ); + delete v; + + Py_RETURN_NONE; +} + +static char SVertex_setPoint2D___doc__[] = +".. method:: setPoint2D(p)\n" +"\n" +" Sets the 2D projected coordinates of the SVertex.\n" +"\n" +" :arg p: A three-dimensional vector.\n" +" :type p: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"; + +static PyObject *SVertex_setPoint2D( BPy_SVertex *self , PyObject *args) { + PyObject *py_point; + + if(!( PyArg_ParseTuple(args, "O", &py_point) )) + return NULL; + Vec3r *v = Vec3r_ptr_from_PyObject(py_point); + if( !v ) { + PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)"); + return NULL; + } + self->sv->setPoint2D( *v ); + delete v; + + Py_RETURN_NONE; +} + +static char SVertex_AddNormal___doc__[] = +".. method:: AddNormal(n)\n" +"\n" +" Adds a normal to the SVertex's set of normals. If the same normal\n" +" is already in the set, nothing changes.\n" +"\n" +" :arg n: A three-dimensional vector.\n" +" :type n: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"; + +static PyObject *SVertex_AddNormal( BPy_SVertex *self , PyObject *args) { + PyObject *py_normal; + + if(!( PyArg_ParseTuple(args, "O", &py_normal) )) + return NULL; + Vec3r *n = Vec3r_ptr_from_PyObject(py_normal); + if( !n ) { + PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)"); + return NULL; + } + self->sv->AddNormal( *n ); + delete n; + + Py_RETURN_NONE; +} + +static char SVertex_setId___doc__[] = +".. method:: setId(id)\n" +"\n" +" Sets the identifier of the SVertex.\n" +"\n" +" :arg id: The identifier.\n" +" :type id: :class:`Id`\n"; + +static PyObject *SVertex_setId( BPy_SVertex *self , PyObject *args) { + BPy_Id *py_id; + + if( !PyArg_ParseTuple(args, "O!", &Id_Type, &py_id) ) + return NULL; + + self->sv->setId( *(py_id->id) ); + + Py_RETURN_NONE; +} + +static char SVertex_AddFEdge___doc__[] = +".. method:: AddFEdge(fe)\n" +"\n" +" Add an FEdge to the list of edges emanating from this SVertex.\n" +"\n" +" :arg fe: An FEdge.\n" +" :type fe: :class:`FEdge`\n"; + +static PyObject *SVertex_AddFEdge( BPy_SVertex *self , PyObject *args) { + PyObject *py_fe; + + if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) )) + return NULL; + + self->sv->AddFEdge( ((BPy_FEdge *) py_fe)->fe ); + + Py_RETURN_NONE; +} + +// virtual bool operator== (const SVertex &iBrother) +// ViewVertex * viewvertex () + +/*----------------------SVertex instance definitions ----------------------------*/ +static PyMethodDef BPy_SVertex_methods[] = { + {"normals", ( PyCFunction ) SVertex_normals, METH_NOARGS, SVertex_normals___doc__}, + {"normalsSize", ( PyCFunction ) SVertex_normalsSize, METH_NOARGS, SVertex_normalsSize___doc__}, + {"viewvertex", ( PyCFunction ) SVertex_viewvertex, METH_NOARGS, SVertex_viewvertex___doc__}, + {"setPoint3D", ( PyCFunction ) SVertex_setPoint3D, METH_VARARGS, SVertex_setPoint3D___doc__}, + {"setPoint2D", ( PyCFunction ) SVertex_setPoint2D, METH_VARARGS, SVertex_setPoint2D___doc__}, + {"AddNormal", ( PyCFunction ) SVertex_AddNormal, METH_VARARGS, SVertex_AddNormal___doc__}, + {"setId", ( PyCFunction ) SVertex_setId, METH_VARARGS, SVertex_setId___doc__}, + {"AddFEdge", ( PyCFunction ) SVertex_AddFEdge, METH_VARARGS, SVertex_AddFEdge___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_SVertex type definition ------------------------------*/ +PyTypeObject SVertex_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "SVertex", /* tp_name */ + sizeof(BPy_SVertex), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + SVertex___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_SVertex_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &Interface0D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)SVertex___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h new file mode 100644 index 00000000000..7d310f2b7dc --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h @@ -0,0 +1,32 @@ +#ifndef FREESTYLE_PYTHON_SVERTEX_H +#define FREESTYLE_PYTHON_SVERTEX_H + +#include "../../view_map/Silhouette.h" +#include "../BPy_Interface0D.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject SVertex_Type; + +#define BPy_SVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SVertex_Type) ) + +/*---------------------------Python BPy_SVertex structure definition----------*/ +typedef struct { + BPy_Interface0D py_if0D; + SVertex *sv; +} BPy_SVertex; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_SVERTEX_H */ diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp new file mode 100644 index 00000000000..9b81ce56400 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp @@ -0,0 +1,193 @@ +#include "BPy_ViewVertex.h" + +#include "../BPy_Convert.h" +#include "../Interface1D/BPy_ViewEdge.h" +#include "../BPy_Nature.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ViewVertex___doc__[] = +"Class to define a view vertex. A view vertex is a feature vertex\n" +"corresponding to a point of the image graph, where the characteristics\n" +"of an edge (e.g., nature and visibility) might change. A\n" +":class:`ViewVertex` can be of two kinds: A :class:`TVertex` when it\n" +"corresponds to the intersection between two ViewEdges or a\n" +":class:`NonTVertex` when it corresponds to a vertex of the initial\n" +"input mesh (it is the case for vertices such as corners for example).\n" +"Thus, this class can be specialized into two classes, the\n" +":class:`TVertex` class and the :class:`NonTVertex` class.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: A ViewVertex object.\n" +" :type iBrother: :class:`ViewVertex`\n"; + +static int ViewVertex___init__( BPy_ViewVertex *self, PyObject *args, PyObject *kwds ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->vv = 0; // ViewVertex is abstract + self->py_if0D.if0D = self->vv; + self->py_if0D.borrowed = 0; + return 0; +} + +static char ViewVertex_setNature___doc__[] = +".. method:: setNature(iNature)\n" +"\n" +" Sets the nature of the vertex.\n" +"\n" +" :arg iNature: A Nature object.\n" +" :type iNature: :class:`Nature`\n"; + +static PyObject * ViewVertex_setNature( BPy_ViewVertex *self, PyObject *args ) { + PyObject *py_n; + + if( !self->vv ) + Py_RETURN_NONE; + + if(!( PyArg_ParseTuple(args, "O!", &Nature_Type, &py_n) )) + return NULL; + + PyObject *i = (PyObject *) &( ((BPy_Nature *) py_n)->i ); + ((ViewVertex *) self->py_if0D.if0D)->setNature( PyLong_AsLong(i) ); + + Py_RETURN_NONE; +} + +static char ViewVertex_edgesBegin___doc__[] = +".. method:: edgesBegin()\n" +"\n" +" Returns an iterator over the ViewEdges that goes to or comes from\n" +" this ViewVertex pointing to the first ViewEdge of the list. The\n" +" orientedViewEdgeIterator allows to iterate in CCW order over these\n" +" ViewEdges and to get the orientation for each ViewEdge\n" +" (incoming/outgoing).\n" +"\n" +" :return: An orientedViewEdgeIterator pointing to the first ViewEdge.\n" +" :rtype: :class:`orientedViewEdgeIterator`\n"; + +static PyObject * ViewVertex_edgesBegin( BPy_ViewVertex *self ) { + if( !self->vv ) + Py_RETURN_NONE; + + ViewVertexInternal::orientedViewEdgeIterator ove_it( self->vv->edgesBegin() ); + return BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator( ove_it, 0 ); +} + +static char ViewVertex_edgesEnd___doc__[] = +".. method:: edgesEnd()\n" +"\n" +" Returns an orientedViewEdgeIterator over the ViewEdges around this\n" +" ViewVertex, pointing after the last ViewEdge.\n" +"\n" +" :return: An orientedViewEdgeIterator pointing after the last ViewEdge.\n" +" :rtype: :class:`orientedViewEdgeIterator`\n"; + +static PyObject * ViewVertex_edgesEnd( BPy_ViewVertex *self ) { +#if 0 + if( !self->vv ) + Py_RETURN_NONE; + + ViewVertexInternal::orientedViewEdgeIterator ove_it( self->vv->edgesEnd() ); + return BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator( ove_it, 1 ); +#else + PyErr_SetString(PyExc_NotImplementedError, "edgesEnd method currently disabled"); + return NULL; +#endif +} + +static char ViewVertex_edgesIterator___doc__[] = +".. method:: edgesIterator(iEdge)\n" +"\n" +" Returns an orientedViewEdgeIterator pointing to the ViewEdge given\n" +" as argument.\n" +"\n" +" :arg iEdge: A ViewEdge object.\n" +" :type iEdge: :class:`ViewEdge`\n" +" :return: An orientedViewEdgeIterator pointing to the given ViewEdge.\n" +" :rtype: :class:`orientedViewEdgeIterator`\n"; + +static PyObject * ViewVertex_edgesIterator( BPy_ViewVertex *self, PyObject *args ) { + PyObject *py_ve; + + if( !self->vv ) + Py_RETURN_NONE; + + if(!( PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve) )) + return NULL; + + ViewEdge *ve = ((BPy_ViewEdge *) py_ve)->ve; + ViewVertexInternal::orientedViewEdgeIterator ove_it( self->vv->edgesIterator( ve ) ); + return BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator( ove_it, 0 ); +} + +/*----------------------ViewVertex instance definitions ----------------------------*/ +static PyMethodDef BPy_ViewVertex_methods[] = { + {"setNature", ( PyCFunction ) ViewVertex_setNature, METH_VARARGS, ViewVertex_setNature___doc__}, + {"edgesBegin", ( PyCFunction ) ViewVertex_edgesBegin, METH_NOARGS, ViewVertex_edgesBegin___doc__}, + {"edgesEnd", ( PyCFunction ) ViewVertex_edgesEnd, METH_NOARGS, ViewVertex_edgesEnd___doc__}, + {"edgesIterator", ( PyCFunction ) ViewVertex_edgesIterator, METH_VARARGS, ViewVertex_edgesIterator___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_ViewVertex type definition ------------------------------*/ +PyTypeObject ViewVertex_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ViewVertex", /* tp_name */ + sizeof(BPy_ViewVertex), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ViewVertex___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_ViewVertex_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &Interface0D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ViewVertex___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h new file mode 100644 index 00000000000..26c06b50d71 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_VIEWVERTEX_H +#define FREESTYLE_PYTHON_VIEWVERTEX_H + +#include "../../view_map/ViewMap.h" +#include "../BPy_Interface0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ViewVertex_Type; + +#define BPy_ViewVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ViewVertex_Type) ) + +/*---------------------------Python BPy_ViewVertex structure definition----------*/ +typedef struct { + BPy_Interface0D py_if0D; + ViewVertex *vv; +} BPy_ViewVertex; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_VIEWVERTEX_H */ diff --git a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp new file mode 100644 index 00000000000..750019f26ad --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp @@ -0,0 +1,398 @@ +#include "BPy_StrokeVertex.h" + +#include "../../BPy_Convert.h" +#include "../../BPy_StrokeAttribute.h" +#include "../../Interface0D/BPy_SVertex.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char StrokeVertex___doc__[] = +"Class to define a stroke vertex.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: A StrokeVertex object.\n" +" :type iBrother: :class:`StrokeVertex`\n" +"\n" +".. method:: __init__(iA, iB, t3)\n" +"\n" +" Builds a stroke vertex from 2 stroke vertices and an interpolation\n" +" parameter.\n" +"\n" +" :arg iA: The first StrokeVertex.\n" +" :type iA: :class:`StrokeVertex`\n" +" :arg iB: The second StrokeVertex.\n" +" :type iB: :class:`StrokeVertex`\n" +" :arg t3: An interpolation parameter.\n" +" :type t3: float\n" +"\n" +".. method:: __init__(iPoint)\n" +"\n" +" Builds a stroke vertex from a CurvePoint\n" +"\n" +" :arg iPoint: A CurvePoint object.\n" +" :type iPoint: :class:`CurvePoint`\n" +"\n" +".. method:: __init__(iSVertex)\n" +"\n" +" Builds a stroke vertex from a SVertex\n" +"\n" +" :arg iSVertex: An SVertex object.\n" +" :type iSVertex: :class:`SVertex`\n" +"\n" +".. method:: __init__(iSVertex, iAttribute)\n" +"\n" +" Builds a stroke vertex from an SVertex and a StrokeAttribute object.\n" +"\n" +" :arg iSVertex: An SVertex object.\n" +" :type iSVertex: :class:`SVertex`\n" +" :arg iAttribute: A StrokeAttribute object.\n" +" :type iAttribute: :class:`StrokeAttribute`\n"; + +static int StrokeVertex___init__(BPy_StrokeVertex *self, PyObject *args, PyObject *kwds) +{ + + PyObject *obj1 = 0, *obj2 = 0 , *obj3 = 0; + + if (! PyArg_ParseTuple(args, "|OOO!", &obj1, &obj2, &PyFloat_Type, &obj3) ) + return -1; + + if( !obj1 ){ + self->sv = new StrokeVertex(); + + } else if( !obj2 && BPy_StrokeVertex_Check(obj1) && ((BPy_StrokeVertex *) obj1)->sv ) { + self->sv = new StrokeVertex( *(((BPy_StrokeVertex *) obj1)->sv) ); + + } else if( !obj2 && BPy_CurvePoint_Check(obj1) && ((BPy_CurvePoint *) obj1)->cp ) { + self->sv = new StrokeVertex( ((BPy_CurvePoint *) obj1)->cp ); + + } else if( !obj2 && BPy_SVertex_Check(obj1) && ((BPy_SVertex *) obj1)->sv ) { + self->sv = new StrokeVertex( ((BPy_SVertex *) obj1)->sv ); + + } else if( obj3 && BPy_StrokeVertex_Check(obj1) && BPy_StrokeVertex_Check(obj2) ) { + StrokeVertex *sv1 = ((BPy_StrokeVertex *) obj1)->sv; + StrokeVertex *sv2 = ((BPy_StrokeVertex *) obj2)->sv; + if( !sv1 || ( sv1->A() == 0 && sv1->B() == 0 ) ) { + PyErr_SetString(PyExc_TypeError, "argument 1 is an invalid StrokeVertex object"); + return -1; + } + if( !sv2 || ( sv2->A() == 0 && sv2->B() == 0 ) ) { + PyErr_SetString(PyExc_TypeError, "argument 2 is an invalid StrokeVertex object"); + return -1; + } + self->sv = new StrokeVertex( sv1, sv2, PyFloat_AsDouble( obj3 ) ); + + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument(s)"); + return -1; + } + + self->py_cp.cp = self->sv; + self->py_cp.py_if0D.if0D = self->sv; + self->py_cp.py_if0D.borrowed = 0; + + return 0; +} + +static char StrokeVertex_x___doc__[] = +".. method:: x()\n" +"\n" +" Returns the 2D point X coordinate.\n" +"\n" +" :return: The X coordinate.\n" +" :rtype: float\n"; + +static PyObject * StrokeVertex_x( BPy_StrokeVertex *self ) { + return PyFloat_FromDouble( self->sv->x() ); +} + +static char StrokeVertex_y___doc__[] = +".. method:: y()\n" +"\n" +" Returns the 2D point Y coordinate.\n" +"\n" +" :return: The Y coordinate.\n" +" :rtype: float\n"; + +static PyObject * StrokeVertex_y( BPy_StrokeVertex *self ) { + return PyFloat_FromDouble( self->sv->y() ); +} + +static char StrokeVertex_getPoint___doc__[] = +".. method:: getPoint()\n" +"\n" +" Returns the 2D point coordinates as a two-dimensional vector.\n" +"\n" +" :return: The 2D coordinates.\n" +" :rtype: :class:`mathutils.Vector`\n"; + +static PyObject * StrokeVertex_getPoint( BPy_StrokeVertex *self ) { + Vec2f v( self->sv->getPoint() ); + return Vector_from_Vec2f( v ); +} + +static char StrokeVertex_attribute___doc__[] = +".. method:: attribute()\n" +"\n" +" Returns the StrokeAttribute for this StrokeVertex.\n" +"\n" +" :return: The StrokeAttribute object.\n" +" :rtype: :class:`StrokeAttribute`\n"; + +static PyObject * StrokeVertex_attribute( BPy_StrokeVertex *self ) { + return BPy_StrokeAttribute_from_StrokeAttribute( self->sv->attribute() ); +} + +static char StrokeVertex_curvilinearAbscissa___doc__[] = +".. method:: curvilinearAbscissa()\n" +"\n" +" Returns the curvilinear abscissa.\n" +"\n" +" :return: The curvilinear abscissa.\n" +" :rtype: float\n"; + +static PyObject * StrokeVertex_curvilinearAbscissa( BPy_StrokeVertex *self ) { + return PyFloat_FromDouble( self->sv->curvilinearAbscissa() ); +} + +static char StrokeVertex_strokeLength___doc__[] = +".. method:: strokeLength()\n" +"\n" +" Returns the length of the Stroke to which this StrokeVertex belongs\n" +"\n" +" :return: The stroke length.\n" +" :rtype: float\n"; + +static PyObject * StrokeVertex_strokeLength( BPy_StrokeVertex *self ) { + return PyFloat_FromDouble( self->sv->strokeLength() ); +} + +static char StrokeVertex_u___doc__[] = +".. method:: u()\n" +"\n" +" Returns the curvilinear abscissa of this StrokeVertex in the Stroke\n" +"\n" +" :return: The curvilinear abscissa.\n" +" :rtype: float\n"; + +static PyObject * StrokeVertex_u( BPy_StrokeVertex *self ) { + return PyFloat_FromDouble( self->sv->u() ); +} + +static char StrokeVertex_setX___doc__[] = +".. method:: setX(x)\n" +"\n" +" Sets the 2D point X coordinate.\n" +"\n" +" :arg x: The X coordinate.\n" +" :type x: float\n"; + +static PyObject *StrokeVertex_setX( BPy_StrokeVertex *self , PyObject *args) { + double r; + + if(!( PyArg_ParseTuple(args, "d", &r) )) + return NULL; + + self->sv->setX( r ); + + Py_RETURN_NONE; +} + +static char StrokeVertex_setY___doc__[] = +".. method:: setY(y)\n" +"\n" +" Sets the 2D point Y coordinate.\n" +"\n" +" :arg y: The Y coordinate.\n" +" :type y: float\n"; + +static PyObject *StrokeVertex_setY( BPy_StrokeVertex *self , PyObject *args) { + double r; + + if(!( PyArg_ParseTuple(args, "d", &r) )) + return NULL; + + self->sv->setY( r ); + + Py_RETURN_NONE; +} + +static char StrokeVertex_setPoint___doc__[] = +".. method:: setPoint(x, y)\n" +"\n" +" Sets the 2D point X and Y coordinates.\n" +"\n" +" :arg x: The X coordinate.\n" +" :type x: float\n" +" :arg y: The Y coordinate.\n" +" :type y: float\n" +"\n" +".. method:: SetPoint(p)\n" +"\n" +" Sets the 2D point X and Y coordinates.\n" +"\n" +" :arg p: A two-dimensional vector.\n" +" :type p: :class:`mathutils.Vector`, list or tuple of 2 real numbers\n"; + +static PyObject *StrokeVertex_setPoint( BPy_StrokeVertex *self , PyObject *args) { + PyObject *obj1 = 0, *obj2 = 0; + + if(!( PyArg_ParseTuple(args, "O|O", &obj1, &obj2) )) + return NULL; + + if( obj1 && !obj2 ){ + Vec2f *v = Vec2f_ptr_from_PyObject(obj1); + if( !v ) { + PyErr_SetString(PyExc_TypeError, "argument 1 must be a 2D vector (either a list of 2 elements or Vector)"); + return NULL; + } + self->sv->setPoint( *v ); + delete v; + } else if( PyFloat_Check(obj1) && obj2 && PyFloat_Check(obj2) ){ + self->sv->setPoint( PyFloat_AsDouble(obj1), PyFloat_AsDouble(obj2) ); + } else { + PyErr_SetString(PyExc_TypeError, "invalid arguments"); + return NULL; + } + + Py_RETURN_NONE; +} + +static char StrokeVertex_setAttribute___doc__[] = +".. method:: setAttribute(iAttribute)\n" +"\n" +" Sets the attribute.\n" +"\n" +" :arg iAttribute: A StrokeAttribute object.\n" +" :type iAttribute: :class:`StrokeAttribute`\n"; + +static PyObject *StrokeVertex_setAttribute( BPy_StrokeVertex *self , PyObject *args) { + PyObject *py_sa; + + if(!( PyArg_ParseTuple(args, "O!", &StrokeAttribute_Type, &py_sa) )) + return NULL; + + self->sv->setAttribute(*( ((BPy_StrokeAttribute *) py_sa)->sa )); + + Py_RETURN_NONE; +} + +static char StrokeVertex_setCurvilinearAbscissa___doc__[] = +".. method:: setCurvilinearAbscissa(iAbscissa)\n" +"\n" +" Sets the curvilinear abscissa of this StrokeVertex in the Stroke\n" +"\n" +" :arg iAbscissa: The curvilinear abscissa.\n" +" :type iAbscissa: float\n"; + +static PyObject *StrokeVertex_setCurvilinearAbscissa( BPy_StrokeVertex *self , PyObject *args) { + double r; + + if(!( PyArg_ParseTuple(args, "d", &r) )) + return NULL; + + self->sv->setCurvilinearAbscissa( r ); + + Py_RETURN_NONE; +} + +static char StrokeVertex_setStrokeLength___doc__[] = +".. method:: setStrokeLength(iLength)\n" +"\n" +" Sets the stroke length (it is only a value retained by the\n" +" StrokeVertex, and it won't change the real stroke length).\n" +"\n" +" :arg iLength: The stroke length.\n" +" :type iLength: float\n"; + +static PyObject *StrokeVertex_setStrokeLength( BPy_StrokeVertex *self , PyObject *args) { + double r; + + if(!( PyArg_ParseTuple(args, "d", &r) )) + return NULL; + + self->sv->setStrokeLength( r ); + + Py_RETURN_NONE; +} + +// real operator[] (const int i) const +// real & operator[] (const int i) + +/*----------------------StrokeVertex instance definitions ----------------------------*/ +static PyMethodDef BPy_StrokeVertex_methods[] = { + {"x", ( PyCFunction ) StrokeVertex_x, METH_NOARGS, StrokeVertex_x___doc__}, + {"y", ( PyCFunction ) StrokeVertex_y, METH_NOARGS, StrokeVertex_y___doc__}, + {"getPoint", ( PyCFunction ) StrokeVertex_getPoint, METH_NOARGS, StrokeVertex_getPoint___doc__}, + {"attribute", ( PyCFunction ) StrokeVertex_attribute, METH_NOARGS, StrokeVertex_attribute___doc__}, + {"curvilinearAbscissa", ( PyCFunction ) StrokeVertex_curvilinearAbscissa, METH_NOARGS, StrokeVertex_curvilinearAbscissa___doc__}, + {"strokeLength", ( PyCFunction ) StrokeVertex_strokeLength, METH_NOARGS, StrokeVertex_strokeLength___doc__}, + {"u", ( PyCFunction ) StrokeVertex_u, METH_NOARGS, StrokeVertex_u___doc__}, + {"setX", ( PyCFunction ) StrokeVertex_setX, METH_VARARGS, StrokeVertex_setX___doc__}, + {"setY", ( PyCFunction ) StrokeVertex_setY, METH_VARARGS, StrokeVertex_setY___doc__}, + {"setPoint", ( PyCFunction ) StrokeVertex_setPoint, METH_VARARGS, StrokeVertex_setPoint___doc__}, + {"setAttribute", ( PyCFunction ) StrokeVertex_setAttribute, METH_VARARGS, StrokeVertex_setAttribute___doc__}, + {"setCurvilinearAbscissa", ( PyCFunction ) StrokeVertex_setCurvilinearAbscissa, METH_VARARGS, StrokeVertex_setCurvilinearAbscissa___doc__}, + {"setStrokeLength", ( PyCFunction ) StrokeVertex_setStrokeLength, METH_VARARGS, StrokeVertex_setStrokeLength___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_StrokeVertex type definition ------------------------------*/ +PyTypeObject StrokeVertex_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "StrokeVertex", /* tp_name */ + sizeof(BPy_StrokeVertex), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + StrokeVertex___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_StrokeVertex_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &CurvePoint_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)StrokeVertex___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h new file mode 100644 index 00000000000..2a84e2480f0 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_STROKEVERTEX_H +#define FREESTYLE_PYTHON_STROKEVERTEX_H + +#include "../BPy_CurvePoint.h" +#include "../../../stroke/Stroke.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject StrokeVertex_Type; + +#define BPy_StrokeVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &StrokeVertex_Type) ) + +/*---------------------------Python BPy_StrokeVertex structure definition----------*/ +typedef struct { + BPy_CurvePoint py_cp; + StrokeVertex *sv; +} BPy_StrokeVertex; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_STROKEVERTEX_H */ diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp new file mode 100644 index 00000000000..c38c5734448 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp @@ -0,0 +1,151 @@ +#include "BPy_NonTVertex.h" + +#include "../../BPy_Convert.h" +#include "../BPy_SVertex.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char NonTVertex___doc__[] = +"View vertex for corners, cusps, etc. associated to a single SVertex.\n" +"Can be associated to 2 or more view edges.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: A NonTVertex object.\n" +" :type iBrother: :class:`NonTVertex`\n" +"\n" +".. method:: __init__(iSVertex)\n" +"\n" +" Builds a NonTVertex from a SVertex.\n" +"\n" +" :arg iSVertex: An SVertex object.\n" +" :type iSVertex: :class:`SVertex`\n"; + +static int NonTVertex___init__(BPy_NonTVertex *self, PyObject *args, PyObject *kwds) +{ + + PyObject *obj = 0; + + if (! PyArg_ParseTuple(args, "|O!", &SVertex_Type, &obj) ) + return -1; + + if( !obj ){ + self->ntv = new NonTVertex(); + + } else if( ((BPy_SVertex *) obj)->sv ) { + self->ntv = new NonTVertex( ((BPy_SVertex *) obj)->sv ); + + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument"); + return -1; + } + + self->py_vv.vv = self->ntv; + self->py_vv.py_if0D.if0D = self->ntv; + self->py_vv.py_if0D.borrowed = 0; + + return 0; +} + +static char NonTVertex_svertex___doc__[] = +".. method:: svertex()\n" +"\n" +" Returns the SVertex on top of which this NonTVertex is built.\n" +"\n" +" :return: The SVertex on top of which this NonTVertex is built.\n" +" :rtype: :class:`SVertex`\n"; + +static PyObject * NonTVertex_svertex( BPy_NonTVertex *self ) { + SVertex *v = self->ntv->svertex(); + if( v ){ + return BPy_SVertex_from_SVertex( *v ); + } + + Py_RETURN_NONE; +} + +static char NonTVertex_setSVertex___doc__[] = +".. method:: setSVertex(iSVertex)\n" +"\n" +" Sets the SVertex on top of which this NonTVertex is built.\n" +"\n" +" :arg iSVertex: The SVertex on top of which this NonTVertex is built.\n" +" :type iSVertex: :class:`SVertex`\n"; + +static PyObject * NonTVertex_setSVertex( BPy_NonTVertex *self, PyObject *args) { + PyObject *py_sv; + + if(!( PyArg_ParseTuple(args, "O!", &SVertex_Type, &py_sv) )) + return NULL; + + self->ntv->setSVertex( ((BPy_SVertex *) py_sv)->sv ); + + Py_RETURN_NONE; +} + +/*----------------------NonTVertex instance definitions ----------------------------*/ +static PyMethodDef BPy_NonTVertex_methods[] = { + {"svertex", ( PyCFunction ) NonTVertex_svertex, METH_NOARGS, NonTVertex_svertex___doc__}, + {"setSVertex", ( PyCFunction ) NonTVertex_setSVertex, METH_VARARGS, NonTVertex_setSVertex___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_NonTVertex type definition ------------------------------*/ +PyTypeObject NonTVertex_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "NonTVertex", /* tp_name */ + sizeof(BPy_NonTVertex), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + NonTVertex___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_NonTVertex_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &ViewVertex_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)NonTVertex___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h new file mode 100644 index 00000000000..071194d2d42 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_NONTVERTEX_H +#define FREESTYLE_PYTHON_NONTVERTEX_H + +#include "../BPy_ViewVertex.h" +#include "../../../view_map/ViewMap.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject NonTVertex_Type; + +#define BPy_NonTVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &NonTVertex_Type) ) + +/*---------------------------Python BPy_NonTVertex structure definition----------*/ +typedef struct { + BPy_ViewVertex py_vv; + NonTVertex *ntv; +} BPy_NonTVertex; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_NONTVERTEX_H */ diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp new file mode 100644 index 00000000000..26ccc48820b --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp @@ -0,0 +1,247 @@ +#include "BPy_TVertex.h" + +#include "../../BPy_Convert.h" +#include "../BPy_SVertex.h" +#include "../../BPy_Id.h" +#include "../../Interface1D/BPy_FEdge.h" +#include "../../Interface1D/BPy_ViewEdge.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char TVertex___doc__[] = +"Class to define a T vertex, i.e. an intersection between two edges.\n" +"It points towards two SVertex and four ViewEdges. Among the\n" +"ViewEdges, two are front and the other two are back. Basically a\n" +"front edge hides part of a back edge. So, among the back edges, one\n" +"is of invisibility N and the other of invisibility N+1.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: A TVertex object.\n" +" :type iBrother: :class:`TVertex`\n"; + +static int TVertex___init__(BPy_TVertex *self, PyObject *args, PyObject *kwds) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->tv = new TVertex(); + self->py_vv.vv = self->tv; + self->py_vv.py_if0D.if0D = self->tv; + self->py_vv.py_if0D.borrowed = 0; + + return 0; +} + +static char TVertex_frontSVertex___doc__[] = +".. method:: frontSVertex()\n" +"\n" +" Returns the SVertex that is closer to the viewpoint.\n" +"\n" +" :return: The SVertex that is closer to the viewpoint.\n" +" :rtype: :class:`SVertex`\n"; + +static PyObject * TVertex_frontSVertex( BPy_TVertex *self ) { + SVertex *v = self->tv->frontSVertex(); + if( v ){ + return BPy_SVertex_from_SVertex( *v ); + } + + Py_RETURN_NONE; +} + +static char TVertex_backSVertex___doc__[] = +".. method:: backSVertex()\n" +"\n" +" Returns the SVertex that is further away from the viewpoint.\n" +"\n" +" :return: The SVertex that is further away from the viewpoint.\n" +" :rtype: :class:`SVertex`\n"; + +static PyObject * TVertex_backSVertex( BPy_TVertex *self ) { + SVertex *v = self->tv->backSVertex(); + if( v ){ + return BPy_SVertex_from_SVertex( *v ); + } + + Py_RETURN_NONE; +} + +static char TVertex_setFrontSVertex___doc__[] = +".. method:: setFrontSVertex(iFrontSVertex)\n" +"\n" +" Sets the SVertex that is closer to the viewpoint.\n" +"\n" +" :arg iFrontSVertex: An SVertex object.\n" +" :type iFrontSVertex: :class:`SVertex`\n"; + +static PyObject * TVertex_setFrontSVertex( BPy_TVertex *self, PyObject *args) { + PyObject *py_sv; + + if(!( PyArg_ParseTuple(args, "O!", &SVertex_Type, &py_sv) )) + return NULL; + + self->tv->setFrontSVertex( ((BPy_SVertex *) py_sv)->sv ); + + Py_RETURN_NONE; +} + +static char TVertex_setBackSVertex___doc__[] = +".. method:: setBackSVertex(iBackSVertex)\n" +"\n" +" Sets the SVertex that is further away from the viewpoint.\n" +"\n" +" :arg iBackSVertex: An SVertex object.\n" +" :type iBackSVertex: :class:`SVertex`\n"; + +static PyObject * TVertex_setBackSVertex( BPy_TVertex *self, PyObject *args) { + PyObject *py_sv; + + if(!( PyArg_ParseTuple(args, "O", &SVertex_Type, &py_sv) )) + return NULL; + + self->tv->setBackSVertex( ((BPy_SVertex *) py_sv)->sv ); + + Py_RETURN_NONE; +} + +static char TVertex_setId___doc__[] = +".. method:: setId(iId)\n" +"\n" +" Sets the Id.\n" +"\n" +" :arg iId: An Id object.\n" +" :type iId: :class:`Id`\n"; + +static PyObject * TVertex_setId( BPy_TVertex *self, PyObject *args) { + PyObject *py_id; + + if(!( PyArg_ParseTuple(args, "O!", &Id_Type, &py_id) )) + return NULL; + + if( ((BPy_Id *) py_id)->id ) + self->tv->setId(*( ((BPy_Id *) py_id)->id )); + + Py_RETURN_NONE; +} + +static char TVertex_getSVertex___doc__[] = +".. method:: getSVertex(iFEdge)\n" +"\n" +" Returns the SVertex (among the 2) belonging to the given FEdge.\n" +"\n" +" :arg iFEdge: An FEdge object.\n" +" :type iFEdge: :class:`FEdge`\n" +" :return: The SVertex belonging to the given FEdge.\n" +" :rtype: :class:`SVertex`\n"; + +static PyObject * TVertex_getSVertex( BPy_TVertex *self, PyObject *args) { + PyObject *py_fe; + + if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) )) + return NULL; + + SVertex *sv = self->tv->getSVertex( ((BPy_FEdge *) py_fe)->fe ); + if( sv ){ + return BPy_SVertex_from_SVertex( *sv ); + } + + Py_RETURN_NONE; +} + +static char TVertex_mate___doc__[] = +".. method:: mate(iEdgeA)\n" +"\n" +" Returns the mate edge of the ViewEdge given as argument. If the\n" +" ViewEdge is frontEdgeA, frontEdgeB is returned. If the ViewEdge is\n" +" frontEdgeB, frontEdgeA is returned. Same for back edges.\n" +"\n" +" :arg iEdgeA: A ViewEdge object.\n" +" :type iEdgeA: :class:`ViewEdge`\n" +" :return: The mate edge of the given ViewEdge.\n" +" :rtype: :class:`ViewEdge`\n"; + +static PyObject * TVertex_mate( BPy_TVertex *self, PyObject *args) { + PyObject *py_ve; + + if(!( PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve) )) + return NULL; + + ViewEdge *ve = self->tv->mate( ((BPy_ViewEdge *) py_ve)->ve ); + if( ve ){ + return BPy_ViewEdge_from_ViewEdge( *ve ); + } + + Py_RETURN_NONE; +} + +/*----------------------TVertex instance definitions ----------------------------*/ +static PyMethodDef BPy_TVertex_methods[] = { + {"frontSVertex", ( PyCFunction ) TVertex_frontSVertex, METH_NOARGS, TVertex_frontSVertex___doc__}, + {"backSVertex", ( PyCFunction ) TVertex_backSVertex, METH_NOARGS, TVertex_backSVertex___doc__}, + {"setFrontSVertex", ( PyCFunction ) TVertex_setFrontSVertex, METH_VARARGS, TVertex_setFrontSVertex___doc__}, + {"setBackSVertex", ( PyCFunction ) TVertex_setBackSVertex, METH_VARARGS, TVertex_setBackSVertex___doc__}, + {"setId", ( PyCFunction ) TVertex_setId, METH_VARARGS, TVertex_setId___doc__}, + {"getSVertex", ( PyCFunction ) TVertex_getSVertex, METH_VARARGS, TVertex_getSVertex___doc__}, + {"mate", ( PyCFunction ) TVertex_mate, METH_VARARGS, TVertex_mate___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_TVertex type definition ------------------------------*/ +PyTypeObject TVertex_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "TVertex", /* tp_name */ + sizeof(BPy_TVertex), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + TVertex___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_TVertex_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &ViewVertex_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)TVertex___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h new file mode 100644 index 00000000000..12fe5c0cb43 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_TVERTEX_H +#define FREESTYLE_PYTHON_TVERTEX_H + +#include "../BPy_ViewVertex.h" +#include "../../../view_map/ViewMap.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject TVertex_Type; + +#define BPy_TVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TVertex_Type) ) + +/*---------------------------Python BPy_TVertex structure definition----------*/ +typedef struct { + BPy_ViewVertex py_vv; + TVertex *tv; +} BPy_TVertex; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_TVERTEX_H */ diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp new file mode 100644 index 00000000000..943b4fb5e46 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp @@ -0,0 +1,414 @@ +#include "BPy_FEdge.h" + +#include "../BPy_Convert.h" +#include "../BPy_Id.h" +#include "../Interface0D/BPy_SVertex.h" +#include "../Interface1D/BPy_ViewEdge.h" +#include "../BPy_Nature.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char FEdge___doc__[] = +"Base Class for feature edges. This FEdge can represent a silhouette,\n" +"a crease, a ridge/valley, a border or a suggestive contour. For\n" +"silhouettes, the FEdge is oriented so that the visible face lies on\n" +"the left of the edge. For borders, the FEdge is oriented so that the\n" +"face lies on the left of the edge. An FEdge can represent an initial\n" +"edge of the mesh or runs accross a face of the initial mesh depending\n" +"on the smoothness or sharpness of the mesh. This class is specialized\n" +"into a smooth and a sharp version since their properties slightly vary\n" +"from one to the other.\n" +"\n" +".. method:: FEdge()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: FEdge(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: An FEdge object.\n" +" :type iBrother: :class:`FEdge`\n" +"\n" +".. method:: FEdge(vA, vB)\n" +"\n" +" Builds an FEdge going from vA to vB.\n" +"\n" +" :arg vA: The first SVertex.\n" +" :type vA: :class:`SVertex`\n" +" :arg vB: The second SVertex.\n" +" :type vB: :class:`SVertex`\n"; + +static int FEdge___init__(BPy_FEdge *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj1 = 0, *obj2 = 0; + + if (! PyArg_ParseTuple(args, "|OO", &obj1, &obj2) ) + return -1; + + if( !obj1 ){ + self->fe = new FEdge(); + + } else if( !obj2 && BPy_FEdge_Check(obj1) ) { + self->fe = new FEdge(*( ((BPy_FEdge *) obj1)->fe )); + + } else if( obj2 && BPy_SVertex_Check(obj1) && BPy_SVertex_Check(obj2) ) { + self->fe = new FEdge( ((BPy_SVertex *) obj1)->sv, ((BPy_SVertex *) obj2)->sv ); + + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument(s)"); + return -1; + } + + self->py_if1D.if1D = self->fe; + self->py_if1D.borrowed = 0; + + return 0; +} + +static char FEdge_vertexA___doc__[] = +".. method:: vertexA()\n" +"\n" +" Returns the first SVertex.\n" +"\n" +" :return: The first SVertex.\n" +" :rtype: :class:`SVertex`\n"; + +static PyObject * FEdge_vertexA( BPy_FEdge *self ) { + SVertex *A = self->fe->vertexA(); + if( A ){ + return BPy_SVertex_from_SVertex( *A ); + } + + Py_RETURN_NONE; +} + +static char FEdge_vertexB___doc__[] = +".. method:: vertexB()\n" +"\n" +" Returns the second SVertex.\n" +"\n" +" :return: The second SVertex.\n" +" :rtype: :class:`SVertex`\n"; + +static PyObject * FEdge_vertexB( BPy_FEdge *self ) { + SVertex *B = self->fe->vertexB(); + if( B ){ + return BPy_SVertex_from_SVertex( *B ); + } + + Py_RETURN_NONE; +} + + +static PyObject * FEdge___getitem__( BPy_FEdge *self, PyObject *args ) { + int i; + + if(!( PyArg_ParseTuple(args, "i", &i) )) + return NULL; + if(!(i == 0 || i == 1)) { + PyErr_SetString(PyExc_IndexError, "index must be either 0 or 1"); + return NULL; + } + + SVertex *v = self->fe->operator[](i); + if( v ) + return BPy_SVertex_from_SVertex( *v ); + + Py_RETURN_NONE; +} + +static char FEdge_nextEdge___doc__[] = +".. method:: nextEdge()\n" +"\n" +" Returns the FEdge following this one in the ViewEdge. If this FEdge\n" +" is the last of the ViewEdge, None is returned.\n" +"\n" +" :return: The edge following this one in the ViewEdge.\n" +" :rtype: :class:`FEdge`\n"; + +static PyObject * FEdge_nextEdge( BPy_FEdge *self ) { + FEdge *fe = self->fe->nextEdge(); + if( fe ) + return Any_BPy_FEdge_from_FEdge( *fe ); + + Py_RETURN_NONE; +} + +static char FEdge_previousEdge___doc__[] = +".. method:: previousEdge()\n" +"\n" +" Returns the FEdge preceding this one in the ViewEdge. If this FEdge\n" +" is the first one of the ViewEdge, None is returned.\n" +"\n" +" :return: The edge preceding this one in the ViewEdge.\n" +" :rtype: :class:`FEdge`\n"; + +static PyObject * FEdge_previousEdge( BPy_FEdge *self ) { + FEdge *fe = self->fe->previousEdge(); + if( fe ) + return Any_BPy_FEdge_from_FEdge( *fe ); + + Py_RETURN_NONE; +} + +static char FEdge_viewedge___doc__[] = +".. method:: viewedge()\n" +"\n" +" Returns the ViewEdge to which this FEdge belongs to.\n" +"\n" +" :return: The ViewEdge to which this FEdge belongs to.\n" +" :rtype: :class:`ViewEdge`\n"; + +static PyObject * FEdge_viewedge( BPy_FEdge *self ) { + ViewEdge *ve = self->fe->viewedge(); + if( ve ) + return BPy_ViewEdge_from_ViewEdge( *ve ); + + Py_RETURN_NONE; +} + +static char FEdge_isSmooth___doc__[] = +".. method:: isSmooth()\n" +"\n" +" Returns true if this FEdge is a smooth FEdge.\n" +"\n" +" :return: True if this FEdge is a smooth FEdge.\n" +" :rtype: bool\n"; + +static PyObject * FEdge_isSmooth( BPy_FEdge *self ) { + return PyBool_from_bool( self->fe->isSmooth() ); +} + +static char FEdge_setVertexA___doc__[] = +".. method:: setVertexA(vA)\n" +"\n" +" Sets the first SVertex.\n" +"\n" +" :arg vA: An SVertex object.\n" +" :type vA: :class:`SVertex`\n"; + +static PyObject *FEdge_setVertexA( BPy_FEdge *self , PyObject *args) { + PyObject *py_sv; + + if(!( PyArg_ParseTuple(args, "O!", &SVertex_Type, &py_sv) )) + return NULL; + + self->fe->setVertexA( ((BPy_SVertex *) py_sv)->sv ); + + Py_RETURN_NONE; +} + +static char FEdge_setVertexB___doc__[] = +".. method:: setVertexB(vB)\n" +"\n" +" Sets the second SVertex.\n" +"\n" +" :arg vB: An SVertex object.\n" +" :type vB: :class:`SVertex`\n"; + +static PyObject *FEdge_setVertexB( BPy_FEdge *self , PyObject *args) { + PyObject *py_sv; + + if(!( PyArg_ParseTuple(args, "O", &py_sv) && BPy_SVertex_Check(py_sv) )) { + cout << "ERROR: FEdge_setVertexB" << endl; + Py_RETURN_NONE; + } + + self->fe->setVertexB( ((BPy_SVertex *) py_sv)->sv ); + + Py_RETURN_NONE; +} + +static char FEdge_setId___doc__[] = +".. method:: setId(id)\n" +"\n" +" Sets the Id of this FEdge.\n" +"\n" +" :arg id: An Id object.\n" +" :type id: :class:`Id`\n"; + +static PyObject *FEdge_setId( BPy_FEdge *self , PyObject *args) { + PyObject *py_id; + + if(!( PyArg_ParseTuple(args, "O!", &Id_Type, &py_id) )) + return NULL; + + self->fe->setId(*( ((BPy_Id *) py_id)->id )); + + Py_RETURN_NONE; +} + +static char FEdge_setNextEdge___doc__[] = +".. method:: setNextEdge(iEdge)\n" +"\n" +" Sets the pointer to the next FEdge.\n" +"\n" +" :arg iEdge: An FEdge object.\n" +" :type iEdge: :class:`FEdge`\n"; + +static PyObject *FEdge_setNextEdge( BPy_FEdge *self , PyObject *args) { + PyObject *py_fe; + + if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) )) + return NULL; + + self->fe->setNextEdge( ((BPy_FEdge *) py_fe)->fe ); + + Py_RETURN_NONE; +} + +static char FEdge_setPreviousEdge___doc__[] = +".. method:: setPreviousEdge(iEdge)\n" +"\n" +" Sets the pointer to the previous FEdge.\n" +"\n" +" :arg iEdge: An FEdge object.\n" +" :type iEdge: :class:`FEdge`\n"; + +static PyObject *FEdge_setPreviousEdge( BPy_FEdge *self , PyObject *args) { + PyObject *py_fe; + + if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) )) + return NULL; + + self->fe->setPreviousEdge( ((BPy_FEdge *) py_fe)->fe ); + + Py_RETURN_NONE; +} + +static char FEdge_setNature___doc__[] = +".. method:: setNature(iNature)\n" +"\n" +" Sets the nature of this FEdge.\n" +"\n" +" :arg iNature: A Nature object.\n" +" :type iNature: :class:`Nature`\n"; + +static PyObject * FEdge_setNature( BPy_FEdge *self, PyObject *args ) { + PyObject *py_n; + + if(!( PyArg_ParseTuple(args, "O!", &Nature_Type, &py_n) )) + return NULL; + + PyObject *i = (PyObject *) &( ((BPy_Nature *) py_n)->i ); + self->fe->setNature( PyLong_AsLong(i) ); + + Py_RETURN_NONE; +} + +static char FEdge_setViewEdge___doc__[] = +".. method:: setViewEdge(iViewEdge)\n" +"\n" +" Sets the ViewEdge to which this FEdge belongs to.\n" +"\n" +" :arg iViewEdge: A ViewEdge object.\n" +" :type iViewEdge: :class:`ViewEdge`\n"; + +static PyObject * FEdge_setViewEdge( BPy_FEdge *self, PyObject *args ) { + PyObject *py_ve; + + if(!( PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve) )) + return NULL; + + ViewEdge *ve = ((BPy_ViewEdge *) py_ve)->ve; + self->fe->setViewEdge( ve ); + + Py_RETURN_NONE; +} + +static char FEdge_setSmooth___doc__[] = +".. method:: setSmooth(iFlag)\n" +"\n" +" Sets the flag telling whether this FEdge is smooth or sharp. True\n" +" for Smooth, false for Sharp.\n" +"\n" +" :arg iFlag: True for Smooth, false for Sharp.\n" +" :type iFlag: bool\n"; + +static PyObject *FEdge_setSmooth( BPy_FEdge *self , PyObject *args) { + PyObject *py_b; + + if(!( PyArg_ParseTuple(args, "O", &py_b) )) + return NULL; + + self->fe->setSmooth( bool_from_PyBool(py_b) ); + + Py_RETURN_NONE; +} + +/*----------------------FEdge instance definitions ----------------------------*/ + +static PyMethodDef BPy_FEdge_methods[] = { + {"vertexA", ( PyCFunction ) FEdge_vertexA, METH_NOARGS, FEdge_vertexA___doc__}, + {"vertexB", ( PyCFunction ) FEdge_vertexB, METH_NOARGS, FEdge_vertexB___doc__}, + {"__getitem__", ( PyCFunction ) FEdge___getitem__, METH_VARARGS, "(int i) Returns the first SVertex if i=0, the seccond SVertex if i=1."}, + {"nextEdge", ( PyCFunction ) FEdge_nextEdge, METH_NOARGS, FEdge_nextEdge___doc__}, + {"previousEdge", ( PyCFunction ) FEdge_previousEdge, METH_NOARGS, FEdge_previousEdge___doc__}, + {"viewedge", ( PyCFunction ) FEdge_viewedge, METH_NOARGS, FEdge_viewedge___doc__}, + {"isSmooth", ( PyCFunction ) FEdge_isSmooth, METH_NOARGS, FEdge_isSmooth___doc__}, + {"setVertexA", ( PyCFunction ) FEdge_setVertexA, METH_VARARGS, FEdge_setVertexA___doc__}, + {"setVertexB", ( PyCFunction ) FEdge_setVertexB, METH_VARARGS, FEdge_setVertexB___doc__}, + {"setId", ( PyCFunction ) FEdge_setId, METH_VARARGS, FEdge_setId___doc__}, + {"setNextEdge", ( PyCFunction ) FEdge_setNextEdge, METH_VARARGS, FEdge_setNextEdge___doc__}, + {"setPreviousEdge", ( PyCFunction ) FEdge_setPreviousEdge, METH_VARARGS, FEdge_setPreviousEdge___doc__}, + {"setSmooth", ( PyCFunction ) FEdge_setSmooth, METH_VARARGS, FEdge_setSmooth___doc__}, + {"setViewEdge", ( PyCFunction ) FEdge_setViewEdge, METH_VARARGS, FEdge_setViewEdge___doc__}, + {"setNature", ( PyCFunction ) FEdge_setNature, METH_VARARGS, FEdge_setNature___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_FEdge type definition ------------------------------*/ + +PyTypeObject FEdge_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "FEdge", /* tp_name */ + sizeof(BPy_FEdge), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + FEdge___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_FEdge_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &Interface1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)FEdge___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.h b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.h new file mode 100644 index 00000000000..9d13145aaf2 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_FEDGE_H +#define FREESTYLE_PYTHON_FEDGE_H + +#include "../BPy_Interface1D.h" +#include "../../view_map/Silhouette.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject FEdge_Type; + +#define BPy_FEdge_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FEdge_Type) ) + +/*---------------------------Python BPy_FEdge structure definition----------*/ +typedef struct { + BPy_Interface1D py_if1D; + FEdge *fe; +} BPy_FEdge; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_FEDGE_H */ diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp new file mode 100644 index 00000000000..d939e18fb3d --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp @@ -0,0 +1,200 @@ +#include "BPy_FrsCurve.h" + +#include "../BPy_Convert.h" +#include "../BPy_Id.h" +#include "../Interface0D/BPy_CurvePoint.h" +#include "../Interface0D/BPy_SVertex.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char FrsCurve___doc__[] = +"Base class for curves made of CurvePoints. :class:`SVertex` is the\n" +"type of the initial curve vertices. A :class:`Chain` is a\n" +"specialization of a Curve.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default Constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy Constructor.\n" +"\n" +" :arg iBrother: A Curve object.\n" +" :type iBrother: :class:`Curve`\n" +"\n" +".. method:: __init__(iId)\n" +"\n" +" Builds a Curve from its Id.\n" +"\n" +" :arg iId: An Id object.\n" +" :type iId: :class:`Id`\n"; + +static int FrsCurve___init__(BPy_FrsCurve *self, PyObject *args, PyObject *kwds) +{ + + PyObject *obj = 0; + + if (! PyArg_ParseTuple(args, "|O", &obj) ) + return -1; + + if( !obj ){ + self->c = new Curve(); + + } else if( BPy_FrsCurve_Check(obj) ) { + self->c = new Curve(*( ((BPy_FrsCurve *) obj)->c )); + + } else if( BPy_Id_Check(obj) ) { + self->c = new Curve(*( ((BPy_Id *) obj)->id )); + + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument"); + return -1; + } + + self->py_if1D.if1D = self->c; + self->py_if1D.borrowed = 0; + + return 0; +} + +static char FrsCurve_push_vertex_back___doc__[] = +".. method:: push_vertex_back(iVertex)\n" +"\n" +" Adds a single vertex at the end of the Curve.\n" +"\n" +" :arg iVertex: A vertex object.\n" +" :type iVertex: :class:`SVertex` or :class:`CurvePoint`\n"; + +static PyObject * FrsCurve_push_vertex_back( BPy_FrsCurve *self, PyObject *args ) { + PyObject *obj; + + if(!( PyArg_ParseTuple(args, "O", &obj) )) + return NULL; + + if( BPy_CurvePoint_Check(obj) ) { + self->c->push_vertex_back( ((BPy_CurvePoint *) obj)->cp ); + } else if( BPy_SVertex_Check(obj) ) { + self->c->push_vertex_back( ((BPy_SVertex *) obj)->sv ); + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument"); + return NULL; + } + + Py_RETURN_NONE; +} + +static char FrsCurve_push_vertex_front___doc__[] = +".. method:: push_vertex_front(iVertex)\n" +"\n" +" Adds a single vertex at the front of the Curve.\n" +"\n" +" :arg iVertex: A vertex object.\n" +" :type iVertex: :class:`SVertex` or :class:`CurvePoint`\n"; + +static PyObject * FrsCurve_push_vertex_front( BPy_FrsCurve *self, PyObject *args ) { + PyObject *obj; + + if(!( PyArg_ParseTuple(args, "O", &obj) )) + return NULL; + + if( BPy_CurvePoint_Check(obj) ) { + self->c->push_vertex_front( ((BPy_CurvePoint *) obj)->cp ); + } else if( BPy_SVertex_Check(obj) ) { + self->c->push_vertex_front( ((BPy_SVertex *) obj)->sv ); + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument"); + return NULL; + } + + Py_RETURN_NONE; +} + +static char FrsCurve_empty___doc__[] = +".. method:: empty()\n" +"\n" +" Returns true if the Curve doesn't have any Vertex yet.\n" +"\n" +" :return: True if the Curve has no vertices.\n" +" :rtype: bool\n"; + +static PyObject * FrsCurve_empty( BPy_FrsCurve *self ) { + return PyBool_from_bool( self->c->empty() ); +} + +static char FrsCurve_nSegments___doc__[] = +".. method:: nSegments()\n" +"\n" +" Returns the number of segments in the polyline constituing the\n" +" Curve.\n" +"\n" +" :return: The number of segments.\n" +" :rtype: int\n"; + +static PyObject * FrsCurve_nSegments( BPy_FrsCurve *self ) { + return PyLong_FromLong( self->c->nSegments() ); +} + +/*----------------------FrsCurve instance definitions ----------------------------*/ +static PyMethodDef BPy_FrsCurve_methods[] = { + {"push_vertex_back", ( PyCFunction ) FrsCurve_push_vertex_back, METH_VARARGS, FrsCurve_push_vertex_back___doc__}, + {"push_vertex_front", ( PyCFunction ) FrsCurve_push_vertex_front, METH_VARARGS, FrsCurve_push_vertex_front___doc__}, + {"empty", ( PyCFunction ) FrsCurve_empty, METH_NOARGS, FrsCurve_empty___doc__}, + {"nSegments", ( PyCFunction ) FrsCurve_nSegments, METH_NOARGS, FrsCurve_nSegments___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_FrsCurve type definition ------------------------------*/ + +PyTypeObject FrsCurve_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "Curve", /* tp_name */ + sizeof(BPy_FrsCurve), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + FrsCurve___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_FrsCurve_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &Interface1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)FrsCurve___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.h b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.h new file mode 100644 index 00000000000..0829cf0ebf5 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_FRSCURVE_H +#define FREESTYLE_PYTHON_FRSCURVE_H + +#include "../BPy_Interface1D.h" +#include "../../stroke/Curve.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject FrsCurve_Type; + +#define BPy_FrsCurve_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FrsCurve_Type) ) + +/*---------------------------Python BPy_FrsCurve structure definition----------*/ +typedef struct { + BPy_Interface1D py_if1D; + Curve *c; +} BPy_FrsCurve; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_FRSCURVE_H */ diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp new file mode 100644 index 00000000000..4edcc52fabf --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp @@ -0,0 +1,490 @@ +#include "BPy_Stroke.h" + +#include "../BPy_Convert.h" +#include "../BPy_Id.h" +#include "../Interface0D/BPy_SVertex.h" +#include "../Interface0D/CurvePoint/BPy_StrokeVertex.h" +#include "../Iterator/BPy_StrokeVertexIterator.h" +#include "../BPy_MediumType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +// Stroke () +// template<class InputVertexIterator> Stroke (InputVertexIterator iBegin, InputVertexIterator iEnd) +// +// pb: - need to be able to switch representation: InputVertexIterator <=> position +// - is it even used ? not even in SWIG version + +static char Stroke___doc__[] = +"Class to define a stroke. A stroke is made of a set of 2D vertices\n" +"(:class:`StrokeVertex`), regularly spaced out. This set of vertices\n" +"defines the stroke's backbone geometry. Each of these stroke vertices\n" +"defines the stroke's shape and appearance at this vertex position.\n" +"\n" +".. method:: Stroke()\n" +"\n" +" Default constructor\n" +"\n" +".. method:: Stroke(iBrother)\n" +"\n" +" Copy constructor\n" +"\n" +" :arg iBrother: \n" +" :type iBrother: :class:`Stroke`\n" +"\n" +".. method:: Stroke(iBegin, iEnd)\n" +"\n" +" Builds a stroke from a set of StrokeVertex. This constructor is\n" +" templated by an iterator type. This iterator type must allow the\n" +" vertices parsing using the ++ operator.\n" +"\n" +" :arg iBegin: The iterator pointing to the first vertex.\n" +" :type iBegin: InputVertexIterator\n" +" :arg iEnd: The iterator pointing to the end of the vertex list.\n" +" :type iEnd: InputVertexIterator\n"; + +static int Stroke___init__(BPy_Stroke *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj1 = NULL, *obj2 = NULL; + + if (! PyArg_ParseTuple(args, "|OO", &obj1, &obj2) ) + return -1; + + if( !obj1 ){ + self->s = new Stroke(); + + } else if ( !obj2 && BPy_Stroke_Check(obj1) ) { + self->s = new Stroke(*( ((BPy_Stroke *)obj1)->s )); + + } else if ( obj2 ) { + PyErr_SetString(PyExc_TypeError, + "Stroke(InputVertexIterator iBegin, InputVertexIterator iEnd) not implemented"); + return -1; + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument(s)"); + return -1; + } + + self->py_if1D.if1D = self->s; + self->py_if1D.borrowed = 0; + + return 0; +} + +static PyObject * Stroke___iter__( PyObject *self ) { + StrokeInternal::StrokeVertexIterator sv_it( ((BPy_Stroke *)self)->s->strokeVerticesBegin() ); + return BPy_StrokeVertexIterator_from_StrokeVertexIterator( sv_it, 0 ); +} + +static Py_ssize_t Stroke_length( BPy_Stroke *self ) { + return self->s->strokeVerticesSize(); +} + +static PyObject * Stroke_item( BPy_Stroke *self, Py_ssize_t i ) { + if (i < 0 || i >= (Py_ssize_t)self->s->strokeVerticesSize()) { + PyErr_SetString(PyExc_IndexError, "subscript index out of range"); + return NULL; + } + return BPy_StrokeVertex_from_StrokeVertex( self->s->strokeVerticeAt(i) ); +} + +static PyObject * Stroke___getitem__( BPy_Stroke *self, PyObject *item ) { + long i; + + if (!PyLong_Check(item)) { + PyErr_SetString(PyExc_TypeError, "subscript indices must be integers"); + return NULL; + } + i = PyLong_AsLong(item); + if (i == -1 && PyErr_Occurred()) + return NULL; + if (i < 0) { + i += self->s->strokeVerticesSize(); + } + return Stroke_item(self, i); +} + +static char Stroke_ComputeSampling___doc__[] = +".. method:: ComputeSampling(iNVertices)\n" +"\n" +" Compute the sampling needed to get iNVertices vertices. If the\n" +" specified number of vertices is less than the actual number of\n" +" vertices, the actual sampling value is returned. (To remove Vertices,\n" +" use the RemoveVertex() method of this class.)\n" +"\n" +" :arg iNVertices: The number of stroke vertices we eventually want\n" +" in our Stroke.\n" +" :type iNVertices: int\n" +" :return: The sampling that must be used in the Resample(float)\n" +" method.\n" +" :rtype: float\n"; + +static PyObject * Stroke_ComputeSampling( BPy_Stroke *self, PyObject *args ) { + int i; + + if(!( PyArg_ParseTuple(args, "i", &i) )) + return NULL; + + return PyFloat_FromDouble( self->s->ComputeSampling( i ) ); +} + +static char Stroke_Resample___doc__[] = +".. method:: Resample(iNPoints)\n" +"\n" +" Resamples the stroke so that it eventually has iNPoints. That means\n" +" it is going to add iNPoints-vertices_size, if vertices_size is the\n" +" number of points we already have. If vertices_size >= iNPoints, no\n" +" resampling is done.\n" +"\n" +" :arg iNPoints: The number of vertices we eventually want in our stroke.\n" +" :type iNPoints: int\n" +"\n" +".. method:: Resample(iSampling)\n" +"\n" +" Resamples the stroke with a given sampling. If the sampling is\n" +" smaller than the actual sampling value, no resampling is done.\n" +"\n" +" :arg iSampling: The new sampling value.\n" +" :type iSampling: float\n"; + +static PyObject * Stroke_Resample( BPy_Stroke *self, PyObject *args ) { + PyObject *obj; + + if(!( PyArg_ParseTuple(args, "O", &obj) )) + return NULL; + + if( PyLong_Check(obj) ) + self->s->Resample( (int) PyLong_AsLong(obj) ); + else if( PyFloat_Check(obj) ) + self->s->Resample( (float) PyFloat_AsDouble(obj) ); + else { + PyErr_SetString(PyExc_TypeError, "invalid argument"); + return NULL; + } + + Py_RETURN_NONE; +} + +static char Stroke_InsertVertex___doc__[] = +".. method:: InsertVertex(iVertex, next)\n" +"\n" +" Inserts the stroke vertex iVertex in the stroke before next. The\n" +" length, curvilinear abscissa are updated consequently.\n" +"\n" +" :arg iVertex: The StrokeVertex to insert in the Stroke.\n" +" :type iVertex: :class:`StrokeVertex`\n" +" :arg next: A StrokeVertexIterator pointing to the StrokeVertex\n" +" before which iVertex must be inserted.\n" +" :type next: :class:`StrokeVertexIterator`\n"; + +static PyObject * Stroke_InsertVertex( BPy_Stroke *self, PyObject *args ) { + PyObject *py_sv = 0, *py_sv_it = 0; + + if(!( PyArg_ParseTuple(args, "O!O!", &StrokeVertex_Type, &py_sv, &StrokeVertexIterator_Type, &py_sv_it) )) + return NULL; + + StrokeVertex *sv = ((BPy_StrokeVertex *) py_sv)->sv; + StrokeInternal::StrokeVertexIterator sv_it(*( ((BPy_StrokeVertexIterator *) py_sv_it)->sv_it )); + self->s->InsertVertex( sv, sv_it ); + + Py_RETURN_NONE; +} + +static char Stroke_RemoveVertex___doc__[] = +".. method:: RemoveVertex(iVertex)\n" +"\n" +" Removes the stroke vertex iVertex from the stroke. The length and\n" +" curvilinear abscissa are updated consequently.\n" +"\n" +" :arg iVertex: \n" +" :type iVertex: :class:`StrokeVertex`\n"; + +static PyObject * Stroke_RemoveVertex( BPy_Stroke *self, PyObject *args ) { + PyObject *py_sv; + + if(!( PyArg_ParseTuple(args, "O!", &StrokeVertex_Type, &py_sv) )) + return NULL; + + if( ((BPy_StrokeVertex *) py_sv)->sv ) + self->s->RemoveVertex( ((BPy_StrokeVertex *) py_sv)->sv ); + else { + PyErr_SetString(PyExc_TypeError, "invalid argument"); + return NULL; + } + + Py_RETURN_NONE; +} + +static char Stroke_getMediumType___doc__[] = +".. method:: getMediumType()\n" +"\n" +" Returns the MediumType used for this Stroke.\n" +"\n" +" :return: the MediumType used for this Stroke.\n" +" :rtype: :class:`MediumType`\n"; + +static PyObject * Stroke_getMediumType( BPy_Stroke *self ) { + return BPy_MediumType_from_MediumType( self->s->getMediumType() ); +} + +static char Stroke_getTextureId___doc__[] = +".. method:: getTextureId()\n" +"\n" +" Returns the ID of the texture used to simulate th marks system for\n" +" this Stroke\n" +"\n" +" :return: The texture ID.\n" +" :rtype: int\n"; + +static PyObject * Stroke_getTextureId( BPy_Stroke *self ) { + return PyLong_FromLong( self->s->getTextureId() ); +} + +static char Stroke_hasTips___doc__[] = +".. method:: hasTips()\n" +"\n" +" Returns true if this Stroke uses a texture with tips, false\n" +" otherwise.\n" +"\n" +" :return: True if this Stroke uses a texture with tips.\n" +" :rtype: bool\n"; + +static PyObject * Stroke_hasTips( BPy_Stroke *self ) { + return PyBool_from_bool( self->s->hasTips() ); +} + +static char Stroke_setId___doc__[] = +".. method:: setId(id)\n" +"\n" +" Sets the Id of the Stroke.\n" +"\n" +" :arg id: the Id of the Stroke.\n" +" :type id: :class:`Id`\n"; + +static PyObject *Stroke_setId( BPy_Stroke *self , PyObject *args) { + PyObject *py_id; + + if(!( PyArg_ParseTuple(args, "O!", &Id_Type, &py_id) )) + return NULL; + + self->s->setId(*( ((BPy_Id *) py_id)->id )); + + Py_RETURN_NONE; +} + +static char Stroke_setLength___doc__[] = +".. method:: setLength(iLength)\n" +"\n" +" Sets the 2D length of the Stroke.\n" +"\n" +" :arg iLength: The 2D length of the Stroke.\n" +" :type iLength: float\n"; + +static PyObject *Stroke_setLength( BPy_Stroke *self , PyObject *args) { + float f; + + if(!( PyArg_ParseTuple(args, "f", &f) )) + return NULL; + + self->s->setLength( f ); + + Py_RETURN_NONE; +} + +static char Stroke_setMediumType___doc__[] = +".. method:: setMediumType(iType)\n" +"\n" +" Sets the medium type that must be used for this Stroke.\n" +"\n" +" :arg iType: A MediumType object.\n" +" :type iType: :class:`MediumType`\n"; + +static PyObject *Stroke_setMediumType( BPy_Stroke *self , PyObject *args) { + PyObject *py_mt; + + if(!( PyArg_ParseTuple(args, "O!", &MediumType_Type, &py_mt) )) + return NULL; + + self->s->setMediumType( MediumType_from_BPy_MediumType(py_mt) ); + + Py_RETURN_NONE; +} + +static char Stroke_setTextureId___doc__[] = +".. method:: setTextureId(iId)\n" +"\n" +" Sets the texture ID to be used to simulate the marks system for this\n" +" Stroke.\n" +"\n" +" :arg iId: A texture ID.\n" +" :type iId: int\n"; + +static PyObject *Stroke_setTextureId( BPy_Stroke *self , PyObject *args) { + unsigned int i; + + if(!( PyArg_ParseTuple(args, "I", &i) )) + return NULL; + + self->s->setTextureId( i ); + + Py_RETURN_NONE; +} + +static char Stroke_setTips___doc__[] = +".. method:: setTips(iTips)\n" +"\n" +" Sets the flag telling whether this stroke is using a texture with\n" +" tips or not.\n" +"\n" +" :arg iTips: True if this stroke uses a texture with tips.\n" +" :type iTips: bool\n"; + +static PyObject *Stroke_setTips( BPy_Stroke *self , PyObject *args) { + PyObject *py_b; + + if(!( PyArg_ParseTuple(args, "O", &py_b) )) + return NULL; + + self->s->setTips( bool_from_PyBool(py_b) ); + + Py_RETURN_NONE; +} + +static char Stroke_strokeVerticesBegin___doc__[] = +".. method:: strokeVerticesBegin(t=0.0)\n" +"\n" +" Returns a StrokeVertexIterator pointing on the first StrokeVertex of\n" +" the Stroke. O ne can specify a sampling value to resample the Stroke\n" +" on the fly if needed.\n" +"\n" +" :arg t: The resampling value with which we want our Stroke to be\n" +" resampled. If 0 is specified, no resampling is done.\n" +" :type t: float\n" +" :return: A StrokeVertexIterator pointing on the first StrokeVertex.\n" +" :rtype: :class:`StrokeVertexIterator`\n"; + +static PyObject * Stroke_strokeVerticesBegin( BPy_Stroke *self , PyObject *args) { + float f = 0; + + if(!( PyArg_ParseTuple(args, "|f", &f) )) + return NULL; + + StrokeInternal::StrokeVertexIterator sv_it( self->s->strokeVerticesBegin(f) ); + return BPy_StrokeVertexIterator_from_StrokeVertexIterator( sv_it, 0 ); +} + +static char Stroke_strokeVerticesEnd___doc__[] = +".. method:: strokeVerticesEnd()\n" +"\n" +" Returns a StrokeVertexIterator pointing after the last StrokeVertex\n" +" of the Stroke.\n" +"\n" +" :return: A StrokeVertexIterator pointing after the last StrokeVertex.\n" +" :rtype: :class:`StrokeVertexIterator`\n"; + +static PyObject * Stroke_strokeVerticesEnd( BPy_Stroke *self ) { + StrokeInternal::StrokeVertexIterator sv_it( self->s->strokeVerticesEnd() ); + return BPy_StrokeVertexIterator_from_StrokeVertexIterator( sv_it, 1 ); +} + +static char Stroke_strokeVerticesSize___doc__[] = +".. method:: strokeVerticesSize()\n" +"\n" +" Returns the number of StrokeVertex constituing the Stroke.\n" +"\n" +" :return: The number of stroke vertices.\n" +" :rtype: int\n"; + +static PyObject * Stroke_strokeVerticesSize( BPy_Stroke *self ) { + return PyLong_FromLong( self->s->strokeVerticesSize() ); +} + +/*----------------------Stroke instance definitions ----------------------------*/ + +static PyMethodDef BPy_Stroke_methods[] = { + {"__getitem__", ( PyCFunction ) Stroke___getitem__, METH_O, "(int i) Returns the i-th StrokeVertex constituting the Stroke."}, + {"ComputeSampling", ( PyCFunction ) Stroke_ComputeSampling, METH_VARARGS, Stroke_ComputeSampling___doc__}, + {"Resample", ( PyCFunction ) Stroke_Resample, METH_VARARGS, Stroke_Resample___doc__}, + {"RemoveVertex", ( PyCFunction ) Stroke_RemoveVertex, METH_VARARGS, Stroke_RemoveVertex___doc__}, + {"InsertVertex", ( PyCFunction ) Stroke_InsertVertex, METH_VARARGS, Stroke_InsertVertex___doc__}, + {"getMediumType", ( PyCFunction ) Stroke_getMediumType, METH_NOARGS, Stroke_getMediumType___doc__}, + {"getTextureId", ( PyCFunction ) Stroke_getTextureId, METH_NOARGS, Stroke_getTextureId___doc__}, + {"hasTips", ( PyCFunction ) Stroke_hasTips, METH_NOARGS, Stroke_hasTips___doc__}, + {"setId", ( PyCFunction ) Stroke_setId, METH_VARARGS, Stroke_setId___doc__}, + {"setLength", ( PyCFunction ) Stroke_setLength, METH_VARARGS, Stroke_setLength___doc__}, + {"setMediumType", ( PyCFunction ) Stroke_setMediumType, METH_VARARGS, Stroke_setMediumType___doc__}, + {"setTextureId", ( PyCFunction ) Stroke_setTextureId, METH_VARARGS, Stroke_setTextureId___doc__}, + {"setTips", ( PyCFunction ) Stroke_setTips, METH_VARARGS, Stroke_setTips___doc__}, + {"strokeVerticesBegin", ( PyCFunction ) Stroke_strokeVerticesBegin, METH_VARARGS, Stroke_strokeVerticesBegin___doc__}, + {"strokeVerticesEnd", ( PyCFunction ) Stroke_strokeVerticesEnd, METH_NOARGS, Stroke_strokeVerticesEnd___doc__}, + {"strokeVerticesSize", ( PyCFunction ) Stroke_strokeVerticesSize, METH_NOARGS, Stroke_strokeVerticesSize___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_Stroke type definition ------------------------------*/ + +static PySequenceMethods Stroke_as_sequence = { + (lenfunc)Stroke_length, /* sq_length */ + NULL, /* sq_concat */ + NULL, /* sq_repeat */ + (ssizeargfunc)Stroke_item, /* sq_item */ + NULL, /* sq_slice */ + NULL, /* sq_ass_item */ + NULL, /* sq_ass_slice */ + NULL, /* sq_contains */ + NULL, /* sq_inplace_concat */ + NULL, /* sq_inplace_repeat */ +}; + +PyTypeObject Stroke_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "Stroke", /* tp_name */ + sizeof(BPy_Stroke), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + &Stroke_as_sequence, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Stroke___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)Stroke___iter__, /* tp_iter */ + 0, /* tp_iternext */ + BPy_Stroke_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &Interface1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)Stroke___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.h b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.h new file mode 100644 index 00000000000..52c6d214b85 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_STROKE_H +#define FREESTYLE_PYTHON_STROKE_H + +#include "../BPy_Interface1D.h" +#include "../../stroke/Stroke.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject Stroke_Type; + +#define BPy_Stroke_Check(v) (( (PyObject *) v)->ob_type == &Stroke_Type) + +/*---------------------------Python BPy_Stroke structure definition----------*/ +typedef struct { + BPy_Interface1D py_if1D; + Stroke *s; +} BPy_Stroke; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_STROKE_H */ diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp new file mode 100644 index 00000000000..49ef52f87aa --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp @@ -0,0 +1,461 @@ +#include "BPy_ViewEdge.h" + +#include "../BPy_Convert.h" +#include "../BPy_Id.h" +#include "../Interface0D/BPy_ViewVertex.h" +#include "../Interface1D/BPy_FEdge.h" +#include "../Interface1D/BPy_ViewEdge.h" +#include "../BPy_Nature.h" +#include "../BPy_ViewShape.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ViewEdge___doc__[] = +"Class defining a ViewEdge. A ViewEdge in an edge of the image graph.\n" +"it connnects two :class:`ViewVertex` objects. It is made by connecting\n" +"a set of FEdges.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: A ViewEdge object.\n" +" :type iBrother: :class:`ViewEdge`\n"; + +static int ViewEdge___init__(BPy_ViewEdge *self, PyObject *args, PyObject *kwds) +{ + if ( !PyArg_ParseTuple(args, "") ) + return -1; + self->ve = new ViewEdge(); + self->py_if1D.if1D = self->ve; + self->py_if1D.borrowed = 0; + + return 0; +} + +static char ViewEdge_A___doc__[] = +".. method:: A()\n" +"\n" +" Returns the first ViewVertex.\n" +"\n" +" :return: The first ViewVertex.\n" +" :rtype: :class:`ViewVertex`\n"; + +static PyObject * ViewEdge_A( BPy_ViewEdge *self ) { + ViewVertex *v = self->ve->A(); + if( v ){ + return Any_BPy_ViewVertex_from_ViewVertex( *v ); + } + + Py_RETURN_NONE; +} + +static char ViewEdge_B___doc__[] = +".. method:: B()\n" +"\n" +" Returns the second ViewVertex.\n" +"\n" +" :return: The second ViewVertex.\n" +" :rtype: :class:`ViewVertex`\n"; + +static PyObject * ViewEdge_B( BPy_ViewEdge *self ) { + ViewVertex *v = self->ve->B(); + if( v ){ + return Any_BPy_ViewVertex_from_ViewVertex( *v ); + } + + Py_RETURN_NONE; +} + +static char ViewEdge_fedgeA___doc__[] = +".. method:: fedgeA()\n" +"\n" +" Returns the first FEdge that constitutes this ViewEdge.\n" +"\n" +" :return: The first FEdge constituting this ViewEdge.\n" +" :rtype: :class:`FEdge`\n"; + +static PyObject * ViewEdge_fedgeA( BPy_ViewEdge *self ) { + FEdge *A = self->ve->fedgeA(); + if( A ){ + return Any_BPy_FEdge_from_FEdge( *A ); + } + + Py_RETURN_NONE; +} + +static char ViewEdge_fedgeB___doc__[] = +".. method:: fedgeB()\n" +"\n" +" Returns the last FEdge that constitutes this ViewEdge.\n" +"\n" +" :return: The last FEdge constituting this ViewEdge.\n" +" :rtype: :class:`FEdge`\n"; + +static PyObject * ViewEdge_fedgeB( BPy_ViewEdge *self ) { + FEdge *B = self->ve->fedgeB(); + if( B ){ + return Any_BPy_FEdge_from_FEdge( *B ); + } + + Py_RETURN_NONE; +} + +static char ViewEdge_viewShape___doc__[] = +".. method:: viewShape()\n" +"\n" +" Returns the ViewShape to which this ViewEdge belongs to.\n" +"\n" +" :return: The ViewShape to which this ViewEdge belongs to.\n" +" :rtype: :class:`ViewShape`\n"; + +static PyObject * ViewEdge_viewShape( BPy_ViewEdge *self ) { + ViewShape *vs = self->ve->viewShape(); + if( vs ){ + return BPy_ViewShape_from_ViewShape( *vs ); + } + + Py_RETURN_NONE; +} + +static char ViewEdge_aShape___doc__[] = +".. method:: aShape()\n" +"\n" +" Returns the shape that is occluded by the ViewShape to which this\n" +" ViewEdge belongs to. If no object is occluded, None is returned.\n" +"\n" +" :return: The occluded ViewShape.\n" +" :rtype: :class:`ViewShape`\n"; + +static PyObject * ViewEdge_aShape( BPy_ViewEdge *self ) { + ViewShape *vs = self->ve->aShape(); + if( vs ){ + return BPy_ViewShape_from_ViewShape( *vs ); + } + + Py_RETURN_NONE; +} + +static char ViewEdge_isClosed___doc__[] = +".. method:: isClosed()\n" +"\n" +" Tells whether this ViewEdge forms a closed loop or not.\n" +"\n" +" :return: True if this ViewEdge forms a closed loop.\n" +" :rtype: bool\n"; + +static PyObject * ViewEdge_isClosed( BPy_ViewEdge *self ) { + return PyBool_from_bool( self->ve->isClosed() ); +} + +static char ViewEdge_getChainingTimeStamp___doc__[] = +".. method:: getChainingTimeStamp()\n" +"\n" +" Returns the time stamp of this ViewEdge.\n" +"\n" +" :return: The time stamp.\n" +" :rtype: int\n"; + +static PyObject * ViewEdge_getChainingTimeStamp( BPy_ViewEdge *self ) { + return PyLong_FromLong( self->ve->getChainingTimeStamp() ); +} + +static char ViewEdge_setChainingTimeStamp___doc__[] = +".. method:: setChainingTimeStamp(ts)\n" +"\n" +" Sets the time stamp value.\n" +"\n" +" :arg ts: The time stamp.\n" +" :type ts: int\n"; + +static PyObject * ViewEdge_setChainingTimeStamp( BPy_ViewEdge *self, PyObject *args) { + int timestamp = 0 ; + + if( !PyArg_ParseTuple(args, "i", ×tamp) ) + return NULL; + + self->ve->setChainingTimeStamp( timestamp ); + + Py_RETURN_NONE; +} + +static char ViewEdge_setA___doc__[] = +".. method:: setA(iA)\n" +"\n" +" Sets the first ViewVertex of the ViewEdge.\n" +"\n" +" :arg iA: The first ViewVertex of the ViewEdge.\n" +" :type iA: :class:`ViewVertex`\n"; + +static PyObject *ViewEdge_setA( BPy_ViewEdge *self , PyObject *args) { + PyObject *py_vv; + + if(!( PyArg_ParseTuple(args, "O!", &ViewVertex_Type, &py_vv) )) + return NULL; + + self->ve->setA( ((BPy_ViewVertex *) py_vv)->vv ); + + Py_RETURN_NONE; +} + +static char ViewEdge_setB___doc__[] = +".. method:: setB(iB)\n" +"\n" +" Sets the last ViewVertex of the ViewEdge.\n" +"\n" +" :arg iB: The last ViewVertex of the ViewEdge.\n" +" :type iB: :class:`ViewVertex`\n"; + +static PyObject *ViewEdge_setB( BPy_ViewEdge *self , PyObject *args) { + PyObject *py_vv; + + if(!( PyArg_ParseTuple(args, "O!", &ViewVertex_Type, &py_vv) )) + return NULL; + + self->ve->setB( ((BPy_ViewVertex *) py_vv)->vv ); + + Py_RETURN_NONE; +} + +static char ViewEdge_setNature___doc__[] = +".. method:: setNature(iNature)\n" +"\n" +" Sets the nature of the ViewEdge.\n" +"\n" +" :arg iNature: The nature of the ViewEdge.\n" +" :type iNature: :class:`Nature`\n"; + +static PyObject * ViewEdge_setNature( BPy_ViewEdge *self, PyObject *args ) { + PyObject *py_n; + + if(!( PyArg_ParseTuple(args, "O!", &Nature_Type, &py_n) )) + return NULL; + + PyObject *i = (PyObject *) &( ((BPy_Nature *) py_n)->i ); + self->ve->setNature( PyLong_AsLong(i) ); + + Py_RETURN_NONE; +} + +static char ViewEdge_setFEdgeA___doc__[] = +".. method:: setFEdgeA(iFEdge)\n" +"\n" +" Sets the first FEdge of the ViewEdge.\n" +"\n" +" :arg iFEdge: The first FEdge of the ViewEdge.\n" +" :type iFEdge: :class:`FEdge`\n"; + +static PyObject * ViewEdge_setFEdgeA( BPy_ViewEdge *self, PyObject *args ) { + PyObject *py_fe; + + if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) )) + return NULL; + + self->ve->setFEdgeA( ((BPy_FEdge *) py_fe)->fe ); + + Py_RETURN_NONE; +} + +static char ViewEdge_setFEdgeB___doc__[] = +".. method:: setFEdgeB(iFEdge)\n" +"\n" +" Sets the last FEdge of the ViewEdge.\n" +"\n" +" :arg iFEdge: The last FEdge of the ViewEdge.\n" +" :type iFEdge: :class:`FEdge`\n"; + +static PyObject * ViewEdge_setFEdgeB( BPy_ViewEdge *self, PyObject *args ) { + PyObject *py_fe; + + if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) )) + return NULL; + + self->ve->setFEdgeB( ((BPy_FEdge *) py_fe)->fe ); + + Py_RETURN_NONE; +} + +static char ViewEdge_setShape___doc__[] = +".. method:: setShape(iVShape)\n" +"\n" +" Sets the ViewShape to which this ViewEdge belongs to.\n" +"\n" +" :arg iVShape: The ViewShape to which this ViewEdge belongs to.\n" +" :type iVShape: :class:`ViewShape`\n"; + +static PyObject * ViewEdge_setShape( BPy_ViewEdge *self, PyObject *args ) { + PyObject *py_vs; + + if(!( PyArg_ParseTuple(args, "O", &ViewShape_Type, &py_vs) )) + return NULL; + + self->ve->setShape( ((BPy_ViewShape *) py_vs)->vs ); + + Py_RETURN_NONE; +} + +static char ViewEdge_setId___doc__[] = +".. method:: setId(id)\n" +"\n" +" Sets the ViewEdge id.\n" +"\n" +" :arg id: An Id object.\n" +" :type id: :class:`Id`\n"; + +static PyObject * ViewEdge_setId( BPy_ViewEdge *self, PyObject *args ) { + PyObject *py_id; + + if(!( PyArg_ParseTuple(args, "O!", &Id_Type, &py_id) )) + return NULL; + + Id id(*( ((BPy_Id *) py_id)->id )); + self->ve->setId( id ); + + Py_RETURN_NONE; +} + +static char ViewEdge_UpdateFEdges___doc__[] = +".. method:: UpdateFEdges()\n" +"\n" +" Sets Viewedge to this for all embedded fedges.\n"; + +static PyObject * ViewEdge_UpdateFEdges( BPy_ViewEdge *self ) { + self->ve->UpdateFEdges(); + + Py_RETURN_NONE; +} + +static char ViewEdge_setaShape___doc__[] = +".. method:: setaShape(iShape)\n" +"\n" +" Sets the occluded ViewShape.\n" +"\n" +" :arg iShape: A ViewShape object.\n" +" :type iShape: :class:`ViewShape`\n"; + +static PyObject * ViewEdge_setaShape( BPy_ViewEdge *self, PyObject *args ) { + PyObject *py_vs; + + if(!( PyArg_ParseTuple(args, "O!", &ViewShape_Type, &py_vs) )) + return NULL; + + ViewShape *vs = ((BPy_ViewShape *) py_vs)->vs; + self->ve->setaShape( vs ); + + Py_RETURN_NONE; +} + +static char ViewEdge_setQI___doc__[] = +".. method:: setQI(qi)\n" +"\n" +" Sets the quantitative invisibility value of the ViewEdge.\n" +"\n" +" :arg qi: The quantitative invisibility.\n" +" :type qi: int\n"; + +static PyObject * ViewEdge_setQI( BPy_ViewEdge *self, PyObject *args ) { + int qi; + + if(!( PyArg_ParseTuple(args, "i", &qi) )) + return NULL; + + self->ve->setQI( qi ); + + Py_RETURN_NONE; +} + +static char ViewEdge_qi___doc__[] = +".. method:: getChainingTimeStamp()\n" +"\n" +" Returns the quantitative invisibility value of the ViewEdge.\n" +"\n" +" :return: The quantitative invisibility.\n" +" :rtype: int\n"; + +static PyObject * ViewEdge_qi( BPy_ViewEdge *self ) { + return PyLong_FromLong( self->ve->qi() ); +} + +/*----------------------ViewEdge instance definitions ----------------------------*/ +static PyMethodDef BPy_ViewEdge_methods[] = { + {"A", ( PyCFunction ) ViewEdge_A, METH_NOARGS, ViewEdge_A___doc__}, + {"B", ( PyCFunction ) ViewEdge_B, METH_NOARGS, ViewEdge_B___doc__}, + {"fedgeA", ( PyCFunction ) ViewEdge_fedgeA, METH_NOARGS, ViewEdge_fedgeA___doc__}, + {"fedgeB", ( PyCFunction ) ViewEdge_fedgeB, METH_NOARGS, ViewEdge_fedgeB___doc__}, + {"viewShape", ( PyCFunction ) ViewEdge_viewShape, METH_NOARGS, ViewEdge_viewShape___doc__}, + {"aShape", ( PyCFunction ) ViewEdge_aShape, METH_NOARGS, ViewEdge_aShape___doc__}, + {"isClosed", ( PyCFunction ) ViewEdge_isClosed, METH_NOARGS, ViewEdge_isClosed___doc__}, + {"getChainingTimeStamp", ( PyCFunction ) ViewEdge_getChainingTimeStamp, METH_NOARGS, ViewEdge_getChainingTimeStamp___doc__}, + {"setChainingTimeStamp", ( PyCFunction ) ViewEdge_setChainingTimeStamp, METH_VARARGS, ViewEdge_setChainingTimeStamp___doc__}, + {"setA", ( PyCFunction ) ViewEdge_setA, METH_VARARGS, ViewEdge_setA___doc__}, + {"setB", ( PyCFunction ) ViewEdge_setB, METH_VARARGS, ViewEdge_setB___doc__}, + {"setNature", ( PyCFunction ) ViewEdge_setNature, METH_VARARGS, ViewEdge_setNature___doc__}, + {"setFEdgeA", ( PyCFunction ) ViewEdge_setFEdgeA, METH_VARARGS, ViewEdge_setFEdgeA___doc__}, + {"setFEdgeB", ( PyCFunction ) ViewEdge_setFEdgeB, METH_VARARGS, ViewEdge_setFEdgeB___doc__}, + {"setShape", ( PyCFunction ) ViewEdge_setShape, METH_VARARGS, ViewEdge_setShape___doc__}, + {"setId", ( PyCFunction ) ViewEdge_setId, METH_VARARGS, ViewEdge_setId___doc__}, + {"UpdateFEdges", ( PyCFunction ) ViewEdge_UpdateFEdges, METH_NOARGS, ViewEdge_UpdateFEdges___doc__}, + {"setaShape", ( PyCFunction ) ViewEdge_setaShape, METH_VARARGS, ViewEdge_setaShape___doc__}, + {"setQI", ( PyCFunction ) ViewEdge_setQI, METH_VARARGS, ViewEdge_setQI___doc__}, + {"qi", ( PyCFunction ) ViewEdge_qi, METH_NOARGS, ViewEdge_qi___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_ViewEdge type definition ------------------------------*/ + +PyTypeObject ViewEdge_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ViewEdge", /* tp_name */ + sizeof(BPy_ViewEdge), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ViewEdge___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_ViewEdge_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &Interface1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ViewEdge___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.h b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.h new file mode 100644 index 00000000000..ead377377e8 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.h @@ -0,0 +1,32 @@ +#ifndef FREESTYLE_PYTHON_VIEWEDGE_H +#define FREESTYLE_PYTHON_VIEWEDGE_H + +#include "../../view_map/ViewMap.h" + +#include "../BPy_Interface1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ViewEdge_Type; + +#define BPy_ViewEdge_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ViewEdge_Type) ) + +/*---------------------------Python BPy_ViewEdge structure definition----------*/ +typedef struct { + BPy_Interface1D py_if1D; + ViewEdge *ve; +} BPy_ViewEdge; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_VIEWEDGE_H */ diff --git a/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp new file mode 100644 index 00000000000..7958a35b851 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp @@ -0,0 +1,169 @@ +#include "BPy_Chain.h" + +#include "../../BPy_Convert.h" +#include "../../BPy_Id.h" +#include "../BPy_ViewEdge.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char Chain___doc__[] = +"Class to represent a 1D elements issued from the chaining process. A\n" +"Chain is the last step before the :class:`Stroke` and is used in the\n" +"Splitting and Creation processes.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Defult constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: A Chain object.\n" +" :type iBrother: :class:`Chain`\n" +"\n" +".. method:: __init__(id)\n" +"\n" +" Builds a chain from its Id.\n" +"\n" +" :arg id: An Id object.\n" +" :type id: :class:`Id`\n"; + +int Chain___init__(BPy_Chain *self, PyObject *args, PyObject *kwds) +{ + + PyObject *obj = 0; + + if (! PyArg_ParseTuple(args, "|O", &obj) ) + return -1; + + if( !obj ){ + self->c = new Chain(); + + } else if( BPy_Chain_Check(obj) ) { + self->c = new Chain(*( ((BPy_Chain *) obj)->c )); + + } else if( BPy_Id_Check(obj) ) { + self->c = new Chain(*( ((BPy_Id *) obj)->id )); + + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument"); + return -1; + } + + self->py_c.c = self->c; + self->py_c.py_if1D.if1D = self->c; + self->py_c.py_if1D.borrowed = 0; + + return 0; +} + +static char Chain_push_viewedge_back___doc__[] = +".. method:: push_viewedge_back(iViewEdge, orientation)\n" +"\n" +" Adds a ViewEdge at the end of the Chain.\n" +"\n" +" :arg iViewEdge: The ViewEdge that must be added.\n" +" :type iViewEdge: :class:`ViewEdge`\n" +" :arg orientation: The orientation with which the ViewEdge must be\n" +" processed.\n" +" :type orientation: bool\n"; + +PyObject * Chain_push_viewedge_back( BPy_Chain *self, PyObject *args ) { + PyObject *obj1 = 0, *obj2 = 0; + + if(!( PyArg_ParseTuple(args, "O!O", &ViewEdge_Type, &obj1, &obj2) )) + return NULL; + + ViewEdge *ve = ((BPy_ViewEdge *) obj1)->ve; + bool orientation = bool_from_PyBool( obj2 ); + self->c->push_viewedge_back( ve, orientation); + + Py_RETURN_NONE; +} + +static char Chain_push_viewedge_front___doc__[] = +".. method:: push_viewedge_front(iViewEdge, orientation)\n" +"\n" +" Adds a ViewEdge at the beginning of the Chain.\n" +"\n" +" :arg iViewEdge: The ViewEdge that must be added.\n" +" :type iViewEdge: :class:`ViewEdge`\n" +" :arg orientation: The orientation with which the ViewEdge must be\n" +" processed.\n" +" :type orientation: bool\n"; + +PyObject * Chain_push_viewedge_front( BPy_Chain *self, PyObject *args ) { + PyObject *obj1 = 0, *obj2 = 0; + + if(!( PyArg_ParseTuple(args, "O!O", &ViewEdge_Type, &obj1, &obj2) )) + return NULL; + + ViewEdge *ve = ((BPy_ViewEdge *) obj1)->ve; + bool orientation = bool_from_PyBool( obj2 ); + self->c->push_viewedge_front(ve, orientation); + + Py_RETURN_NONE; +} + +/*----------------------Chain instance definitions ----------------------------*/ +static PyMethodDef BPy_Chain_methods[] = { + {"push_viewedge_back", ( PyCFunction ) Chain_push_viewedge_back, METH_VARARGS, Chain_push_viewedge_back___doc__}, + {"push_viewedge_front", ( PyCFunction ) Chain_push_viewedge_front, METH_VARARGS, Chain_push_viewedge_front___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_Chain type definition ------------------------------*/ + +PyTypeObject Chain_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "Chain", /* tp_name */ + sizeof(BPy_Chain), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Chain___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_Chain_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &FrsCurve_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)Chain___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.h b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.h new file mode 100644 index 00000000000..19f325ef513 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_CHAIN_H +#define FREESTYLE_PYTHON_CHAIN_H + +#include "../BPy_FrsCurve.h" +#include "../../../stroke/Chain.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject Chain_Type; + +#define BPy_Chain_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Chain_Type) ) + +/*---------------------------Python BPy_Chain structure definition----------*/ +typedef struct { + BPy_FrsCurve py_c; + Chain *c; +} BPy_Chain; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_CHAIN_H */ diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp new file mode 100644 index 00000000000..f98b6f49940 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp @@ -0,0 +1,303 @@ +#include "BPy_FEdgeSharp.h" + +#include "../../BPy_Convert.h" +#include "../../Interface0D/BPy_SVertex.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char FEdgeSharp___doc__[] = +"Class defining a sharp FEdge. A Sharp FEdge corresponds to an initial\n" +"edge of the input mesh. It can be a silhouette, a crease or a border.\n" +"If it is a crease edge, then it is borded by two faces of the mesh.\n" +"Face a lies on its right whereas Face b lies on its left. If it is a\n" +"border edge, then it doesn't have any face on its right, and thus Face\n" +"a is None.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: An FEdgeSharp object.\n" +" :type iBrother: :class:`FEdgeSharp`\n" +"\n" +".. method:: __init__(vA, vB)\n" +"\n" +" Builds an FEdgeSharp going from vA to vB.\n" +"\n" +" :arg vA: The first SVertex object.\n" +" :type vA: :class:`SVertex`\n" +" :arg vB: The second SVertex object.\n" +" :type vB: :class:`SVertex`\n"; + +static int FEdgeSharp___init__(BPy_FEdgeSharp *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj1 = 0, *obj2 = 0; + + if (! PyArg_ParseTuple(args, "|OO", &obj1, &obj2) ) + return -1; + + if( !obj1 ){ + self->fes = new FEdgeSharp(); + + } else if( !obj2 && BPy_FEdgeSharp_Check(obj1) ) { + self->fes = new FEdgeSharp(*( ((BPy_FEdgeSharp *) obj1)->fes )); + + } else if( obj2 && BPy_SVertex_Check(obj1) && BPy_SVertex_Check(obj2) ) { + self->fes = new FEdgeSharp( ((BPy_SVertex *) obj1)->sv, ((BPy_SVertex *) obj2)->sv ); + + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument(s)"); + return -1; + } + + self->py_fe.fe = self->fes; + self->py_fe.py_if1D.if1D = self->fes; + self->py_fe.py_if1D.borrowed = 0; + + return 0; +} + +static char FEdgeSharp_normalA___doc__[] = +".. method:: normalA()\n" +"\n" +" Returns the normal to the face lying on the right of the FEdge. If\n" +" this FEdge is a border, it has no Face on its right and therefore, no\n" +" normal.\n" +"\n" +" :return: The normal to the face lying on the right of the FEdge.\n" +" :rtype: :class:`mathutils.Vector`\n"; + +static PyObject * FEdgeSharp_normalA( BPy_FEdgeSharp *self ) { + Vec3r v( self->fes->normalA() ); + return Vector_from_Vec3r( v ); +} + +static char FEdgeSharp_normalB___doc__[] = +".. method:: normalB()\n" +"\n" +" Returns the normal to the face lying on the left of the FEdge.\n" +"\n" +" :return: The normal to the face lying on the left of the FEdge.\n" +" :rtype: :class:`mathutils.Vector`\n"; + +static PyObject * FEdgeSharp_normalB( BPy_FEdgeSharp *self ) { + Vec3r v( self->fes->normalB() ); + return Vector_from_Vec3r( v ); +} + +static char FEdgeSharp_aMaterialIndex___doc__[] = +".. method:: aMaterialIndex()\n" +"\n" +" Returns the index of the material of the face lying on the right of\n" +" the FEdge. If this FEdge is a border, it has no Face on its right and\n" +" therefore, no material.\n" +"\n" +" :return: The index of the material of the face lying on the right of\n" +" the FEdge.\n" +" :rtype: int\n"; + +static PyObject * FEdgeSharp_aMaterialIndex( BPy_FEdgeSharp *self ) { + return PyLong_FromLong( self->fes->aFrsMaterialIndex() ); +} + +static char FEdgeSharp_bMaterialIndex___doc__[] = +".. method:: bMaterialIndex()\n" +"\n" +" Returns the index of the material of the face lying on the left of\n" +" the FEdge.\n" +"\n" +" :return: The index of the material of the face lying on the left of\n" +" the FEdge.\n" +" :rtype: int\n"; + +static PyObject * FEdgeSharp_bMaterialIndex( BPy_FEdgeSharp *self ) { + return PyLong_FromLong( self->fes->bFrsMaterialIndex() ); +} + +static char FEdgeSharp_aMaterial___doc__[] = +".. method:: aMaterial()\n" +"\n" +" Returns the material of the face lying on the right of the FEdge. If\n" +" this FEdge is a border, it has no Face on its right and therefore, no\n" +" material.\n" +"\n" +" :return: The material of the face lying on the right of the FEdge.\n" +" :rtype: :class:`Material`\n"; + +static PyObject * FEdgeSharp_aMaterial( BPy_FEdgeSharp *self ) { + FrsMaterial m( self->fes->aFrsMaterial() ); + return BPy_FrsMaterial_from_FrsMaterial(m); +} + +static char FEdgeSharp_bMaterial___doc__[] = +".. method:: bMaterial()\n" +"\n" +" Returns the material of the face lying on the left of the FEdge.\n" +"\n" +" :return: The material of the face lying on the left of the FEdge.\n" +" :rtype: :class:`Material`\n"; + +static PyObject * FEdgeSharp_bMaterial( BPy_FEdgeSharp *self ) { + FrsMaterial m( self->fes->aFrsMaterial() ); + return BPy_FrsMaterial_from_FrsMaterial(m); +} + +static char FEdgeSharp_setNormalA___doc__[] = +".. method:: setNormalA(iNormal)\n" +"\n" +" Sets the normal to the face lying on the right of the FEdge.\n" +"\n" +" :arg iNormal: A three-dimensional vector.\n" +" :type iNormal: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"; + +static PyObject * FEdgeSharp_setNormalA( BPy_FEdgeSharp *self, PyObject *args ) { + PyObject *obj = 0; + + if(!( PyArg_ParseTuple(args, "O", &obj) )) + return NULL; + Vec3r *v = Vec3r_ptr_from_PyObject(obj); + if( !v ) { + PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)"); + return NULL; + } + self->fes->setNormalA( *v ); + delete v; + + Py_RETURN_NONE; +} + +static char FEdgeSharp_setNormalB___doc__[] = +".. method:: setNormalB(iNormal)\n" +"\n" +" Sets the normal to the face lying on the left of the FEdge.\n" +"\n" +" :arg iNormal: A three-dimensional vector.\n" +" :type iNormal: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"; + +static PyObject * FEdgeSharp_setNormalB( BPy_FEdgeSharp *self, PyObject *args ) { + PyObject *obj = 0; + + if(!( PyArg_ParseTuple(args, "O", &obj) )) + return NULL; + Vec3r *v = Vec3r_ptr_from_PyObject(obj); + if( !v ) { + PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)"); + return NULL; + } + self->fes->setNormalB( *v ); + delete v; + + Py_RETURN_NONE; +} + +static char FEdgeSharp_setaMaterialIndex___doc__[] = +".. method:: setaMaterialIndex(i)\n" +"\n" +" Sets the index of the material lying on the right of the FEdge.\n" +"\n" +" :arg i: A material index.\n" +" :type i: int\n"; + +static PyObject * FEdgeSharp_setaMaterialIndex( BPy_FEdgeSharp *self, PyObject *args ) { + unsigned int i; + + if(!( PyArg_ParseTuple(args, "I", &i) )) + return NULL; + + self->fes->setaFrsMaterialIndex( i ); + + Py_RETURN_NONE; +} + +static char FEdgeSharp_setbMaterialIndex___doc__[] = +".. method:: setbMaterialIndex(i)\n" +"\n" +" Sets the index of the material lying on the left of the FEdge.\n" +"\n" +" :arg i: A material index.\n" +" :type i: int\n"; + +static PyObject * FEdgeSharp_setbMaterialIndex( BPy_FEdgeSharp *self, PyObject *args ) { + unsigned int i; + + if(!( PyArg_ParseTuple(args, "I", &i) )) + return NULL; + + self->fes->setbFrsMaterialIndex( i ); + + Py_RETURN_NONE; +} + +/*----------------------FEdgeSharp instance definitions ----------------------------*/ +static PyMethodDef BPy_FEdgeSharp_methods[] = { + {"normalA", ( PyCFunction ) FEdgeSharp_normalA, METH_NOARGS, FEdgeSharp_normalA___doc__}, + {"normalB", ( PyCFunction ) FEdgeSharp_normalB, METH_NOARGS, FEdgeSharp_normalB___doc__}, + {"aMaterialIndex", ( PyCFunction ) FEdgeSharp_aMaterialIndex, METH_NOARGS, FEdgeSharp_aMaterialIndex___doc__}, + {"bMaterialIndex", ( PyCFunction ) FEdgeSharp_bMaterialIndex, METH_NOARGS, FEdgeSharp_bMaterialIndex___doc__}, + {"aMaterial", ( PyCFunction ) FEdgeSharp_aMaterial, METH_NOARGS, FEdgeSharp_aMaterial___doc__}, + {"bMaterial", ( PyCFunction ) FEdgeSharp_bMaterial, METH_NOARGS, FEdgeSharp_bMaterial___doc__}, + {"setNormalA", ( PyCFunction ) FEdgeSharp_setNormalA, METH_VARARGS, FEdgeSharp_setNormalA___doc__}, + {"setNormalB", ( PyCFunction ) FEdgeSharp_setNormalB, METH_VARARGS, FEdgeSharp_setNormalB___doc__}, + {"setaMaterialIndex", ( PyCFunction ) FEdgeSharp_setaMaterialIndex, METH_VARARGS, FEdgeSharp_setaMaterialIndex___doc__}, + {"setbMaterialIndex", ( PyCFunction ) FEdgeSharp_setbMaterialIndex, METH_VARARGS, FEdgeSharp_setbMaterialIndex___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_FEdgeSharp type definition ------------------------------*/ + +PyTypeObject FEdgeSharp_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "FEdgeSharp", /* tp_name */ + sizeof(BPy_FEdgeSharp), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + FEdgeSharp___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_FEdgeSharp_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &FEdge_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)FEdgeSharp___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.h b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.h new file mode 100644 index 00000000000..84b01e27c21 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_FEDGESHARP_H +#define FREESTYLE_PYTHON_FEDGESHARP_H + +#include "../BPy_FEdge.h" +#include "../../../view_map/Silhouette.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject FEdgeSharp_Type; + +#define BPy_FEdgeSharp_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FEdgeSharp_Type) ) + +/*---------------------------Python BPy_FEdgeSharp structure definition----------*/ +typedef struct { + BPy_FEdge py_fe; + FEdgeSharp *fes; +} BPy_FEdgeSharp; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_FEDGESHARP_H */ diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp new file mode 100644 index 00000000000..3e043108d98 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp @@ -0,0 +1,205 @@ +#include "BPy_FEdgeSmooth.h" + +#include "../../BPy_Convert.h" +#include "../../Interface0D/BPy_SVertex.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char FEdgeSmooth___doc__[] = +"Class defining a smooth edge. This kind of edge typically runs across\n" +"a face of the input mesh. It can be a silhouette, a ridge or valley,\n" +"a suggestive contour.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: An FEdgeSmooth object.\n" +" :type iBrother: :class:`FEdgeSmooth`\n" +"\n" +".. method:: __init__(vA, vB)\n" +"\n" +" Builds an FEdgeSmooth going from vA to vB.\n" +"\n" +" :arg vA: The first SVertex object.\n" +" :type vA: :class:`SVertex`\n" +" :arg vB: The second SVertex object.\n" +" :type vB: :class:`SVertex`\n"; + +static int FEdgeSmooth___init__(BPy_FEdgeSmooth *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj1 = 0, *obj2 = 0; + + if (! PyArg_ParseTuple(args, "|OO", &obj1, &obj2) ) + return -1; + + if( !obj1 ){ + self->fes = new FEdgeSmooth(); + + } else if( !obj2 && BPy_FEdgeSmooth_Check(obj1) ) { + self->fes = new FEdgeSmooth(*( ((BPy_FEdgeSmooth *) obj1)->fes )); + + } else if( obj2 && BPy_SVertex_Check(obj1) && BPy_SVertex_Check(obj2) ) { + self->fes = new FEdgeSmooth( ((BPy_SVertex *) obj1)->sv, ((BPy_SVertex *) obj2)->sv ); + + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument(s)"); + return -1; + } + + self->py_fe.fe = self->fes; + self->py_fe.py_if1D.if1D = self->fes; + self->py_fe.py_if1D.borrowed = 0; + + return 0; +} + +static char FEdgeSmooth_normal___doc__[] = +".. method:: normal()\n" +"\n" +" Returns the normal to the Face it is running accross.\n" +"\n" +" :return: The normal to the Face it is running accross.\n" +" :rtype: :class:`mathutils.Vector`\n"; + +static PyObject * FEdgeSmooth_normal( BPy_FEdgeSmooth *self ) { + Vec3r v( self->fes->normal() ); + return Vector_from_Vec3r( v ); +} + +static char FEdgeSmooth_materialIndex___doc__[] = +".. method:: materialIndex()\n" +"\n" +" Returns the index of the material of the face it is running accross.\n" +"\n" +" :return: The index of the material of the face it is running accross.\n" +" :rtype: int\n"; + +static PyObject * FEdgeSmooth_materialIndex( BPy_FEdgeSmooth *self ) { + return PyLong_FromLong( self->fes->frs_materialIndex() ); +} + +static char FEdgeSmooth_material___doc__[] = +".. method:: material()\n" +"\n" +" Returns the material of the face it is running accross.\n" +"\n" +" :return: The material of the face it is running accross.\n" +" :rtype: :class:`Material`\n"; + +static PyObject * FEdgeSmooth_material( BPy_FEdgeSmooth *self ) { + FrsMaterial m( self->fes->frs_material() ); + return BPy_FrsMaterial_from_FrsMaterial(m); +} + +static char FEdgeSmooth_setNormal___doc__[] = +".. method:: setNormal(iNormal)\n" +"\n" +" Sets the normal to the Face it is running accross.\n" +"\n" +" :arg iNormal: A three-dimensional vector.\n" +" :type iNormal: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"; + +static PyObject * FEdgeSmooth_setNormal( BPy_FEdgeSmooth *self, PyObject *args ) { + PyObject *obj = 0; + + if(!( PyArg_ParseTuple(args, "O", &obj) )) + return NULL; + Vec3r *v = Vec3r_ptr_from_PyObject(obj); + if( !v ) { + PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)"); + return NULL; + } + self->fes->setNormal( *v ); + delete v; + + Py_RETURN_NONE; +} + +static char FEdgeSmooth_setMaterialIndex___doc__[] = +".. method:: setMaterialIndex(i)\n" +"\n" +" Sets the index of the material of the face it is running accross.\n" +"\n" +" :arg i: The index of the material of the face it is running accross.\n" +" :type i: int\n"; + +static PyObject * FEdgeSmooth_setMaterialIndex( BPy_FEdgeSmooth *self, PyObject *args ) { + unsigned int i; + + if(!( PyArg_ParseTuple(args, "I", &i) )) + return NULL; + + self->fes->setFrsMaterialIndex( i ); + + Py_RETURN_NONE; +} + +/*----------------------FEdgeSmooth instance definitions ----------------------------*/ +static PyMethodDef BPy_FEdgeSmooth_methods[] = { + {"normal", ( PyCFunction ) FEdgeSmooth_normal, METH_NOARGS, FEdgeSmooth_normal___doc__}, + {"materialIndex", ( PyCFunction ) FEdgeSmooth_materialIndex, METH_NOARGS, FEdgeSmooth_materialIndex___doc__}, + {"material", ( PyCFunction ) FEdgeSmooth_material, METH_NOARGS, FEdgeSmooth_material___doc__}, + {"setNormal", ( PyCFunction ) FEdgeSmooth_setNormal, METH_VARARGS, FEdgeSmooth_setNormal___doc__}, + {"setMaterialIndex", ( PyCFunction ) FEdgeSmooth_setMaterialIndex, METH_VARARGS, FEdgeSmooth_setMaterialIndex___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_FEdgeSmooth type definition ------------------------------*/ + +PyTypeObject FEdgeSmooth_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "FEdgeSmooth", /* tp_name */ + sizeof(BPy_FEdgeSmooth), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + FEdgeSmooth___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_FEdgeSmooth_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &FEdge_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)FEdgeSmooth___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.h b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.h new file mode 100644 index 00000000000..d7b44bb1da7 --- /dev/null +++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_FEDGESMOOTH_H +#define FREESTYLE_PYTHON_FEDGESMOOTH_H + +#include "../BPy_FEdge.h" +#include "../../../view_map/Silhouette.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject FEdgeSmooth_Type; + +#define BPy_FEdgeSmooth_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FEdgeSmooth_Type) ) + +/*---------------------------Python BPy_FEdgeSmooth structure definition----------*/ +typedef struct { + BPy_FEdge py_fe; + FEdgeSmooth *fes; +} BPy_FEdgeSmooth; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_FEDGESMOOTH_H */ diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp new file mode 100644 index 00000000000..7df7ab25e1c --- /dev/null +++ b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp @@ -0,0 +1,165 @@ +#include "BPy_AdjacencyIterator.h" + +#include "../BPy_Convert.h" +#include "../Interface0D/BPy_ViewVertex.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char AdjacencyIterator___doc__[] = +"Class for representing adjacency iterators used in the chaining\n" +"process. An AdjacencyIterator is created in the increment() and\n" +"decrement() methods of a :class:`ChainingIterator` and passed to the\n" +"traverse() method of the ChainingIterator.\n" +"\n" +".. method:: __init__(iVertex, iRestrictToSelection=True, iRestrictToUnvisited=True)\n" +"\n" +" Builds a AdjacencyIterator object.\n" +"\n" +" :arg iVertex: The vertex which is the next crossing.\n" +" :type iVertex: :class:`ViewVertex`\n" +" :arg iRestrictToSelection: Indicates whether to force the chaining\n" +" to stay within the set of selected ViewEdges or not.\n" +" :type iRestrictToSelection: bool\n" +" :arg iRestrictToUnvisited: Indicates whether a ViewEdge that has\n" +" already been chained must be ignored ot not.\n" +" :type iRestrictToUnvisited: bool\n" +"\n" +".. method:: __init__(it)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg it: An AdjacencyIterator object.\n" +" :type it: :class:`AdjacencyIterator`\n"; + +static int AdjacencyIterator___init__(BPy_AdjacencyIterator *self, PyObject *args ) +{ + PyObject *obj1 = 0, *obj2 = 0 , *obj3 = 0; + + if (! PyArg_ParseTuple(args, "|OOO", &obj1, &obj2, &obj3) ) + return -1; + + if( !obj1 && !obj2 && !obj3 ){ + self->a_it = new AdjacencyIterator(); + + } else if( BPy_AdjacencyIterator_Check(obj1) ) { + self->a_it = new AdjacencyIterator(*( ((BPy_AdjacencyIterator *) obj1)->a_it )); + + } else if( BPy_ViewVertex_Check(obj1) ) { + bool restrictToSelection = ( obj2 ) ? bool_from_PyBool(obj2) : true; + bool restrictToUnvisited = ( obj3 ) ? bool_from_PyBool(obj3) : true; + + self->a_it = new AdjacencyIterator( ((BPy_ViewVertex *) obj1)->vv, restrictToSelection, restrictToUnvisited ); + + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument(s)"); + return -1; + } + + self->py_it.it = self->a_it; + + return 0; + +} + +static PyObject * AdjacencyIterator_iternext(BPy_AdjacencyIterator *self) { + if (self->a_it->isEnd()) { + PyErr_SetNone(PyExc_StopIteration); + return NULL; + } + ViewEdge *ve = self->a_it->operator*(); + self->a_it->increment(); + return BPy_ViewEdge_from_ViewEdge( *ve ); +} + +static char AdjacencyIterator_isIncoming___doc__[] = +".. method:: isIncoming()\n" +"\n" +" Returns true if the current ViewEdge is coming towards the\n" +" iteration vertex. False otherwise.\n" +"\n" +" :return: True if the current ViewEdge is coming towards the\n" +" iteration vertex\n" +" :rtype: bool\n"; + +static PyObject * AdjacencyIterator_isIncoming(BPy_AdjacencyIterator *self) { + return PyBool_from_bool(self->a_it->isIncoming()); +} + +static char AdjacencyIterator_getObject___doc__[] = +".. method:: getObject()\n" +"\n" +" Returns the pointed ViewEdge.\n" +"\n" +" :return: The pointed ViewEdge.\n" +" :rtype: :class:`ViewEdge`\n"; + +static PyObject * AdjacencyIterator_getObject(BPy_AdjacencyIterator *self) { + + ViewEdge *ve = self->a_it->operator*(); + if( ve ) + return BPy_ViewEdge_from_ViewEdge( *ve ); + + Py_RETURN_NONE; +} + +/*----------------------AdjacencyIterator instance definitions ----------------------------*/ +static PyMethodDef BPy_AdjacencyIterator_methods[] = { + {"isIncoming", ( PyCFunction ) AdjacencyIterator_isIncoming, METH_NOARGS, AdjacencyIterator_isIncoming___doc__}, + {"getObject", ( PyCFunction ) AdjacencyIterator_getObject, METH_NOARGS, AdjacencyIterator_getObject___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_AdjacencyIterator type definition ------------------------------*/ + +PyTypeObject AdjacencyIterator_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "AdjacencyIterator", /* tp_name */ + sizeof(BPy_AdjacencyIterator), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + AdjacencyIterator___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)AdjacencyIterator_iternext, /* tp_iternext */ + BPy_AdjacencyIterator_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &Iterator_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)AdjacencyIterator___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.h new file mode 100644 index 00000000000..733a9f2fcab --- /dev/null +++ b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.h @@ -0,0 +1,32 @@ +#ifndef FREESTYLE_PYTHON_ADJACENCYITERATOR_H +#define FREESTYLE_PYTHON_ADJACENCYITERATOR_H + +#include "../../stroke/ChainingIterators.h" +#include "../BPy_Iterator.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject AdjacencyIterator_Type; + +#define BPy_AdjacencyIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &AdjacencyIterator_Type) ) + +/*---------------------------Python BPy_AdjacencyIterator structure definition----------*/ +typedef struct { + BPy_Iterator py_it; + AdjacencyIterator *a_it; +} BPy_AdjacencyIterator; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_ADJACENCYITERATOR_H */ diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp new file mode 100644 index 00000000000..38670f20d7f --- /dev/null +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp @@ -0,0 +1,203 @@ +#include "BPy_ChainPredicateIterator.h" + +#include "../BPy_Convert.h" +#include "../BPy_BinaryPredicate1D.h" +#include "../Interface1D/BPy_ViewEdge.h" +#include "../BPy_UnaryPredicate1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ChainPredicateIterator___doc__[] = +"A \"generic\" user-controlled ViewEdge iterator. This iterator is in\n" +"particular built from a unary predicate and a binary predicate.\n" +"First, the unary predicate is evaluated for all potential next\n" +"ViewEdges in order to only keep the ones respecting a certain\n" +"constraint. Then, the binary predicate is evaluated on the current\n" +"ViewEdge together with each ViewEdge of the previous selection. The\n" +"first ViewEdge respecting both the unary predicate and the binary\n" +"predicate is kept as the next one. If none of the potential next\n" +"ViewEdge respects these two predicates, None is returned.\n" +"\n" +".. method:: __init__(iRestrictToSelection=True, iRestrictToUnvisited=True, begin=None, orientation=True)\n" +"\n" +" Builds a ChainPredicateIterator from a starting ViewEdge and its\n" +" orientation.\n" +"\n" +" :arg iRestrictToSelection: Indicates whether to force the chaining\n" +" to stay within the set of selected ViewEdges or not.\n" +" :type iRestrictToSelection: bool\n" +" :arg iRestrictToUnvisited: Indicates whether a ViewEdge that has\n" +" already been chained must be ignored ot not.\n" +" :type iRestrictToUnvisited: bool\n" +" :arg begin: The ViewEdge from where to start the iteration.\n" +" :type begin: :class:`ViewEdge` or None\n" +" :arg orientation: If true, we'll look for the next ViewEdge among\n" +" the ViewEdges that surround the ending ViewVertex of begin. If\n" +" false, we'll search over the ViewEdges surrounding the ending\n" +" ViewVertex of begin. \n" +" :type orientation: bool\n" +"\n" +".. method:: __init__(upred, bpred, iRestrictToSelection=True, iRestrictToUnvisited=True, begin=None, orientation=True)\n" +"\n" +" Builds a ChainPredicateIterator from a unary predicate, a binary\n" +" predicate, a starting ViewEdge and its orientation.\n" +"\n" +" :arg upred: The unary predicate that the next ViewEdge must satisfy.\n" +" :type upred: :class:`UnaryPredicate1D`\n" +" :arg bpred: The binary predicate that the next ViewEdge must\n" +" satisfy together with the actual pointed ViewEdge.\n" +" :type bpred: :class:`BinaryPredicate1D`\n" +" :arg iRestrictToSelection: Indicates whether to force the chaining\n" +" to stay within the set of selected ViewEdges or not.\n" +" :type iRestrictToSelection: bool\n" +" :arg iRestrictToUnvisited: Indicates whether a ViewEdge that has\n" +" already been chained must be ignored ot not.\n" +" :type iRestrictToUnvisited: bool\n" +" :arg begin: The ViewEdge from where to start the iteration.\n" +" :type begin: :class:`ViewEdge` or None\n" +" :arg orientation: If true, we'll look for the next ViewEdge among\n" +" the ViewEdges that surround the ending ViewVertex of begin. If\n" +" false, we'll search over the ViewEdges surrounding the ending\n" +" ViewVertex of begin.\n" +" :type orientation: bool\n" +"\n" +".. method:: __init__(brother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg brother: A ChainPredicateIterator object.\n" +" :type brother: :class:`ChainPredicateIterator`\n"; + +static int ChainPredicateIterator___init__(BPy_ChainPredicateIterator *self, PyObject *args ) +{ + PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0, *obj4 = 0, *obj5 = 0, *obj6 = 0; + + if (!( PyArg_ParseTuple(args, "|OOOOOO", &obj1, &obj2, &obj3, &obj4, &obj5, &obj6) )) + return -1; + + if( obj1 && BPy_ChainPredicateIterator_Check(obj1) ) { + self->cp_it = new ChainPredicateIterator(*( ((BPy_ChainPredicateIterator *) obj1)->cp_it )); + self->upred = NULL; + self->bpred = NULL; + + } else if( obj1 && BPy_UnaryPredicate1D_Check(obj1) && + obj2 && BPy_BinaryPredicate1D_Check(obj2) ) { + + if (!((BPy_UnaryPredicate1D *) obj1)->up1D) { + PyErr_SetString(PyExc_TypeError, "1st argument: invalid UnaryPredicate1D object"); + return -1; + } + if (!((BPy_BinaryPredicate1D *) obj2)->bp1D) { + PyErr_SetString(PyExc_TypeError, "2nd argument: invalid BinaryPredicate1D object"); + return -1; + } + UnaryPredicate1D *up1D = ((BPy_UnaryPredicate1D *) obj1)->up1D; + BinaryPredicate1D *bp1D = ((BPy_BinaryPredicate1D *) obj2)->bp1D; + bool restrictToSelection = ( obj3 ) ? bool_from_PyBool(obj3) : true; + bool restrictToUnvisited = ( obj4 ) ? bool_from_PyBool(obj4) : true; + ViewEdge *begin; + if ( !obj5 || obj5 == Py_None ) + begin = NULL; + else if ( BPy_ViewEdge_Check(obj5) ) + begin = ((BPy_ViewEdge *) obj5)->ve; + else { + PyErr_SetString(PyExc_TypeError, "5th argument must be either a ViewEdge object or None"); + return -1; + } + bool orientation = ( obj6 ) ? bool_from_PyBool(obj6) : true; + + self->cp_it = new ChainPredicateIterator( *up1D, *bp1D, restrictToSelection, restrictToUnvisited, begin, orientation); + self->upred = obj1; + self->bpred = obj2; + Py_INCREF( self->upred ); + Py_INCREF( self->bpred ); + + } else { + bool restrictToSelection = ( obj1 ) ? bool_from_PyBool(obj1) : true; + bool restrictToUnvisited = ( obj2 ) ? bool_from_PyBool(obj2) : true; + ViewEdge *begin; + if ( !obj3 || obj3 == Py_None ) + begin = NULL; + else if ( BPy_ViewEdge_Check(obj3) ) + begin = ((BPy_ViewEdge *) obj3)->ve; + else { + PyErr_SetString(PyExc_TypeError, "3rd argument must be either a ViewEdge object or None"); + return -1; + } + bool orientation = ( obj4 ) ? bool_from_PyBool(obj4) : true; + + self->cp_it = new ChainPredicateIterator( restrictToSelection, restrictToUnvisited, begin, orientation); + self->upred = NULL; + self->bpred = NULL; + } + + self->py_c_it.c_it = self->cp_it; + self->py_c_it.py_ve_it.ve_it = self->cp_it; + self->py_c_it.py_ve_it.py_it.it = self->cp_it; + + + return 0; + +} + +static void ChainPredicateIterator___dealloc__(BPy_ChainPredicateIterator *self) +{ + Py_XDECREF( self->upred ); + Py_XDECREF( self->bpred ); + ChainingIterator_Type.tp_dealloc((PyObject *)self); +} + +/*-----------------------BPy_ChainPredicateIterator type definition ------------------------------*/ + +PyTypeObject ChainPredicateIterator_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ChainPredicateIterator", /* tp_name */ + sizeof(BPy_ChainPredicateIterator), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)ChainPredicateIterator___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ChainPredicateIterator___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &ChainingIterator_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ChainPredicateIterator___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.h new file mode 100644 index 00000000000..5a31ac407d5 --- /dev/null +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.h @@ -0,0 +1,35 @@ +#ifndef FREESTYLE_PYTHON_CHAINPREDICATEITERATOR_H +#define FREESTYLE_PYTHON_CHAINPREDICATEITERATOR_H + + +#include "../../stroke/ChainingIterators.h" + +#include "BPy_ChainingIterator.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ChainPredicateIterator_Type; + +#define BPy_ChainPredicateIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ChainPredicateIterator_Type) ) + +/*---------------------------Python BPy_ChainPredicateIterator structure definition----------*/ +typedef struct { + BPy_ChainingIterator py_c_it; + ChainPredicateIterator *cp_it; + PyObject *upred; + PyObject *bpred; +} BPy_ChainPredicateIterator; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_CHAINPREDICATEITERATOR_H */ diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp new file mode 100644 index 00000000000..0549a4ac12b --- /dev/null +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp @@ -0,0 +1,129 @@ +#include "BPy_ChainSilhouetteIterator.h" + +#include "../BPy_Convert.h" +#include "../Interface1D/BPy_ViewEdge.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +// ChainSilhouetteIterator (bool iRestrictToSelection=true, ViewEdge *begin=NULL, bool orientation=true) +// ChainSilhouetteIterator (const ChainSilhouetteIterator &brother) + +static char ChainSilhouetteIterator___doc__[] = +"A ViewEdge Iterator used to follow ViewEdges the most naturally. For\n" +"example, it will follow visible ViewEdges of same nature. As soon, as\n" +"the nature or the visibility changes, the iteration stops (by setting\n" +"the pointed ViewEdge to 0). In the case of an iteration over a set of\n" +"ViewEdge that are both Silhouette and Crease, there will be a\n" +"precedence of the silhouette over the crease criterion.\n" +"\n" +".. method:: __init__(iRestrictToSelection=True, begin=None, orientation=True)\n" +"\n" +" Builds a ChainSilhouetteIterator from the first ViewEdge used for\n" +" iteration and its orientation.\n" +"\n" +" :arg iRestrictToSelection: Indicates whether to force the chaining\n" +" to stay within the set of selected ViewEdges or not.\n" +" :type iRestrictToSelection: bool\n" +" :arg begin: The ViewEdge from where to start the iteration.\n" +" :type begin: :class:`ViewEdge` or None\n" +" :arg orientation: If true, we'll look for the next ViewEdge among\n" +" the ViewEdges that surround the ending ViewVertex of begin. If\n" +" false, we'll search over the ViewEdges surrounding the ending\n" +" ViewVertex of begin.\n" +" :type orientation: bool\n" +"\n" +".. method:: __init__(brother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg brother: A ChainSilhouetteIterator object.\n" +" :type brother: :class:`ChainSilhouetteIterator`\n"; + +static int ChainSilhouetteIterator___init__(BPy_ChainSilhouetteIterator *self, PyObject *args ) +{ + PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0; + + if (!( PyArg_ParseTuple(args, "|OOO", &obj1, &obj2, &obj3) )) + return -1; + + if( obj1 && BPy_ChainSilhouetteIterator_Check(obj1) ) { + self->cs_it = new ChainSilhouetteIterator(*( ((BPy_ChainSilhouetteIterator *) obj1)->cs_it )); + + } else { + bool restrictToSelection = ( obj1 ) ? bool_from_PyBool(obj1) : true; + ViewEdge *begin; + if ( !obj2 || obj2 == Py_None ) + begin = NULL; + else if ( BPy_ViewEdge_Check(obj2) ) + begin = ((BPy_ViewEdge *) obj2)->ve; + else { + PyErr_SetString(PyExc_TypeError, "2nd argument must be either a ViewEdge object or None"); + return -1; + } + bool orientation = ( obj3 ) ? bool_from_PyBool(obj3) : true; + + self->cs_it = new ChainSilhouetteIterator( restrictToSelection, begin, orientation); + } + + self->py_c_it.c_it = self->cs_it; + self->py_c_it.py_ve_it.ve_it = self->cs_it; + self->py_c_it.py_ve_it.py_it.it = self->cs_it; + + return 0; + +} + +/*-----------------------BPy_ChainSilhouetteIterator type definition ------------------------------*/ + +PyTypeObject ChainSilhouetteIterator_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ChainSilhouetteIterator", /* tp_name */ + sizeof(BPy_ChainSilhouetteIterator), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ChainSilhouetteIterator___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &ChainingIterator_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ChainSilhouetteIterator___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.h new file mode 100644 index 00000000000..912d397d279 --- /dev/null +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.h @@ -0,0 +1,33 @@ +#ifndef FREESTYLE_PYTHON_CHAINSILHOUETTEITERATOR_H +#define FREESTYLE_PYTHON_CHAINSILHOUETTEITERATOR_H + + +#include "../../stroke/ChainingIterators.h" + +#include "BPy_ChainingIterator.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ChainSilhouetteIterator_Type; + +#define BPy_ChainSilhouetteIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ChainSilhouetteIterator_Type) ) + +/*---------------------------Python BPy_ChainSilhouetteIterator structure definition----------*/ +typedef struct { + BPy_ChainingIterator py_c_it; + ChainSilhouetteIterator *cs_it; +} BPy_ChainSilhouetteIterator; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_CHAINSILHOUETTEITERATOR_H */ diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp new file mode 100644 index 00000000000..9d3b1e5c0be --- /dev/null +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp @@ -0,0 +1,234 @@ +#include "BPy_ChainingIterator.h" + +#include "../BPy_Convert.h" +#include "../Interface0D/BPy_ViewVertex.h" +#include "../Interface1D/BPy_ViewEdge.h" +#include "BPy_AdjacencyIterator.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ChainingIterator___doc__[] = +"Base class for chaining iterators. This class is designed to be\n" +"overloaded in order to describe chaining rules. It makes the\n" +"description of chaining rules easier. The two main methods that need\n" +"to overloaded are traverse() and init(). traverse() tells which\n" +":class:`ViewEdge` to follow, among the adjacent ones. If you specify\n" +"restriction rules (such as \"Chain only ViewEdges of the selection\"),\n" +"they will be included in the adjacency iterator (i.e, the adjacent\n" +"iterator will only stop on \"valid\" edges).\n" +"\n" +".. method:: __init__(iRestrictToSelection=True, iRestrictToUnvisited=True, begin=None, orientation=True)\n" +"\n" +" Builds a Chaining Iterator from the first ViewEdge used for\n" +" iteration and its orientation.\n" +"\n" +" :arg iRestrictToSelection: Indicates whether to force the chaining\n" +" to stay within the set of selected ViewEdges or not.\n" +" :type iRestrictToSelection: bool\n" +" :arg iRestrictToUnvisited: Indicates whether a ViewEdge that has\n" +" already been chained must be ignored ot not.\n" +" :type iRestrictToUnvisited: bool\n" +" :arg begin: The ViewEdge from which to start the chain.\n" +" :type begin: :class:`ViewEdge` or None\n" +" :arg orientation: The direction to follow to explore the graph. If\n" +" true, the direction indicated by the first ViewEdge is used.\n" +" :type orientation: bool\n" +"\n" +".. method:: __init__(brother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg brother: \n" +" :type brother: ChainingIterator\n"; + +static int ChainingIterator___init__(BPy_ChainingIterator *self, PyObject *args ) +{ + PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0, *obj4 = 0; + + if (!( PyArg_ParseTuple(args, "|OOOO", &obj1, &obj2, &obj3, &obj4) )) + return -1; + + if( obj1 && BPy_ChainingIterator_Check(obj1) ) { + self->c_it = new ChainingIterator(*( ((BPy_ChainingIterator *) obj1)->c_it )); + + } else { + bool restrictToSelection = ( obj1 ) ? bool_from_PyBool(obj1) : true; + bool restrictToUnvisited = ( obj2 ) ? bool_from_PyBool(obj2) : true; + ViewEdge *begin; + if ( !obj3 || obj3 == Py_None ) + begin = NULL; + else if ( BPy_ViewEdge_Check(obj3) ) + begin = ((BPy_ViewEdge *) obj3)->ve; + else { + PyErr_SetString(PyExc_TypeError, "3rd argument must be either a ViewEdge object or None"); + return -1; + } + bool orientation = ( obj4 ) ? bool_from_PyBool(obj4) : true; + + self->c_it = new ChainingIterator( restrictToSelection, restrictToUnvisited, begin, orientation); + } + + self->py_ve_it.ve_it = self->c_it; + self->py_ve_it.py_it.it = self->c_it; + + self->c_it->py_c_it = (PyObject *) self; + + return 0; +} + +static char ChainingIterator_init___doc__[] = +".. method:: init()\n" +"\n" +" Initializes the iterator context. This method is called each\n" +" time a new chain is started. It can be used to reset some\n" +" history information that you might want to keep.\n"; + +static PyObject *ChainingIterator_init( BPy_ChainingIterator *self ) { + if( typeid(*(self->c_it)) == typeid(ChainingIterator) ) { + PyErr_SetString(PyExc_TypeError, "init() method not properly overridden"); + return NULL; + } + self->c_it->init(); + + Py_RETURN_NONE; +} + +static char ChainingIterator_traverse___doc__[] = +".. method:: traverse(it)\n" +"\n" +" This method iterates over the potential next ViewEdges and returns\n" +" the one that will be followed next. Returns the next ViewEdge to\n" +" follow or None when the end of the chain is reached.\n" +"\n" +" :arg it: The iterator over the ViewEdges adjacent to the end vertex\n" +" of the current ViewEdge. The adjacency iterator reflects the\n" +" restriction rules by only iterating over the valid ViewEdges.\n" +" :type it: :class:`AdjacencyIterator`\n" +" :return: Returns the next ViewEdge to follow, or None if chaining ends.\n" +" :rtype: :class:`ViewEdge` or None\n"; + +static PyObject *ChainingIterator_traverse( BPy_ChainingIterator *self, PyObject *args ) { + PyObject *py_a_it; + + if(!( PyArg_ParseTuple(args, "O!", &AdjacencyIterator_Type, &py_a_it) )) + return NULL; + + if( typeid(*(self->c_it)) == typeid(ChainingIterator) ) { + PyErr_SetString(PyExc_TypeError, "traverse() method not properly overridden"); + return NULL; + } + if( ((BPy_AdjacencyIterator *) py_a_it)->a_it ) + self->c_it->traverse(*( ((BPy_AdjacencyIterator *) py_a_it)->a_it )); + + Py_RETURN_NONE; +} + +static char ChainingIterator_getVertex___doc__[] = +".. method:: getVertex()\n" +"\n" +" Returns the vertex which is the next crossing.\n" +"\n" +" :return: The vertex which is the next crossing.\n" +" :rtype: :class:`ViewVertex`\n"; + +static PyObject *ChainingIterator_getVertex( BPy_ChainingIterator *self ) { + ViewVertex *v = self->c_it->getVertex(); + if( v ) + return Any_BPy_ViewVertex_from_ViewVertex( *v ); + + Py_RETURN_NONE; +} + +static char ChainingIterator_isIncrementing___doc__[] = +".. method:: isIncrementing()\n" +"\n" +" Returns true if the current iteration is an incrementation.\n" +"\n" +" :return: True if the current iteration is an incrementation.\n" +" :rtype: bool\n"; + +static PyObject *ChainingIterator_isIncrementing( BPy_ChainingIterator *self ) { + return PyBool_from_bool( self->c_it->isIncrementing() ); +} + +static char ChainingIterator_getObject___doc__[] = +".. method:: getObject()\n" +"\n" +" Returns the pointed ViewEdge.\n" +"\n" +" :return: The pointed ViewEdge.\n" +" :rtype: :class:`ViewEdge`\n"; + +static PyObject * ChainingIterator_getObject( BPy_ChainingIterator *self) { + + ViewEdge *ve = self->c_it->operator*(); + if( ve ) + return BPy_ViewEdge_from_ViewEdge( *ve ); + + Py_RETURN_NONE; +} + +/*----------------------ChainingIterator instance definitions ----------------------------*/ +static PyMethodDef BPy_ChainingIterator_methods[] = { + {"init", ( PyCFunction ) ChainingIterator_init, METH_NOARGS, ChainingIterator_init___doc__}, + {"traverse", ( PyCFunction ) ChainingIterator_traverse, METH_VARARGS, ChainingIterator_traverse___doc__}, + {"getVertex", ( PyCFunction ) ChainingIterator_getVertex, METH_NOARGS, ChainingIterator_getVertex___doc__}, + {"isIncrementing", ( PyCFunction ) ChainingIterator_isIncrementing, METH_NOARGS, ChainingIterator_isIncrementing___doc__}, + {"getObject", ( PyCFunction ) ChainingIterator_getObject, METH_NOARGS, ChainingIterator_getObject___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_ChainingIterator type definition ------------------------------*/ + +PyTypeObject ChainingIterator_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ChainingIterator", /* tp_name */ + sizeof(BPy_ChainingIterator), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ChainingIterator___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_ChainingIterator_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &ViewEdgeIterator_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ChainingIterator___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.h new file mode 100644 index 00000000000..2a00aa8072f --- /dev/null +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.h @@ -0,0 +1,33 @@ +#ifndef FREESTYLE_PYTHON_CHAININGITERATOR_H +#define FREESTYLE_PYTHON_CHAININGITERATOR_H + + +#include "../../stroke/ChainingIterators.h" + +#include "BPy_ViewEdgeIterator.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ChainingIterator_Type; + +#define BPy_ChainingIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ChainingIterator_Type) ) + +/*---------------------------Python BPy_ChainingIterator structure definition----------*/ +typedef struct { + BPy_ViewEdgeIterator py_ve_it; + ChainingIterator *c_it; +} BPy_ChainingIterator; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_CHAININGITERATOR_H */ diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp new file mode 100644 index 00000000000..9af842b7612 --- /dev/null +++ b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp @@ -0,0 +1,169 @@ +#include "BPy_CurvePointIterator.h" + +#include "../BPy_Convert.h" +#include "BPy_Interface0DIterator.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char CurvePointIterator___doc__[] = +"Class representing an iterator on a curve. Allows an iterating\n" +"outside initial vertices. A CurvePoint is instanciated and returned\n" +"by getObject().\n" +"\n" +".. method:: __init__(step=0.0)\n" +"\n" +" Builds a CurvePointIterator object.\n" +"\n" +" :arg step: A resampling resolution with which the curve is resampled.\n" +" If zero, no resampling is done (i.e., the iterator iterates over\n" +" initial vertices).\n" +" :type step: float\n" +"\n" +".. method:: __init__(brother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg brother: A CurvePointIterator object.\n" +" :type brother: :class:`CurvePointIterator`\n"; + +static int CurvePointIterator___init__(BPy_CurvePointIterator *self, PyObject *args ) +{ + PyObject *obj = 0; + + if (! PyArg_ParseTuple(args, "|O", &obj) ) + return -1; + + if( !obj ){ + self->cp_it = new CurveInternal::CurvePointIterator(); + + } else if( BPy_CurvePointIterator_Check(obj) ) { + self->cp_it = new CurveInternal::CurvePointIterator(*( ((BPy_CurvePointIterator *) obj)->cp_it )); + + } else if( PyFloat_Check(obj) ) { + self->cp_it = new CurveInternal::CurvePointIterator( PyFloat_AsDouble(obj) ); + + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument"); + return -1; + } + + self->py_it.it = self->cp_it; + + return 0; +} + +static char CurvePointIterator_t___doc__[] = +".. method:: t()\n" +"\n" +" Returns the curvilinear abscissa.\n" +"\n" +" :return: The curvilinear abscissa.\n" +" :rtype: float\n"; + +PyObject * CurvePointIterator_t( BPy_CurvePointIterator *self ) { + return PyFloat_FromDouble( self->cp_it->t() ); +} + +static char CurvePointIterator_u___doc__[] = +".. method:: u()\n" +"\n" +" Returns the point parameter in the curve (0<=u<=1).\n" +"\n" +" :return: The point parameter.\n" +" :rtype: float\n"; + +static PyObject * CurvePointIterator_u( BPy_CurvePointIterator *self ) { + return PyFloat_FromDouble( self->cp_it->u() ); +} + +static char CurvePointIterator_castToInterface0DIterator___doc__[] = +".. method:: castToInterface0DIterator()\n" +"\n" +" Returns an Interface0DIterator converted from this\n" +" CurvePointIterator. Useful for any call to a function of the\n" +" UnaryFunction0D type.\n" +"\n" +" :return: An Interface0DIterator object converted from the\n" +" iterator.\n" +" :rtype: :class:`Interface0DIterator`\n"; + +static PyObject * CurvePointIterator_castToInterface0DIterator( BPy_CurvePointIterator *self ) { + Interface0DIterator it( self->cp_it->castToInterface0DIterator() ); + return BPy_Interface0DIterator_from_Interface0DIterator( it, 0 ); +} + +static char CurvePointIterator_getObject___doc__[] = +".. method:: getObject()\n" +"\n" +" Returns a CurvePoint pointed by the iterator.\n" +"\n" +" :return: \n" +" :rtype: :class:`CurvePoint`\n"; + +static PyObject * CurvePointIterator_getObject(BPy_CurvePointIterator *self) { + return BPy_CurvePoint_from_CurvePoint( self->cp_it->operator*() ); +} + +/*----------------------CurvePointIterator instance definitions ----------------------------*/ +static PyMethodDef BPy_CurvePointIterator_methods[] = { + {"t", ( PyCFunction ) CurvePointIterator_t, METH_NOARGS, CurvePointIterator_t___doc__}, + {"u", ( PyCFunction ) CurvePointIterator_u, METH_NOARGS, CurvePointIterator_u___doc__}, + {"castToInterface0DIterator", ( PyCFunction ) CurvePointIterator_castToInterface0DIterator, METH_NOARGS, CurvePointIterator_castToInterface0DIterator___doc__}, + {"getObject", ( PyCFunction ) CurvePointIterator_getObject, METH_NOARGS, CurvePointIterator_getObject___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_CurvePointIterator type definition ------------------------------*/ + +PyTypeObject CurvePointIterator_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "CurvePointIterator", /* tp_name */ + sizeof(BPy_CurvePointIterator), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + CurvePointIterator___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_CurvePointIterator_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &Iterator_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)CurvePointIterator___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.h new file mode 100644 index 00000000000..ad04c7208bb --- /dev/null +++ b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.h @@ -0,0 +1,32 @@ +#ifndef FREESTYLE_PYTHON_CURVEPOINTITERATOR_H +#define FREESTYLE_PYTHON_CURVEPOINTITERATOR_H + +#include "../../stroke/CurveIterators.h" + +#include "../BPy_Iterator.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject CurvePointIterator_Type; + +#define BPy_CurvePointIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &CurvePointIterator_Type) ) + +/*---------------------------Python BPy_CurvePointIterator structure definition----------*/ +typedef struct { + BPy_Iterator py_it; + CurveInternal::CurvePointIterator *cp_it; +} BPy_CurvePointIterator; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_CURVEPOINTITERATOR_H */ diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp new file mode 100644 index 00000000000..7276f7cd46b --- /dev/null +++ b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp @@ -0,0 +1,149 @@ +#include "BPy_Interface0DIterator.h" + +#include "../BPy_Convert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char Interface0DIterator___doc__[] = +"Class defining an iterator over Interface0D elements. An instance of\n" +"this iterator is always obtained from a 1D element.\n" +"\n" +".. method:: __init__(it)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n"; + +static int Interface0DIterator___init__(BPy_Interface0DIterator *self, PyObject *args ) +{ + PyObject *obj = 0; + + if (!( PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj) )) + return -1; + + self->if0D_it = new Interface0DIterator(*( ((BPy_Interface0DIterator *) obj)->if0D_it )); + self->py_it.it = self->if0D_it; + self->reversed = 0; + + return 0; +} + +static PyObject * Interface0DIterator_iternext( BPy_Interface0DIterator *self ) { + Interface0D *if0D; + if (self->reversed) { + if (self->if0D_it->isBegin()) { + PyErr_SetNone(PyExc_StopIteration); + return NULL; + } + self->if0D_it->decrement(); + if0D = self->if0D_it->operator->(); + } else { + if (self->if0D_it->isEnd()) { + PyErr_SetNone(PyExc_StopIteration); + return NULL; + } + if0D = self->if0D_it->operator->(); + self->if0D_it->increment(); + } + return Any_BPy_Interface0D_from_Interface0D( *if0D ); +} + +static char Interface0DIterator_t___doc__[] = +".. method:: t()\n" +"\n" +" Returns the curvilinear abscissa.\n" +"\n" +" :return: The curvilinear abscissa.\n" +" :rtype: float\n"; + +static PyObject * Interface0DIterator_t( BPy_Interface0DIterator *self ) { + return PyFloat_FromDouble( self->if0D_it->t() ); +} + +static char Interface0DIterator_u___doc__[] = +".. method:: u()\n" +"\n" +" Returns the point parameter in the curve 0<=u<=1.\n" +"\n" +" :return: The point parameter.\n" +" :rtype: float\n"; + +static PyObject * Interface0DIterator_u( BPy_Interface0DIterator *self ) { + return PyFloat_FromDouble( self->if0D_it->u() ); +} + +static char Interface0DIterator_getObject___doc__[] = +".. method:: getObject()\n" +"\n" +" Returns the pointed Interface0D.\n" +"\n" +" :return: The pointed Interface0D.\n" +" :rtype: :class:`Interface0D`\n"; + +static PyObject * Interface0DIterator_getObject(BPy_Interface0DIterator *self) { + return Any_BPy_Interface0D_from_Interface0D( self->if0D_it->operator*() ); +} + +/*----------------------Interface0DIterator instance definitions ----------------------------*/ +static PyMethodDef BPy_Interface0DIterator_methods[] = { + {"t", ( PyCFunction ) Interface0DIterator_t, METH_NOARGS, Interface0DIterator_t___doc__}, + {"u", ( PyCFunction ) Interface0DIterator_u, METH_NOARGS, Interface0DIterator_u___doc__}, + {"getObject", ( PyCFunction ) Interface0DIterator_getObject, METH_NOARGS, Interface0DIterator_getObject___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_Interface0DIterator type definition ------------------------------*/ + +PyTypeObject Interface0DIterator_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "Interface0DIterator", /* tp_name */ + sizeof(BPy_Interface0DIterator), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Interface0DIterator___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)Interface0DIterator_iternext, /* tp_iternext */ + BPy_Interface0DIterator_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &Iterator_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)Interface0DIterator___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.h new file mode 100644 index 00000000000..1972763b2eb --- /dev/null +++ b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.h @@ -0,0 +1,33 @@ +#ifndef FREESTYLE_PYTHON_INTERFACE0DITERATOR_H +#define FREESTYLE_PYTHON_INTERFACE0DITERATOR_H + +#include "../../view_map/Interface0D.h" +#include "../BPy_Iterator.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject Interface0DIterator_Type; + +#define BPy_Interface0DIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Interface0DIterator_Type) ) + +/*---------------------------Python BPy_Interface0DIterator structure definition----------*/ +typedef struct { + BPy_Iterator py_it; + Interface0DIterator *if0D_it; + int reversed; +} BPy_Interface0DIterator; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_INTERFACE0DITERATOR_H */ diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp new file mode 100644 index 00000000000..06329ce2e30 --- /dev/null +++ b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp @@ -0,0 +1,179 @@ +#include "BPy_SVertexIterator.h" + +#include "../BPy_Convert.h" +#include "../Interface0D/BPy_SVertex.h" +#include "../Interface1D/BPy_FEdge.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char SVertexIterator___doc__[] = +"Class representing an iterator over :class:`SVertex` of a\n" +":class:`ViewEdge`. An instance of an SVertexIterator can be obtained\n" +"from a ViewEdge by calling verticesBegin() or verticesEnd().\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(it)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg it: An SVertexIterator object.\n" +" :type it: :class:`SVertexIterator`\n" +"\n" +".. method:: __init__(v, begin, prev, next, t)\n" +"\n" +" Builds an SVertexIterator that starts iteration from an SVertex\n" +" object v.\n" +"\n" +" :arg v: The SVertex from which the iterator starts iteration.\n" +" :type v: :class:`SVertex`\n" +" :arg begin: The first vertex of a view edge.\n" +" :type begin: :class:`SVertex`\n" +" :arg prev: The previous FEdge coming to v.\n" +" :type prev: :class:`FEdge`\n" +" :arg next: The next FEdge going out from v.\n" +" :type next: :class:`FEdge`\n" +" :arg t: The curvilinear abscissa at v.\n" +" :type t: float\n"; + +static int SVertexIterator___init__(BPy_SVertexIterator *self, PyObject *args ) +{ + PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0, *obj4 = 0; + float f = 0; + + if (! PyArg_ParseTuple(args, "|OOOOf", &obj1, &obj2, &obj3, &obj4, f) ) + return -1; + + if( !obj1 ){ + self->sv_it = new ViewEdgeInternal::SVertexIterator(); + + } else if( BPy_SVertexIterator_Check(obj1) ) { + self->sv_it = new ViewEdgeInternal::SVertexIterator(*( ((BPy_SVertexIterator *) obj1)->sv_it )); + + } else if( obj1 && BPy_SVertex_Check(obj1) && + obj2 && BPy_SVertex_Check(obj2) && + obj3 && BPy_FEdge_Check(obj3) && + obj4 && BPy_FEdge_Check(obj4) ) { + + self->sv_it = new ViewEdgeInternal::SVertexIterator( + ((BPy_SVertex *) obj1)->sv, + ((BPy_SVertex *) obj2)->sv, + ((BPy_FEdge *) obj3)->fe, + ((BPy_FEdge *) obj4)->fe, + f ); + + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument(s)"); + return -1; + } + + self->py_it.it = self->sv_it; + + return 0; +} + +static char SVertexIterator_t___doc__[] = +".. method:: t()\n" +"\n" +" Returns the curvilinear abscissa.\n" +"\n" +" :return: The curvilinear abscissa.\n" +" :rtype: float\n"; + +static PyObject * SVertexIterator_t( BPy_SVertexIterator *self ) { + return PyFloat_FromDouble( self->sv_it->t() ); +} + +static char SVertexIterator_u___doc__[] = +".. method:: u()\n" +"\n" +" Returns the point parameter (0<=u<=1).\n" +"\n" +" :return: The point parameter.\n" +" :rtype: float\n"; + +static PyObject * SVertexIterator_u( BPy_SVertexIterator *self ) { + return PyFloat_FromDouble( self->sv_it->u() ); +} + +static char SVertexIterator_getObject___doc__[] = +".. method:: getObject()\n" +"\n" +" Returns the pointed SVertex.\n" +"\n" +" :return: the pointed SVertex.\n" +" :rtype: :class:`SVertex`\n"; + +static PyObject * SVertexIterator_getObject( BPy_SVertexIterator *self) { + SVertex *sv = self->sv_it->operator->(); + + if( sv ) + return BPy_SVertex_from_SVertex( *sv ); + + Py_RETURN_NONE; +} + +/*----------------------SVertexIterator instance definitions ----------------------------*/ +static PyMethodDef BPy_SVertexIterator_methods[] = { + {"t", ( PyCFunction ) SVertexIterator_t, METH_NOARGS, SVertexIterator_t___doc__}, + {"u", ( PyCFunction ) SVertexIterator_u, METH_NOARGS, SVertexIterator_u___doc__}, + {"getObject", ( PyCFunction ) SVertexIterator_getObject, METH_NOARGS, SVertexIterator_getObject___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_SVertexIterator type definition ------------------------------*/ + +PyTypeObject SVertexIterator_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "SVertexIterator", /* tp_name */ + sizeof(BPy_SVertexIterator), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + SVertexIterator___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_SVertexIterator_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &Iterator_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)SVertexIterator___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.h new file mode 100644 index 00000000000..b40f4d36420 --- /dev/null +++ b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.h @@ -0,0 +1,33 @@ +#ifndef FREESTYLE_PYTHON_SVERTEXITERATOR_H +#define FREESTYLE_PYTHON_SVERTEXITERATOR_H + +#include "../../view_map/ViewMapIterators.h" + +#include "../BPy_Iterator.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject SVertexIterator_Type; + +#define BPy_SVertexIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SVertexIterator_Type) ) + +/*---------------------------Python BPy_SVertexIterator structure definition----------*/ +typedef struct { + BPy_Iterator py_it; + ViewEdgeInternal::SVertexIterator *sv_it; +} BPy_SVertexIterator; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_SVERTEXITERATOR_H */ diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp new file mode 100644 index 00000000000..1273cc2a471 --- /dev/null +++ b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp @@ -0,0 +1,196 @@ +#include "BPy_StrokeVertexIterator.h" + +#include "../BPy_Convert.h" +#include "BPy_Interface0DIterator.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char StrokeVertexIterator___doc__[] = + +"Class defining an iterator designed to iterate over the\n" +":class:`StrokeVertex` of a :class:`Stroke`. An instance of a\n" +"StrokeVertexIterator can only be obtained from a Stroke by calling\n" +"strokeVerticesBegin() or strokeVerticesEnd(). It is iterating over\n" +"the same vertices as an :class:`Interface0DIterator`. The difference\n" +"resides in the object access. Indeed, an Interface0DIterator allows\n" +"only an access to an Interface0D whereas we could need to access the\n" +"specialized StrokeVertex type. In this case, one should use a\n" +"StrokeVertexIterator. The castToInterface0DIterator() method is\n" +"useful to get an Interface0DIterator from a StrokeVertexIterator in\n" +"order to call any functions of the UnaryFunction0D type.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(it)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg it: A StrokeVertexIterator object.\n" +" :type it: :class:`StrokeVertexIterator`\n"; + +static int StrokeVertexIterator___init__(BPy_StrokeVertexIterator *self, PyObject *args ) +{ + PyObject *obj = 0; + + if (! PyArg_ParseTuple(args, "|O", &obj) ) + return -1; + + if( !obj ){ + self->sv_it = new StrokeInternal::StrokeVertexIterator(); + + } else if( BPy_StrokeVertexIterator_Check(obj) ) { + self->sv_it = new StrokeInternal::StrokeVertexIterator(*( ((BPy_StrokeVertexIterator *) obj)->sv_it )); + + } else { + PyErr_SetString(PyExc_TypeError, "invalid argument"); + return -1; + } + + self->py_it.it = self->sv_it; + self->reversed = 0; + + return 0; +} + +static PyObject * StrokeVertexIterator_iternext( BPy_StrokeVertexIterator *self ) { + StrokeVertex *sv; + if (self->reversed) { + if (self->sv_it->isBegin()) { + PyErr_SetNone(PyExc_StopIteration); + return NULL; + } + self->sv_it->decrement(); + sv = self->sv_it->operator->(); + } else { + if (self->sv_it->isEnd()) { + PyErr_SetNone(PyExc_StopIteration); + return NULL; + } + sv = self->sv_it->operator->(); + self->sv_it->increment(); + } + return BPy_StrokeVertex_from_StrokeVertex( *sv ); +} + +static char StrokeVertexIterator_t___doc__[] = +".. method:: t()\n" +"\n" +" Returns the curvilinear abscissa of the current point.\n" +"\n" +" :return: The curvilinear abscissa of the current point.\n" +" :rtype: float\n"; + +static PyObject * StrokeVertexIterator_t( BPy_StrokeVertexIterator *self ) { + return PyFloat_FromDouble( self->sv_it->t() ); +} + +static char StrokeVertexIterator_u___doc__[] = +".. method:: u()\n" +"\n" +" Returns the point parameter in the stroke (0<=u<=1).\n" +"\n" +" :return: The point parameter in the stroke\n" +" :rtype: float\n"; + +static PyObject * StrokeVertexIterator_u( BPy_StrokeVertexIterator *self ) { + return PyFloat_FromDouble( self->sv_it->u() ); +} + +static char StrokeVertexIterator_castToInterface0DIterator___doc__[] = +".. method:: castToInterface0DIterator()\n" +"\n" +" Returns an Interface0DIterator converted from this\n" +" StrokeVertexIterator. Useful for any call to a function of the\n" +" UnaryFunction0D type.\n" +"\n" +" :return: An Interface0DIterator converted from the StrokeVertexIterator.\n" +" :rtype: :class:`Interface0DIterator`\n"; + +static PyObject * StrokeVertexIterator_castToInterface0DIterator( BPy_StrokeVertexIterator *self ) { + Interface0DIterator it( self->sv_it->castToInterface0DIterator() ); + return BPy_Interface0DIterator_from_Interface0DIterator( it, 0 ); +} + +static char StrokeVertexIterator_getObject___doc__[] = +".. method:: getObject()\n" +"\n" +" Returns the pointed StrokeVertex.\n" +"\n" +" :return: The pointed StrokeVertex.\n" +" :rtype: :class:`StrokeVertex`\n"; + +static PyObject * StrokeVertexIterator_getObject( BPy_StrokeVertexIterator *self) { + if (!self->reversed && self->sv_it->isEnd()) + Py_RETURN_NONE; + StrokeVertex *sv = self->sv_it->operator->(); + if( sv ) + return BPy_StrokeVertex_from_StrokeVertex( *sv ); + + Py_RETURN_NONE; +} + +/*----------------------StrokeVertexIterator instance definitions ----------------------------*/ +static PyMethodDef BPy_StrokeVertexIterator_methods[] = { + {"t", ( PyCFunction ) StrokeVertexIterator_t, METH_NOARGS, StrokeVertexIterator_t___doc__}, + {"u", ( PyCFunction ) StrokeVertexIterator_u, METH_NOARGS, StrokeVertexIterator_u___doc__}, + {"castToInterface0DIterator", ( PyCFunction ) StrokeVertexIterator_castToInterface0DIterator, METH_NOARGS, StrokeVertexIterator_castToInterface0DIterator___doc__}, + {"getObject", ( PyCFunction ) StrokeVertexIterator_getObject, METH_NOARGS, StrokeVertexIterator_getObject___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_StrokeVertexIterator type definition ------------------------------*/ + +PyTypeObject StrokeVertexIterator_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "StrokeVertexIterator", /* tp_name */ + sizeof(BPy_StrokeVertexIterator), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + StrokeVertexIterator___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)StrokeVertexIterator_iternext, /* tp_iternext */ + BPy_StrokeVertexIterator_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &Iterator_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)StrokeVertexIterator___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.h new file mode 100644 index 00000000000..0c4b6e4bb6c --- /dev/null +++ b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.h @@ -0,0 +1,33 @@ +#ifndef FREESTYLE_PYTHON_STROKEVERTEXITERATOR_H +#define FREESTYLE_PYTHON_STROKEVERTEXITERATOR_H + +#include "../../stroke/StrokeIterators.h" + +#include "../BPy_Iterator.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject StrokeVertexIterator_Type; + +#define BPy_StrokeVertexIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &StrokeVertexIterator_Type) ) + +/*---------------------------Python BPy_StrokeVertexIterator structure definition----------*/ +typedef struct { + BPy_Iterator py_it; + StrokeInternal::StrokeVertexIterator *sv_it; + int reversed; +} BPy_StrokeVertexIterator; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_STROKEVERTEXITERATOR_H */ diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp new file mode 100644 index 00000000000..55402165226 --- /dev/null +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp @@ -0,0 +1,264 @@ +#include "BPy_ViewEdgeIterator.h" + +#include "../BPy_Convert.h" +#include "../Interface1D/BPy_ViewEdge.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ViewEdgeIterator___doc__[] = +"Base class for iterators over ViewEdges of the :class:`ViewMap` Graph.\n" +"Basically the increment() operator of this class should be able to\n" +"take the decision of \"where\" (on which ViewEdge) to go when pointing\n" +"on a given ViewEdge.\n" +"\n" +".. method:: __init__(begin=None, orientation=True)\n" +"\n" +" Builds a ViewEdgeIterator from a starting ViewEdge and its\n" +" orientation.\n" +"\n" +" :arg begin: The ViewEdge from where to start the iteration.\n" +" :type begin: :class:`ViewEdge` or None\n" +" :arg orientation: If true, we'll look for the next ViewEdge among\n" +" the ViewEdges that surround the ending ViewVertex of begin. If\n" +" false, we'll search over the ViewEdges surrounding the ending\n" +" ViewVertex of begin.\n" +" :type orientation: bool\n" +"\n" +".. method:: __init__(it)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg it: A ViewEdgeIterator object.\n" +" :type it: :class:`ViewEdgeIterator`\n"; + +static int ViewEdgeIterator___init__(BPy_ViewEdgeIterator *self, PyObject *args ) +{ + PyObject *obj1 = 0, *obj2 = 0; + + if (!( PyArg_ParseTuple(args, "O|O", &obj1, &obj2) )) + return -1; + + if( obj1 && BPy_ViewEdgeIterator_Check(obj1) ) { + self->ve_it = new ViewEdgeInternal::ViewEdgeIterator(*( ((BPy_ViewEdgeIterator *) obj1)->ve_it )); + + } else { + ViewEdge *begin; + if ( !obj1 || obj1 == Py_None ) + begin = NULL; + else if ( BPy_ViewEdge_Check(obj1) ) + begin = ((BPy_ViewEdge *) obj1)->ve; + else { + PyErr_SetString(PyExc_TypeError, "1st argument must be either a ViewEdge object or None"); + return -1; + } + bool orientation = ( obj2 ) ? bool_from_PyBool(obj2) : true; + + self->ve_it = new ViewEdgeInternal::ViewEdgeIterator( begin, orientation); + + } + + self->py_it.it = self->ve_it; + + return 0; +} + +static char ViewEdgeIterator_getCurrentEdge___doc__[] = +".. method:: getCurrentEdge()\n" +"\n" +" Returns the current pointed ViewEdge.\n" +"\n" +" :return: The current pointed ViewEdge.\n" +" :rtype: :class:`ViewEdge`\n"; + +static PyObject *ViewEdgeIterator_getCurrentEdge( BPy_ViewEdgeIterator *self ) { + ViewEdge *ve = self->ve_it->getCurrentEdge(); + if( ve ) + return BPy_ViewEdge_from_ViewEdge( *ve ); + + Py_RETURN_NONE; +} + +static char ViewEdgeIterator_setCurrentEdge___doc__[] = +".. method:: setCurrentEdge(edge)\n" +"\n" +" Sets the current pointed ViewEdge.\n" +"\n" +" :arg edge: The current pointed ViewEdge.\n" +" :type edge: :class:`ViewEdge`\n"; + +static PyObject *ViewEdgeIterator_setCurrentEdge( BPy_ViewEdgeIterator *self, PyObject *args ) { + PyObject *py_ve; + + if(!( PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve) )) + return NULL; + + self->ve_it->setCurrentEdge( ((BPy_ViewEdge *) py_ve)->ve ); + + Py_RETURN_NONE; +} + +static char ViewEdgeIterator_getBegin___doc__[] = +".. method:: getBegin()\n" +"\n" +" Returns the first ViewEdge used for the iteration.\n" +"\n" +" :return: The first ViewEdge used for the iteration.\n" +" :rtype: :class:`ViewEdge`\n"; + +static PyObject *ViewEdgeIterator_getBegin( BPy_ViewEdgeIterator *self ) { + ViewEdge *ve = self->ve_it->getBegin(); + if( ve ) + return BPy_ViewEdge_from_ViewEdge( *ve ); + + Py_RETURN_NONE; +} + +static char ViewEdgeIterator_setBegin___doc__[] = +".. method:: setBegin(begin)\n" +"\n" +" Sets the first ViewEdge used for the iteration.\n" +"\n" +" :arg begin: The first ViewEdge used for the iteration.\n" +" :type begin: :class:`ViewEdge`\n"; + +static PyObject *ViewEdgeIterator_setBegin( BPy_ViewEdgeIterator *self, PyObject *args ) { + PyObject *py_ve; + + if(!( PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve) )) + return NULL; + + self->ve_it->setBegin( ((BPy_ViewEdge *) py_ve)->ve ); + + Py_RETURN_NONE; +} + +static char ViewEdgeIterator_getOrientation___doc__[] = +".. method:: getOrientation()\n" +"\n" +" Returns the orientation of the pointed ViewEdge in the iteration.\n" +"\n" +" :return: The orientation of the pointed ViewEdge in the iteration.\n" +" :rtype: bool\n"; + +static PyObject *ViewEdgeIterator_getOrientation( BPy_ViewEdgeIterator *self ) { + return PyBool_from_bool( self->ve_it->getOrientation() ); +} + +static char ViewEdgeIterator_setOrientation___doc__[] = +".. method:: setOrientation(orientation)\n" +"\n" +" Sets the orientation of the pointed ViewEdge in the iteration.\n" +"\n" +" :arg orientation: If true, we'll look for the next ViewEdge among\n" +" the ViewEdges that surround the ending ViewVertex of begin. If\n" +" false, we'll search over the ViewEdges surrounding the ending\n" +" ViewVertex of begin.\n" +" :type orientation: bool\n"; + +static PyObject *ViewEdgeIterator_setOrientation( BPy_ViewEdgeIterator *self, PyObject *args ) { + PyObject *py_b; + + if(!( PyArg_ParseTuple(args, "O", &py_b) )) + return NULL; + + self->ve_it->setOrientation( bool_from_PyBool(py_b) ); + + Py_RETURN_NONE; +} + +static char ViewEdgeIterator_changeOrientation___doc__[] = +".. method:: changeOrientation()\n" +"\n" +" Changes the current orientation.\n"; + +static PyObject *ViewEdgeIterator_changeOrientation( BPy_ViewEdgeIterator *self ) { + self->ve_it->changeOrientation(); + + Py_RETURN_NONE; +} + +static char ViewEdgeIterator_getObject___doc__[] = +".. method:: getObject()\n" +"\n" +" Returns the pointed ViewEdge.\n" +"\n" +" :return: The pointed ViewEdge.\n" +" :rtype: :class:`ViewEdge`\n"; + +static PyObject * ViewEdgeIterator_getObject( BPy_ViewEdgeIterator *self) { + + ViewEdge *ve = self->ve_it->operator*(); + if( ve ) + return BPy_ViewEdge_from_ViewEdge( *ve ); + + Py_RETURN_NONE; +} + +/*----------------------ViewEdgeIterator instance definitions ----------------------------*/ +static PyMethodDef BPy_ViewEdgeIterator_methods[] = { + {"getCurrentEdge", ( PyCFunction ) ViewEdgeIterator_getCurrentEdge, METH_NOARGS, ViewEdgeIterator_getCurrentEdge___doc__}, + {"setCurrentEdge", ( PyCFunction ) ViewEdgeIterator_setCurrentEdge, METH_VARARGS, ViewEdgeIterator_setCurrentEdge___doc__}, + {"getBegin", ( PyCFunction ) ViewEdgeIterator_getBegin, METH_NOARGS, ViewEdgeIterator_getBegin___doc__}, + {"setBegin", ( PyCFunction ) ViewEdgeIterator_setBegin, METH_VARARGS, ViewEdgeIterator_setBegin___doc__}, + {"getOrientation", ( PyCFunction ) ViewEdgeIterator_getOrientation, METH_NOARGS, ViewEdgeIterator_getOrientation___doc__}, + {"setOrientation", ( PyCFunction ) ViewEdgeIterator_setOrientation, METH_VARARGS, ViewEdgeIterator_setOrientation___doc__}, + {"changeOrientation", ( PyCFunction ) ViewEdgeIterator_changeOrientation, METH_NOARGS, ViewEdgeIterator_changeOrientation___doc__}, + {"getObject", ( PyCFunction ) ViewEdgeIterator_getObject, METH_NOARGS, ViewEdgeIterator_getObject___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_ViewEdgeIterator type definition ------------------------------*/ + +PyTypeObject ViewEdgeIterator_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ViewEdgeIterator", /* tp_name */ + sizeof(BPy_ViewEdgeIterator), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ViewEdgeIterator___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_ViewEdgeIterator_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &Iterator_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ViewEdgeIterator___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.h new file mode 100644 index 00000000000..dce90efc8cf --- /dev/null +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.h @@ -0,0 +1,33 @@ +#ifndef FREESTYLE_PYTHON_VIEWEDGEITERATOR_H +#define FREESTYLE_PYTHON_VIEWEDGEITERATOR_H + + +#include "../../view_map/ViewMapIterators.h" + +#include "../BPy_Iterator.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ViewEdgeIterator_Type; + +#define BPy_ViewEdgeIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ViewEdgeIterator_Type) ) + +/*---------------------------Python BPy_ViewEdgeIterator structure definition----------*/ +typedef struct { + BPy_Iterator py_it; + ViewEdgeInternal::ViewEdgeIterator *ve_it; +} BPy_ViewEdgeIterator; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_VIEWEDGEITERATOR_H */ diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp new file mode 100644 index 00000000000..c080426daa8 --- /dev/null +++ b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp @@ -0,0 +1,138 @@ +#include "BPy_orientedViewEdgeIterator.h" + +#include "../BPy_Convert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char orientedViewEdgeIterator___doc__[] = +"Class representing an iterator over oriented ViewEdges around a\n" +":class:`ViewVertex`. This iterator allows a CCW iteration (in the image\n" +"plane). An instance of an orientedViewEdgeIterator can only be\n" +"obtained from a ViewVertex by calling edgesBegin() or edgesEnd().\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(iBrother)\n" +"\n" +" Copy constructor.\n" +"\n" +" :arg iBrother: An orientedViewEdgeIterator object.\n" +" :type iBrother: :class:`orientedViewEdgeIterator`\n"; + +static int orientedViewEdgeIterator___init__(BPy_orientedViewEdgeIterator *self, PyObject *args ) +{ + PyObject *obj = 0; + + if (!( PyArg_ParseTuple(args, "|O", &obj) )) + return -1; + + if( !obj ) + self->ove_it = new ViewVertexInternal::orientedViewEdgeIterator(); + else if( BPy_orientedViewEdgeIterator_Check(obj) ) + self->ove_it = new ViewVertexInternal::orientedViewEdgeIterator(*( ((BPy_orientedViewEdgeIterator *) obj)->ove_it )); + else { + PyErr_SetString(PyExc_TypeError, "invalid argument"); + return -1; + } + + self->py_it.it = self->ove_it; + self->reversed = 0; + + return 0; +} + +static PyObject * orientedViewEdgeIterator_iternext( BPy_orientedViewEdgeIterator *self ) { + ViewVertex::directedViewEdge *dve; + if (self->reversed) { + if (self->ove_it->isBegin()) { + PyErr_SetNone(PyExc_StopIteration); + return NULL; + } + self->ove_it->decrement(); + dve = self->ove_it->operator->(); + } else { + if (self->ove_it->isEnd()) { + PyErr_SetNone(PyExc_StopIteration); + return NULL; + } + dve = self->ove_it->operator->(); + self->ove_it->increment(); + } + return BPy_directedViewEdge_from_directedViewEdge( *dve ); +} + +static char orientedViewEdgeIterator_getObject___doc__[] = +".. method:: getObject()\n" +"\n" +" Returns the pointed oriented ViewEdge.\n" +"\n" +" :return: A tuple of the pointed ViewEdge and a boolean value. If\n" +" the boolean value is true, the ViewEdge is incoming.\n" +" :rtype: (:class:`directedViewEdge`, bool)\n"; + +static PyObject * orientedViewEdgeIterator_getObject( BPy_orientedViewEdgeIterator *self) { + return BPy_directedViewEdge_from_directedViewEdge( self->ove_it->operator*() ); +} + +/*----------------------orientedViewEdgeIterator instance definitions ----------------------------*/ +static PyMethodDef BPy_orientedViewEdgeIterator_methods[] = { + {"getObject", ( PyCFunction ) orientedViewEdgeIterator_getObject, METH_NOARGS, orientedViewEdgeIterator_getObject___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_orientedViewEdgeIterator type definition ------------------------------*/ + +PyTypeObject orientedViewEdgeIterator_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "orientedViewEdgeIterator", /* tp_name */ + sizeof(BPy_orientedViewEdgeIterator), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + orientedViewEdgeIterator___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)orientedViewEdgeIterator_iternext, /* tp_iternext */ + BPy_orientedViewEdgeIterator_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &Iterator_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)orientedViewEdgeIterator___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.h new file mode 100644 index 00000000000..cd9edf1e224 --- /dev/null +++ b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.h @@ -0,0 +1,34 @@ +#ifndef FREESTYLE_PYTHON_ORIENTEDVIEWEDGEITERATOR_H +#define FREESTYLE_PYTHON_ORIENTEDVIEWEDGEITERATOR_H + +#include "../../stroke/Stroke.h" +#include "../../view_map/ViewMapIterators.h" + +#include "../BPy_Iterator.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject orientedViewEdgeIterator_Type; + +#define BPy_orientedViewEdgeIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &orientedViewEdgeIterator_Type) ) + +/*---------------------------Python BPy_orientedViewEdgeIterator structure definition----------*/ +typedef struct { + BPy_Iterator py_it; + ViewVertexInternal::orientedViewEdgeIterator *ove_it; + int reversed; +} BPy_orientedViewEdgeIterator; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_ORIENTEDVIEWEDGEITERATOR_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp new file mode 100644 index 00000000000..7ead138defb --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp @@ -0,0 +1,89 @@ +#include "BPy_BackboneStretcherShader.h" + +#include "../../stroke/BasicStrokeShaders.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char BackboneStretcherShader___doc__[] = +"[Geometry shader]\n" +"\n" +".. method:: __init__(iAmount=2.0)\n" +"\n" +" Builds a BackboneStretcherShader object.\n" +"\n" +" :arg iAmount: The stretching amount value.\n" +" :type iAmount: float\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Stretches the stroke at its two extremities and following the\n" +" respective directions: v(1)v(0) and v(n-1)v(n).\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int BackboneStretcherShader___init__( BPy_BackboneStretcherShader* self, PyObject *args) +{ + float f = 2.0; + + if(!( PyArg_ParseTuple(args, "|f", &f) )) + return -1; + + self->py_ss.ss = new StrokeShaders::BackboneStretcherShader(f); + return 0; +} + +/*-----------------------BPy_BackboneStretcherShader type definition ------------------------------*/ + +PyTypeObject BackboneStretcherShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "BackboneStretcherShader", /* tp_name */ + sizeof(BPy_BackboneStretcherShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + BackboneStretcherShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)BackboneStretcherShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.h new file mode 100644 index 00000000000..35a74c0bda2 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_BACKBONESTRETCHERSHADER_H +#define FREESTYLE_PYTHON_BACKBONESTRETCHERSHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject BackboneStretcherShader_Type; + +#define BPy_BackboneStretcherShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &BackboneStretcherShader_Type) ) + +/*---------------------------Python BPy_BackboneStretcherShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_BackboneStretcherShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_BACKBONESTRETCHERSHADER_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp new file mode 100644 index 00000000000..1ead40f4f6d --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp @@ -0,0 +1,91 @@ +#include "BPy_BezierCurveShader.h" + +#include "../../stroke/BasicStrokeShaders.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char BezierCurveShader___doc__[] = +"[Geometry shader]\n" +"\n" +".. method:: __init__(error=4.0)\n" +"\n" +" Builds a BezierCurveShader object.\n" +"\n" +" :arg error: The error we're allowing for the approximation. This\n" +" error is the max distance allowed between the new curve and the\n" +" original geometry.\n" +" :type error: float\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Transforms the stroke backbone geometry so that it corresponds to a\n" +" Bezier Curve approximation of the original backbone geometry.\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int BezierCurveShader___init__( BPy_BezierCurveShader* self, PyObject *args) +{ + float f = 4.0; + + if(!( PyArg_ParseTuple(args, "|f", &f) )) + return -1; + + self->py_ss.ss = new StrokeShaders::BezierCurveShader(f); + return 0; +} + +/*-----------------------BPy_BezierCurveShader type definition ------------------------------*/ + +PyTypeObject BezierCurveShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "BezierCurveShader", /* tp_name */ + sizeof(BPy_BezierCurveShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + BezierCurveShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)BezierCurveShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.h new file mode 100644 index 00000000000..b94ef88acea --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_BEZIERCURVESHADER_H +#define FREESTYLE_PYTHON_BEZIERCURVESHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject BezierCurveShader_Type; + +#define BPy_BezierCurveShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &BezierCurveShader_Type) ) + +/*---------------------------Python BPy_BezierCurveShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_BezierCurveShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_BEZIERCURVESHADER_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp new file mode 100644 index 00000000000..acb2569f83c --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp @@ -0,0 +1,111 @@ +#include "BPy_CalligraphicShader.h" + +#include "../../stroke/AdvancedStrokeShaders.h" +#include "../BPy_Convert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char CalligraphicShader___doc__[] = +"[Thickness Shader]\n" +"\n" +".. method:: __init__(iMinThickness, iMaxThickness, iOrientation, iClamp)\n" +"\n" +" Builds a CalligraphicShader object.\n" +"\n" +" :arg iMinThickness: The minimum thickness in the direction\n" +" perpandicular to the main direction.\n" +" :type iMinThickness: float\n" +" :arg iMaxThickness: The maximum thickness in the main direction.\n" +" :type iMaxThickness: float\n" +" :arg iOrientation: The 2D vector giving the main direction.\n" +" :type iOrientation: :class:`mathutils.Vector`\n" +" :arg iClamp: If true, the strokes are drawn in black when the stroke\n" +" direction is between -90 and 90 degrees with respect to the main\n" +" direction and drawn in white otherwise. If false, the strokes\n" +" are always drawn in black.\n" +" :type iClamp: bool\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Assigns thicknesses to the stroke vertices so that the stroke looks\n" +" like made with a calligraphic tool, i.e. the stroke will be the\n" +" thickest in a main direction, and the thinest in the direction\n" +" perpendicular to this one, and an interpolation inbetween.\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int CalligraphicShader___init__( BPy_CalligraphicShader* self, PyObject *args) +{ + double d1, d2; + PyObject *obj3 = 0, *obj4 = 0; + + + if(!( PyArg_ParseTuple(args, "ddOO", &d1, &d2, &obj3, &obj4) )) + return -1; + Vec2f *v = Vec2f_ptr_from_PyObject(obj3); + if( !v ) { + PyErr_SetString(PyExc_TypeError, "argument 3 must be a 2D vector (either a list of 2 elements or Vector)"); + return -1; + } + self->py_ss.ss = new CalligraphicShader(d1, d2, *v, bool_from_PyBool(obj4) ); + delete v; + + return 0; + +} + +/*-----------------------BPy_CalligraphicShader type definition ------------------------------*/ + +PyTypeObject CalligraphicShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "CalligraphicShader", /* tp_name */ + sizeof(BPy_CalligraphicShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + CalligraphicShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)CalligraphicShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.h new file mode 100644 index 00000000000..c573b0184ad --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_CALLIGRAPHICSHADER_H +#define FREESTYLE_PYTHON_CALLIGRAPHICSHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject CalligraphicShader_Type; + +#define BPy_CalligraphicShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &CalligraphicShader_Type) + +/*---------------------------Python BPy_CalligraphicShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_CalligraphicShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_CALLIGRAPHICSHADER_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp new file mode 100644 index 00000000000..5293e449cf2 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp @@ -0,0 +1,90 @@ +#include "BPy_ColorNoiseShader.h" + +#include "../../stroke/BasicStrokeShaders.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ColorNoiseShader___doc__[] = +"[Color shader]\n" +"\n" +".. method:: __init__(iAmplitude, iPeriod)\n" +"\n" +" Builds a ColorNoiseShader object.\n" +"\n" +" :arg iAmplitude: The amplitude of the noise signal.\n" +" :type iAmplitude: float\n" +" :arg iPeriod: The period of the noise signal.\n" +" :type iPeriod: float\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Shader to add noise to the stroke colors.\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int ColorNoiseShader___init__( BPy_ColorNoiseShader* self, PyObject *args) +{ + float f1, f2; + + if(!( PyArg_ParseTuple(args, "ff", &f1, &f2) )) + return -1; + + self->py_ss.ss = new StrokeShaders::ColorNoiseShader(f1, f2); + return 0; +} + +/*-----------------------BPy_ColorNoiseShader type definition ------------------------------*/ + +PyTypeObject ColorNoiseShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ColorNoiseShader", /* tp_name */ + sizeof(BPy_ColorNoiseShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ColorNoiseShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ColorNoiseShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.h new file mode 100644 index 00000000000..694b847565e --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_COLORNOISESHADER_H +#define FREESTYLE_PYTHON_COLORNOISESHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ColorNoiseShader_Type; + +#define BPy_ColorNoiseShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ColorNoiseShader_Type) ) + +/*---------------------------Python BPy_ColorNoiseShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_ColorNoiseShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_COLORNOISESHADER_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp new file mode 100644 index 00000000000..9c0817fa1a2 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp @@ -0,0 +1,96 @@ +#include "BPy_ColorVariationPatternShader.h" + +#include "../../stroke/BasicStrokeShaders.h" +#include "../BPy_Convert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ColorVariationPatternShader___doc__[] = +"[Color shader]\n" +"\n" +".. method:: __init__(pattern_name, stretch=True)\n" +"\n" +" Builds a ColorVariationPatternShader object.\n" +"\n" +" :arg pattern_name: The file name of the texture file to use as\n" +" pattern.\n" +" :type pattern_name: str\n" +" :arg stretch: Tells whether the texture must be strecthed or\n" +" repeted to fit the stroke.\n" +" :type stretch: bool\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Applies a pattern to vary the original color. The new color is the\n" +" result of the multiplication of the pattern and the original color.\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int ColorVariationPatternShader___init__( BPy_ColorVariationPatternShader* self, PyObject *args) +{ + const char *s; + PyObject *obj = 0; + + if(!( PyArg_ParseTuple(args, "s|O", &s, &obj) )) + return -1; + + bool b = (obj) ? bool_from_PyBool(obj) : true; + self->py_ss.ss = new StrokeShaders::ColorVariationPatternShader(s,b); + return 0; +} + +/*-----------------------BPy_ColorVariationPatternShader type definition ------------------------------*/ + +PyTypeObject ColorVariationPatternShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ColorVariationPatternShader", /* tp_name */ + sizeof(BPy_ColorVariationPatternShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ColorVariationPatternShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ColorVariationPatternShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.h new file mode 100644 index 00000000000..b1898ebfecf --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_COLORVARIATIONPATTERNSHADER_H +#define FREESTYLE_PYTHON_COLORVARIATIONPATTERNSHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ColorVariationPatternShader_Type; + +#define BPy_ColorVariationPatternShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ColorVariationPatternShader_Type) ) + +/*---------------------------Python BPy_ColorVariationPatternShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_ColorVariationPatternShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_COLORVARIATIONPATTERNSHADER_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp new file mode 100644 index 00000000000..2b21acabc42 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp @@ -0,0 +1,94 @@ +#include "BPy_ConstantColorShader.h" + +#include "../../stroke/BasicStrokeShaders.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ConstantColorShader___doc__[] = +"[Color shader]\n" +"\n" +".. method:: __init__(iR, iG, iB, iAlpha=1.0)\n" +"\n" +" Builds a ConstantColorShader object.\n" +"\n" +" :arg iR: The red component.\n" +" :type iR: float\n" +" :arg iG: The green component.\n" +" :type iG: float\n" +" :arg iB: The blue component.\n" +" :type iB: float\n" +" :arg iAlpha: The alpha value.\n" +" :type iAlpha: float\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Assigns a constant color to every vertex of the Stroke.\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int ConstantColorShader___init__( BPy_ConstantColorShader* self, PyObject *args) +{ + float f1, f2, f3, f4 = 1.0; + + if(!( PyArg_ParseTuple(args, "fff|f", &f1, &f2, &f3, &f4) )) + return -1; + + self->py_ss.ss = new StrokeShaders::ConstantColorShader(f1, f2, f3, f4); + return 0; +} + +/*-----------------------BPy_ConstantColorShader type definition ------------------------------*/ + +PyTypeObject ConstantColorShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ConstantColorShader", /* tp_name */ + sizeof(BPy_ConstantColorShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ConstantColorShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ConstantColorShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.h new file mode 100644 index 00000000000..30a09d852fd --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_CONSTANTCOLORSHADER_H +#define FREESTYLE_PYTHON_CONSTANTCOLORSHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ConstantColorShader_Type; + +#define BPy_ConstantColorShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ConstantColorShader_Type) ) + +/*---------------------------Python BPy_ConstantColorShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_ConstantColorShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_CONSTANTCOLORSHADER_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp new file mode 100644 index 00000000000..2db3685122f --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp @@ -0,0 +1,88 @@ +#include "BPy_ConstantThicknessShader.h" + +#include "../../stroke/BasicStrokeShaders.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ConstantThicknessShader___doc__[] = +"[Thickness shader]\n" +"\n" +".. method:: __init__(thickness)\n" +"\n" +" Builds a ConstantThicknessShader object.\n" +"\n" +" :arg thickness: The thickness that must be assigned to the stroke.\n" +" :type thickness: float\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Assigns an absolute constant thickness to every vertex of the Stroke.\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int ConstantThicknessShader___init__( BPy_ConstantThicknessShader* self, PyObject *args) +{ + float f; + + if(!( PyArg_ParseTuple(args, "f", &f) )) + return -1; + + self->py_ss.ss = new StrokeShaders::ConstantThicknessShader(f); + return 0; +} + +/*-----------------------BPy_ConstantThicknessShader type definition ------------------------------*/ + +PyTypeObject ConstantThicknessShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ConstantThicknessShader", /* tp_name */ + sizeof(BPy_ConstantThicknessShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ConstantThicknessShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ConstantThicknessShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.h new file mode 100644 index 00000000000..bb7f3c0f622 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_CONSTANTTHICKNESSSHADER_H +#define FREESTYLE_PYTHON_CONSTANTTHICKNESSSHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ConstantThicknessShader_Type; + +#define BPy_ConstantThicknessShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ConstantThicknessShader_Type) ) + +/*---------------------------Python BPy_ConstantThicknessShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_ConstantThicknessShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_CONSTANTTHICKNESSSHADER_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp new file mode 100644 index 00000000000..6dacca246b3 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp @@ -0,0 +1,94 @@ +#include "BPy_ConstrainedIncreasingThicknessShader.h" + +#include "../../stroke/BasicStrokeShaders.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ConstrainedIncreasingThicknessShader___doc__[] = +"[Thickness shader]\n" +"\n" +".. method:: __init__(iThicknessMin, iThicknessMax, iRatio)\n" +"\n" +" Builds a ConstrainedIncreasingThicknessShader object.\n" +"\n" +" :arg iThicknessMin: The minimum thickness.\n" +" :type iThicknessMin: float\n" +" :arg iThicknessMax: The maximum thickness.\n" +" :type iThicknessMax: float\n" +" :arg iRatio: The thickness/length ratio that we don't want to exceed. \n" +" :type iRatio: float\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Same as the :class:`IncreasingThicknessShader`, but here we allow\n" +" the user to control the thickness/length ratio so that we don't get\n" +" fat short lines.\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int ConstrainedIncreasingThicknessShader___init__( BPy_ConstrainedIncreasingThicknessShader* self, PyObject *args) +{ + float f1, f2, f3; + + if(!( PyArg_ParseTuple(args, "fff", &f1, &f2, &f3) )) + return -1; + + self->py_ss.ss = new StrokeShaders::ConstrainedIncreasingThicknessShader(f1, f2, f3); + return 0; +} + +/*-----------------------BPy_ConstrainedIncreasingThicknessShader type definition ------------------------------*/ + +PyTypeObject ConstrainedIncreasingThicknessShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ConstrainedIncreasingThicknessShader", /* tp_name */ + sizeof(BPy_ConstrainedIncreasingThicknessShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ConstrainedIncreasingThicknessShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ConstrainedIncreasingThicknessShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.h new file mode 100644 index 00000000000..38a8aa2bfe0 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_CONSTRAINEDINCREASINGTHICKNESSSHADER_H +#define FREESTYLE_PYTHON_CONSTRAINEDINCREASINGTHICKNESSSHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ConstrainedIncreasingThicknessShader_Type; + +#define BPy_ConstrainedIncreasingThicknessShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ConstrainedIncreasingThicknessShader_Type) ) + +/*---------------------------Python BPy_ConstrainedIncreasingThicknessShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_ConstrainedIncreasingThicknessShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_CONSTRAINEDINCREASINGTHICKNESSSHADER_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp new file mode 100644 index 00000000000..4be1358147a --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp @@ -0,0 +1,96 @@ +#include "BPy_GuidingLinesShader.h" + +#include "../../stroke/BasicStrokeShaders.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GuidingLinesShader___doc__[] = +"[Geometry shader]\n" +"\n" +".. method:: __init__(iOffset)\n" +"\n" +" Builds a GuidingLinesShader object.\n" +"\n" +" :arg iOffset: The line that replaces the stroke is initially in the\n" +" middle of the initial stroke bounding box. iOffset is the value\n" +" of the displacement which is applied to this line along its\n" +" normal.\n" +" :type iOffset: float\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Shader to modify the Stroke geometry so that it corresponds to its\n" +" main direction line. This shader must be used together with the\n" +" splitting operator using the curvature criterion. Indeed, the\n" +" precision of the approximation will depend on the size of the\n" +" stroke's pieces. The bigger the pieces are, the rougher the\n" +" approximation is.\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int GuidingLinesShader___init__( BPy_GuidingLinesShader* self, PyObject *args) +{ + float f; + + if(!( PyArg_ParseTuple(args, "f", &f) )) + return -1; + + self->py_ss.ss = new StrokeShaders::GuidingLinesShader(f); + return 0; +} + +/*-----------------------BPy_GuidingLinesShader type definition ------------------------------*/ + +PyTypeObject GuidingLinesShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GuidingLinesShader", /* tp_name */ + sizeof(BPy_GuidingLinesShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GuidingLinesShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GuidingLinesShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.h new file mode 100644 index 00000000000..e25704c33ba --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_GUIDINGLINESSHADER_H +#define FREESTYLE_PYTHON_GUIDINGLINESSHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GuidingLinesShader_Type; + +#define BPy_GuidingLinesShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GuidingLinesShader_Type) ) + +/*---------------------------Python BPy_GuidingLinesShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_GuidingLinesShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_GUIDINGLINESSHADER_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp new file mode 100644 index 00000000000..892585bf842 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp @@ -0,0 +1,104 @@ +#include "BPy_IncreasingColorShader.h" + +#include "../../stroke/BasicStrokeShaders.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char IncreasingColorShader___doc__[] = +"[Color shader]\n" +"\n" +".. method:: __init__(iRm, iGm, iBm, iAlpham, iRM, iGM, iBM, iAlphaM)\n" +"\n" +" Builds an IncreasingColorShader object.\n" +"\n" +" :arg iRm: The first color red component.\n" +" :type iRm: float\n" +" :arg iGm: The first color green component.\n" +" :type iGm: float\n" +" :arg iBm: The first color blue component.\n" +" :type iBm: float\n" +" :arg iAlpham: The first color alpha value.\n" +" :type iAlpham: float\n" +" :arg iRM: The second color red component.\n" +" :type iRM: float\n" +" :arg iGM: The second color green component.\n" +" :type iGM: float\n" +" :arg iBM: The second color blue component.\n" +" :type iBM: float\n" +" :arg iAlphaM: The second color alpha value.\n" +" :type iAlphaM: float\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Assigns a varying color to the stroke. The user specifies two\n" +" colors A and B. The stroke color will change linearly from A to B\n" +" between the first and the last vertex.\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int IncreasingColorShader___init__( BPy_IncreasingColorShader* self, PyObject *args) +{ + float f1, f2, f3, f4, f5, f6, f7, f8; + + if(!( PyArg_ParseTuple(args, "ffffffff", &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8) )) + return -1; + + self->py_ss.ss = new StrokeShaders::IncreasingColorShader(f1, f2, f3, f4, f5, f6, f7, f8); + return 0; +} + +/*-----------------------BPy_IncreasingColorShader type definition ------------------------------*/ + +PyTypeObject IncreasingColorShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "IncreasingColorShader", /* tp_name */ + sizeof(BPy_IncreasingColorShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + IncreasingColorShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)IncreasingColorShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.h new file mode 100644 index 00000000000..9bc82e98098 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_INCREASINGCOLORSHADER_H +#define FREESTYLE_PYTHON_INCREASINGCOLORSHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject IncreasingColorShader_Type; + +#define BPy_IncreasingColorShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &IncreasingColorShader_Type) ) + +/*---------------------------Python BPy_IncreasingColorShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_IncreasingColorShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_INCREASINGCOLORSHADER_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp new file mode 100644 index 00000000000..b5d067a4e44 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp @@ -0,0 +1,94 @@ +#include "BPy_IncreasingThicknessShader.h" + +#include "../../stroke/BasicStrokeShaders.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char IncreasingThicknessShader___doc__[] = +"[Thickness shader]\n" +"\n" +".. method:: __init__(iThicknessA, iThicknessB)\n" +"\n" +" Builds an IncreasingThicknessShader object.\n" +"\n" +" :arg iThicknessA: The first thickness value.\n" +" :type iThicknessA: float\n" +" :arg iThicknessB: The second thickness value.\n" +" :type iThicknessB: float\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Assigns thicknesses values such as the thickness increases from a\n" +" thickness value A to a thickness value B between the first vertex\n" +" to the midpoint vertex and then decreases from B to a A between\n" +" this midpoint vertex and the last vertex. The thickness is\n" +" linearly interpolated from A to B.\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int IncreasingThicknessShader___init__( BPy_IncreasingThicknessShader* self, PyObject *args) +{ + float f1, f2; + + if(!( PyArg_ParseTuple(args, "ff", &f1, &f2) )) + return -1; + + self->py_ss.ss = new StrokeShaders::IncreasingThicknessShader(f1, f2); + return 0; +} + +/*-----------------------BPy_IncreasingThicknessShader type definition ------------------------------*/ + +PyTypeObject IncreasingThicknessShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "IncreasingThicknessShader", /* tp_name */ + sizeof(BPy_IncreasingThicknessShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + IncreasingThicknessShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)IncreasingThicknessShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.h new file mode 100644 index 00000000000..33d883b1860 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_INCREASINGTHICKNESSSHADER_H +#define FREESTYLE_PYTHON_INCREASINGTHICKNESSSHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject IncreasingThicknessShader_Type; + +#define BPy_IncreasingThicknessShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &IncreasingThicknessShader_Type) ) + +/*---------------------------Python BPy_IncreasingThicknessShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_IncreasingThicknessShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_INCREASINGTHICKNESSSHADER_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp new file mode 100644 index 00000000000..7c0c758a318 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp @@ -0,0 +1,95 @@ +#include "BPy_PolygonalizationShader.h" + +#include "../../stroke/BasicStrokeShaders.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char PolygonalizationShader___doc__[] = +"[Geometry shader]\n" +"\n" +".. method:: __init__(iError)\n" +"\n" +" Builds a PolygonalizationShader object.\n" +"\n" +" :arg iError: The error we want our polygonal approximation to have\n" +" with respect to the original geometry. The smaller, the closer\n" +" the new stroke is to the orinal one. This error corresponds to\n" +" the maximum distance between the new stroke and the old one.\n" +" :type iError: float\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Modifies the Stroke geometry so that it looks more \"polygonal\".\n" +" The basic idea is to start from the minimal stroke approximation\n" +" consisting in a line joining the first vertex to the last one and\n" +" to subdivide using the original stroke vertices until a certain\n" +" error is reached.\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int PolygonalizationShader___init__( BPy_PolygonalizationShader* self, PyObject *args) +{ + float f; + + if(!( PyArg_ParseTuple(args, "f", &f) )) + return -1; + + self->py_ss.ss = new StrokeShaders::PolygonalizationShader(f); + return 0; +} + +/*-----------------------BPy_PolygonalizationShader type definition ------------------------------*/ + +PyTypeObject PolygonalizationShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "PolygonalizationShader", /* tp_name */ + sizeof(BPy_PolygonalizationShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + PolygonalizationShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)PolygonalizationShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.h new file mode 100644 index 00000000000..85bcc00e869 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_POLYGONALIZATIONSHADER_H +#define FREESTYLE_PYTHON_POLYGONALIZATIONSHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject PolygonalizationShader_Type; + +#define BPy_PolygonalizationShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &PolygonalizationShader_Type) ) + +/*---------------------------Python BPy_PolygonalizationShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_PolygonalizationShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_POLYGONALIZATIONSHADER_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp new file mode 100644 index 00000000000..1dacb1499e9 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp @@ -0,0 +1,88 @@ +#include "BPy_SamplingShader.h" + +#include "../../stroke/BasicStrokeShaders.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char SamplingShader___doc__[] = +"[Geometry shader]\n" +"\n" +".. method:: __init__(sampling)\n" +"\n" +" Builds a SamplingShader object.\n" +"\n" +" :arg sampling: The sampling to use for the stroke resampling.\n" +" :type sampling: float\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Resamples the stroke.\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int SamplingShader___init__( BPy_SamplingShader* self, PyObject *args) +{ + float f; + + if(!( PyArg_ParseTuple(args, "f", &f) )) + return -1; + + self->py_ss.ss = new StrokeShaders::SamplingShader(f); + return 0; +} + +/*-----------------------BPy_SamplingShader type definition ------------------------------*/ + +PyTypeObject SamplingShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "SamplingShader", /* tp_name */ + sizeof(BPy_SamplingShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + SamplingShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)SamplingShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.h new file mode 100644 index 00000000000..dfc6efb3319 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_SAMPLINGSHADER_H +#define FREESTYLE_PYTHON_SAMPLINGSHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject SamplingShader_Type; + +#define BPy_SamplingShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SamplingShader_Type) ) + +/*---------------------------Python BPy_SamplingShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_SamplingShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_SAMPLINGSHADER_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp new file mode 100644 index 00000000000..20be1575bb3 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp @@ -0,0 +1,106 @@ +#include "BPy_SmoothingShader.h" + +#include "../../stroke/AdvancedStrokeShaders.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char SmoothingShader___doc__[] = +"[Geometry shader]\n" +"\n" +".. method:: __init__(iNbIteration, iFactorPoint, ifactorCurvature, iFactorCurvatureDifference, iAnisoPoint, iAnisNormal, iAnisoCurvature, icarricatureFactor)\n" +"\n" +" Builds a SmoothingShader object.\n" +"\n" +" :arg iNbIteration: The number of iterations (400).\n" +" :type iNbIteration: int\n" +" :arg iFactorPoint: 0.0\n" +" :type iFactorPoint: float\n" +" :arg ifactorCurvature: 0.0\n" +" :type ifactorCurvature: float\n" +" :arg iFactorCurvatureDifference: 0.2\n" +" :type iFactorCurvatureDifference: float\n" +" :arg iAnisoPoint: \n" +" :type iAnisoPoint: float\n" +" :arg iAnisNormal: 0.0\n" +" :type iAnisNormal: float\n" +" :arg iAnisoCurvature: 0.0\n" +" :type iAnisoCurvature: float\n" +" :arg icarricatureFactor: 1.0\n" +" :type icarricatureFactor: float\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Smoothes the stroke by moving the vertices to make the stroke\n" +" smoother. Uses curvature flow to converge towards a curve of\n" +" constant curvature. The diffusion method we use is anisotropic to\n" +" prevent the diffusion accross corners.\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int SmoothingShader___init__( BPy_SmoothingShader* self, PyObject *args) +{ + int i1; + double d2, d3, d4, d5, d6, d7, d8; + + if(!( PyArg_ParseTuple(args, "iddddddd", &i1, &d2, &d3, &d4, &d5, &d6, &d7, &d8) )) + return -1; + + self->py_ss.ss = new SmoothingShader(i1, d2, d3, d4, d5, d6, d7, d8); + return 0; +} + +/*-----------------------BPy_SmoothingShader type definition ------------------------------*/ + +PyTypeObject SmoothingShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "SmoothingShader", /* tp_name */ + sizeof(BPy_SmoothingShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + SmoothingShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)SmoothingShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.h new file mode 100644 index 00000000000..18d6ca3cc30 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHONSMOOTHINGSHADER_H +#define FREESTYLE_PYTHONSMOOTHINGSHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject SmoothingShader_Type; + +#define BPy_SmoothingShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SmoothingShader_Type) ) + +/*---------------------------Python BPy_SmoothingShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_SmoothingShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHONSMOOTHINGSHADER_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp new file mode 100644 index 00000000000..7df1d31a16d --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp @@ -0,0 +1,100 @@ +#include "BPy_SpatialNoiseShader.h" + +#include "../../stroke/AdvancedStrokeShaders.h" +#include "../BPy_Convert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char SpatialNoiseShader___doc__[] = +"[Geometry shader]\n" +"\n" +".. method:: __init__(iAmount, ixScale, nbOctave, smooth, pureRandom)\n" +"\n" +" Builds a SpatialNoiseShader object.\n" +"\n" +" :arg iAmount: The amplitude of the noise.\n" +" :type iAmount: float\n" +" :arg ixScale: The noise frequency.\n" +" :type ixScale: float\n" +" :arg nbOctave: The number of octaves\n" +" :type nbOctave: int\n" +" :arg smooth: True if you want the noise to be smooth.\n" +" :type smooth: bool\n" +" :arg pureRandom: True if you don't want any coherence.\n" +" :type pureRandom: bool\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Spatial Noise stroke shader. Moves the vertices to make the stroke\n" +" more noisy.\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int SpatialNoiseShader___init__( BPy_SpatialNoiseShader* self, PyObject *args) +{ + float f1, f2; + int i3; + PyObject *obj4 = 0, *obj5 = 0; + + if(!( PyArg_ParseTuple(args, "ffiOO", &f1, &f2, &i3, &obj4, &obj5) )) + return -1; + + self->py_ss.ss = new SpatialNoiseShader(f1, f2, i3, bool_from_PyBool(obj4), bool_from_PyBool(obj5) ); + return 0; +} + +/*-----------------------BPy_SpatialNoiseShader type definition ------------------------------*/ + +PyTypeObject SpatialNoiseShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "SpatialNoiseShader", /* tp_name */ + sizeof(BPy_SpatialNoiseShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + SpatialNoiseShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)SpatialNoiseShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.h new file mode 100644 index 00000000000..46e1c12385d --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_SPATIALNOISESHADER_H +#define FREESTYLE_PYTHON_SPATIALNOISESHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject SpatialNoiseShader_Type; + +#define BPy_SpatialNoiseShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SpatialNoiseShader_Type) ) + +/*---------------------------Python BPy_SpatialNoiseShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_SpatialNoiseShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_SPATIALNOISESHADER_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp new file mode 100644 index 00000000000..77f82790c23 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp @@ -0,0 +1,115 @@ +#include "BPy_StrokeTextureShader.h" + +#include "../../stroke/BasicStrokeShaders.h" +#include "../BPy_Convert.h" +#include "../BPy_MediumType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char StrokeTextureShader___doc__[] = +"[Texture shader]\n" +"\n" +".. method:: __init__(textureFile, mediumType=MediumType.OPAQUE_MEDIUM, iTips=False)\n" +"\n" +" Builds a StrokeTextureShader object.\n" +"\n" +" :arg textureFile: \n" +" :type textureFile: str\n" +" :arg mediumType: The medium type and therefore, the blending mode\n" +" that must be used for the rendering of this stroke.\n" +" :type mediumType: :class:`MediumType`\n" +" :arg iTips: Tells whether the texture includes tips or not. If it\n" +" is the case, the texture image must respect the following format.\n" +" :type iTips: bool\n" +"\n" +" The format of a texture image including tips::\n" +"\n" +" ___________\n" +" | |\n" +" | A |\n" +" |___________|\n" +" | | |\n" +" | B | C |\n" +" |_____|_____|\n" +"\n" +" * A : The stroke's corpus texture.\n" +" * B : The stroke's left extremity texture.\n" +" * C : The stroke's right extremity texture.\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Assigns a texture and a blending mode to the stroke in order to\n" +" simulate its marks system.\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int StrokeTextureShader___init__( BPy_StrokeTextureShader* self, PyObject *args) +{ + const char *s1; + PyObject *obj2 = 0, *obj3 = 0; + + if(!( PyArg_ParseTuple(args, "s|O!O", &s1, &MediumType_Type, &obj2, &obj3) )) + return -1; + + Stroke::MediumType mt = (obj2) ? MediumType_from_BPy_MediumType(obj2) : Stroke::OPAQUE_MEDIUM; + bool b = (obj3) ? bool_from_PyBool(obj3) : true; + + self->py_ss.ss = new StrokeShaders::StrokeTextureShader(s1,mt,b); + return 0; +} + +/*-----------------------BPy_StrokeTextureShader type definition ------------------------------*/ + +PyTypeObject StrokeTextureShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "StrokeTextureShader", /* tp_name */ + sizeof(BPy_StrokeTextureShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + StrokeTextureShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)StrokeTextureShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.h new file mode 100644 index 00000000000..c65506f2f14 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_STROKETEXTURESHADER_H +#define FREESTYLE_PYTHON_STROKETEXTURESHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject StrokeTextureShader_Type; + +#define BPy_StrokeTextureShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &StrokeTextureShader_Type) ) + +/*---------------------------Python BPy_StrokeTextureShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_StrokeTextureShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_STROKETEXTURESHADER_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp new file mode 100644 index 00000000000..4df76f6646b --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp @@ -0,0 +1,104 @@ +#include "BPy_TextureAssignerShader.h" + +#include "../../stroke/BasicStrokeShaders.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char TextureAssignerShader___doc__[] = +"[Texture shader]\n" +"\n" +".. method:: __init__(id)\n" +"\n" +" Builds a TextureAssignerShader object.\n" +"\n" +" :arg id: The preset number to use.\n" +" :type id: int\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Assigns a texture to the stroke in order to simulate its marks\n" +" system. This shader takes as input an integer value telling which\n" +" texture and blending mode to use among a set of predefined\n" +" textures. Here are the different presets:\n" +"\n" +" * 0: `/brushes/charcoalAlpha.bmp`, `MediumType.HUMID_MEDIUM`\n" +" * 1: `/brushes/washbrushAlpha.bmp`, `MediumType.HUMID_MEDIUM`\n" +" * 2: `/brushes/oil.bmp`, `MediumType.HUMID_MEDIUM`\n" +" * 3: `/brushes/oilnoblend.bmp`, `MediumType.HUMID_MEDIUM`\n" +" * 4: `/brushes/charcoalAlpha.bmp`, `MediumType.DRY_MEDIUM`\n" +" * 5: `/brushes/washbrushAlpha.bmp`, `MediumType.DRY_MEDIUM`\n" +" * 6: `/brushes/opaqueDryBrushAlpha.bmp`, `MediumType.OPAQUE_MEDIUM`\n" +" * 7: `/brushes/opaqueBrushAlpha.bmp`, `MediumType.OPAQUE_MEDIUM`\n" +"\n" +" Any other value will lead to the following preset:\n" +"\n" +" * Default: `/brushes/smoothAlpha.bmp`, `MediumType.OPAQUE_MEDIUM`\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int TextureAssignerShader___init__( BPy_TextureAssignerShader* self, PyObject *args) +{ + int i; + + if(!( PyArg_ParseTuple(args, "i", &i) )) + return -1; + + self->py_ss.ss = new StrokeShaders::TextureAssignerShader(i); + return 0; +} + +/*-----------------------BPy_TextureAssignerShader type definition ------------------------------*/ + +PyTypeObject TextureAssignerShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "TextureAssignerShader", /* tp_name */ + sizeof(BPy_TextureAssignerShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + TextureAssignerShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)TextureAssignerShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.h new file mode 100644 index 00000000000..9cffc1c1662 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_TEXTUREASSIGNERSHADER_H +#define FREESTYLE_PYTHON_TEXTUREASSIGNERSHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject TextureAssignerShader_Type; + +#define BPy_TextureAssignerShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TextureAssignerShader_Type) ) + +/*---------------------------Python BPy_TextureAssignerShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_TextureAssignerShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_TEXTUREASSIGNERSHADER_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp new file mode 100644 index 00000000000..c880f05ed7b --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp @@ -0,0 +1,90 @@ +#include "BPy_ThicknessNoiseShader.h" + +#include "../../stroke/BasicStrokeShaders.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ThicknessNoiseShader___doc__[] = +"[Thickness shader]\n" +"\n" +".. method:: __init__(iAmplitude, iPeriod)\n" +"\n" +" Builds a ThicknessNoiseShader object.\n" +"\n" +" :arg iAmplitude: The amplitude of the noise signal.\n" +" :type iAmplitude: float\n" +" :arg iPeriod: The period of the noise signal.\n" +" :type iPeriod: float\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Adds some noise to the stroke thickness.\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int ThicknessNoiseShader___init__( BPy_ThicknessNoiseShader* self, PyObject *args) +{ + float f1, f2; + + if(!( PyArg_ParseTuple(args, "ff", &f1, &f2) )) + return -1; + + self->py_ss.ss = new StrokeShaders::ThicknessNoiseShader(f1, f2); + return 0; +} + +/*-----------------------BPy_ThicknessNoiseShader type definition ------------------------------*/ + +PyTypeObject ThicknessNoiseShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ThicknessNoiseShader", /* tp_name */ + sizeof(BPy_ThicknessNoiseShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ThicknessNoiseShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ThicknessNoiseShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.h new file mode 100644 index 00000000000..c3ef101683e --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_THICKNESSNOISESHADER_H +#define FREESTYLE_PYTHON_THICKNESSNOISESHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ThicknessNoiseShader_Type; + +#define BPy_ThicknessNoiseShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ThicknessNoiseShader_Type) ) + +/*---------------------------Python BPy_ThicknessNoiseShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_ThicknessNoiseShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_THICKNESSNOISESHADER_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp new file mode 100644 index 00000000000..097de7a432c --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp @@ -0,0 +1,101 @@ +#include "BPy_ThicknessVariationPatternShader.h" + +#include "../../stroke/BasicStrokeShaders.h" +#include "../BPy_Convert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ThicknessVariationPatternShader___doc__[] = +"[Thickness shader]\n" +"\n" +".. method:: __init__(pattern_name, iMinThickness, iMaxThickness, stretch)\n" +"\n" +" Builds a ThicknessVariationPatternShader object.\n" +"\n" +" :arg pattern_name: The texture file name.\n" +" :type pattern_name: str\n" +" :arg iMinThickness: The minimum thickness we don't want to exceed.\n" +" :type iMinThickness: float\n" +" :arg iMaxThickness: The maximum thickness we don't want to exceed.\n" +" :type iMaxThickness: float\n" +" :arg stretch: Tells whether the pattern texture must be stretched\n" +" or repeted to fit the stroke.\n" +" :type stretch: bool\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Applies a pattern (texture) to vary thickness. The new thicknesses\n" +" are the result of the multiplication of the pattern and the\n" +" original thickness.\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int ThicknessVariationPatternShader___init__( BPy_ThicknessVariationPatternShader* self, PyObject *args) +{ + const char *s1; + float f2 = 1.0, f3 = 5.0; + PyObject *obj4 = 0; + + if(!( PyArg_ParseTuple(args, "s|ffO", &s1, &f2, &f3, &obj4) )) + return -1; + + bool b = (obj4) ? bool_from_PyBool(obj4) : true; + self->py_ss.ss = new StrokeShaders::ThicknessVariationPatternShader(s1, f2, f3, b); + return 0; +} + +/*-----------------------BPy_ThicknessVariationPatternShader type definition ------------------------------*/ + +PyTypeObject ThicknessVariationPatternShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ThicknessVariationPatternShader", /* tp_name */ + sizeof(BPy_ThicknessVariationPatternShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ThicknessVariationPatternShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ThicknessVariationPatternShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.h new file mode 100644 index 00000000000..302c9e005ae --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_THICKNESSVARIATIONPATTERNSHADER_H +#define FREESTYLE_PYTHON_THICKNESSVARIATIONPATTERNSHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ThicknessVariationPatternShader_Type; + +#define BPy_ThicknessVariationPatternShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ThicknessVariationPatternShader_Type) ) + +/*---------------------------Python BPy_ThicknessVariationPatternShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_ThicknessVariationPatternShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_THICKNESSVARIATIONPATTERNSHADER_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp new file mode 100644 index 00000000000..ec90499a49b --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp @@ -0,0 +1,89 @@ +#include "BPy_TipRemoverShader.h" + +#include "../../stroke/BasicStrokeShaders.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char TipRemoverShader___doc__[] = +"[Geometry shader]\n" +"\n" +".. method:: __init__(tipLength)\n" +"\n" +" Builds a TipRemoverShader object.\n" +"\n" +" :arg tipLength: The length of the piece of stroke we want to remove\n" +" at each extremity.\n" +" :type tipLength: float\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Removes the stroke's extremities.\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int TipRemoverShader___init__( BPy_TipRemoverShader* self, PyObject *args) +{ + double d; + + if(!( PyArg_ParseTuple(args, "d", &d) )) + return -1; + + self->py_ss.ss = new StrokeShaders::TipRemoverShader(d); + return 0; +} + +/*-----------------------BPy_TipRemoverShader type definition ------------------------------*/ + +PyTypeObject TipRemoverShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "TipRemoverShader", /* tp_name */ + sizeof(BPy_TipRemoverShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + TipRemoverShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)TipRemoverShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.h new file mode 100644 index 00000000000..a1b2e3988bc --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_TIPREMOVERSHADER_H +#define FREESTYLE_PYTHON_TIPREMOVERSHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject TipRemoverShader_Type; + +#define BPy_TipRemoverShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TipRemoverShader_Type) ) + +/*---------------------------Python BPy_TipRemoverShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_TipRemoverShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_TIPREMOVERSHADER_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp new file mode 100644 index 00000000000..806f4e8f9a5 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp @@ -0,0 +1,88 @@ +#include "BPy_fstreamShader.h" + +#include "../../stroke/AdvancedStrokeShaders.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char fstreamShader___doc__[] = +"[Output shader]\n" +"\n" +".. method:: __init__(iFileName)\n" +"\n" +" Builds a fstreamShader object.\n" +"\n" +" :arg iFileName: The output file name.\n" +" :type iFileName: str\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Streams the Stroke in a file.\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int fstreamShader___init__( BPy_fstreamShader* self, PyObject *args) +{ + const char *s; + + if(!( PyArg_ParseTuple(args, "s", &s) )) + return -1; + + self->py_ss.ss = new StrokeShaders::fstreamShader(s); + return 0; +} + +/*-----------------------BPy_fstreamShader type definition ------------------------------*/ + +PyTypeObject fstreamShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "fstreamShader", /* tp_name */ + sizeof(BPy_fstreamShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + fstreamShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)fstreamShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.h new file mode 100644 index 00000000000..843d50505db --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_FSTREAMSHADER_H +#define FREESTYLE_PYTHON_FSTREAMSHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject fstreamShader_Type; + +#define BPy_fstreamShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &fstreamShader_Type) ) + +/*---------------------------Python BPy_fstreamShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_fstreamShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_FSTREAMSHADER_H */ diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp new file mode 100644 index 00000000000..31e0971b875 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp @@ -0,0 +1,82 @@ +#include "BPy_streamShader.h" + +#include "../../stroke/BasicStrokeShaders.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char streamShader___doc__[] = +"[Output shader]\n" +"\n" +".. method:: __init__()\n" +"\n" +" Builds a streamShader object.\n" +"\n" +".. method:: shade(s)\n" +"\n" +" Streams the Stroke into stdout.\n" +"\n" +" :arg s: A Stroke object.\n" +" :type s: :class:`Stroke`\n"; + +static int streamShader___init__( BPy_streamShader* self, PyObject *args) +{ + if(!( PyArg_ParseTuple(args, "") )) + return -1; + self->py_ss.ss = new StrokeShaders::streamShader(); + return 0; +} + +/*-----------------------BPy_streamShader type definition ------------------------------*/ + +PyTypeObject streamShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "streamShader", /* tp_name */ + sizeof(BPy_streamShader), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + streamShader___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &StrokeShader_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)streamShader___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.h new file mode 100644 index 00000000000..38056d5fa59 --- /dev/null +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.h @@ -0,0 +1,31 @@ +#ifndef FREESTYLE_PYTHON_STREAMSHADER_H +#define FREESTYLE_PYTHON_STREAMSHADER_H + +#include "../BPy_StrokeShader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject streamShader_Type; + +#define BPy_streamShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &streamShader_Type) ) + +/*---------------------------Python BPy_streamShader structure definition----------*/ +typedef struct { + BPy_StrokeShader py_ss; +} BPy_streamShader; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + + +#endif /* FREESTYLE_PYTHON_STREAMSHADER_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.cpp new file mode 100644 index 00000000000..27651e3fd08 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.cpp @@ -0,0 +1,213 @@ +#include "BPy_UnaryFunction0DDouble.h" + +#include "../BPy_Convert.h" +#include "../Iterator/BPy_Interface0DIterator.h" + +#include "UnaryFunction0D_double/BPy_Curvature2DAngleF0D.h" +#include "UnaryFunction0D_double/BPy_DensityF0D.h" +#include "UnaryFunction0D_double/BPy_GetProjectedXF0D.h" +#include "UnaryFunction0D_double/BPy_GetProjectedYF0D.h" +#include "UnaryFunction0D_double/BPy_GetProjectedZF0D.h" +#include "UnaryFunction0D_double/BPy_GetXF0D.h" +#include "UnaryFunction0D_double/BPy_GetYF0D.h" +#include "UnaryFunction0D_double/BPy_GetZF0D.h" +#include "UnaryFunction0D_double/BPy_LocalAverageDepthF0D.h" +#include "UnaryFunction0D_double/BPy_ZDiscontinuityF0D.h" + +#include "../Director.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- + +int UnaryFunction0DDouble_Init( PyObject *module ) { + + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryFunction0DDouble_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryFunction0DDouble_Type ); + PyModule_AddObject(module, "UnaryFunction0DDouble", (PyObject *)&UnaryFunction0DDouble_Type); + + if( PyType_Ready( &DensityF0D_Type ) < 0 ) + return -1; + Py_INCREF( &DensityF0D_Type ); + PyModule_AddObject(module, "DensityF0D", (PyObject *)&DensityF0D_Type); + + if( PyType_Ready( &LocalAverageDepthF0D_Type ) < 0 ) + return -1; + Py_INCREF( &LocalAverageDepthF0D_Type ); + PyModule_AddObject(module, "LocalAverageDepthF0D", (PyObject *)&LocalAverageDepthF0D_Type); + + if( PyType_Ready( &Curvature2DAngleF0D_Type ) < 0 ) + return -1; + Py_INCREF( &Curvature2DAngleF0D_Type ); + PyModule_AddObject(module, "Curvature2DAngleF0D", (PyObject *)&Curvature2DAngleF0D_Type); + + if( PyType_Ready( &GetProjectedXF0D_Type ) < 0 ) + return -1; + Py_INCREF( &GetProjectedXF0D_Type ); + PyModule_AddObject(module, "GetProjectedXF0D", (PyObject *)&GetProjectedXF0D_Type); + + if( PyType_Ready( &GetProjectedYF0D_Type ) < 0 ) + return -1; + Py_INCREF( &GetProjectedYF0D_Type ); + PyModule_AddObject(module, "GetProjectedYF0D", (PyObject *)&GetProjectedYF0D_Type); + + if( PyType_Ready( &GetProjectedZF0D_Type ) < 0 ) + return -1; + Py_INCREF( &GetProjectedZF0D_Type ); + PyModule_AddObject(module, "GetProjectedZF0D", (PyObject *)&GetProjectedZF0D_Type); + + if( PyType_Ready( &GetXF0D_Type ) < 0 ) + return -1; + Py_INCREF( &GetXF0D_Type ); + PyModule_AddObject(module, "GetXF0D", (PyObject *)&GetXF0D_Type); + + if( PyType_Ready( &GetYF0D_Type ) < 0 ) + return -1; + Py_INCREF( &GetYF0D_Type ); + PyModule_AddObject(module, "GetYF0D", (PyObject *)&GetYF0D_Type); + + if( PyType_Ready( &GetZF0D_Type ) < 0 ) + return -1; + Py_INCREF( &GetZF0D_Type ); + PyModule_AddObject(module, "GetZF0D", (PyObject *)&GetZF0D_Type); + + if( PyType_Ready( &ZDiscontinuityF0D_Type ) < 0 ) + return -1; + Py_INCREF( &ZDiscontinuityF0D_Type ); + PyModule_AddObject(module, "ZDiscontinuityF0D", (PyObject *)&ZDiscontinuityF0D_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryFunction0DDouble___doc__[] = +"Base class for unary functions (functors) that work on\n" +":class:`Interface0DIterator` and return a float value.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n"; + +static int UnaryFunction0DDouble___init__(BPy_UnaryFunction0DDouble* self, PyObject *args, PyObject *kwds) +{ + if ( !PyArg_ParseTuple(args, "") ) + return -1; + self->uf0D_double = new UnaryFunction0D<double>(); + self->uf0D_double->py_uf0D = (PyObject *)self; + return 0; +} + +static void UnaryFunction0DDouble___dealloc__(BPy_UnaryFunction0DDouble* self) +{ + if (self->uf0D_double) + delete self->uf0D_double; + UnaryFunction0D_Type.tp_dealloc((PyObject*)self); +} + +static PyObject * UnaryFunction0DDouble___repr__(BPy_UnaryFunction0DDouble* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_double->getName().c_str(), self->uf0D_double ); +} + +static char UnaryFunction0DDouble_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the unary 0D predicate.\n" +"\n" +" :return: The name of the unary 0D predicate.\n" +" :rtype: str\n"; + +static PyObject * UnaryFunction0DDouble_getName( BPy_UnaryFunction0DDouble *self ) +{ + return PyUnicode_FromString( self->uf0D_double->getName().c_str() ); +} + +static PyObject * UnaryFunction0DDouble___call__( BPy_UnaryFunction0DDouble *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj)) + return NULL; + + if( typeid(*(self->uf0D_double)) == typeid(UnaryFunction0D<double>) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if (self->uf0D_double->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it)) < 0) { + if (!PyErr_Occurred()) { + string msg(self->uf0D_double->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + return PyFloat_FromDouble( self->uf0D_double->result ); + +} + +/*----------------------UnaryFunction0DDouble instance definitions ----------------------------*/ +static PyMethodDef BPy_UnaryFunction0DDouble_methods[] = { + {"getName", ( PyCFunction ) UnaryFunction0DDouble_getName, METH_NOARGS, UnaryFunction0DDouble_getName___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_UnaryFunction0DDouble type definition ------------------------------*/ + +PyTypeObject UnaryFunction0DDouble_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryFunction0DDouble", /* tp_name */ + sizeof(BPy_UnaryFunction0DDouble), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryFunction0DDouble___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryFunction0DDouble___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)UnaryFunction0DDouble___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryFunction0DDouble___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_UnaryFunction0DDouble_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)UnaryFunction0DDouble___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.h new file mode 100644 index 00000000000..dbeb70cc082 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.h @@ -0,0 +1,34 @@ +#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DDOUBLE_H +#define FREESTYLE_PYTHON_UNARYFUNCTION0DDOUBLE_H + +#include "../BPy_UnaryFunction0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject UnaryFunction0DDouble_Type; + +#define BPy_UnaryFunction0DDouble_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DDouble_Type) ) + +/*---------------------------Python BPy_UnaryFunction0DDouble structure definition----------*/ +typedef struct { + BPy_UnaryFunction0D py_uf0D; + UnaryFunction0D<double> *uf0D_double; +} BPy_UnaryFunction0DDouble; + +/*---------------------------Python BPy_UnaryFunction0DDouble visible prototypes-----------*/ +int UnaryFunction0DDouble_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DDOUBLE_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.cpp new file mode 100644 index 00000000000..b02776d9b82 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.cpp @@ -0,0 +1,157 @@ +#include "BPy_UnaryFunction0DEdgeNature.h" + +#include "../BPy_Convert.h" +#include "../Iterator/BPy_Interface0DIterator.h" + +#include "UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- + +int UnaryFunction0DEdgeNature_Init( PyObject *module ) { + + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryFunction0DEdgeNature_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryFunction0DEdgeNature_Type ); + PyModule_AddObject(module, "UnaryFunction0DEdgeNature", (PyObject *)&UnaryFunction0DEdgeNature_Type); + + if( PyType_Ready( &CurveNatureF0D_Type ) < 0 ) + return -1; + Py_INCREF( &CurveNatureF0D_Type ); + PyModule_AddObject(module, "CurveNatureF0D", (PyObject *)&CurveNatureF0D_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryFunction0DEdgeNature___doc__[] = +"Base class for unary functions (functors) that work on\n" +":class:`Interface0DIterator` and return a :class:`Nature` object.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n"; + +static int UnaryFunction0DEdgeNature___init__(BPy_UnaryFunction0DEdgeNature* self, PyObject *args, PyObject *kwds) +{ + if ( !PyArg_ParseTuple(args, "") ) + return -1; + self->uf0D_edgenature = new UnaryFunction0D<Nature::EdgeNature>(); + self->uf0D_edgenature->py_uf0D = (PyObject *)self; + return 0; +} + +static void UnaryFunction0DEdgeNature___dealloc__(BPy_UnaryFunction0DEdgeNature* self) +{ + if (self->uf0D_edgenature) + delete self->uf0D_edgenature; + UnaryFunction0D_Type.tp_dealloc((PyObject*)self); +} + +static PyObject * UnaryFunction0DEdgeNature___repr__(BPy_UnaryFunction0DEdgeNature* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_edgenature->getName().c_str(), self->uf0D_edgenature ); +} + +static char UnaryFunction0DEdgeNature_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the unary 0D predicate.\n" +"\n" +" :return: The name of the unary 0D predicate.\n" +" :rtype: str\n"; + +static PyObject * UnaryFunction0DEdgeNature_getName( BPy_UnaryFunction0DEdgeNature *self ) +{ + return PyUnicode_FromString( self->uf0D_edgenature->getName().c_str() ); +} + +static PyObject * UnaryFunction0DEdgeNature___call__( BPy_UnaryFunction0DEdgeNature *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj)) + return NULL; + + if( typeid(*(self->uf0D_edgenature)) == typeid(UnaryFunction0D<Nature::EdgeNature>) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if (self->uf0D_edgenature->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) { + if (!PyErr_Occurred()) { + string msg(self->uf0D_edgenature->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + return BPy_Nature_from_Nature( self->uf0D_edgenature->result ); + +} + +/*----------------------UnaryFunction0DEdgeNature instance definitions ----------------------------*/ +static PyMethodDef BPy_UnaryFunction0DEdgeNature_methods[] = { + {"getName", ( PyCFunction ) UnaryFunction0DEdgeNature_getName, METH_NOARGS, UnaryFunction0DEdgeNature_getName___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_UnaryFunction0DEdgeNature type definition ------------------------------*/ + +PyTypeObject UnaryFunction0DEdgeNature_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryFunction0DEdgeNature", /* tp_name */ + sizeof(BPy_UnaryFunction0DEdgeNature), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryFunction0DEdgeNature___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryFunction0DEdgeNature___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)UnaryFunction0DEdgeNature___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryFunction0DEdgeNature___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_UnaryFunction0DEdgeNature_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)UnaryFunction0DEdgeNature___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h new file mode 100644 index 00000000000..d6959cae57f --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h @@ -0,0 +1,36 @@ +#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DEDGENATURE_H +#define FREESTYLE_PYTHON_UNARYFUNCTION0DEDGENATURE_H + +#include "../BPy_UnaryFunction0D.h" + +#include "../../winged_edge/Nature.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject UnaryFunction0DEdgeNature_Type; + +#define BPy_UnaryFunction0DEdgeNature_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DEdgeNature_Type) ) + +/*---------------------------Python BPy_UnaryFunction0DEdgeNature structure definition----------*/ +typedef struct { + BPy_UnaryFunction0D py_uf0D; + UnaryFunction0D<Nature::EdgeNature> *uf0D_edgenature; +} BPy_UnaryFunction0DEdgeNature; + +/*---------------------------Python BPy_UnaryFunction0DEdgeNature visible prototypes-----------*/ +int UnaryFunction0DEdgeNature_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DEDGENATURE_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.cpp new file mode 100644 index 00000000000..978293ca88a --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.cpp @@ -0,0 +1,187 @@ +#include "BPy_UnaryFunction0DFloat.h" + +#include "../BPy_Convert.h" +#include "../Iterator/BPy_Interface0DIterator.h" + +#include "UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.h" +#include "UnaryFunction0D_float/BPy_GetParameterF0D.h" +#include "UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.h" +#include "UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.h" +#include "UnaryFunction0D_float/BPy_ReadMapPixelF0D.h" +#include "UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- + +int UnaryFunction0DFloat_Init( PyObject *module ) { + + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryFunction0DFloat_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryFunction0DFloat_Type ); + PyModule_AddObject(module, "UnaryFunction0DFloat", (PyObject *)&UnaryFunction0DFloat_Type); + + if( PyType_Ready( &GetCurvilinearAbscissaF0D_Type ) < 0 ) + return -1; + Py_INCREF( &GetCurvilinearAbscissaF0D_Type ); + PyModule_AddObject(module, "GetCurvilinearAbscissaF0D", (PyObject *)&GetCurvilinearAbscissaF0D_Type); + + if( PyType_Ready( &GetParameterF0D_Type ) < 0 ) + return -1; + Py_INCREF( &GetParameterF0D_Type ); + PyModule_AddObject(module, "GetParameterF0D", (PyObject *)&GetParameterF0D_Type); + + if( PyType_Ready( &GetViewMapGradientNormF0D_Type ) < 0 ) + return -1; + Py_INCREF( &GetViewMapGradientNormF0D_Type ); + PyModule_AddObject(module, "GetViewMapGradientNormF0D", (PyObject *)&GetViewMapGradientNormF0D_Type); + + if( PyType_Ready( &ReadCompleteViewMapPixelF0D_Type ) < 0 ) + return -1; + Py_INCREF( &ReadCompleteViewMapPixelF0D_Type ); + PyModule_AddObject(module, "ReadCompleteViewMapPixelF0D", (PyObject *)&ReadCompleteViewMapPixelF0D_Type); + + if( PyType_Ready( &ReadMapPixelF0D_Type ) < 0 ) + return -1; + Py_INCREF( &ReadMapPixelF0D_Type ); + PyModule_AddObject(module, "ReadMapPixelF0D", (PyObject *)&ReadMapPixelF0D_Type); + + if( PyType_Ready( &ReadSteerableViewMapPixelF0D_Type ) < 0 ) + return -1; + Py_INCREF( &ReadSteerableViewMapPixelF0D_Type ); + PyModule_AddObject(module, "ReadSteerableViewMapPixelF0D", (PyObject *)&ReadSteerableViewMapPixelF0D_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryFunction0DFloat___doc__[] = +"Base class for unary functions (functors) that work on\n" +":class:`Interface0DIterator` and return a float value.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n"; + +static int UnaryFunction0DFloat___init__(BPy_UnaryFunction0DFloat* self, PyObject *args, PyObject *kwds) +{ + if ( !PyArg_ParseTuple(args, "") ) + return -1; + self->uf0D_float = new UnaryFunction0D<float>(); + self->uf0D_float->py_uf0D = (PyObject *)self; + return 0; +} + +static void UnaryFunction0DFloat___dealloc__(BPy_UnaryFunction0DFloat* self) +{ + if (self->uf0D_float) + delete self->uf0D_float; + UnaryFunction0D_Type.tp_dealloc((PyObject*)self); +} + +static PyObject * UnaryFunction0DFloat___repr__(BPy_UnaryFunction0DFloat* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_float->getName().c_str(), self->uf0D_float ); +} + +static char UnaryFunction0DFloat_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the unary 0D predicate.\n" +"\n" +" :return: The name of the unary 0D predicate.\n" +" :rtype: str\n"; + +static PyObject * UnaryFunction0DFloat_getName( BPy_UnaryFunction0DFloat *self ) +{ + return PyUnicode_FromString( self->uf0D_float->getName().c_str() ); +} + +static PyObject * UnaryFunction0DFloat___call__( BPy_UnaryFunction0DFloat *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj)) + return NULL; + + if( typeid(*(self->uf0D_float)) == typeid(UnaryFunction0D<float>) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if (self->uf0D_float->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) { + if (!PyErr_Occurred()) { + string msg(self->uf0D_float->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + return PyFloat_FromDouble( self->uf0D_float->result ); + +} + +/*----------------------UnaryFunction0DFloat instance definitions ----------------------------*/ +static PyMethodDef BPy_UnaryFunction0DFloat_methods[] = { + {"getName", ( PyCFunction ) UnaryFunction0DFloat_getName, METH_NOARGS, UnaryFunction0DFloat_getName___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_UnaryFunction0DFloat type definition ------------------------------*/ + +PyTypeObject UnaryFunction0DFloat_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryFunction0DFloat", /* tp_name */ + sizeof(BPy_UnaryFunction0DFloat), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryFunction0DFloat___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryFunction0DFloat___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)UnaryFunction0DFloat___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryFunction0DFloat___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_UnaryFunction0DFloat_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)UnaryFunction0DFloat___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.h new file mode 100644 index 00000000000..fbf207d48c7 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.h @@ -0,0 +1,34 @@ +#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DFLOAT_H +#define FREESTYLE_PYTHON_UNARYFUNCTION0DFLOAT_H + +#include "../BPy_UnaryFunction0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject UnaryFunction0DFloat_Type; + +#define BPy_UnaryFunction0DFloat_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DFloat_Type) ) + +/*---------------------------Python BPy_UnaryFunction0DFloat structure definition----------*/ +typedef struct { + BPy_UnaryFunction0D py_uf0D; + UnaryFunction0D<float> *uf0D_float; +} BPy_UnaryFunction0DFloat; + +/*---------------------------Python BPy_UnaryFunction0DFloat visible prototypes-----------*/ +int UnaryFunction0DFloat_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DFLOAT_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.cpp new file mode 100644 index 00000000000..2d80997ec22 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.cpp @@ -0,0 +1,156 @@ +#include "BPy_UnaryFunction0DId.h" + +#include "../BPy_Convert.h" +#include "../Iterator/BPy_Interface0DIterator.h" + +#include "UnaryFunction0D_Id/BPy_ShapeIdF0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- + +int UnaryFunction0DId_Init( PyObject *module ) { + + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryFunction0DId_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryFunction0DId_Type ); + PyModule_AddObject(module, "UnaryFunction0DId", (PyObject *)&UnaryFunction0DId_Type); + + if( PyType_Ready( &ShapeIdF0D_Type ) < 0 ) + return -1; + Py_INCREF( &ShapeIdF0D_Type ); + PyModule_AddObject(module, "ShapeIdF0D", (PyObject *)&ShapeIdF0D_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryFunction0DId___doc__[] = +"Base class for unary functions (functors) that work on\n" +":class:`Interface0DIterator` and return an :class:`Id` object.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n"; + +static int UnaryFunction0DId___init__(BPy_UnaryFunction0DId* self, PyObject *args, PyObject *kwds) +{ + if ( !PyArg_ParseTuple(args, "") ) + return -1; + self->uf0D_id = new UnaryFunction0D<Id>(); + self->uf0D_id->py_uf0D = (PyObject *)self; + return 0; +} + +static void UnaryFunction0DId___dealloc__(BPy_UnaryFunction0DId* self) +{ + if (self->uf0D_id) + delete self->uf0D_id; + UnaryFunction0D_Type.tp_dealloc((PyObject*)self); +} + +static PyObject * UnaryFunction0DId___repr__(BPy_UnaryFunction0DId* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_id->getName().c_str(), self->uf0D_id ); +} + +static char UnaryFunction0DId_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the unary 0D predicate.\n" +"\n" +" :return: The name of the unary 0D predicate.\n" +" :rtype: str\n"; + +static PyObject * UnaryFunction0DId_getName( BPy_UnaryFunction0DId *self ) +{ + return PyUnicode_FromString( self->uf0D_id->getName().c_str() ); +} + +static PyObject * UnaryFunction0DId___call__( BPy_UnaryFunction0DId *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj)) + return NULL; + + if( typeid(*(self->uf0D_id)) == typeid(UnaryFunction0D<Id>) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if (self->uf0D_id->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) { + if (!PyErr_Occurred()) { + string msg(self->uf0D_id->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + return BPy_Id_from_Id( self->uf0D_id->result ); +} + +/*----------------------UnaryFunction0DId instance definitions ----------------------------*/ +static PyMethodDef BPy_UnaryFunction0DId_methods[] = { + {"getName", ( PyCFunction ) UnaryFunction0DId_getName, METH_NOARGS, UnaryFunction0DId_getName___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_UnaryFunction0DId type definition ------------------------------*/ + +PyTypeObject UnaryFunction0DId_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryFunction0DId", /* tp_name */ + sizeof(BPy_UnaryFunction0DId), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryFunction0DId___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryFunction0DId___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)UnaryFunction0DId___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryFunction0DId___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_UnaryFunction0DId_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)UnaryFunction0DId___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.h new file mode 100644 index 00000000000..159e24e2674 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.h @@ -0,0 +1,36 @@ +#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DID_H +#define FREESTYLE_PYTHON_UNARYFUNCTION0DID_H + +#include "../BPy_UnaryFunction0D.h" + +#include "../../system/Id.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject UnaryFunction0DId_Type; + +#define BPy_UnaryFunction0DId_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DId_Type) ) + +/*---------------------------Python BPy_UnaryFunction0DId structure definition----------*/ +typedef struct { + BPy_UnaryFunction0D py_uf0D; + UnaryFunction0D<Id> *uf0D_id; +} BPy_UnaryFunction0DId; + +/*---------------------------Python BPy_UnaryFunction0DId visible prototypes-----------*/ +int UnaryFunction0DId_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DID_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.cpp new file mode 100644 index 00000000000..221cfc4f4ee --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.cpp @@ -0,0 +1,158 @@ +#include "BPy_UnaryFunction0DMaterial.h" + +#include "../BPy_Convert.h" +#include "../Iterator/BPy_Interface0DIterator.h" + +#include "UnaryFunction0D_Material/BPy_MaterialF0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- + +int UnaryFunction0DMaterial_Init( PyObject *module ) { + + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryFunction0DMaterial_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryFunction0DMaterial_Type ); + PyModule_AddObject(module, "UnaryFunction0DMaterial", (PyObject *)&UnaryFunction0DMaterial_Type); + + if( PyType_Ready( &MaterialF0D_Type ) < 0 ) + return -1; + Py_INCREF( &MaterialF0D_Type ); + PyModule_AddObject(module, "MaterialF0D", (PyObject *)&MaterialF0D_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryFunction0DMaterial___doc__[] = +"Base class for unary functions (functors) that work on\n" +":class:`Interface0DIterator` and return a :class:`Material` object.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n"; + +static int UnaryFunction0DMaterial___init__(BPy_UnaryFunction0DMaterial* self, PyObject *args, PyObject *kwds) +{ + if ( !PyArg_ParseTuple(args, "") ) + return -1; + self->uf0D_material = new UnaryFunction0D<FrsMaterial>(); + self->uf0D_material->py_uf0D = (PyObject *)self; + return 0; +} + +static void UnaryFunction0DMaterial___dealloc__(BPy_UnaryFunction0DMaterial* self) +{ + if (self->uf0D_material) + delete self->uf0D_material; + UnaryFunction0D_Type.tp_dealloc((PyObject*)self); +} + + +static PyObject * UnaryFunction0DMaterial___repr__(BPy_UnaryFunction0DMaterial* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_material->getName().c_str(), self->uf0D_material ); +} + +static char UnaryFunction0DMaterial_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the unary 0D predicate.\n" +"\n" +" :return: The name of the unary 0D predicate.\n" +" :rtype: str\n"; + +static PyObject * UnaryFunction0DMaterial_getName( BPy_UnaryFunction0DMaterial *self ) +{ + return PyUnicode_FromString( self->uf0D_material->getName().c_str() ); +} + +static PyObject * UnaryFunction0DMaterial___call__( BPy_UnaryFunction0DMaterial *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj)) + return NULL; + + if( typeid(*(self->uf0D_material)) == typeid(UnaryFunction0D<FrsMaterial>) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if (self->uf0D_material->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) { + if (!PyErr_Occurred()) { + string msg(self->uf0D_material->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + return BPy_FrsMaterial_from_FrsMaterial( self->uf0D_material->result ); + +} + +/*----------------------UnaryFunction0DMaterial instance definitions ----------------------------*/ +static PyMethodDef BPy_UnaryFunction0DMaterial_methods[] = { + {"getName", ( PyCFunction ) UnaryFunction0DMaterial_getName, METH_NOARGS, UnaryFunction0DMaterial_getName___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_UnaryFunction0DMaterial type definition ------------------------------*/ + +PyTypeObject UnaryFunction0DMaterial_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryFunction0DMaterial", /* tp_name */ + sizeof(BPy_UnaryFunction0DMaterial), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryFunction0DMaterial___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryFunction0DMaterial___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)UnaryFunction0DMaterial___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryFunction0DMaterial___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_UnaryFunction0DMaterial_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)UnaryFunction0DMaterial___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.h new file mode 100644 index 00000000000..02fb2b99ccd --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.h @@ -0,0 +1,36 @@ +#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DMATERIAL_H +#define FREESTYLE_PYTHON_UNARYFUNCTION0DMATERIAL_H + +#include "../BPy_UnaryFunction0D.h" + +#include "../../scene_graph/FrsMaterial.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject UnaryFunction0DMaterial_Type; + +#define BPy_UnaryFunction0DMaterial_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DMaterial_Type) ) + +/*---------------------------Python BPy_UnaryFunction0DMaterial structure definition----------*/ +typedef struct { + BPy_UnaryFunction0D py_uf0D; + UnaryFunction0D<FrsMaterial> *uf0D_material; +} BPy_UnaryFunction0DMaterial; + +/*---------------------------Python BPy_UnaryFunction0DMaterial visible prototypes-----------*/ +int UnaryFunction0DMaterial_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DMATERIAL_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp new file mode 100644 index 00000000000..a106761585c --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp @@ -0,0 +1,157 @@ +#include "BPy_UnaryFunction0DUnsigned.h" + +#include "../BPy_Convert.h" +#include "../Iterator/BPy_Interface0DIterator.h" + +#include "UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- + +int UnaryFunction0DUnsigned_Init( PyObject *module ) { + + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryFunction0DUnsigned_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryFunction0DUnsigned_Type ); + PyModule_AddObject(module, "UnaryFunction0DUnsigned", (PyObject *)&UnaryFunction0DUnsigned_Type); + + if( PyType_Ready( &QuantitativeInvisibilityF0D_Type ) < 0 ) + return -1; + Py_INCREF( &QuantitativeInvisibilityF0D_Type ); + PyModule_AddObject(module, "QuantitativeInvisibilityF0D", (PyObject *)&QuantitativeInvisibilityF0D_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryFunction0DUnsigned___doc__[] = +"Base class for unary functions (functors) that work on\n" +":class:`Interface0DIterator` and return an int value.\n" +"\n" +".. method:: __init__()\n" +"\n" + " Default constructor.\n"; + +static int UnaryFunction0DUnsigned___init__(BPy_UnaryFunction0DUnsigned* self, PyObject *args, PyObject *kwds) +{ + if ( !PyArg_ParseTuple(args, "") ) + return -1; + self->uf0D_unsigned = new UnaryFunction0D<unsigned int>(); + self->uf0D_unsigned->py_uf0D = (PyObject *)self; + return 0; +} + +static void UnaryFunction0DUnsigned___dealloc__(BPy_UnaryFunction0DUnsigned* self) +{ + if (self->uf0D_unsigned) + delete self->uf0D_unsigned; + UnaryFunction0D_Type.tp_dealloc((PyObject*)self); +} + +static PyObject * UnaryFunction0DUnsigned___repr__(BPy_UnaryFunction0DUnsigned* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_unsigned->getName().c_str(), self->uf0D_unsigned ); +} + +static char UnaryFunction0DUnsigned_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the unary 0D predicate.\n" +"\n" +" :return: The name of the unary 0D predicate.\n" +" :rtype: str\n"; + +static PyObject * UnaryFunction0DUnsigned_getName( BPy_UnaryFunction0DUnsigned *self ) +{ + return PyUnicode_FromString( self->uf0D_unsigned->getName().c_str() ); +} + +static PyObject * UnaryFunction0DUnsigned___call__( BPy_UnaryFunction0DUnsigned *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj)) + return NULL; + + if( typeid(*(self->uf0D_unsigned)) == typeid(UnaryFunction0D<unsigned int>) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if (self->uf0D_unsigned->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) { + if (!PyErr_Occurred()) { + string msg(self->uf0D_unsigned->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + return PyLong_FromLong( self->uf0D_unsigned->result ); + +} + +/*----------------------UnaryFunction0DUnsigned instance definitions ----------------------------*/ +static PyMethodDef BPy_UnaryFunction0DUnsigned_methods[] = { + {"getName", ( PyCFunction ) UnaryFunction0DUnsigned_getName, METH_NOARGS, UnaryFunction0DUnsigned_getName___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_UnaryFunction0DUnsigned type definition ------------------------------*/ + +PyTypeObject UnaryFunction0DUnsigned_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryFunction0DUnsigned", /* tp_name */ + sizeof(BPy_UnaryFunction0DUnsigned), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryFunction0DUnsigned___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryFunction0DUnsigned___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)UnaryFunction0DUnsigned___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryFunction0DUnsigned___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_UnaryFunction0DUnsigned_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)UnaryFunction0DUnsigned___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h new file mode 100644 index 00000000000..4776ce30918 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h @@ -0,0 +1,34 @@ +#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DUNSIGNED_H +#define FREESTYLE_PYTHON_UNARYFUNCTION0DUNSIGNED_H + +#include "../BPy_UnaryFunction0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject UnaryFunction0DUnsigned_Type; + +#define BPy_UnaryFunction0DUnsigned_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DUnsigned_Type) ) + +/*---------------------------Python BPy_UnaryFunction0DUnsigned structure definition----------*/ +typedef struct { + BPy_UnaryFunction0D py_uf0D; + UnaryFunction0D<unsigned int> *uf0D_unsigned; +} BPy_UnaryFunction0DUnsigned; + +/*---------------------------Python BPy_UnaryFunction0DUnsigned visible prototypes-----------*/ +int UnaryFunction0DUnsigned_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DUNSIGNED_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.cpp new file mode 100644 index 00000000000..a11805a9e88 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.cpp @@ -0,0 +1,163 @@ +#include "BPy_UnaryFunction0DVec2f.h" + +#include "../BPy_Convert.h" +#include "../Iterator/BPy_Interface0DIterator.h" + +#include "UnaryFunction0D_Vec2f/BPy_Normal2DF0D.h" +#include "UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- + +int UnaryFunction0DVec2f_Init( PyObject *module ) { + + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryFunction0DVec2f_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryFunction0DVec2f_Type ); + PyModule_AddObject(module, "UnaryFunction0DVec2f", (PyObject *)&UnaryFunction0DVec2f_Type); + + if( PyType_Ready( &Normal2DF0D_Type ) < 0 ) + return -1; + Py_INCREF( &Normal2DF0D_Type ); + PyModule_AddObject(module, "Normal2DF0D", (PyObject *)&Normal2DF0D_Type); + + if( PyType_Ready( &VertexOrientation2DF0D_Type ) < 0 ) + return -1; + Py_INCREF( &VertexOrientation2DF0D_Type ); + PyModule_AddObject(module, "VertexOrientation2DF0D", (PyObject *)&VertexOrientation2DF0D_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryFunction0DVec2f___doc__[] = +"Base class for unary functions (functors) that work on\n" +":class:`Interface0DIterator` and return a 2D vector.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n"; + +static int UnaryFunction0DVec2f___init__(BPy_UnaryFunction0DVec2f* self, PyObject *args, PyObject *kwds) +{ + if ( !PyArg_ParseTuple(args, "") ) + return -1; + self->uf0D_vec2f = new UnaryFunction0D<Vec2f>(); + self->uf0D_vec2f->py_uf0D = (PyObject *)self; + return 0; +} + +static void UnaryFunction0DVec2f___dealloc__(BPy_UnaryFunction0DVec2f* self) +{ + if (self->uf0D_vec2f) + delete self->uf0D_vec2f; + UnaryFunction0D_Type.tp_dealloc((PyObject*)self); +} + +static PyObject * UnaryFunction0DVec2f___repr__(BPy_UnaryFunction0DVec2f* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_vec2f->getName().c_str(), self->uf0D_vec2f ); +} + +static char UnaryFunction0DVec2f_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the unary 0D predicate.\n" +"\n" +" :return: The name of the unary 0D predicate.\n" +" :rtype: str\n"; + +static PyObject * UnaryFunction0DVec2f_getName( BPy_UnaryFunction0DVec2f *self ) +{ + return PyUnicode_FromString( self->uf0D_vec2f->getName().c_str() ); +} + +static PyObject * UnaryFunction0DVec2f___call__( BPy_UnaryFunction0DVec2f *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj)) + return NULL; + + if( typeid(*(self->uf0D_vec2f)) == typeid(UnaryFunction0D<Vec2f>) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if (self->uf0D_vec2f->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) { + if (!PyErr_Occurred()) { + string msg(self->uf0D_vec2f->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + return Vector_from_Vec2f( self->uf0D_vec2f->result ); + +} + +/*----------------------UnaryFunction0DVec2f instance definitions ----------------------------*/ +static PyMethodDef BPy_UnaryFunction0DVec2f_methods[] = { + {"getName", ( PyCFunction ) UnaryFunction0DVec2f_getName, METH_NOARGS, UnaryFunction0DVec2f_getName___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_UnaryFunction0DVec2f type definition ------------------------------*/ + +PyTypeObject UnaryFunction0DVec2f_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryFunction0DVec2f", /* tp_name */ + sizeof(BPy_UnaryFunction0DVec2f), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryFunction0DVec2f___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryFunction0DVec2f___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)UnaryFunction0DVec2f___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryFunction0DVec2f___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_UnaryFunction0DVec2f_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)UnaryFunction0DVec2f___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.h new file mode 100644 index 00000000000..6628d629a41 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.h @@ -0,0 +1,37 @@ +#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DVEC2F_H +#define FREESTYLE_PYTHON_UNARYFUNCTION0DVEC2F_H + +#include "../BPy_UnaryFunction0D.h" + +#include "../../geometry/Geom.h" +using namespace Geometry; + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject UnaryFunction0DVec2f_Type; + +#define BPy_UnaryFunction0DVec2f_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DVec2f_Type) ) + +/*---------------------------Python BPy_UnaryFunction0DVec2f structure definition----------*/ +typedef struct { + BPy_UnaryFunction0D py_uf0D; + UnaryFunction0D<Vec2f> *uf0D_vec2f; +} BPy_UnaryFunction0DVec2f; + +/*---------------------------Python BPy_UnaryFunction0DVec2f visible prototypes-----------*/ +int UnaryFunction0DVec2f_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DVEC2F_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.cpp new file mode 100644 index 00000000000..1d47f18bafd --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.cpp @@ -0,0 +1,157 @@ +#include "BPy_UnaryFunction0DVec3f.h" + +#include "../BPy_Convert.h" +#include "../Iterator/BPy_Interface0DIterator.h" + +#include "UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- + +int UnaryFunction0DVec3f_Init( PyObject *module ) { + + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryFunction0DVec3f_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryFunction0DVec3f_Type ); + PyModule_AddObject(module, "UnaryFunction0DVec3f", (PyObject *)&UnaryFunction0DVec3f_Type); + + if( PyType_Ready( &VertexOrientation3DF0D_Type ) < 0 ) + return -1; + Py_INCREF( &VertexOrientation3DF0D_Type ); + PyModule_AddObject(module, "VertexOrientation3DF0D", (PyObject *)&VertexOrientation3DF0D_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryFunction0DVec3f___doc__[] = +"Base class for unary functions (functors) that work on\n" +":class:`Interface0DIterator` and return a 3D vector.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n"; + +static int UnaryFunction0DVec3f___init__(BPy_UnaryFunction0DVec3f* self, PyObject *args, PyObject *kwds) +{ + if ( !PyArg_ParseTuple(args, "") ) + return -1; + self->uf0D_vec3f = new UnaryFunction0D<Vec3f>(); + self->uf0D_vec3f->py_uf0D = (PyObject *)self; + return 0; +} + +static void UnaryFunction0DVec3f___dealloc__(BPy_UnaryFunction0DVec3f* self) +{ + if (self->uf0D_vec3f) + delete self->uf0D_vec3f; + UnaryFunction0D_Type.tp_dealloc((PyObject*)self); +} + +static PyObject * UnaryFunction0DVec3f___repr__(BPy_UnaryFunction0DVec3f* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_vec3f->getName().c_str(), self->uf0D_vec3f ); +} + +static char UnaryFunction0DVec3f_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the unary 0D predicate.\n" +"\n" +" :return: The name of the unary 0D predicate.\n" +" :rtype: str\n"; + +static PyObject * UnaryFunction0DVec3f_getName( BPy_UnaryFunction0DVec3f *self ) +{ + return PyUnicode_FromString( self->uf0D_vec3f->getName().c_str() ); +} + +static PyObject * UnaryFunction0DVec3f___call__( BPy_UnaryFunction0DVec3f *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj)) + return NULL; + + if( typeid(*(self->uf0D_vec3f)) == typeid(UnaryFunction0D<Vec3f>) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if (self->uf0D_vec3f->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) { + if (!PyErr_Occurred()) { + string msg(self->uf0D_vec3f->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + return Vector_from_Vec3f( self->uf0D_vec3f->result ); + +} + +/*----------------------UnaryFunction0DVec3f instance definitions ----------------------------*/ +static PyMethodDef BPy_UnaryFunction0DVec3f_methods[] = { + {"getName", ( PyCFunction ) UnaryFunction0DVec3f_getName, METH_NOARGS, UnaryFunction0DVec3f_getName___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_UnaryFunction0DVec3f type definition ------------------------------*/ + +PyTypeObject UnaryFunction0DVec3f_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryFunction0DVec3f", /* tp_name */ + sizeof(BPy_UnaryFunction0DVec3f), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryFunction0DVec3f___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryFunction0DVec3f___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)UnaryFunction0DVec3f___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryFunction0DVec3f___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_UnaryFunction0DVec3f_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)UnaryFunction0DVec3f___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.h new file mode 100644 index 00000000000..47ec89fb179 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.h @@ -0,0 +1,37 @@ +#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DVEC3F_H +#define FREESTYLE_PYTHON_UNARYFUNCTION0DVEC3F_H + +#include "../BPy_UnaryFunction0D.h" + +#include "../../geometry/Geom.h" +using namespace Geometry; + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject UnaryFunction0DVec3f_Type; + +#define BPy_UnaryFunction0DVec3f_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DVec3f_Type) ) + +/*---------------------------Python BPy_UnaryFunction0DVec3f structure definition----------*/ +typedef struct { + BPy_UnaryFunction0D py_uf0D; + UnaryFunction0D<Vec3f> *uf0D_vec3f; +} BPy_UnaryFunction0DVec3f; + +/*---------------------------Python BPy_UnaryFunction0DVec3f visible prototypes-----------*/ +int UnaryFunction0DVec3f_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DVEC3F_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp new file mode 100644 index 00000000000..aaa3fa9198d --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp @@ -0,0 +1,170 @@ +#include "BPy_UnaryFunction0DVectorViewShape.h" + +#include "../BPy_Convert.h" +#include "../Iterator/BPy_Interface0DIterator.h" + +#include "UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- + +int UnaryFunction0DVectorViewShape_Init( PyObject *module ) { + + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryFunction0DVectorViewShape_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryFunction0DVectorViewShape_Type ); + PyModule_AddObject(module, "UnaryFunction0DVectorViewShape", (PyObject *)&UnaryFunction0DVectorViewShape_Type); + + if( PyType_Ready( &GetOccludersF0D_Type ) < 0 ) + return -1; + Py_INCREF( &GetOccludersF0D_Type ); + PyModule_AddObject(module, "GetOccludersF0D", (PyObject *)&GetOccludersF0D_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryFunction0DVectorViewShape___doc__[] = +"Base class for unary functions (functors) that work on\n" +":class:`Interface0DIterator` and return a list of :class:`ViewShape`\n" +"objects.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n"; + +static int UnaryFunction0DVectorViewShape___init__(BPy_UnaryFunction0DVectorViewShape* self, PyObject *args, PyObject *kwds) +{ + if ( !PyArg_ParseTuple(args, "") ) + return -1; + self->uf0D_vectorviewshape = new UnaryFunction0D< std::vector<ViewShape*> >(); + self->uf0D_vectorviewshape->py_uf0D = (PyObject *)self; + return 0; +} + +static void UnaryFunction0DVectorViewShape___dealloc__(BPy_UnaryFunction0DVectorViewShape* self) +{ + if (self->uf0D_vectorviewshape) + delete self->uf0D_vectorviewshape; + UnaryFunction0D_Type.tp_dealloc((PyObject*)self); +} + +static PyObject * UnaryFunction0DVectorViewShape___repr__(BPy_UnaryFunction0DVectorViewShape* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_vectorviewshape->getName().c_str(), self->uf0D_vectorviewshape ); +} + +static char UnaryFunction0DVectorViewShape_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the unary 0D predicate.\n" +"\n" +" :return: The name of the unary 0D predicate.\n" +" :rtype: str\n"; + +static PyObject * UnaryFunction0DVectorViewShape_getName( BPy_UnaryFunction0DVectorViewShape *self ) +{ + return PyUnicode_FromString( self->uf0D_vectorviewshape->getName().c_str() ); +} + +static PyObject * UnaryFunction0DVectorViewShape___call__( BPy_UnaryFunction0DVectorViewShape *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj)) + return NULL; + + if( typeid(*(self->uf0D_vectorviewshape)) == typeid(UnaryFunction0D< std::vector<ViewShape*> >) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if (self->uf0D_vectorviewshape->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) { + if (!PyErr_Occurred()) { + string msg(self->uf0D_vectorviewshape->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + PyObject *list = PyList_New(0); + PyObject *item; + for( unsigned int i = 0; i < self->uf0D_vectorviewshape->result.size(); i++) { + ViewShape *v = self->uf0D_vectorviewshape->result[i]; + if (v) { + item = BPy_ViewShape_from_ViewShape(*v); + } else { + item = Py_None; + Py_INCREF(item); + } + PyList_Append(list, item); + } + + return list; +} + +/*----------------------UnaryFunction0DVectorViewShape instance definitions ----------------------------*/ +static PyMethodDef BPy_UnaryFunction0DVectorViewShape_methods[] = { + {"getName", ( PyCFunction ) UnaryFunction0DVectorViewShape_getName, METH_NOARGS, UnaryFunction0DVectorViewShape_getName___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_UnaryFunction0DVectorViewShape type definition ------------------------------*/ + +PyTypeObject UnaryFunction0DVectorViewShape_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryFunction0DVectorViewShape", /* tp_name */ + sizeof(BPy_UnaryFunction0DVectorViewShape), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryFunction0DVectorViewShape___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryFunction0DVectorViewShape___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)UnaryFunction0DVectorViewShape___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryFunction0DVectorViewShape___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_UnaryFunction0DVectorViewShape_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)UnaryFunction0DVectorViewShape___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h new file mode 100644 index 00000000000..77f96e96f20 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h @@ -0,0 +1,37 @@ +#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DVECTORVIEWSHAPE_H +#define FREESTYLE_PYTHON_UNARYFUNCTION0DVECTORVIEWSHAPE_H + +#include "../BPy_UnaryFunction0D.h" + +#include <vector> +#include "../../view_map/ViewMap.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject UnaryFunction0DVectorViewShape_Type; + +#define BPy_UnaryFunction0DVectorViewShape_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DVectorViewShape_Type) ) + +/*---------------------------Python BPy_UnaryFunction0DVectorViewShape structure definition----------*/ +typedef struct { + BPy_UnaryFunction0D py_uf0D; + UnaryFunction0D< std::vector<ViewShape*> > *uf0D_vectorviewshape; +} BPy_UnaryFunction0DVectorViewShape; + +/*---------------------------Python BPy_UnaryFunction0DVectorViewShape visible prototypes-----------*/ +int UnaryFunction0DVectorViewShape_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DVECTORVIEWSHAPE_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.cpp new file mode 100644 index 00000000000..e43808697c4 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.cpp @@ -0,0 +1,163 @@ +#include "BPy_UnaryFunction0DViewShape.h" + +#include "../BPy_Convert.h" +#include "../Iterator/BPy_Interface0DIterator.h" + +#include "UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.h" +#include "UnaryFunction0D_ViewShape/BPy_GetShapeF0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- + +int UnaryFunction0DViewShape_Init( PyObject *module ) { + + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryFunction0DViewShape_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryFunction0DViewShape_Type ); + PyModule_AddObject(module, "UnaryFunction0DViewShape", (PyObject *)&UnaryFunction0DViewShape_Type); + + if( PyType_Ready( &GetOccludeeF0D_Type ) < 0 ) + return -1; + Py_INCREF( &GetOccludeeF0D_Type ); + PyModule_AddObject(module, "GetOccludeeF0D", (PyObject *)&GetOccludeeF0D_Type); + + if( PyType_Ready( &GetShapeF0D_Type ) < 0 ) + return -1; + Py_INCREF( &GetShapeF0D_Type ); + PyModule_AddObject(module, "GetShapeF0D", (PyObject *)&GetShapeF0D_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryFunction0DViewShape___doc__[] = +"Base class for unary functions (functors) that work on\n" +":class:`Interface0DIterator` and return a :class:`ViewShape` object.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n"; + +static int UnaryFunction0DViewShape___init__(BPy_UnaryFunction0DViewShape* self, PyObject *args, PyObject *kwds) +{ + if ( !PyArg_ParseTuple(args, "") ) + return -1; + self->uf0D_viewshape = new UnaryFunction0D<ViewShape*>(); + self->uf0D_viewshape->py_uf0D = (PyObject *)self; + return 0; +} + +static void UnaryFunction0DViewShape___dealloc__(BPy_UnaryFunction0DViewShape* self) +{ + if (self->uf0D_viewshape) + delete self->uf0D_viewshape; + UnaryFunction0D_Type.tp_dealloc((PyObject*)self); +} + +static PyObject * UnaryFunction0DViewShape___repr__(BPy_UnaryFunction0DViewShape* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_viewshape->getName().c_str(), self->uf0D_viewshape ); +} + +static char UnaryFunction0DViewShape_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the unary 0D predicate.\n" +"\n" +" :return: The name of the unary 0D predicate.\n" +" :rtype: str\n"; + +static PyObject * UnaryFunction0DViewShape_getName( BPy_UnaryFunction0DViewShape *self ) +{ + return PyUnicode_FromString( self->uf0D_viewshape->getName().c_str() ); +} + +static PyObject * UnaryFunction0DViewShape___call__( BPy_UnaryFunction0DViewShape *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj)) + return NULL; + + if( typeid(*(self->uf0D_viewshape)) == typeid(UnaryFunction0D<ViewShape*>) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if (self->uf0D_viewshape->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) { + if (!PyErr_Occurred()) { + string msg(self->uf0D_viewshape->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + return BPy_ViewShape_from_ViewShape( *(self->uf0D_viewshape->result) ); + +} + +/*----------------------UnaryFunction0DViewShape instance definitions ----------------------------*/ +static PyMethodDef BPy_UnaryFunction0DViewShape_methods[] = { + {"getName", ( PyCFunction ) UnaryFunction0DViewShape_getName, METH_NOARGS, UnaryFunction0DViewShape_getName___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_UnaryFunction0DViewShape type definition ------------------------------*/ + +PyTypeObject UnaryFunction0DViewShape_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryFunction0DViewShape", /* tp_name */ + sizeof(BPy_UnaryFunction0DViewShape), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryFunction0DViewShape___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryFunction0DViewShape___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)UnaryFunction0DViewShape___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryFunction0DViewShape___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_UnaryFunction0DViewShape_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)UnaryFunction0DViewShape___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.h new file mode 100644 index 00000000000..68c888eb36b --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.h @@ -0,0 +1,36 @@ +#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DVIEWSHAPE_H +#define FREESTYLE_PYTHON_UNARYFUNCTION0DVIEWSHAPE_H + +#include "../BPy_UnaryFunction0D.h" + +#include "../../view_map/ViewMap.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject UnaryFunction0DViewShape_Type; + +#define BPy_UnaryFunction0DViewShape_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DViewShape_Type) ) + +/*---------------------------Python BPy_UnaryFunction0DViewShape structure definition----------*/ +typedef struct { + BPy_UnaryFunction0D py_uf0D; + UnaryFunction0D<ViewShape*> *uf0D_viewshape; +} BPy_UnaryFunction0DViewShape; + +/*---------------------------Python BPy_UnaryFunction0DViewShape visible prototypes-----------*/ +int UnaryFunction0DViewShape_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DVIEWSHAPE_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp new file mode 100644 index 00000000000..8acb96f8d0f --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp @@ -0,0 +1,90 @@ +#include "BPy_ShapeIdF0D.h" + +#include "../../../view_map/Functions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ShapeIdF0D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a ShapeIdF0D object.\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns the :class:`Id` of the Shape the :class:`Interface0D`\n" +" pointed by the Interface0DIterator belongs to. This evaluation can\n" +" be ambiguous (in the case of a :class:`TVertex` for example). This\n" +" functor tries to remove this ambiguity using the context offered by\n" +" the 1D element to which the Interface0DIterator belongs to.\n" +" However, there still can be problematic cases, and the user willing\n" +" to deal with this cases in a specific way should implement its own\n" +" getShapeIdF0D functor.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The Id of the Shape the pointed Interface0D belongs to.\n" +" :rtype: :class:`Id`\n"; + +static int ShapeIdF0D___init__( BPy_ShapeIdF0D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf0D_id.uf0D_id = new Functions0D::ShapeIdF0D(); + self->py_uf0D_id.uf0D_id->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_ShapeIdF0D type definition ------------------------------*/ + +PyTypeObject ShapeIdF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ShapeIdF0D", /* tp_name */ + sizeof(BPy_ShapeIdF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ShapeIdF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DId_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ShapeIdF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.h new file mode 100644 index 00000000000..11995bb4e88 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_SHAPEIDF0D_H +#define FREESTYLE_PYTHON_SHAPEIDF0D_H + +#include "../BPy_UnaryFunction0DId.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ShapeIdF0D_Type; + +#define BPy_ShapeIdF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ShapeIdF0D_Type) ) + +/*---------------------------Python BPy_ShapeIdF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DId py_uf0D_id; +} BPy_ShapeIdF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_SHAPEIDF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp new file mode 100644 index 00000000000..1f709947d0e --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp @@ -0,0 +1,94 @@ +#include "BPy_MaterialF0D.h" + +#include "../../../view_map/Functions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char MaterialF0D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a MaterialF0D object.\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns the material of the object evaluated at the\n" +" :class:`Interface0D` pointed by the Interface0DIterator. This\n" +" evaluation can be ambiguous (in the case of a :class:`TVertex` for\n" +" example. This functor tries to remove this ambiguity using the\n" +" context offered by the 1D element to which the Interface0DIterator\n" +" belongs to and by arbitrary chosing the material of the face that\n" +" lies on its left when following the 1D element if there are two\n" +" different materials on each side of the point. However, there\n" +" still can be problematic cases, and the user willing to deal with\n" +" this cases in a specific way should implement its own getMaterial\n" +" functor.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The material of the object evaluated at the pointed\n" +" Interface0D.\n" +" :rtype: :class:`Material`\n"; + +static int MaterialF0D___init__( BPy_MaterialF0D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf0D_material.uf0D_material = new Functions0D::MaterialF0D(); + self->py_uf0D_material.uf0D_material->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_MaterialF0D type definition ------------------------------*/ + +PyTypeObject MaterialF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "MaterialF0D", /* tp_name */ + sizeof(BPy_MaterialF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + MaterialF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DMaterial_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)MaterialF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.h new file mode 100644 index 00000000000..1ae30484ba5 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_MATERIALF0D_H +#define FREESTYLE_PYTHON_MATERIALF0D_H + +#include "../BPy_UnaryFunction0DMaterial.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject MaterialF0D_Type; + +#define BPy_MaterialF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &MaterialF0D_Type) ) + +/*---------------------------Python BPy_MaterialF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DMaterial py_uf0D_material; +} BPy_MaterialF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_MATERIALF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp new file mode 100644 index 00000000000..0216d01baba --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp @@ -0,0 +1,85 @@ +#include "BPy_CurveNatureF0D.h" + +#include "../../../view_map/Functions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char CurveNatureF0D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a CurveNatureF0D object.\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns the :class:`Nature` of the 1D element the Interface0D pointed\n" +" by the Interface0DIterator belongs to.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The nature of the 1D element to which the pointed Interface0D\n" +" belongs.\n" +" :rtype: :class:`Nature`\n"; + +static int CurveNatureF0D___init__( BPy_CurveNatureF0D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf0D_edgenature.uf0D_edgenature = new Functions0D::CurveNatureF0D(); + self->py_uf0D_edgenature.uf0D_edgenature->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_CurveNatureF0D type definition ------------------------------*/ + +PyTypeObject CurveNatureF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "CurveNatureF0D", /* tp_name */ + sizeof(BPy_CurveNatureF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + CurveNatureF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DEdgeNature_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)CurveNatureF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.h new file mode 100644 index 00000000000..63b3050c474 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_CURVENATUREF0D_H +#define FREESTYLE_PYTHON_CURVENATUREF0D_H + +#include "../BPy_UnaryFunction0DEdgeNature.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject CurveNatureF0D_Type; + +#define BPy_CurveNatureF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &CurveNatureF0D_Type) ) + +/*---------------------------Python BPy_CurveNatureF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DEdgeNature py_uf0D_edgenature; +} BPy_CurveNatureF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_CURVENATUREF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp new file mode 100644 index 00000000000..e1b5e14c9bd --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp @@ -0,0 +1,87 @@ +#include "BPy_Normal2DF0D.h" + +#include "../../../view_map/Functions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char Normal2DF0D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a Normal2DF0D object.\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns a two-dimensional vector giving the normalized 2D normal to\n" +" the 1D element to which the :class:`Interface0D` pointed by the\n" +" Interface0DIterator belongs. The normal is evaluated at the pointed\n" +" Interface0D.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The 2D normal of the 1D element evaluated at the pointed\n" +" Interface0D.\n" +" :rtype: :class:`mathutils.Vector`\n"; + +static int Normal2DF0D___init__( BPy_Normal2DF0D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf0D_vec2f.uf0D_vec2f = new Functions0D::Normal2DF0D(); + self->py_uf0D_vec2f.uf0D_vec2f->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_Normal2DF0D type definition ------------------------------*/ + +PyTypeObject Normal2DF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "Normal2DF0D", /* tp_name */ + sizeof(BPy_Normal2DF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Normal2DF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DVec2f_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)Normal2DF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.h new file mode 100644 index 00000000000..0b3be2df428 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_NORMAL2DF0D_H +#define FREESTYLE_PYTHON_NORMAL2DF0D_H + +#include "../BPy_UnaryFunction0DVec2f.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject Normal2DF0D_Type; + +#define BPy_Normal2DF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Normal2DF0D_Type) ) + +/*---------------------------Python BPy_Normal2DF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DVec2f py_uf0D_vec2f; +} BPy_Normal2DF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_NORMAL2DF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp new file mode 100644 index 00000000000..e1663468307 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp @@ -0,0 +1,87 @@ +#include "BPy_VertexOrientation2DF0D.h" + +#include "../../../view_map/Functions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char VertexOrientation2DF0D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a VertexOrientation2DF0D object.\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns a two-dimensional vector giving the 2D oriented tangent to\n" +" the 1D element to which the :class:`Interface0D` pointed by the\n" +" Interface0DIterator belongs. The 2D oriented tangent is evaluated\n" +" at the pointed Interface0D.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The 2D oriented tangent to the 1D element evaluated at the\n" +" pointed Interface0D.\n" +" :rtype: :class:`mathutils.Vector`\n"; + +static int VertexOrientation2DF0D___init__( BPy_VertexOrientation2DF0D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf0D_vec2f.uf0D_vec2f = new Functions0D::VertexOrientation2DF0D(); + self->py_uf0D_vec2f.uf0D_vec2f->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_VertexOrientation2DF0D type definition ------------------------------*/ + +PyTypeObject VertexOrientation2DF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "VertexOrientation2DF0D", /* tp_name */ + sizeof(BPy_VertexOrientation2DF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + VertexOrientation2DF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DVec2f_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)VertexOrientation2DF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.h new file mode 100644 index 00000000000..1cce9b592ba --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_VERTEXORIENTATION2DF0D_H +#define FREESTYLE_PYTHON_VERTEXORIENTATION2DF0D_H + +#include "../BPy_UnaryFunction0DVec2f.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject VertexOrientation2DF0D_Type; + +#define BPy_VertexOrientation2DF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &VertexOrientation2DF0D_Type) ) + +/*---------------------------Python BPy_VertexOrientation2DF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DVec2f py_uf0D_vec2f; +} BPy_VertexOrientation2DF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_VERTEXORIENTATION2DF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp new file mode 100644 index 00000000000..0455eeac20e --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp @@ -0,0 +1,87 @@ +#include "BPy_VertexOrientation3DF0D.h" + +#include "../../../view_map/Functions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char VertexOrientation3DF0D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a VertexOrientation3DF0D object.\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns a three-dimensional vector giving the 3D oriented tangent\n" +" to the 1D element to which the :class:`Interface0D` pointed by the\n" +" Interface0DIterator belongs. The 3D oriented tangent is evaluated\n" +" at the pointed Interface0D.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The 3D oriented tangent to the 1D element evaluated at the\n" +" pointed Interface0D.\n" +" :rtype: :class:`mathutils.Vector`\n"; + +static int VertexOrientation3DF0D___init__( BPy_VertexOrientation3DF0D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf0D_vec3f.uf0D_vec3f = new Functions0D::VertexOrientation3DF0D(); + self->py_uf0D_vec3f.uf0D_vec3f->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_VertexOrientation3DF0D type definition ------------------------------*/ + +PyTypeObject VertexOrientation3DF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "VertexOrientation3DF0D", /* tp_name */ + sizeof(BPy_VertexOrientation3DF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + VertexOrientation3DF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DVec3f_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)VertexOrientation3DF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.h new file mode 100644 index 00000000000..80cac529f0b --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_VERTEXORIENTATION3DF0D_H +#define FREESTYLE_PYTHON_VERTEXORIENTATION3DF0D_H + +#include "../BPy_UnaryFunction0DVec3f.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject VertexOrientation3DF0D_Type; + +#define BPy_VertexOrientation3DF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &VertexOrientation3DF0D_Type) ) + +/*---------------------------Python BPy_VertexOrientation3DF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DVec3f py_uf0D_vec3f; +} BPy_VertexOrientation3DF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_VERTEXORIENTATION3DF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp new file mode 100644 index 00000000000..d4af0b2f95d --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp @@ -0,0 +1,84 @@ +#include "BPy_GetOccludeeF0D.h" + +#include "../../../view_map/Functions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetOccludeeF0D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a GetOccludeeF0D object.\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns the :class:`ViewShape` that the Interface0D pointed by the\n" +" Interface0DIterator occludes.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The ViewShape occluded by the pointed Interface0D.\n" +" :rtype: :class:`ViewShape`\n"; + +static int GetOccludeeF0D___init__( BPy_GetOccludeeF0D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf0D_viewshape.uf0D_viewshape = new Functions0D::GetOccludeeF0D(); + self->py_uf0D_viewshape.uf0D_viewshape->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_GetOccludeeF0D type definition ------------------------------*/ + +PyTypeObject GetOccludeeF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetOccludeeF0D", /* tp_name */ + sizeof(BPy_GetOccludeeF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetOccludeeF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DViewShape_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetOccludeeF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.h new file mode 100644 index 00000000000..fd4f7d92bbb --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETOCCLUDEEF0D_H +#define FREESTYLE_PYTHON_GETOCCLUDEEF0D_H + +#include "../BPy_UnaryFunction0DViewShape.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetOccludeeF0D_Type; + +#define BPy_GetOccludeeF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetOccludeeF0D_Type) ) + +/*---------------------------Python BPy_GetOccludeeF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DViewShape py_uf0D_viewshape; +} BPy_GetOccludeeF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETOCCLUDEEF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp new file mode 100644 index 00000000000..331ee590b91 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp @@ -0,0 +1,84 @@ +#include "BPy_GetShapeF0D.h" + +#include "../../../view_map/Functions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetShapeF0D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a GetShapeF0D.cpp object.\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns the :class:`ViewShape` containing the Interface0D pointed\n" +" by the Interface0DIterator.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The ViewShape containing the pointed Interface0D.\n" +" :rtype: :class:`ViewShape`\n"; + +static int GetShapeF0D___init__( BPy_GetShapeF0D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf0D_viewshape.uf0D_viewshape = new Functions0D::GetShapeF0D(); + self->py_uf0D_viewshape.uf0D_viewshape->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_GetShapeF0D type definition ------------------------------*/ + +PyTypeObject GetShapeF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetShapeF0D", /* tp_name */ + sizeof(BPy_GetShapeF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetShapeF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DViewShape_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetShapeF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.h new file mode 100644 index 00000000000..040c753968d --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETSHAPEF0D_H +#define FREESTYLE_PYTHON_GETSHAPEF0D_H + +#include "../BPy_UnaryFunction0DViewShape.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetShapeF0D_Type; + +#define BPy_GetShapeF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetShapeF0D_Type) ) + +/*---------------------------Python BPy_GetShapeF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DViewShape py_uf0D_viewshape; +} BPy_GetShapeF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETSHAPEF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp new file mode 100644 index 00000000000..9223c7d0088 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp @@ -0,0 +1,87 @@ +#include "BPy_Curvature2DAngleF0D.h" + +#include "../../../view_map/Functions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char Curvature2DAngleF0D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a Curvature2DAngleF0D object.\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns a real value giving the 2D curvature (as an angle) of the\n" +" 1D element to which the :class:`Interface0D` pointed by the\n" +" Interface0DIterator belongs. The 2D curvature is evaluated at the\n" +" Interface0D.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The 2D curvature of the 1D element evaluated at the\n" +" pointed Interface0D.\n" +" :rtype: float\n"; + +static int Curvature2DAngleF0D___init__( BPy_Curvature2DAngleF0D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf0D_double.uf0D_double = new Functions0D::Curvature2DAngleF0D(); + self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_Curvature2DAngleF0D type definition ------------------------------*/ + +PyTypeObject Curvature2DAngleF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "Curvature2DAngleF0D", /* tp_name */ + sizeof(BPy_Curvature2DAngleF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Curvature2DAngleF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)Curvature2DAngleF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.h new file mode 100644 index 00000000000..810ba04db8a --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_CURVATURE2DANGLEF0D_H +#define FREESTYLE_PYTHON_CURVATURE2DANGLEF0D_H + +#include "../BPy_UnaryFunction0DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject Curvature2DAngleF0D_Type; + +#define BPy_Curvature2DAngleF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Curvature2DAngleF0D_Type) ) + +/*---------------------------Python BPy_Curvature2DAngleF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DDouble py_uf0D_double; +} BPy_Curvature2DAngleF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_CURVATURE2DANGLEF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp new file mode 100644 index 00000000000..4b2f56104a2 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp @@ -0,0 +1,94 @@ +#include "BPy_DensityF0D.h" + +#include "../../../stroke/AdvancedFunctions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char DensityF0D___doc__[] = +".. method:: __init__(sigma=2.0)\n" +"\n" +" Builds a DensityF0D object.\n" +"\n" +" :arg sigma: The gaussian sigma value ndicating the X value for\n" +" which the gaussian function is 0.5. It leads to the window size\n" +" value (the larger, the smoother).\n" +" :type sigma: float\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns the density of the (result) image evaluated at the\n" +" :class:`Interface0D` pointed by the Interface0DIterator. This\n" +" density is evaluated using a pixels square window around the\n" +" evaluation point and integrating these values using a gaussian.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The density of the image evaluated at the pointed\n" +" Interface0D.\n" +" :rtype: float\n"; + +static int DensityF0D___init__( BPy_DensityF0D* self, PyObject *args) +{ + double d = 2; + + if( !PyArg_ParseTuple(args, "|d", &d) ) + return -1; + self->py_uf0D_double.uf0D_double = new Functions0D::DensityF0D(d); + self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_DensityF0D type definition ------------------------------*/ + +PyTypeObject DensityF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "DensityF0D", /* tp_name */ + sizeof(BPy_DensityF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + DensityF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)DensityF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.h new file mode 100644 index 00000000000..17ea95a771c --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_DENSITYF0D_H +#define FREESTYLE_PYTHON_DENSITYF0D_H + +#include "../BPy_UnaryFunction0DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject DensityF0D_Type; + +#define BPy_DensityF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &DensityF0D_Type) ) + +/*---------------------------Python BPy_DensityF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DDouble py_uf0D_double; +} BPy_DensityF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_DENSITYF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp new file mode 100644 index 00000000000..f11555a1e3c --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp @@ -0,0 +1,84 @@ +#include "BPy_GetProjectedXF0D.h" + +#include "../../../view_map/Functions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetProjectedXF0D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a GetProjectedXF0D object.\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns the X 3D projected coordinate of the :class:`Interface0D`\n" +" pointed by the Interface0DIterator.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The X 3D projected coordinate of the pointed Interface0D.\n" +" :rtype: float\n"; + +static int GetProjectedXF0D___init__( BPy_GetProjectedXF0D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf0D_double.uf0D_double = new Functions0D::GetProjectedXF0D(); + self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_GetProjectedXF0D type definition ------------------------------*/ + +PyTypeObject GetProjectedXF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetProjectedXF0D", /* tp_name */ + sizeof(BPy_GetProjectedXF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetProjectedXF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetProjectedXF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.h new file mode 100644 index 00000000000..da73623cbf0 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETPROJECTEDXF0D_H +#define FREESTYLE_PYTHON_GETPROJECTEDXF0D_H + +#include "../BPy_UnaryFunction0DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetProjectedXF0D_Type; + +#define BPy_GetProjectedXF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetProjectedXF0D_Type) ) + +/*---------------------------Python BPy_GetProjectedXF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DDouble py_uf0D_double; +} BPy_GetProjectedXF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETPROJECTEDXF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp new file mode 100644 index 00000000000..fa00514869a --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp @@ -0,0 +1,84 @@ +#include "BPy_GetProjectedYF0D.h" + +#include "../../../view_map/Functions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetProjectedYF0D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a GetProjectedYF0D object.\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns the Y 3D projected coordinate of the :class:`Interface0D`\n" +" pointed by the Interface0DIterator.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The Y 3D projected coordinate of the pointed Interface0D.\n" +" :rtype: float\n"; + +static int GetProjectedYF0D___init__( BPy_GetProjectedYF0D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf0D_double.uf0D_double = new Functions0D::GetProjectedYF0D(); + self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_GetProjectedYF0D type definition ------------------------------*/ + +PyTypeObject GetProjectedYF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetProjectedYF0D", /* tp_name */ + sizeof(BPy_GetProjectedYF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetProjectedYF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetProjectedYF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.h new file mode 100644 index 00000000000..3a26e093747 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETPROJECTEDYF0D_H +#define FREESTYLE_PYTHON_GETPROJECTEDYF0D_H + +#include "../BPy_UnaryFunction0DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetProjectedYF0D_Type; + +#define BPy_GetProjectedYF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetProjectedYF0D_Type) ) + +/*---------------------------Python BPy_GetProjectedYF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DDouble py_uf0D_double; +} BPy_GetProjectedYF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETPROJECTEDYF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp new file mode 100644 index 00000000000..19f61fc8203 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp @@ -0,0 +1,84 @@ +#include "BPy_GetProjectedZF0D.h" + +#include "../../../view_map/Functions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetProjectedZF0D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a GetProjectedZF0D object.\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns the Z 3D projected coordinate of the :class:`Interface0D`\n" +" pointed by the Interface0DIterator.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The Z 3D projected coordinate of the pointed Interface0D.\n" +" :rtype: float\n"; + +static int GetProjectedZF0D___init__( BPy_GetProjectedZF0D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf0D_double.uf0D_double = new Functions0D::GetProjectedZF0D(); + self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_GetProjectedZF0D type definition ------------------------------*/ + +PyTypeObject GetProjectedZF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetProjectedZF0D", /* tp_name */ + sizeof(BPy_GetProjectedZF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetProjectedZF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetProjectedZF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.h new file mode 100644 index 00000000000..aa41b70c660 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETPROJECTEDZF0D_H +#define FREESTYLE_PYTHON_GETPROJECTEDZF0D_H + +#include "../BPy_UnaryFunction0DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetProjectedZF0D_Type; + +#define BPy_GetProjectedZF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetProjectedZF0D_Type) ) + +/*---------------------------Python BPy_GetProjectedZF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DDouble py_uf0D_double; +} BPy_GetProjectedZF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETPROJECTEDZF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp new file mode 100644 index 00000000000..0dde08e6f35 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp @@ -0,0 +1,84 @@ +#include "BPy_GetXF0D.h" + +#include "../../../view_map/Functions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetXF0D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a GetXF0D object.\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns the X 3D coordinate of the :class:`Interface0D` pointed by\n" +" the Interface0DIterator.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The X 3D coordinate of the pointed Interface0D.\n" +" :rtype: float\n"; + +static int GetXF0D___init__( BPy_GetXF0D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf0D_double.uf0D_double = new Functions0D::GetXF0D(); + self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_GetXF0D type definition ------------------------------*/ + +PyTypeObject GetXF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetXF0D", /* tp_name */ + sizeof(BPy_GetXF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetXF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetXF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.h new file mode 100644 index 00000000000..69e9a892f4a --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETXF0D_H +#define FREESTYLE_PYTHON_GETXF0D_H + +#include "../BPy_UnaryFunction0DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetXF0D_Type; + +#define BPy_GetXF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetXF0D_Type) ) + +/*---------------------------Python BPy_GetXF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DDouble py_uf0D_double; +} BPy_GetXF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETXF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp new file mode 100644 index 00000000000..4775c65c199 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp @@ -0,0 +1,84 @@ +#include "BPy_GetYF0D.h" + +#include "../../../view_map/Functions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetYF0D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a GetYF0D object.\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns the Y 3D coordinate of the :class:`Interface0D` pointed by\n" +" the Interface0DIterator.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The Y 3D coordinate of the pointed Interface0D.\n" +" :rtype: float\n"; + +static int GetYF0D___init__( BPy_GetYF0D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf0D_double.uf0D_double = new Functions0D::GetYF0D(); + self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_GetYF0D type definition ------------------------------*/ + +PyTypeObject GetYF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetYF0D", /* tp_name */ + sizeof(BPy_GetYF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetYF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetYF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.h new file mode 100644 index 00000000000..0601f38585f --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETYF0D_H +#define FREESTYLE_PYTHON_GETYF0D_H + +#include "../BPy_UnaryFunction0DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetYF0D_Type; + +#define BPy_GetYF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetYF0D_Type) ) + +/*---------------------------Python BPy_GetYF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DDouble py_uf0D_double; +} BPy_GetYF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETYF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp new file mode 100644 index 00000000000..7a5fdfadf92 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp @@ -0,0 +1,84 @@ +#include "BPy_GetZF0D.h" + +#include "../../../view_map/Functions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetZF0D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a GetZF0D object.\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns the Z 3D coordinate of the :class:`Interface0D` pointed by\n" +" the Interface0DIterator.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The Z 3D coordinate of the pointed Interface0D.\n" +" :rtype: float\n"; + +static int GetZF0D___init__( BPy_GetZF0D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf0D_double.uf0D_double = new Functions0D::GetZF0D(); + self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_GetZF0D type definition ------------------------------*/ + +PyTypeObject GetZF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetZF0D", /* tp_name */ + sizeof(BPy_GetZF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetZF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetZF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.h new file mode 100644 index 00000000000..eac52426600 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETZF0D_H +#define FREESTYLE_PYTHON_GETZF0D_H + +#include "../BPy_UnaryFunction0DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetZF0D_Type; + +#define BPy_GetZF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetZF0D_Type) ) + +/*---------------------------Python BPy_GetZF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DDouble py_uf0D_double; +} BPy_GetZF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETZF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp new file mode 100644 index 00000000000..5c07913100e --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp @@ -0,0 +1,90 @@ +#include "BPy_LocalAverageDepthF0D.h" + +#include "../../../stroke/AdvancedFunctions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char LocalAverageDepthF0D___doc__[] = +".. method:: __init__(maskSize=5.0)\n" +"\n" +" Builds a LocalAverageDepthF0D object.\n" +"\n" +" :arg maskSize: The size of the mask.\n" +" :type maskSize: float\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns the average depth around the :class:`Interface0D` pointed\n" +" by the Interface0DIterator. The result is obtained by querying the\n" +" depth buffer on a window around that point.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The average depth around the pointed Interface0D.\n" +" :rtype: float\n"; + +static int LocalAverageDepthF0D___init__( BPy_LocalAverageDepthF0D* self, PyObject *args) +{ + double d = 5.0; + + if( !PyArg_ParseTuple(args, "|d", &d) ) + return -1; + self->py_uf0D_double.uf0D_double = new Functions0D::LocalAverageDepthF0D(d); + self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_LocalAverageDepthF0D type definition ------------------------------*/ + +PyTypeObject LocalAverageDepthF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "LocalAverageDepthF0D", /* tp_name */ + sizeof(BPy_LocalAverageDepthF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + LocalAverageDepthF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)LocalAverageDepthF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.h new file mode 100644 index 00000000000..7385e1d24c1 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF0D_H +#define FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF0D_H + +#include "../BPy_UnaryFunction0DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject LocalAverageDepthF0D_Type; + +#define BPy_LocalAverageDepthF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &LocalAverageDepthF0D_Type) ) + +/*---------------------------Python BPy_LocalAverageDepthF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DDouble py_uf0D_double; +} BPy_LocalAverageDepthF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp new file mode 100644 index 00000000000..f9bcbb6ee21 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp @@ -0,0 +1,89 @@ +#include "BPy_ZDiscontinuityF0D.h" + +#include "../../../view_map/Functions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ZDiscontinuityF0D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a ZDiscontinuityF0D object.\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns a real value giving the distance between the\n" +" :class:`Interface0D` pointed by the Interface0DIterator and the\n" +" shape that lies behind (occludee). This distance is evaluated in\n" +" the camera space and normalized between 0 and 1. Therefore, if no\n" +" oject is occluded by the shape to which the Interface0D belongs to,\n" +" 1 is returned.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The normalized distance between the pointed Interface0D\n" +" and the occludee.\n" +" :rtype: float\n"; + +static int ZDiscontinuityF0D___init__( BPy_ZDiscontinuityF0D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf0D_double.uf0D_double = new Functions0D::ZDiscontinuityF0D(); + self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_ZDiscontinuityF0D type definition ------------------------------*/ + +PyTypeObject ZDiscontinuityF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ZDiscontinuityF0D", /* tp_name */ + sizeof(BPy_ZDiscontinuityF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ZDiscontinuityF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ZDiscontinuityF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.h new file mode 100644 index 00000000000..a26ba4fdbd6 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_ZDISCONTINUITYF0D_H +#define FREESTYLE_PYTHON_ZDISCONTINUITYF0D_H + +#include "../BPy_UnaryFunction0DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ZDiscontinuityF0D_Type; + +#define BPy_ZDiscontinuityF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ZDiscontinuityF0D_Type) ) + +/*---------------------------Python BPy_ZDiscontinuityF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DDouble py_uf0D_double; +} BPy_ZDiscontinuityF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_ZDISCONTINUITYF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp new file mode 100644 index 00000000000..9dfcf776103 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp @@ -0,0 +1,85 @@ +#include "BPy_GetCurvilinearAbscissaF0D.h" + +#include "../../../view_map/Functions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetCurvilinearAbscissaF0D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a GetCurvilinearAbscissaF0D object.\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns the curvilinear abscissa of the :class:`Interface0D`\n" +" pointed by the Interface0DIterator in the context of its 1D\n" +" element.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The curvilinear abscissa of the pointed Interface0D.\n" +" :rtype: float\n"; + +static int GetCurvilinearAbscissaF0D___init__( BPy_GetCurvilinearAbscissaF0D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf0D_float.uf0D_float = new Functions0D::GetCurvilinearAbscissaF0D(); + self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_GetCurvilinearAbscissaF0D type definition ------------------------------*/ + +PyTypeObject GetCurvilinearAbscissaF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetCurvilinearAbscissaF0D", /* tp_name */ + sizeof(BPy_GetCurvilinearAbscissaF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetCurvilinearAbscissaF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DFloat_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetCurvilinearAbscissaF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.h new file mode 100644 index 00000000000..0cb56fcec70 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETCURVILINEARABSCISSAF0D_H +#define FREESTYLE_PYTHON_GETCURVILINEARABSCISSAF0D_H + +#include "../BPy_UnaryFunction0DFloat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetCurvilinearAbscissaF0D_Type; + +#define BPy_GetCurvilinearAbscissaF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetCurvilinearAbscissaF0D_Type) ) + +/*---------------------------Python BPy_GetCurvilinearAbscissaF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DFloat py_uf0D_float; +} BPy_GetCurvilinearAbscissaF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETCURVILINEARABSCISSAF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp new file mode 100644 index 00000000000..d8861ac2f77 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp @@ -0,0 +1,84 @@ +#include "BPy_GetParameterF0D.h" + +#include "../../../view_map/Functions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetParameterF0D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a GetParameterF0D object.\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns the parameter of the :class:`Interface0D` pointed by the\n" +" Interface0DIterator in the context of its 1D element.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The parameter of an Interface0D.\n" +" :rtype: float\n"; + +static int GetParameterF0D___init__( BPy_GetParameterF0D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf0D_float.uf0D_float = new Functions0D::GetParameterF0D(); + self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_GetParameterF0D type definition ------------------------------*/ + +PyTypeObject GetParameterF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetParameterF0D", /* tp_name */ + sizeof(BPy_GetParameterF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetParameterF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DFloat_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetParameterF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.h new file mode 100644 index 00000000000..4817e5cec86 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETPARAMETERF0D_H +#define FREESTYLE_PYTHON_GETPARAMETERF0D_H + +#include "../BPy_UnaryFunction0DFloat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetParameterF0D_Type; + +#define BPy_GetParameterF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetParameterF0D_Type) ) + +/*---------------------------Python BPy_GetParameterF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DFloat py_uf0D_float; +} BPy_GetParameterF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETPARAMETERF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp new file mode 100644 index 00000000000..b753727fbf5 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp @@ -0,0 +1,91 @@ +#include "BPy_GetViewMapGradientNormF0D.h" + +#include "../../../stroke/AdvancedFunctions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetViewMapGradientNormF0D___doc__[] = +".. method:: __init__(level)\n" +"\n" +" Builds a GetViewMapGradientNormF0D object.\n" +"\n" +" :arg level: The level of the pyramid from which the pixel must be\n" +" read.\n" +" :type level: int\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns the norm of the gradient of the global viewmap density\n" +" image.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The norm of the gradient of the global viewmap density\n" +" image.\n" +" :rtype: float\n"; + +static int GetViewMapGradientNormF0D___init__( BPy_GetViewMapGradientNormF0D* self, PyObject *args) +{ + int i; + + if( !PyArg_ParseTuple(args, "i", &i) ) + return -1; + self->py_uf0D_float.uf0D_float = new Functions0D::GetViewMapGradientNormF0D(i); + self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_GetViewMapGradientNormF0D type definition ------------------------------*/ + +PyTypeObject GetViewMapGradientNormF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetViewMapGradientNormF0D", /* tp_name */ + sizeof(BPy_GetViewMapGradientNormF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetViewMapGradientNormF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DFloat_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetViewMapGradientNormF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.h new file mode 100644 index 00000000000..c072ba7f408 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF0D_H +#define FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF0D_H + +#include "../BPy_UnaryFunction0DFloat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetViewMapGradientNormF0D_Type; + +#define BPy_GetViewMapGradientNormF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetViewMapGradientNormF0D_Type) ) + +/*---------------------------Python BPy_GetViewMapGradientNormF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DFloat py_uf0D_float; +} BPy_GetViewMapGradientNormF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp new file mode 100644 index 00000000000..660f2b9f0c5 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp @@ -0,0 +1,89 @@ +#include "BPy_ReadCompleteViewMapPixelF0D.h" + +#include "../../../stroke/AdvancedFunctions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ReadCompleteViewMapPixelF0D___doc__[] = +".. method:: __init__(level)\n" +"\n" +" Builds a ReadCompleteViewMapPixelF0D object.\n" +"\n" +" :arg level: The level of the pyramid from which the pixel must be\n" +" read.\n" +" :type level: int\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Reads a pixel in one of the level of the complete viewmap.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: A pixel in one of the level of the complete viewmap.\n" +" :rtype: float\n"; + +static int ReadCompleteViewMapPixelF0D___init__( BPy_ReadCompleteViewMapPixelF0D* self, PyObject *args) +{ + int i; + + if( !PyArg_ParseTuple(args, "i", &i) ) + return -1; + self->py_uf0D_float.uf0D_float = new Functions0D::ReadCompleteViewMapPixelF0D(i); + self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_ReadCompleteViewMapPixelF0D type definition ------------------------------*/ + +PyTypeObject ReadCompleteViewMapPixelF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ReadCompleteViewMapPixelF0D", /* tp_name */ + sizeof(BPy_ReadCompleteViewMapPixelF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ReadCompleteViewMapPixelF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DFloat_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ReadCompleteViewMapPixelF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.h new file mode 100644 index 00000000000..6a10e6c06a4 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_READCOMPLETEVIEWMAPPIXELF0D_H +#define FREESTYLE_PYTHON_READCOMPLETEVIEWMAPPIXELF0D_H + +#include "../BPy_UnaryFunction0DFloat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ReadCompleteViewMapPixelF0D_Type; + +#define BPy_ReadCompleteViewMapPixelF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ReadCompleteViewMapPixelF0D_Type) ) + +/*---------------------------Python BPy_ReadCompleteViewMapPixelF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DFloat py_uf0D_float; +} BPy_ReadCompleteViewMapPixelF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_READCOMPLETEVIEWMAPPIXELF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp new file mode 100644 index 00000000000..6c727a86887 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp @@ -0,0 +1,92 @@ +#include "BPy_ReadMapPixelF0D.h" + +#include "../../../stroke/AdvancedFunctions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ReadMapPixelF0D___doc__[] = +".. method:: __init__(iMapName, level)\n" +"\n" +" Builds a ReadMapPixelF0D object.\n" +"\n" +" :arg iMapName: The name of the map to be read.\n" +" :type iMapName: str\n" +" :arg level: The level of the pyramid from which the pixel must be\n" +" read.\n" +" :type level: int\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Reads a pixel in a map.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: A pixel in a map.\n" +" :rtype: float\n"; + +static int ReadMapPixelF0D___init__( BPy_ReadMapPixelF0D* self, PyObject *args) +{ + const char *s; + int i; + + if( !PyArg_ParseTuple(args, "si", &s, &i) ) + return -1; + self->py_uf0D_float.uf0D_float = new Functions0D::ReadMapPixelF0D(s,i); + self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_ReadMapPixelF0D type definition ------------------------------*/ + +PyTypeObject ReadMapPixelF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ReadMapPixelF0D", /* tp_name */ + sizeof(BPy_ReadMapPixelF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ReadMapPixelF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DFloat_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ReadMapPixelF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.h new file mode 100644 index 00000000000..9aed0cd82bf --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_READMAPPIXELF0D_H +#define FREESTYLE_PYTHON_READMAPPIXELF0D_H + +#include "../BPy_UnaryFunction0DFloat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ReadMapPixelF0D_Type; + +#define BPy_ReadMapPixelF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ReadMapPixelF0D_Type) ) + +/*---------------------------Python BPy_ReadMapPixelF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DFloat py_uf0D_float; +} BPy_ReadMapPixelF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_READMAPPIXELF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp new file mode 100644 index 00000000000..5d551d9b910 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp @@ -0,0 +1,93 @@ +#include "BPy_ReadSteerableViewMapPixelF0D.h" + +#include "../../../stroke/AdvancedFunctions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ReadSteerableViewMapPixelF0D___doc__[] = +".. method:: __init__(nOrientation, level)\n" +"\n" +" Builds a ReadSteerableViewMapPixelF0D object.\n" +"\n" +" :arg nOrientation: The integer belonging to [0, 4] indicating the\n" +" orientation (E, NE, N, NW) we are interested in.\n" +" :type nOrientation: int\n" +" :arg level: The level of the pyramid from which the pixel must be\n" +" read.\n" +" :type level: int\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Reads a pixel in one of the level of one of the steerable viewmaps.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: A pixel in one of the level of one of the steerable viewmaps.\n" +" :rtype: float\n"; + +static int ReadSteerableViewMapPixelF0D___init__( BPy_ReadSteerableViewMapPixelF0D* self, PyObject *args) +{ + unsigned int u; + int i; + + if( !PyArg_ParseTuple(args, "Ii", &u, &i) ) + return -1; + self->py_uf0D_float.uf0D_float = new Functions0D::ReadSteerableViewMapPixelF0D(u,i); + self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_ReadSteerableViewMapPixelF0D type definition ------------------------------*/ + +PyTypeObject ReadSteerableViewMapPixelF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ReadSteerableViewMapPixelF0D", /* tp_name */ + sizeof(BPy_ReadSteerableViewMapPixelF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ReadSteerableViewMapPixelF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DFloat_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ReadSteerableViewMapPixelF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.h new file mode 100644 index 00000000000..a881a10f72d --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_READSTEERABLEVIEWMAPPIXELF0D_H +#define FREESTYLE_PYTHON_READSTEERABLEVIEWMAPPIXELF0D_H + +#include "../BPy_UnaryFunction0DFloat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ReadSteerableViewMapPixelF0D_Type; + +#define BPy_ReadSteerableViewMapPixelF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ReadSteerableViewMapPixelF0D_Type) ) + +/*---------------------------Python BPy_ReadSteerableViewMapPixelF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DFloat py_uf0D_float; +} BPy_ReadSteerableViewMapPixelF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_READSTEERABLEVIEWMAPPIXELF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp new file mode 100644 index 00000000000..91093e482ff --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp @@ -0,0 +1,90 @@ +#include "BPy_QuantitativeInvisibilityF0D.h" + +#include "../../../view_map/Functions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char QuantitativeInvisibilityF0D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a QuantitativeInvisibilityF0D object.\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns the quantitative invisibility of the :class:`Interface0D`\n" +" pointed by the Interface0DIterator. This evaluation can be\n" +" ambiguous (in the case of a :class:`TVertex` for example). This\n" +" functor tries to remove this ambiguity using the context offered by\n" +" the 1D element to which the Interface0D belongs to. However, there\n" +" still can be problematic cases, and the user willing to deal with\n" +" this cases in a specific way should implement its own getQIF0D\n" +" functor.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: The quantitative invisibility of the pointed Interface0D.\n" +" :rtype: int\n"; + +static int QuantitativeInvisibilityF0D___init__( BPy_QuantitativeInvisibilityF0D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf0D_unsigned.uf0D_unsigned = new Functions0D::QuantitativeInvisibilityF0D(); + self->py_uf0D_unsigned.uf0D_unsigned->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_QuantitativeInvisibilityF0D type definition ------------------------------*/ + +PyTypeObject QuantitativeInvisibilityF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "QuantitativeInvisibilityF0D", /* tp_name */ + sizeof(BPy_QuantitativeInvisibilityF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + QuantitativeInvisibilityF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DUnsigned_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)QuantitativeInvisibilityF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h new file mode 100644 index 00000000000..39b73343608 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF0D_H +#define FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF0D_H + +#include "../BPy_UnaryFunction0DUnsigned.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject QuantitativeInvisibilityF0D_Type; + +#define BPy_QuantitativeInvisibilityF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &QuantitativeInvisibilityF0D_Type) ) + +/*---------------------------Python BPy_QuantitativeInvisibilityF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DUnsigned py_uf0D_unsigned; +} BPy_QuantitativeInvisibilityF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp new file mode 100644 index 00000000000..943d1950016 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp @@ -0,0 +1,85 @@ +#include "BPy_GetOccludersF0D.h" + +#include "../../../view_map/Functions0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetOccludersF0D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a GetOccludersF0D object.\n" +"\n" +".. method:: __call__(it)\n" +"\n" +" Returns a list of :class:`ViewShape` objects occluding the\n" +" :class:`Interface0D` pointed by the Interface0DIterator.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: A list of ViewShape objects occluding the pointed\n" +" Interface0D.\n" +" :rtype: list of :class:`ViewShape` objects\n"; + +static int GetOccludersF0D___init__( BPy_GetOccludersF0D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf0D_vectorviewshape.uf0D_vectorviewshape = new Functions0D::GetOccludersF0D(); + self->py_uf0D_vectorviewshape.uf0D_vectorviewshape->py_uf0D = (PyObject *)self; + return 0; +} + +/*-----------------------BPy_GetOccludersF0D type definition ------------------------------*/ + +PyTypeObject GetOccludersF0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetOccludersF0D", /* tp_name */ + sizeof(BPy_GetOccludersF0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetOccludersF0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction0DVectorViewShape_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetOccludersF0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h new file mode 100644 index 00000000000..0e92158a2e7 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETOCCLUDERSF0D_H +#define FREESTYLE_PYTHON_GETOCCLUDERSF0D_H + +#include "../BPy_UnaryFunction0DVectorViewShape.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetOccludersF0D_Type; + +#define BPy_GetOccludersF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetOccludersF0D_Type) ) + +/*---------------------------Python BPy_GetOccludersF0D structure definition----------*/ +typedef struct { + BPy_UnaryFunction0DVectorViewShape py_uf0D_vectorviewshape; +} BPy_GetOccludersF0D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETOCCLUDERSF0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp new file mode 100644 index 00000000000..ac61161f65c --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp @@ -0,0 +1,287 @@ +#include "BPy_UnaryFunction1DDouble.h" + +#include "../BPy_Convert.h" +#include "../BPy_Interface1D.h" +#include "../BPy_IntegrationType.h" + +#include "UnaryFunction1D_double/BPy_Curvature2DAngleF1D.h" +#include "UnaryFunction1D_double/BPy_DensityF1D.h" +#include "UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.h" +#include "UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.h" +#include "UnaryFunction1D_double/BPy_GetProjectedXF1D.h" +#include "UnaryFunction1D_double/BPy_GetProjectedYF1D.h" +#include "UnaryFunction1D_double/BPy_GetProjectedZF1D.h" +#include "UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.h" +#include "UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.h" +#include "UnaryFunction1D_double/BPy_GetXF1D.h" +#include "UnaryFunction1D_double/BPy_GetYF1D.h" +#include "UnaryFunction1D_double/BPy_GetZF1D.h" +#include "UnaryFunction1D_double/BPy_LocalAverageDepthF1D.h" +#include "UnaryFunction1D_double/BPy_ZDiscontinuityF1D.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- + +int UnaryFunction1DDouble_Init( PyObject *module ) { + + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryFunction1DDouble_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryFunction1DDouble_Type ); + PyModule_AddObject(module, "UnaryFunction1DDouble", (PyObject *)&UnaryFunction1DDouble_Type); + + if( PyType_Ready( &DensityF1D_Type ) < 0 ) + return -1; + Py_INCREF( &DensityF1D_Type ); + PyModule_AddObject(module, "DensityF1D", (PyObject *)&DensityF1D_Type); + + if( PyType_Ready( &Curvature2DAngleF1D_Type ) < 0 ) + return -1; + Py_INCREF( &Curvature2DAngleF1D_Type ); + PyModule_AddObject(module, "Curvature2DAngleF1D", (PyObject *)&Curvature2DAngleF1D_Type); + + if( PyType_Ready( &GetCompleteViewMapDensityF1D_Type ) < 0 ) + return -1; + Py_INCREF( &GetCompleteViewMapDensityF1D_Type ); + PyModule_AddObject(module, "GetCompleteViewMapDensityF1D", (PyObject *)&GetCompleteViewMapDensityF1D_Type); + + if( PyType_Ready( &GetDirectionalViewMapDensityF1D_Type ) < 0 ) + return -1; + Py_INCREF( &GetDirectionalViewMapDensityF1D_Type ); + PyModule_AddObject(module, "GetDirectionalViewMapDensityF1D", (PyObject *)&GetDirectionalViewMapDensityF1D_Type); + + if( PyType_Ready( &GetProjectedXF1D_Type ) < 0 ) + return -1; + Py_INCREF( &GetProjectedXF1D_Type ); + PyModule_AddObject(module, "GetProjectedXF1D", (PyObject *)&GetProjectedXF1D_Type); + + if( PyType_Ready( &GetProjectedYF1D_Type ) < 0 ) + return -1; + Py_INCREF( &GetProjectedYF1D_Type ); + PyModule_AddObject(module, "GetProjectedYF1D", (PyObject *)&GetProjectedYF1D_Type); + + if( PyType_Ready( &GetProjectedZF1D_Type ) < 0 ) + return -1; + Py_INCREF( &GetProjectedZF1D_Type ); + PyModule_AddObject(module, "GetProjectedZF1D", (PyObject *)&GetProjectedZF1D_Type); + + if( PyType_Ready( &GetSteerableViewMapDensityF1D_Type ) < 0 ) + return -1; + Py_INCREF( &GetSteerableViewMapDensityF1D_Type ); + PyModule_AddObject(module, "GetSteerableViewMapDensityF1D", (PyObject *)&GetSteerableViewMapDensityF1D_Type); + + if( PyType_Ready( &GetViewMapGradientNormF1D_Type ) < 0 ) + return -1; + Py_INCREF( &GetViewMapGradientNormF1D_Type ); + PyModule_AddObject(module, "GetViewMapGradientNormF1D", (PyObject *)&GetViewMapGradientNormF1D_Type); + + if( PyType_Ready( &GetXF1D_Type ) < 0 ) + return -1; + Py_INCREF( &GetXF1D_Type ); + PyModule_AddObject(module, "GetXF1D", (PyObject *)&GetXF1D_Type); + + if( PyType_Ready( &GetYF1D_Type ) < 0 ) + return -1; + Py_INCREF( &GetYF1D_Type ); + PyModule_AddObject(module, "GetYF1D", (PyObject *)&GetYF1D_Type); + + if( PyType_Ready( &GetZF1D_Type ) < 0 ) + return -1; + Py_INCREF( &GetZF1D_Type ); + PyModule_AddObject(module, "GetZF1D", (PyObject *)&GetZF1D_Type); + + if( PyType_Ready( &LocalAverageDepthF1D_Type ) < 0 ) + return -1; + Py_INCREF( &LocalAverageDepthF1D_Type ); + PyModule_AddObject(module, "LocalAverageDepthF1D", (PyObject *)&LocalAverageDepthF1D_Type); + + if( PyType_Ready( &ZDiscontinuityF1D_Type ) < 0 ) + return -1; + Py_INCREF( &ZDiscontinuityF1D_Type ); + PyModule_AddObject(module, "ZDiscontinuityF1D", (PyObject *)&ZDiscontinuityF1D_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryFunction1DDouble___doc__[] = +"Base class for unary functions (functors) that work on\n" +":class:`Interface1D` and return a float value.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(integration)\n" +"\n" +" Builds a unary 1D function using the integration method given as\n" +" argument.\n" +"\n" +" :arg integration: An integration method.\n" +" :type integration: :class:`IntegrationType`\n"; + +static int UnaryFunction1DDouble___init__(BPy_UnaryFunction1DDouble* self, PyObject *args) +{ + PyObject *obj = 0; + + if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) ) + return -1; + + if( !obj ) + self->uf1D_double = new UnaryFunction1D<double>(); + else { + self->uf1D_double = new UnaryFunction1D<double>( IntegrationType_from_BPy_IntegrationType(obj) ); + } + + self->uf1D_double->py_uf1D = (PyObject *)self; + + return 0; +} + +static void UnaryFunction1DDouble___dealloc__(BPy_UnaryFunction1DDouble* self) +{ + if (self->uf1D_double) + delete self->uf1D_double; + UnaryFunction1D_Type.tp_dealloc((PyObject*)self); +} + +static PyObject * UnaryFunction1DDouble___repr__(BPy_UnaryFunction1DDouble* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_double->getName().c_str(), self->uf1D_double ); +} + +static char UnaryFunction1DDouble_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the unary 1D function.\n" +"\n" +" :return: The name of the unary 1D function.\n" +" :rtype: str\n"; + +static PyObject * UnaryFunction1DDouble_getName( BPy_UnaryFunction1DDouble *self ) +{ + return PyUnicode_FromString( self->uf1D_double->getName().c_str() ); +} + +static PyObject * UnaryFunction1DDouble___call__( BPy_UnaryFunction1DDouble *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) ) + return NULL; + + if( typeid(*(self->uf1D_double)) == typeid(UnaryFunction1D<double>) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if (self->uf1D_double->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) { + if (!PyErr_Occurred()) { + string msg(self->uf1D_double->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + return PyFloat_FromDouble( self->uf1D_double->result ); + +} + +static char UnaryFunction1DDouble_setIntegrationType___doc__[] = +".. method:: setIntegrationType(integration)\n" +"\n" +" Sets the integration method.\n" +"\n" +" :arg integration: An integration method.\n" +" :type integration: :class:`IntegrationType`\n"; + +static PyObject * UnaryFunction1DDouble_setIntegrationType(BPy_UnaryFunction1DDouble* self, PyObject *args) +{ + PyObject *obj; + + if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) ) + return NULL; + + self->uf1D_double->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) ); + Py_RETURN_NONE; +} + +static char UnaryFunction1DDouble_getIntegrationType___doc__[] = +".. method:: getIntegrationType(integration)\n" +"\n" +" Returns the integration method.\n" +"\n" +" :return: The integration method.\n" +" :rtype: :class:`IntegrationType`\n"; + +static PyObject * UnaryFunction1DDouble_getIntegrationType(BPy_UnaryFunction1DDouble* self) { + return BPy_IntegrationType_from_IntegrationType( self->uf1D_double->getIntegrationType() ); +} + +/*----------------------UnaryFunction1DDouble instance definitions ----------------------------*/ +static PyMethodDef BPy_UnaryFunction1DDouble_methods[] = { + {"getName", ( PyCFunction ) UnaryFunction1DDouble_getName, METH_NOARGS, UnaryFunction1DDouble_getName___doc__}, + {"setIntegrationType", ( PyCFunction ) UnaryFunction1DDouble_setIntegrationType, METH_VARARGS, UnaryFunction1DDouble_setIntegrationType___doc__}, + {"getIntegrationType", ( PyCFunction ) UnaryFunction1DDouble_getIntegrationType, METH_NOARGS, UnaryFunction1DDouble_getIntegrationType___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_UnaryFunction1DDouble type definition ------------------------------*/ + +PyTypeObject UnaryFunction1DDouble_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryFunction1DDouble", /* tp_name */ + sizeof(BPy_UnaryFunction1DDouble), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryFunction1DDouble___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryFunction1DDouble___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)UnaryFunction1DDouble___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryFunction1DDouble___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_UnaryFunction1DDouble_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)UnaryFunction1DDouble___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.h new file mode 100644 index 00000000000..9a9170cfe17 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.h @@ -0,0 +1,34 @@ +#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DDOUBLE_H +#define FREESTYLE_PYTHON_UNARYFUNCTION1DDOUBLE_H + +#include "../BPy_UnaryFunction1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject UnaryFunction1DDouble_Type; + +#define BPy_UnaryFunction1DDouble_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DDouble_Type) ) + +/*---------------------------Python BPy_UnaryFunction1DDouble structure definition----------*/ +typedef struct { + BPy_UnaryFunction1D py_uf1D; + UnaryFunction1D<double> *uf1D_double; +} BPy_UnaryFunction1DDouble; + +/*---------------------------Python BPy_UnaryFunction1DDouble visible prototypes-----------*/ +int UnaryFunction1DDouble_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DDOUBLE_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp new file mode 100644 index 00000000000..be58cbdaa35 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp @@ -0,0 +1,208 @@ +#include "BPy_UnaryFunction1DEdgeNature.h" + +#include "../BPy_Convert.h" +#include "../BPy_Interface1D.h" +#include "../BPy_IntegrationType.h" + +#include "UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- + +int UnaryFunction1DEdgeNature_Init( PyObject *module ) { + + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryFunction1DEdgeNature_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryFunction1DEdgeNature_Type ); + PyModule_AddObject(module, "UnaryFunction1DEdgeNature", (PyObject *)&UnaryFunction1DEdgeNature_Type); + + if( PyType_Ready( &CurveNatureF1D_Type ) < 0 ) + return -1; + Py_INCREF( &CurveNatureF1D_Type ); + PyModule_AddObject(module, "CurveNatureF1D", (PyObject *)&CurveNatureF1D_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryFunction1DEdgeNature___doc__[] = +"Base class for unary functions (functors) that work on\n" +":class:`Interface1D` and return a :class:`Nature` object.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(integration)\n" +"\n" +" Builds a unary 1D function using the integration method given as\n" +" argument.\n" +"\n" +" :arg integration: An integration method.\n" +" :type integration: :class:`IntegrationType`\n"; + +static int UnaryFunction1DEdgeNature___init__(BPy_UnaryFunction1DEdgeNature* self, PyObject *args) +{ + PyObject *obj = 0; + + if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) ) + return -1; + + if( !obj ) + self->uf1D_edgenature = new UnaryFunction1D<Nature::EdgeNature>(); + else { + self->uf1D_edgenature = new UnaryFunction1D<Nature::EdgeNature>( IntegrationType_from_BPy_IntegrationType(obj) ); + } + + self->uf1D_edgenature->py_uf1D = (PyObject *)self; + + return 0; +} + +static void UnaryFunction1DEdgeNature___dealloc__(BPy_UnaryFunction1DEdgeNature* self) +{ + if (self->uf1D_edgenature) + delete self->uf1D_edgenature; + UnaryFunction1D_Type.tp_dealloc((PyObject*)self); +} + +static PyObject * UnaryFunction1DEdgeNature___repr__(BPy_UnaryFunction1DEdgeNature* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_edgenature->getName().c_str(), self->uf1D_edgenature ); +} + +static char UnaryFunction1DEdgeNature_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the unary 1D function.\n" +"\n" +" :return: The name of the unary 1D function.\n" +" :rtype: str\n"; + +static PyObject * UnaryFunction1DEdgeNature_getName( BPy_UnaryFunction1DEdgeNature *self ) +{ + return PyUnicode_FromString( self->uf1D_edgenature->getName().c_str() ); +} + +static PyObject * UnaryFunction1DEdgeNature___call__( BPy_UnaryFunction1DEdgeNature *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) ) + return NULL; + + if( typeid(*(self->uf1D_edgenature)) == typeid(UnaryFunction1D<Nature::EdgeNature>) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if (self->uf1D_edgenature->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) { + if (!PyErr_Occurred()) { + string msg(self->uf1D_edgenature->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + return BPy_Nature_from_Nature( self->uf1D_edgenature->result ); + +} + +static char UnaryFunction1DEdgeNature_setIntegrationType___doc__[] = +".. method:: setIntegrationType(integration)\n" +"\n" +" Sets the integration method.\n" +"\n" +" :arg integration: An integration method.\n" +" :type integration: :class:`IntegrationType`\n"; + +static PyObject * UnaryFunction1DEdgeNature_setIntegrationType(BPy_UnaryFunction1DEdgeNature* self, PyObject *args) +{ + PyObject *obj; + + if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) ) + return NULL; + + self->uf1D_edgenature->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) ); + Py_RETURN_NONE; +} + +static char UnaryFunction1DEdgeNature_getIntegrationType___doc__[] = +".. method:: getIntegrationType(integration)\n" +"\n" +" Returns the integration method.\n" +"\n" +" :return: The integration method.\n" +" :rtype: :class:`IntegrationType`\n"; + +static PyObject * UnaryFunction1DEdgeNature_getIntegrationType(BPy_UnaryFunction1DEdgeNature* self) { + return BPy_IntegrationType_from_IntegrationType( self->uf1D_edgenature->getIntegrationType() ); +} + +/*----------------------UnaryFunction1DEdgeNature instance definitions ----------------------------*/ +static PyMethodDef BPy_UnaryFunction1DEdgeNature_methods[] = { + {"getName", ( PyCFunction ) UnaryFunction1DEdgeNature_getName, METH_NOARGS, UnaryFunction1DEdgeNature_getName___doc__}, + {"setIntegrationType", ( PyCFunction ) UnaryFunction1DEdgeNature_setIntegrationType, METH_VARARGS, UnaryFunction1DEdgeNature_setIntegrationType___doc__}, + {"getIntegrationType", ( PyCFunction ) UnaryFunction1DEdgeNature_getIntegrationType, METH_NOARGS, UnaryFunction1DEdgeNature_getIntegrationType___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_UnaryFunction1DEdgeNature type definition ------------------------------*/ + +PyTypeObject UnaryFunction1DEdgeNature_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryFunction1DEdgeNature", /* tp_name */ + sizeof(BPy_UnaryFunction1DEdgeNature), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryFunction1DEdgeNature___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryFunction1DEdgeNature___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)UnaryFunction1DEdgeNature___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryFunction1DEdgeNature___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_UnaryFunction1DEdgeNature_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)UnaryFunction1DEdgeNature___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h new file mode 100644 index 00000000000..05e3e522c4b --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h @@ -0,0 +1,36 @@ +#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DEDGENATURE_H +#define FREESTYLE_PYTHON_UNARYFUNCTION1DEDGENATURE_H + +#include "../BPy_UnaryFunction1D.h" + +#include "../../winged_edge/Nature.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject UnaryFunction1DEdgeNature_Type; + +#define BPy_UnaryFunction1DEdgeNature_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DEdgeNature_Type) ) + +/*---------------------------Python BPy_UnaryFunction1DEdgeNature structure definition----------*/ +typedef struct { + BPy_UnaryFunction1D py_uf1D; + UnaryFunction1D<Nature::EdgeNature> *uf1D_edgenature; +} BPy_UnaryFunction1DEdgeNature; + +/*---------------------------Python BPy_UnaryFunction1DEdgeNature visible prototypes-----------*/ +int UnaryFunction1DEdgeNature_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DEDGENATURE_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp new file mode 100644 index 00000000000..04e98e683d1 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp @@ -0,0 +1,201 @@ +#include "BPy_UnaryFunction1DFloat.h" + +#include "../BPy_Convert.h" +#include "../BPy_Interface1D.h" +#include "../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- + +int UnaryFunction1DFloat_Init( PyObject *module ) { + + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryFunction1DFloat_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryFunction1DFloat_Type ); + PyModule_AddObject(module, "UnaryFunction1DFloat", (PyObject *)&UnaryFunction1DFloat_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryFunction1DFloat___doc__[] = +"Base class for unary functions (functors) that work on\n" +":class:`Interface1D` and return a float value.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(integration)\n" +"\n" +" Builds a unary 1D function using the integration method given as\n" +" argument.\n" +"\n" +" :arg integration: An integration method.\n" +" :type integration: :class:`IntegrationType`\n"; + +static int UnaryFunction1DFloat___init__(BPy_UnaryFunction1DFloat* self, PyObject *args) +{ + PyObject *obj = 0; + + if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) ) + return -1; + + if( !obj ) + self->uf1D_float = new UnaryFunction1D<float>(); + else { + self->uf1D_float = new UnaryFunction1D<float>( IntegrationType_from_BPy_IntegrationType(obj) ); + } + + self->uf1D_float->py_uf1D = (PyObject *)self; + + return 0; +} + +static void UnaryFunction1DFloat___dealloc__(BPy_UnaryFunction1DFloat* self) +{ + if (self->uf1D_float) + delete self->uf1D_float; + UnaryFunction1D_Type.tp_dealloc((PyObject*)self); +} + +static PyObject * UnaryFunction1DFloat___repr__(BPy_UnaryFunction1DFloat* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_float->getName().c_str(), self->uf1D_float ); +} + +static char UnaryFunction1DFloat_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the unary 1D function.\n" +"\n" +" :return: The name of the unary 1D function.\n" +" :rtype: str\n"; + +static PyObject * UnaryFunction1DFloat_getName( BPy_UnaryFunction1DFloat *self ) +{ + return PyUnicode_FromString( self->uf1D_float->getName().c_str() ); +} + +static PyObject * UnaryFunction1DFloat___call__( BPy_UnaryFunction1DFloat *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) ) + return NULL; + + if( typeid(*(self->uf1D_float)) == typeid(UnaryFunction1D<float>) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if (self->uf1D_float->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) { + if (!PyErr_Occurred()) { + string msg(self->uf1D_float->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + return PyFloat_FromDouble( self->uf1D_float->result ); + +} + +static char UnaryFunction1DFloat_setIntegrationType___doc__[] = +".. method:: setIntegrationType(integration)\n" +"\n" +" Sets the integration method.\n" +"\n" +" :arg integration: An integration method.\n" +" :type integration: :class:`IntegrationType`\n"; + +static PyObject * UnaryFunction1DFloat_setIntegrationType(BPy_UnaryFunction1DFloat* self, PyObject *args) +{ + PyObject *obj; + + if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) ) + return NULL; + + self->uf1D_float->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) ); + Py_RETURN_NONE; +} + +static char UnaryFunction1DFloat_getIntegrationType___doc__[] = +".. method:: getIntegrationType(integration)\n" +"\n" +" Returns the integration method.\n" +"\n" +" :return: The integration method.\n" +" :rtype: :class:`IntegrationType`\n"; + +static PyObject * UnaryFunction1DFloat_getIntegrationType(BPy_UnaryFunction1DFloat* self) { + return BPy_IntegrationType_from_IntegrationType( self->uf1D_float->getIntegrationType() ); +} + +/*----------------------UnaryFunction1DFloat instance definitions ----------------------------*/ +static PyMethodDef BPy_UnaryFunction1DFloat_methods[] = { + {"getName", ( PyCFunction ) UnaryFunction1DFloat_getName, METH_NOARGS, UnaryFunction1DFloat_getName___doc__}, + {"setIntegrationType", ( PyCFunction ) UnaryFunction1DFloat_setIntegrationType, METH_VARARGS, UnaryFunction1DFloat_setIntegrationType___doc__}, + {"getIntegrationType", ( PyCFunction ) UnaryFunction1DFloat_getIntegrationType, METH_NOARGS, UnaryFunction1DFloat_getIntegrationType___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_UnaryFunction1DFloat type definition ------------------------------*/ + +PyTypeObject UnaryFunction1DFloat_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryFunction1DFloat", /* tp_name */ + sizeof(BPy_UnaryFunction1DFloat), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryFunction1DFloat___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryFunction1DFloat___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)UnaryFunction1DFloat___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryFunction1DFloat___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_UnaryFunction1DFloat_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)UnaryFunction1DFloat___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.h new file mode 100644 index 00000000000..529b382372e --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.h @@ -0,0 +1,34 @@ +#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DFLOAT_H +#define FREESTYLE_PYTHON_UNARYFUNCTION1DFLOAT_H + +#include "../BPy_UnaryFunction1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject UnaryFunction1DFloat_Type; + +#define BPy_UnaryFunction1DFloat_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DFloat_Type) ) + +/*---------------------------Python BPy_UnaryFunction1DFloat structure definition----------*/ +typedef struct { + BPy_UnaryFunction1D py_uf1D; + UnaryFunction1D<float> *uf1D_float; +} BPy_UnaryFunction1DFloat; + +/*---------------------------Python BPy_UnaryFunction1DFloat visible prototypes-----------*/ +int UnaryFunction1DFloat_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DFLOAT_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp new file mode 100644 index 00000000000..74d9a858efa --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp @@ -0,0 +1,208 @@ +#include "BPy_UnaryFunction1DUnsigned.h" + +#include "../BPy_Convert.h" +#include "../BPy_Interface1D.h" +#include "../BPy_IntegrationType.h" + +#include "UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- + +int UnaryFunction1DUnsigned_Init( PyObject *module ) { + + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryFunction1DUnsigned_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryFunction1DUnsigned_Type ); + PyModule_AddObject(module, "UnaryFunction1DUnsigned", (PyObject *)&UnaryFunction1DUnsigned_Type); + + if( PyType_Ready( &QuantitativeInvisibilityF1D_Type ) < 0 ) + return -1; + Py_INCREF( &QuantitativeInvisibilityF1D_Type ); + PyModule_AddObject(module, "QuantitativeInvisibilityF1D", (PyObject *)&QuantitativeInvisibilityF1D_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryFunction1DUnsigned___doc__[] = +"Base class for unary functions (functors) that work on\n" +":class:`Interface1D` and return an int value.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(integration)\n" +"\n" +" Builds a unary 1D function using the integration method given as\n" +" argument.\n" +"\n" +" :arg integration: An integration method.\n" +" :type integration: :class:`IntegrationType`\n"; + +static int UnaryFunction1DUnsigned___init__(BPy_UnaryFunction1DUnsigned* self, PyObject *args) +{ + PyObject *obj = 0; + + if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) ) + return -1; + + if( !obj ) + self->uf1D_unsigned = new UnaryFunction1D<unsigned int>(); + else { + self->uf1D_unsigned = new UnaryFunction1D<unsigned int>( IntegrationType_from_BPy_IntegrationType(obj) ); + } + + self->uf1D_unsigned->py_uf1D = (PyObject *)self; + + return 0; +} + +static void UnaryFunction1DUnsigned___dealloc__(BPy_UnaryFunction1DUnsigned* self) +{ + if (self->uf1D_unsigned) + delete self->uf1D_unsigned; + UnaryFunction1D_Type.tp_dealloc((PyObject*)self); +} + +static PyObject * UnaryFunction1DUnsigned___repr__(BPy_UnaryFunction1DUnsigned* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_unsigned->getName().c_str(), self->uf1D_unsigned ); +} + +static char UnaryFunction1DUnsigned_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the unary 1D function.\n" +"\n" +" :return: The name of the unary 1D function.\n" +" :rtype: str\n"; + +static PyObject * UnaryFunction1DUnsigned_getName( BPy_UnaryFunction1DUnsigned *self ) +{ + return PyUnicode_FromString( self->uf1D_unsigned->getName().c_str() ); +} + +static PyObject * UnaryFunction1DUnsigned___call__( BPy_UnaryFunction1DUnsigned *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) ) + return NULL; + + if( typeid(*(self->uf1D_unsigned)) == typeid(UnaryFunction1D<unsigned int>) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if (self->uf1D_unsigned->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) { + if (!PyErr_Occurred()) { + string msg(self->uf1D_unsigned->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + return PyLong_FromLong( self->uf1D_unsigned->result ); + +} + +static char UnaryFunction1DUnsigned_setIntegrationType___doc__[] = +".. method:: setIntegrationType(integration)\n" +"\n" +" Sets the integration method.\n" +"\n" +" :arg integration: An integration method.\n" +" :type integration: :class:`IntegrationType`\n"; + +static PyObject * UnaryFunction1DUnsigned_setIntegrationType(BPy_UnaryFunction1DUnsigned* self, PyObject *args) +{ + PyObject *obj; + + if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) ) + return NULL; + + self->uf1D_unsigned->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) ); + Py_RETURN_NONE; +} + +static char UnaryFunction1DUnsigned_getIntegrationType___doc__[] = +".. method:: getIntegrationType(integration)\n" +"\n" +" Returns the integration method.\n" +"\n" +" :return: The integration method.\n" +" :rtype: :class:`IntegrationType`\n"; + +static PyObject * UnaryFunction1DUnsigned_getIntegrationType(BPy_UnaryFunction1DUnsigned* self) { + return BPy_IntegrationType_from_IntegrationType( self->uf1D_unsigned->getIntegrationType() ); +} + +/*----------------------UnaryFunction1DUnsigned instance definitions ----------------------------*/ +static PyMethodDef BPy_UnaryFunction1DUnsigned_methods[] = { + {"getName", ( PyCFunction ) UnaryFunction1DUnsigned_getName, METH_NOARGS, UnaryFunction1DUnsigned_getName___doc__}, + {"setIntegrationType", ( PyCFunction ) UnaryFunction1DUnsigned_setIntegrationType, METH_VARARGS, UnaryFunction1DUnsigned_setIntegrationType___doc__}, + {"getIntegrationType", ( PyCFunction ) UnaryFunction1DUnsigned_getIntegrationType, METH_NOARGS, UnaryFunction1DUnsigned_getIntegrationType___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_UnaryFunction1DUnsigned type definition ------------------------------*/ + +PyTypeObject UnaryFunction1DUnsigned_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryFunction1DUnsigned", /* tp_name */ + sizeof(BPy_UnaryFunction1DUnsigned), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryFunction1DUnsigned___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryFunction1DUnsigned___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)UnaryFunction1DUnsigned___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryFunction1DUnsigned___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_UnaryFunction1DUnsigned_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)UnaryFunction1DUnsigned___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h new file mode 100644 index 00000000000..c70cc6257a7 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h @@ -0,0 +1,34 @@ +#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DUNSIGNED_H +#define FREESTYLE_PYTHON_UNARYFUNCTION1DUNSIGNED_H + +#include "../BPy_UnaryFunction1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject UnaryFunction1DUnsigned_Type; + +#define BPy_UnaryFunction1DUnsigned_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DUnsigned_Type) ) + +/*---------------------------Python BPy_UnaryFunction1DUnsigned structure definition----------*/ +typedef struct { + BPy_UnaryFunction1D py_uf1D; + UnaryFunction1D<unsigned int> *uf1D_unsigned; +} BPy_UnaryFunction1DUnsigned; + +/*---------------------------Python BPy_UnaryFunction1DUnsigned visible prototypes-----------*/ +int UnaryFunction1DUnsigned_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DUNSIGNED_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp new file mode 100644 index 00000000000..4bbe40cfdef --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp @@ -0,0 +1,214 @@ +#include "BPy_UnaryFunction1DVec2f.h" + +#include "../BPy_Convert.h" +#include "../BPy_Interface1D.h" +#include "../BPy_IntegrationType.h" + +#include "UnaryFunction1D_Vec2f/BPy_Normal2DF1D.h" +#include "UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- + +int UnaryFunction1DVec2f_Init( PyObject *module ) { + + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryFunction1DVec2f_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryFunction1DVec2f_Type ); + PyModule_AddObject(module, "UnaryFunction1DVec2f", (PyObject *)&UnaryFunction1DVec2f_Type); + + if( PyType_Ready( &Normal2DF1D_Type ) < 0 ) + return -1; + Py_INCREF( &Normal2DF1D_Type ); + PyModule_AddObject(module, "Normal2DF1D", (PyObject *)&Normal2DF1D_Type); + + if( PyType_Ready( &Orientation2DF1D_Type ) < 0 ) + return -1; + Py_INCREF( &Orientation2DF1D_Type ); + PyModule_AddObject(module, "Orientation2DF1D", (PyObject *)&Orientation2DF1D_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryFunction1DVec2f___doc__[] = +"Base class for unary functions (functors) that work on\n" +":class:`Interface1D` and return a 2D vector.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(integration)\n" +"\n" +" Builds a unary 1D function using the integration method given as\n" +" argument.\n" +"\n" +" :arg integration: An integration method.\n" +" :type integration: :class:`IntegrationType`\n"; + +static int UnaryFunction1DVec2f___init__(BPy_UnaryFunction1DVec2f* self, PyObject *args) +{ + PyObject *obj = 0; + + if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) ) + return -1; + + if( !obj ) + self->uf1D_vec2f = new UnaryFunction1D<Vec2f>(); + else { + self->uf1D_vec2f = new UnaryFunction1D<Vec2f>( IntegrationType_from_BPy_IntegrationType(obj) ); + } + + self->uf1D_vec2f->py_uf1D = (PyObject *)self; + + return 0; +} + +static void UnaryFunction1DVec2f___dealloc__(BPy_UnaryFunction1DVec2f* self) +{ + if (self->uf1D_vec2f) + delete self->uf1D_vec2f; + UnaryFunction1D_Type.tp_dealloc((PyObject*)self); +} + +static PyObject * UnaryFunction1DVec2f___repr__(BPy_UnaryFunction1DVec2f* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_vec2f->getName().c_str(), self->uf1D_vec2f ); +} + +static char UnaryFunction1DVec2f_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the unary 1D function.\n" +"\n" +" :return: The name of the unary 1D function.\n" +" :rtype: str\n"; + +static PyObject * UnaryFunction1DVec2f_getName( BPy_UnaryFunction1DVec2f *self ) +{ + return PyUnicode_FromString( self->uf1D_vec2f->getName().c_str() ); +} + +static PyObject * UnaryFunction1DVec2f___call__( BPy_UnaryFunction1DVec2f *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) ) + return NULL; + + if( typeid(*(self->uf1D_vec2f)) == typeid(UnaryFunction1D<Vec2f>) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if (self->uf1D_vec2f->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) { + if (!PyErr_Occurred()) { + string msg(self->uf1D_vec2f->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + return Vector_from_Vec2f( self->uf1D_vec2f->result ); + +} + +static char UnaryFunction1DVec2f_setIntegrationType___doc__[] = +".. method:: setIntegrationType(integration)\n" +"\n" +" Sets the integration method.\n" +"\n" +" :arg integration: An integration method.\n" +" :type integration: :class:`IntegrationType`\n"; + +static PyObject * UnaryFunction1DVec2f_setIntegrationType(BPy_UnaryFunction1DVec2f* self, PyObject *args) +{ + PyObject *obj; + + if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) ) + return NULL; + + self->uf1D_vec2f->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) ); + Py_RETURN_NONE; +} + +static char UnaryFunction1DVec2f_getIntegrationType___doc__[] = +".. method:: getIntegrationType(integration)\n" +"\n" +" Returns the integration method.\n" +"\n" +" :return: The integration method.\n" +" :rtype: :class:`IntegrationType`\n"; + +static PyObject * UnaryFunction1DVec2f_getIntegrationType(BPy_UnaryFunction1DVec2f* self) { + return BPy_IntegrationType_from_IntegrationType( self->uf1D_vec2f->getIntegrationType() ); +} + +/*----------------------UnaryFunction1DVec2f instance definitions ----------------------------*/ +static PyMethodDef BPy_UnaryFunction1DVec2f_methods[] = { + {"getName", ( PyCFunction ) UnaryFunction1DVec2f_getName, METH_NOARGS, UnaryFunction1DVec2f_getName___doc__}, + {"setIntegrationType", ( PyCFunction ) UnaryFunction1DVec2f_setIntegrationType, METH_VARARGS, UnaryFunction1DVec2f_setIntegrationType___doc__}, + {"getIntegrationType", ( PyCFunction ) UnaryFunction1DVec2f_getIntegrationType, METH_NOARGS, UnaryFunction1DVec2f_getIntegrationType___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_UnaryFunction1DVec2f type definition ------------------------------*/ + +PyTypeObject UnaryFunction1DVec2f_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryFunction1DVec2f", /* tp_name */ + sizeof(BPy_UnaryFunction1DVec2f), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryFunction1DVec2f___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryFunction1DVec2f___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)UnaryFunction1DVec2f___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryFunction1DVec2f___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_UnaryFunction1DVec2f_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)UnaryFunction1DVec2f___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.h new file mode 100644 index 00000000000..64a616e211a --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.h @@ -0,0 +1,37 @@ +#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DVEC2F_H +#define FREESTYLE_PYTHON_UNARYFUNCTION1DVEC2F_H + +#include "../BPy_UnaryFunction1D.h" + +#include "../../geometry/Geom.h" +using namespace Geometry; + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject UnaryFunction1DVec2f_Type; + +#define BPy_UnaryFunction1DVec2f_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DVec2f_Type) ) + +/*---------------------------Python BPy_UnaryFunction1DVec2f structure definition----------*/ +typedef struct { + BPy_UnaryFunction1D py_uf1D; + UnaryFunction1D<Vec2f> *uf1D_vec2f; +} BPy_UnaryFunction1DVec2f; + +/*---------------------------Python BPy_UnaryFunction1DVec2f visible prototypes-----------*/ +int UnaryFunction1DVec2f_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DVEC2F_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp new file mode 100644 index 00000000000..6682dbb7904 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp @@ -0,0 +1,208 @@ +#include "BPy_UnaryFunction1DVec3f.h" + +#include "../BPy_Convert.h" +#include "../BPy_Interface1D.h" +#include "../BPy_IntegrationType.h" + +#include "UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- + +int UnaryFunction1DVec3f_Init( PyObject *module ) { + + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryFunction1DVec3f_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryFunction1DVec3f_Type ); + PyModule_AddObject(module, "UnaryFunction1DVec3f", (PyObject *)&UnaryFunction1DVec3f_Type); + + if( PyType_Ready( &Orientation3DF1D_Type ) < 0 ) + return -1; + Py_INCREF( &Orientation3DF1D_Type ); + PyModule_AddObject(module, "Orientation3DF1D", (PyObject *)&Orientation3DF1D_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryFunction1DVec3f___doc__[] = +"Base class for unary functions (functors) that work on\n" +":class:`Interface1D` and return a 3D vector.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(integration)\n" +"\n" +" Builds a unary 1D function using the integration method given as\n" +" argument.\n" +"\n" +" :arg integration: An integration method.\n" +" :type integration: :class:`IntegrationType`\n"; + +int UnaryFunction1DVec3f___init__(BPy_UnaryFunction1DVec3f* self, PyObject *args) +{ + PyObject *obj = 0; + + if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) ) + return -1; + + if( !obj ) + self->uf1D_vec3f = new UnaryFunction1D<Vec3f>(); + else { + self->uf1D_vec3f = new UnaryFunction1D<Vec3f>( IntegrationType_from_BPy_IntegrationType(obj) ); + } + + self->uf1D_vec3f->py_uf1D = (PyObject *)self; + + return 0; +} +void UnaryFunction1DVec3f___dealloc__(BPy_UnaryFunction1DVec3f* self) +{ + if (self->uf1D_vec3f) + delete self->uf1D_vec3f; + UnaryFunction1D_Type.tp_dealloc((PyObject*)self); +} + + +PyObject * UnaryFunction1DVec3f___repr__(BPy_UnaryFunction1DVec3f* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_vec3f->getName().c_str(), self->uf1D_vec3f ); +} + +static char UnaryFunction1DVec3f_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the unary 1D function.\n" +"\n" +" :return: The name of the unary 1D function.\n" +" :rtype: str\n"; + +PyObject * UnaryFunction1DVec3f_getName( BPy_UnaryFunction1DVec3f *self ) +{ + return PyUnicode_FromString( self->uf1D_vec3f->getName().c_str() ); +} + +PyObject * UnaryFunction1DVec3f___call__( BPy_UnaryFunction1DVec3f *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) ) + return NULL; + + if( typeid(*(self->uf1D_vec3f)) == typeid(UnaryFunction1D<Vec3f>) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if (self->uf1D_vec3f->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) { + if (!PyErr_Occurred()) { + string msg(self->uf1D_vec3f->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + return Vector_from_Vec3f( self->uf1D_vec3f->result ); + +} + +static char UnaryFunction1DVec3f_setIntegrationType___doc__[] = +".. method:: setIntegrationType(integration)\n" +"\n" +" Sets the integration method.\n" +"\n" +" :arg integration: An integration method.\n" +" :type integration: :class:`IntegrationType`\n"; + +PyObject * UnaryFunction1DVec3f_setIntegrationType(BPy_UnaryFunction1DVec3f* self, PyObject *args) +{ + PyObject *obj; + + if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) ) + return NULL; + + self->uf1D_vec3f->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) ); + Py_RETURN_NONE; +} + +static char UnaryFunction1DVec3f_getIntegrationType___doc__[] = +".. method:: getIntegrationType(integration)\n" +"\n" +" Returns the integration method.\n" +"\n" +" :return: The integration method.\n" +" :rtype: :class:`IntegrationType`\n"; + +PyObject * UnaryFunction1DVec3f_getIntegrationType(BPy_UnaryFunction1DVec3f* self) { + return BPy_IntegrationType_from_IntegrationType( self->uf1D_vec3f->getIntegrationType() ); +} + +/*----------------------UnaryFunction1DVec3f instance definitions ----------------------------*/ +static PyMethodDef BPy_UnaryFunction1DVec3f_methods[] = { + {"getName", ( PyCFunction ) UnaryFunction1DVec3f_getName, METH_NOARGS, UnaryFunction1DVec3f_getName___doc__}, + {"setIntegrationType", ( PyCFunction ) UnaryFunction1DVec3f_setIntegrationType, METH_VARARGS, UnaryFunction1DVec3f_setIntegrationType___doc__}, + {"getIntegrationType", ( PyCFunction ) UnaryFunction1DVec3f_getIntegrationType, METH_NOARGS, UnaryFunction1DVec3f_getIntegrationType___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_UnaryFunction1DVec3f type definition ------------------------------*/ + +PyTypeObject UnaryFunction1DVec3f_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryFunction1DVec3f", /* tp_name */ + sizeof(BPy_UnaryFunction1DVec3f), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryFunction1DVec3f___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryFunction1DVec3f___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)UnaryFunction1DVec3f___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryFunction1DVec3f___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_UnaryFunction1DVec3f_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)UnaryFunction1DVec3f___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.h new file mode 100644 index 00000000000..7730271fc09 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.h @@ -0,0 +1,37 @@ +#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DVEC3F_H +#define FREESTYLE_PYTHON_UNARYFUNCTION1DVEC3F_H + +#include "../BPy_UnaryFunction1D.h" + +#include "../../geometry/Geom.h" +using namespace Geometry; + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject UnaryFunction1DVec3f_Type; + +#define BPy_UnaryFunction1DVec3f_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DVec3f_Type) ) + +/*---------------------------Python BPy_UnaryFunction1DVec3f structure definition----------*/ +typedef struct { + BPy_UnaryFunction1D py_uf1D; + UnaryFunction1D<Vec3f> *uf1D_vec3f; +} BPy_UnaryFunction1DVec3f; + +/*---------------------------Python BPy_UnaryFunction1DVec3f visible prototypes-----------*/ +int UnaryFunction1DVec3f_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DVEC3F_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp new file mode 100644 index 00000000000..54827871861 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp @@ -0,0 +1,233 @@ +#include "BPy_UnaryFunction1DVectorViewShape.h" + +#include "../BPy_Convert.h" +#include "../BPy_Interface1D.h" +#include "../BPy_IntegrationType.h" + +#include "UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.h" +#include "UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h" +#include "UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- + +int UnaryFunction1DVectorViewShape_Init( PyObject *module ) { + + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryFunction1DVectorViewShape_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryFunction1DVectorViewShape_Type ); + PyModule_AddObject(module, "UnaryFunction1DVectorViewShape", (PyObject *)&UnaryFunction1DVectorViewShape_Type); + + if( PyType_Ready( &GetOccludeeF1D_Type ) < 0 ) + return -1; + Py_INCREF( &GetOccludeeF1D_Type ); + PyModule_AddObject(module, "GetOccludeeF1D", (PyObject *)&GetOccludeeF1D_Type); + + if( PyType_Ready( &GetOccludersF1D_Type ) < 0 ) + return -1; + Py_INCREF( &GetOccludersF1D_Type ); + PyModule_AddObject(module, "GetOccludersF1D", (PyObject *)&GetOccludersF1D_Type); + + if( PyType_Ready( &GetShapeF1D_Type ) < 0 ) + return -1; + Py_INCREF( &GetShapeF1D_Type ); + PyModule_AddObject(module, "GetShapeF1D", (PyObject *)&GetShapeF1D_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryFunction1DVectorViewShape___doc__[] = +"Base class for unary functions (functors) that work on\n" +":class:`Interface1D` and return a list of :class:`ViewShape`\n" +"objects.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(integration)\n" +"\n" +" Builds a unary 1D function using the integration method given as\n" +" argument.\n" +"\n" +" :arg integration: An integration method.\n" +" :type integration: :class:`IntegrationType`\n"; + +static int UnaryFunction1DVectorViewShape___init__(BPy_UnaryFunction1DVectorViewShape* self, PyObject *args) +{ + PyObject *obj = 0; + + if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) ) + return -1; + + if( !obj ) + self->uf1D_vectorviewshape = new UnaryFunction1D< std::vector<ViewShape*> >(); + else { + self->uf1D_vectorviewshape = new UnaryFunction1D< std::vector<ViewShape*> >( IntegrationType_from_BPy_IntegrationType(obj) ); + } + + self->uf1D_vectorviewshape->py_uf1D = (PyObject *)self; + + return 0; +} + +static void UnaryFunction1DVectorViewShape___dealloc__(BPy_UnaryFunction1DVectorViewShape* self) +{ + if (self->uf1D_vectorviewshape) + delete self->uf1D_vectorviewshape; + UnaryFunction1D_Type.tp_dealloc((PyObject*)self); +} + +static PyObject * UnaryFunction1DVectorViewShape___repr__(BPy_UnaryFunction1DVectorViewShape* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_vectorviewshape->getName().c_str(), self->uf1D_vectorviewshape ); +} + +static char UnaryFunction1DVectorViewShape_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the unary 1D function.\n" +"\n" +" :return: The name of the unary 1D function.\n" +" :rtype: str\n"; + +static PyObject * UnaryFunction1DVectorViewShape_getName( BPy_UnaryFunction1DVectorViewShape *self ) +{ + return PyUnicode_FromString( self->uf1D_vectorviewshape->getName().c_str() ); +} + +static PyObject * UnaryFunction1DVectorViewShape___call__( BPy_UnaryFunction1DVectorViewShape *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) ) + return NULL; + + if( typeid(*(self->uf1D_vectorviewshape)) == typeid(UnaryFunction1D< std::vector<ViewShape*> >) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if (self->uf1D_vectorviewshape->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) { + if (!PyErr_Occurred()) { + string msg(self->uf1D_vectorviewshape->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + PyObject *list = PyList_New(0); + PyObject *item; + for( unsigned int i = 0; i < self->uf1D_vectorviewshape->result.size(); i++) { + ViewShape *v = self->uf1D_vectorviewshape->result[i]; + if (v) { + item = BPy_ViewShape_from_ViewShape(*v); + } else { + item = Py_None; + Py_INCREF(item); + } + PyList_Append(list, item); + } + + return list; +} + +static char UnaryFunction1DVectorViewShape_setIntegrationType___doc__[] = +".. method:: setIntegrationType(integration)\n" +"\n" +" Sets the integration method.\n" +"\n" +" :arg integration: An integration method.\n" +" :type integration: :class:`IntegrationType`\n"; + +static PyObject * UnaryFunction1DVectorViewShape_setIntegrationType(BPy_UnaryFunction1DVectorViewShape* self, PyObject *args) +{ + PyObject *obj; + + if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) ) + return NULL; + + self->uf1D_vectorviewshape->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) ); + Py_RETURN_NONE; +} + +static char UnaryFunction1DVectorViewShape_getIntegrationType___doc__[] = +".. method:: getIntegrationType(integration)\n" +"\n" +" Returns the integration method.\n" +"\n" +" :return: The integration method.\n" +" :rtype: :class:`IntegrationType`\n"; + +static PyObject * UnaryFunction1DVectorViewShape_getIntegrationType(BPy_UnaryFunction1DVectorViewShape* self) { + return BPy_IntegrationType_from_IntegrationType( self->uf1D_vectorviewshape->getIntegrationType() ); +} + +/*----------------------UnaryFunction1DVectorViewShape instance definitions ----------------------------*/ +static PyMethodDef BPy_UnaryFunction1DVectorViewShape_methods[] = { + {"getName", ( PyCFunction ) UnaryFunction1DVectorViewShape_getName, METH_NOARGS, UnaryFunction1DVectorViewShape_getName___doc__}, + {"setIntegrationType", ( PyCFunction ) UnaryFunction1DVectorViewShape_setIntegrationType, METH_VARARGS, UnaryFunction1DVectorViewShape_setIntegrationType___doc__}, + {"getIntegrationType", ( PyCFunction ) UnaryFunction1DVectorViewShape_getIntegrationType, METH_NOARGS, UnaryFunction1DVectorViewShape_getIntegrationType___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_UnaryFunction1DVectorViewShape type definition ------------------------------*/ + +PyTypeObject UnaryFunction1DVectorViewShape_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryFunction1DVectorViewShape", /* tp_name */ + sizeof(BPy_UnaryFunction1DVectorViewShape), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryFunction1DVectorViewShape___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryFunction1DVectorViewShape___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)UnaryFunction1DVectorViewShape___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryFunction1DVectorViewShape___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_UnaryFunction1DVectorViewShape_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)UnaryFunction1DVectorViewShape___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h new file mode 100644 index 00000000000..e2321a6107f --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h @@ -0,0 +1,37 @@ +#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DVECTORVIEWSHAPE_H +#define FREESTYLE_PYTHON_UNARYFUNCTION1DVECTORVIEWSHAPE_H + +#include "../BPy_UnaryFunction1D.h" + +#include <vector> +#include "../../view_map/ViewMap.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject UnaryFunction1DVectorViewShape_Type; + +#define BPy_UnaryFunction1DVectorViewShape_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DVectorViewShape_Type) ) + +/*---------------------------Python BPy_UnaryFunction1DVectorViewShape structure definition----------*/ +typedef struct { + BPy_UnaryFunction1D py_uf1D; + UnaryFunction1D< std::vector<ViewShape*> > *uf1D_vectorviewshape; +} BPy_UnaryFunction1DVectorViewShape; + +/*---------------------------Python BPy_UnaryFunction1DVectorViewShape visible prototypes-----------*/ +int UnaryFunction1DVectorViewShape_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DVECTORVIEWSHAPE_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp new file mode 100644 index 00000000000..8bfb5dde6eb --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp @@ -0,0 +1,220 @@ +#include "BPy_UnaryFunction1DVoid.h" + +#include "../BPy_Convert.h" +#include "../BPy_Interface1D.h" +#include "../BPy_IntegrationType.h" + +#include "UnaryFunction1D_void/BPy_ChainingTimeStampF1D.h" +#include "UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.h" +#include "UnaryFunction1D_void/BPy_TimeStampF1D.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//-------------------MODULE INITIALIZATION-------------------------------- + +int UnaryFunction1DVoid_Init( PyObject *module ) { + + if( module == NULL ) + return -1; + + if( PyType_Ready( &UnaryFunction1DVoid_Type ) < 0 ) + return -1; + Py_INCREF( &UnaryFunction1DVoid_Type ); + PyModule_AddObject(module, "UnaryFunction1DVoid", (PyObject *)&UnaryFunction1DVoid_Type); + + if( PyType_Ready( &ChainingTimeStampF1D_Type ) < 0 ) + return -1; + Py_INCREF( &ChainingTimeStampF1D_Type ); + PyModule_AddObject(module, "ChainingTimeStampF1D", (PyObject *)&ChainingTimeStampF1D_Type); + + if( PyType_Ready( &IncrementChainingTimeStampF1D_Type ) < 0 ) + return -1; + Py_INCREF( &IncrementChainingTimeStampF1D_Type ); + PyModule_AddObject(module, "IncrementChainingTimeStampF1D", (PyObject *)&IncrementChainingTimeStampF1D_Type); + + if( PyType_Ready( &TimeStampF1D_Type ) < 0 ) + return -1; + Py_INCREF( &TimeStampF1D_Type ); + PyModule_AddObject(module, "TimeStampF1D", (PyObject *)&TimeStampF1D_Type); + + return 0; +} + +//------------------------INSTANCE METHODS ---------------------------------- + +static char UnaryFunction1DVoid___doc__[] = +"Base class for unary functions (functors) working on\n" +":class:`Interface1D`.\n" +"\n" +".. method:: __init__()\n" +"\n" +" Default constructor.\n" +"\n" +".. method:: __init__(integration)\n" +"\n" +" Builds a unary 1D function using the integration method given as\n" +" argument.\n" +"\n" +" :arg integration: An integration method.\n" +" :type integration: :class:`IntegrationType`\n"; + +static int UnaryFunction1DVoid___init__(BPy_UnaryFunction1DVoid* self, PyObject *args) +{ + PyObject *obj = 0; + + if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) ) + return -1; + + if( !obj ) + self->uf1D_void = new UnaryFunction1D_void(); + else { + self->uf1D_void = new UnaryFunction1D_void( IntegrationType_from_BPy_IntegrationType(obj) ); + } + + self->uf1D_void->py_uf1D = (PyObject *)self; + + return 0; +} + +static void UnaryFunction1DVoid___dealloc__(BPy_UnaryFunction1DVoid* self) +{ + if (self->uf1D_void) + delete self->uf1D_void; + UnaryFunction1D_Type.tp_dealloc((PyObject*)self); +} + +static PyObject * UnaryFunction1DVoid___repr__(BPy_UnaryFunction1DVoid* self) +{ + return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_void->getName().c_str(), self->uf1D_void ); +} + +static char UnaryFunction1DVoid_getName___doc__[] = +".. method:: getName()\n" +"\n" +" Returns the name of the unary 1D function.\n" +"\n" +" :return: The name of the unary 1D function.\n" +" :rtype: str\n"; + +static PyObject * UnaryFunction1DVoid_getName( BPy_UnaryFunction1DVoid *self ) +{ + return PyUnicode_FromString( self->uf1D_void->getName().c_str() ); +} + +static PyObject * UnaryFunction1DVoid___call__( BPy_UnaryFunction1DVoid *self, PyObject *args, PyObject *kwds) +{ + PyObject *obj; + + if( kwds != NULL ) { + PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported"); + return NULL; + } + if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) ) + return NULL; + + if( typeid(*(self->uf1D_void)) == typeid(UnaryFunction1D_void) ) { + PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden"); + return NULL; + } + if (self->uf1D_void->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) { + if (!PyErr_Occurred()) { + string msg(self->uf1D_void->getName() + " __call__ method failed"); + PyErr_SetString(PyExc_RuntimeError, msg.c_str()); + } + return NULL; + } + Py_RETURN_NONE; +} + +static char UnaryFunction1DVoid_setIntegrationType___doc__[] = +".. method:: setIntegrationType(integration)\n" +"\n" +" Sets the integration method.\n" +"\n" +" :arg integration: An integration method.\n" +" :type integration: :class:`IntegrationType`\n"; + +static PyObject * UnaryFunction1DVoid_setIntegrationType(BPy_UnaryFunction1DVoid* self, PyObject *args) +{ + PyObject *obj; + + if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) ) + return NULL; + + self->uf1D_void->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) ); + Py_RETURN_NONE; +} + +static char UnaryFunction1DVoid_getIntegrationType___doc__[] = +".. method:: getIntegrationType(integration)\n" +"\n" +" Returns the integration method.\n" +"\n" +" :return: The integration method.\n" +" :rtype: :class:`IntegrationType`\n"; + +static PyObject * UnaryFunction1DVoid_getIntegrationType(BPy_UnaryFunction1DVoid* self) { + return BPy_IntegrationType_from_IntegrationType( self->uf1D_void->getIntegrationType() ); +} + +/*----------------------UnaryFunction1DVoid instance definitions ----------------------------*/ +static PyMethodDef BPy_UnaryFunction1DVoid_methods[] = { + {"getName", ( PyCFunction ) UnaryFunction1DVoid_getName, METH_NOARGS, UnaryFunction1DVoid_getName___doc__}, + {"setIntegrationType", ( PyCFunction ) UnaryFunction1DVoid_setIntegrationType, METH_VARARGS, UnaryFunction1DVoid_setIntegrationType___doc__}, + {"getIntegrationType", ( PyCFunction ) UnaryFunction1DVoid_getIntegrationType, METH_NOARGS, UnaryFunction1DVoid_getIntegrationType___doc__}, + {NULL, NULL, 0, NULL} +}; + +/*-----------------------BPy_UnaryFunction1DVoid type definition ------------------------------*/ + +PyTypeObject UnaryFunction1DVoid_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "UnaryFunction1DVoid", /* tp_name */ + sizeof(BPy_UnaryFunction1DVoid), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)UnaryFunction1DVoid___dealloc__, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + (reprfunc)UnaryFunction1DVoid___repr__, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)UnaryFunction1DVoid___call__, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + UnaryFunction1DVoid___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BPy_UnaryFunction1DVoid_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)UnaryFunction1DVoid___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.h new file mode 100644 index 00000000000..af907aeec84 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.h @@ -0,0 +1,34 @@ +#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DVOID_H +#define FREESTYLE_PYTHON_UNARYFUNCTION1DVOID_H + +#include "../BPy_UnaryFunction1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject UnaryFunction1DVoid_Type; + +#define BPy_UnaryFunction1DVoid_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DVoid_Type) ) + +/*---------------------------Python BPy_UnaryFunction1DVoid structure definition----------*/ +typedef struct { + BPy_UnaryFunction1D py_uf1D; + UnaryFunction1D_void *uf1D_void; +} BPy_UnaryFunction1DVoid; + +/*---------------------------Python BPy_UnaryFunction1DVoid visible prototypes-----------*/ +int UnaryFunction1DVoid_Init( PyObject *module ); + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DVOID_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp new file mode 100644 index 00000000000..3ee5daec439 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp @@ -0,0 +1,97 @@ +#include "BPy_CurveNatureF1D.h" + +#include "../../../view_map/Functions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char CurveNatureF1D___doc__[] = +".. method:: __init__(iType=IntegrationType.MEAN)\n" +"\n" +" Builds a CurveNatureF1D object.\n" +"\n" +" :arg iType: The integration method used to compute a single value\n" +" from a set of values.\n" +" :type iType: :class:`IntegrationType`\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns the nature of the Interface1D (silhouette, ridge, crease,\n" +" and so on). Except if the Interface1D is a :class:`ViewEdge`, this\n" +" result might be ambiguous. Indeed, the Interface1D might result\n" +" from the gathering of several 1D elements, each one being of a\n" +" different nature. An integration method, such as the MEAN, might\n" +" give, in this case, irrelevant results.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: The nature of the Interface1D.\n" +" :rtype: :class:`Nature`\n"; + +static int CurveNatureF1D___init__( BPy_CurveNatureF1D* self, PyObject *args) +{ + PyObject *obj = 0; + + if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) ) + return -1; + + IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN; + self->py_uf1D_edgenature.uf1D_edgenature = new Functions1D::CurveNatureF1D(t); + return 0; +} + +/*-----------------------BPy_CurveNatureF1D type definition ------------------------------*/ + +PyTypeObject CurveNatureF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "CurveNatureF1D", /* tp_name */ + sizeof(BPy_CurveNatureF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + CurveNatureF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DEdgeNature_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)CurveNatureF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.h new file mode 100644 index 00000000000..852f8937954 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_CURVENATUREF1D_H +#define FREESTYLE_PYTHON_CURVENATUREF1D_H + +#include "../BPy_UnaryFunction1DEdgeNature.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject CurveNatureF1D_Type; + +#define BPy_CurveNatureF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &CurveNatureF1D_Type) ) + +/*---------------------------Python BPy_CurveNatureF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DEdgeNature py_uf1D_edgenature; +} BPy_CurveNatureF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_CURVENATUREF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp new file mode 100644 index 00000000000..f5ae4e885de --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp @@ -0,0 +1,92 @@ +#include "BPy_Normal2DF1D.h" + +#include "../../../view_map/Functions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char Normal2DF1D___doc__[] = +".. method:: __init__(iType=IntegrationType.MEAN)\n" +"\n" +" Builds a Normal2DF1D object.\n" +"\n" +" :arg iType: The integration method used to compute a single value\n" +" from a set of values.\n" +" :type iType: :class:`IntegrationType`\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns the 2D normal for the Interface1D.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: The 2D normal for the Interface1D.\n" +" :rtype: :class:`mathutils.Vector`\n"; + +static int Normal2DF1D___init__( BPy_Normal2DF1D* self, PyObject *args) +{ + PyObject *obj = 0; + + if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) ) + return -1; + + IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN; + self->py_uf1D_vec2f.uf1D_vec2f = new Functions1D::Normal2DF1D(t); + return 0; +} + +/*-----------------------BPy_Normal2DF1D type definition ------------------------------*/ + +PyTypeObject Normal2DF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "Normal2DF1D", /* tp_name */ + sizeof(BPy_Normal2DF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Normal2DF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DVec2f_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)Normal2DF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.h new file mode 100644 index 00000000000..32078558d0c --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_NORMAL2DF1D_H +#define FREESTYLE_PYTHON_NORMAL2DF1D_H + +#include "../BPy_UnaryFunction1DVec2f.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject Normal2DF1D_Type; + +#define BPy_Normal2DF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Normal2DF1D_Type) ) + +/*---------------------------Python BPy_Normal2DF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DVec2f py_uf1D_vec2f; +} BPy_Normal2DF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_NORMAL2DF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp new file mode 100644 index 00000000000..c83ea650cb2 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp @@ -0,0 +1,94 @@ +#include "BPy_Orientation2DF1D.h" + +#include "../../../view_map/Functions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char Orientation2DF1D___doc__[] = +".. method:: __init__(iType=IntegrationType.MEAN)\n" +"\n" +" Builds an Orientation2DF1D object.\n" +"\n" +" :arg iType: The integration method used to compute a single value\n" +" from a set of values.\n" +" :type iType: :class:`IntegrationType`\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns the 2D orientation of the Interface1D.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: The 2D orientation of the Interface1D.\n" +" :rtype: :class:`mathutils.Vector`\n"; + +static int Orientation2DF1D___init__( BPy_Orientation2DF1D* self, PyObject *args) +{ + PyObject *obj = 0; + + if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) ) + return -1; + + IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN; + self->py_uf1D_vec2f.uf1D_vec2f = new Functions1D::Orientation2DF1D(t); + return 0; + +} + + +/*-----------------------BPy_Orientation2DF1D type definition ------------------------------*/ + +PyTypeObject Orientation2DF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "Orientation2DF1D", /* tp_name */ + sizeof(BPy_Orientation2DF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Orientation2DF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DVec2f_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)Orientation2DF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.h new file mode 100644 index 00000000000..189ab04db4f --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_ORIENTATION2DF1D_H +#define FREESTYLE_PYTHON_ORIENTATION2DF1D_H + +#include "../BPy_UnaryFunction1DVec2f.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject Orientation2DF1D_Type; + +#define BPy_Orientation2DF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Orientation2DF1D_Type) ) + +/*---------------------------Python BPy_Orientation2DF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DVec2f py_uf1D_vec2f; +} BPy_Orientation2DF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_ORIENTATION2DF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp new file mode 100644 index 00000000000..41339111906 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp @@ -0,0 +1,92 @@ +#include "BPy_Orientation3DF1D.h" + +#include "../../../view_map/Functions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char Orientation3DF1D___doc__[] = +".. method:: __init__(iType=IntegrationType.MEAN)\n" +"\n" +" Builds an Orientation3DF1D object.\n" +"\n" +" :arg iType: The integration method used to compute a single value\n" +" from a set of values.\n" +" :type iType: :class:`IntegrationType`\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns the 3D orientation of the Interface1D.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: The 3D orientation of the Interface1D.\n" +" :rtype: :class:`mathutils.Vector`\n"; + +static int Orientation3DF1D___init__( BPy_Orientation3DF1D* self, PyObject *args) +{ + PyObject *obj = 0; + + if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) ) + return -1; + + IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN; + self->py_uf1D_vec3f.uf1D_vec3f = new Functions1D::Orientation3DF1D(t); + return 0; +} + +/*-----------------------BPy_Orientation3DF1D type definition ------------------------------*/ + +PyTypeObject Orientation3DF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "Orientation3DF1D", /* tp_name */ + sizeof(BPy_Orientation3DF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Orientation3DF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DVec3f_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)Orientation3DF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.h new file mode 100644 index 00000000000..b69baf106f4 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_ORIENTATION3DF1D_H +#define FREESTYLE_PYTHON_ORIENTATION3DF1D_H + +#include "../BPy_UnaryFunction1DVec3f.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject Orientation3DF1D_Type; + +#define BPy_Orientation3DF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Orientation3DF1D_Type) ) + +/*---------------------------Python BPy_Orientation3DF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DVec3f py_uf1D_vec3f; +} BPy_Orientation3DF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_ORIENTATION3DF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp new file mode 100644 index 00000000000..da80aaa0b6e --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp @@ -0,0 +1,92 @@ +#include "BPy_Curvature2DAngleF1D.h" + +#include "../../../view_map/Functions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char Curvature2DAngleF1D___doc__[] = +".. method:: __init__(iType=IntegrationType.MEAN)\n" +"\n" +" Builds a Curvature2DAngleF1D object.\n" +"\n" +" :arg iType: The integration method used to compute a single value\n" +" from a set of values.\n" +" :type iType: :class:`IntegrationType`\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns the 2D curvature as an angle for an Interface1D.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: The 2D curvature as an angle.\n" +" :rtype: float\n"; + +static int Curvature2DAngleF1D___init__( BPy_Curvature2DAngleF1D* self, PyObject *args) +{ + PyObject *obj = 0; + + if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) ) + return -1; + + IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN; + self->py_uf1D_double.uf1D_double = new Functions1D::Curvature2DAngleF1D(t); + return 0; + +} +/*-----------------------BPy_Curvature2DAngleF1D type definition ------------------------------*/ + +PyTypeObject Curvature2DAngleF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "Curvature2DAngleF1D", /* tp_name */ + sizeof(BPy_Curvature2DAngleF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Curvature2DAngleF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)Curvature2DAngleF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.h new file mode 100644 index 00000000000..1603a7dc4ea --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_CURVATURE2DANGLEF1D_H +#define FREESTYLE_PYTHON_CURVATURE2DANGLEF1D_H + +#include "../BPy_UnaryFunction1DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject Curvature2DAngleF1D_Type; + +#define BPy_Curvature2DAngleF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Curvature2DAngleF1D_Type) ) + +/*---------------------------Python BPy_Curvature2DAngleF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DDouble py_uf1D_double; +} BPy_Curvature2DAngleF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_CURVATURE2DANGLEF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp new file mode 100644 index 00000000000..7035375a3f6 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp @@ -0,0 +1,107 @@ +#include "BPy_DensityF1D.h" + +#include "../../../stroke/AdvancedFunctions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char DensityF1D___doc__[] = +".. method:: __init__(sigma=2.0, iType=IntegrationType.MEAN, sampling=2.0)\n" +"\n" +" Builds a DensityF1D object.\n" +"\n" +" :arg sigma: The sigma used in DensityF0D and determining the window size\n" +" used in each density query.\n" +" :type sigma: float\n" +" :arg iType: The integration method used to compute a single value\n" +" from a set of values.\n" +" :type iType: :class:`IntegrationType`\n" +" :arg sampling: The resolution used to sample the chain: the\n" +" corresponding 0D function is evaluated at each sample point and\n" +" the result is obtained by combining the resulting values into a\n" +" single one, following the method specified by iType.\n" +" :type sampling: float\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns the density evaluated for an Interface1D. The density is\n" +" evaluated for a set of points along the Interface1D (using the\n" +" :class:`DensityF0D` functor) with a user-defined sampling and then\n" +" integrated into a single value using a user-defined integration\n" +" method.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: The density evaluated for an Interface1D.\n" +" :rtype: float\n"; + +static int DensityF1D___init__( BPy_DensityF1D* self, PyObject *args) +{ + PyObject *obj = 0; + double d = 2.0; + float f = 2.0; + + if( !PyArg_ParseTuple(args, "|dO!f", &d, &IntegrationType_Type, &obj, &f) ) + return -1; + + IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN; + self->py_uf1D_double.uf1D_double = new Functions1D::DensityF1D(d,t,f); + return 0; + +} + +/*-----------------------BPy_DensityF1D type definition ------------------------------*/ + +PyTypeObject DensityF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "DensityF1D", /* tp_name */ + sizeof(BPy_DensityF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + DensityF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)DensityF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.h new file mode 100644 index 00000000000..36426536b36 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_DENSITYF1D_H +#define FREESTYLE_PYTHON_DENSITYF1D_H + +#include "../BPy_UnaryFunction1DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject DensityF1D_Type; + +#define BPy_DensityF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &DensityF1D_Type) ) + +/*---------------------------Python BPy_DensityF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DDouble py_uf1D_double; +} BPy_DensityF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_DENSITYF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp new file mode 100644 index 00000000000..5343d9e3236 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp @@ -0,0 +1,108 @@ +#include "BPy_GetCompleteViewMapDensityF1D.h" + +#include "../../../stroke/AdvancedFunctions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetCompleteViewMapDensityF1D___doc__[] = +".. method:: __init__(level, iType=IntegrationType.MEAN, sampling=2.0)\n" +"\n" +" Builds a GetCompleteViewMapDensityF1D object.\n" +"\n" +" :arg level: The level of the pyramid from which the pixel must be\n" +" read.\n" +" :type level: int\n" +" :arg iType: The integration method used to compute a single value\n" +" from a set of values.\n" +" :type iType: :class:`IntegrationType`\n" +" :arg sampling: The resolution used to sample the chain: the\n" +" corresponding 0D function is evaluated at each sample point and\n" +" the result is obtained by combining the resulting values into a\n" +" single one, following the method specified by iType.\n" +" :type sampling: float\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns the density evaluated for an Interface1D in the complete\n" +" viewmap image. The density is evaluated for a set of points along\n" +" the Interface1D (using the :class:`ReadCompleteViewMapPixelF0D`\n" +" functor) and then integrated into a single value using a\n" +" user-defined integration method.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: The density evaluated for the Interface1D in the complete\n" +" viewmap image.\n" +" :rtype: float\n"; + +static int GetCompleteViewMapDensityF1D___init__( BPy_GetCompleteViewMapDensityF1D* self, PyObject *args) +{ + PyObject *obj = 0; + unsigned i; + float f = 2.0; + + if( !PyArg_ParseTuple(args, "i|O!f", &i, &IntegrationType_Type, &obj, &f) ) + return -1; + + IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN; + self->py_uf1D_double.uf1D_double = new Functions1D::GetCompleteViewMapDensityF1D(i,t,f); + return 0; + +} + +/*-----------------------BPy_GetCompleteViewMapDensityF1D type definition ------------------------------*/ + +PyTypeObject GetCompleteViewMapDensityF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetCompleteViewMapDensityF1D", /* tp_name */ + sizeof(BPy_GetCompleteViewMapDensityF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetCompleteViewMapDensityF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetCompleteViewMapDensityF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.h new file mode 100644 index 00000000000..5963b820348 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETCOMPLETEVIEWMAPDENSITYF1D_H +#define FREESTYLE_PYTHON_GETCOMPLETEVIEWMAPDENSITYF1D_H + +#include "../BPy_UnaryFunction1DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetCompleteViewMapDensityF1D_Type; + +#define BPy_GetCompleteViewMapDensityF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetCompleteViewMapDensityF1D_Type) ) + +/*---------------------------Python BPy_GetCompleteViewMapDensityF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DDouble py_uf1D_double; +} BPy_GetCompleteViewMapDensityF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETCOMPLETEVIEWMAPDENSITYF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp new file mode 100644 index 00000000000..5f543c30027 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp @@ -0,0 +1,112 @@ +#include "BPy_GetDirectionalViewMapDensityF1D.h" + +#include "../../../stroke/AdvancedFunctions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetDirectionalViewMapDensityF1D___doc__[] = +".. method:: __init__(iOrientation, level, iType=IntegrationType.MEAN, sampling=2.0)\n" +"\n" +" Builds a GetDirectionalViewMapDensityF1D object.\n" +"\n" +" :arg iOrientation: The number of the directional map we must work\n" +" with.\n" +" :type iOrientation: int\n" +" :arg level: The level of the pyramid from which the pixel must be\n" +" read.\n" +" :type level: int\n" +" :arg iType: The integration method used to compute a single value\n" +" from a set of values.\n" +" :type iType: :class:`IntegrationType`\n" +" :arg sampling: The resolution used to sample the chain: the\n" +" corresponding 0D function is evaluated at each sample point and\n" +" the result is obtained by combining the resulting values into a\n" +" single one, following the method specified by iType.\n" +" :type sampling: float\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns the density evaluated for an Interface1D in of the\n" +" steerable viewmaps image. The direction telling which Directional\n" +" map to choose is explicitely specified by the user. The density is\n" +" evaluated for a set of points along the Interface1D (using the\n" +" :class:`ReadSteerableViewMapPixelF0D` functor) and then integrated\n" +" into a single value using a user-defined integration method.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: the density evaluated for an Interface1D in of the\n" +" steerable viewmaps image.\n" +" :rtype: float\n"; + +static int GetDirectionalViewMapDensityF1D___init__( BPy_GetDirectionalViewMapDensityF1D* self, PyObject *args) +{ + PyObject *obj = 0; + unsigned int u1, u2; + float f = 2.0; + + if( !PyArg_ParseTuple(args, "II|O!f", &u1, &u2, &IntegrationType_Type, &obj, &f) ) + return -1; + + IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN; + self->py_uf1D_double.uf1D_double = new Functions1D::GetDirectionalViewMapDensityF1D(u1, u2, t, f); + return 0; + +} + +/*-----------------------BPy_GetDirectionalViewMapDensityF1D type definition ------------------------------*/ + +PyTypeObject GetDirectionalViewMapDensityF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetDirectionalViewMapDensityF1D", /* tp_name */ + sizeof(BPy_GetDirectionalViewMapDensityF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetDirectionalViewMapDensityF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetDirectionalViewMapDensityF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.h new file mode 100644 index 00000000000..0e2d7ec2718 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETDIRECTIONALVIEWMAPDENSITYF1D_H +#define FREESTYLE_PYTHON_GETDIRECTIONALVIEWMAPDENSITYF1D_H + +#include "../BPy_UnaryFunction1DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetDirectionalViewMapDensityF1D_Type; + +#define BPy_GetDirectionalViewMapDensityF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetDirectionalViewMapDensityF1D_Type) ) + +/*---------------------------Python BPy_GetDirectionalViewMapDensityF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DDouble py_uf1D_double; +} BPy_GetDirectionalViewMapDensityF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETDIRECTIONALVIEWMAPDENSITYF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp new file mode 100644 index 00000000000..3c8fa2f1f0f --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp @@ -0,0 +1,93 @@ +#include "BPy_GetProjectedXF1D.h" + +#include "../../../view_map/Functions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetProjectedXF1D___doc__[] = +".. method:: __init__(iType=IntegrationType.MEAN)\n" +"\n" +" Builds a GetProjectedXF1D object.\n" +"\n" +" :arg iType: The integration method used to compute a single value\n" +" from a set of values. \n" +" :type iType: :class:`IntegrationType`\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns the projected X 3D coordinate of an Interface1D.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: The projected X 3D coordinate of an Interface1D.\n" +" :rtype: float\n"; + +static int GetProjectedXF1D___init__( BPy_GetProjectedXF1D* self, PyObject *args ) +{ + PyObject *obj = 0; + + if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) ) + return -1; + + IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN; + self->py_uf1D_double.uf1D_double = new Functions1D::GetProjectedXF1D(t); + return 0; +} + + +/*-----------------------BPy_GetProjectedXF1D type definition ------------------------------*/ + +PyTypeObject GetProjectedXF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetProjectedXF1D", /* tp_name */ + sizeof(BPy_GetProjectedXF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetProjectedXF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetProjectedXF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.h new file mode 100644 index 00000000000..d799fb7b334 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETPROJECTEDXF1D_H +#define FREESTYLE_PYTHON_GETPROJECTEDXF1D_H + +#include "../BPy_UnaryFunction1DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetProjectedXF1D_Type; + +#define BPy_GetProjectedXF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetProjectedXF1D_Type) ) + +/*---------------------------Python BPy_GetProjectedXF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DDouble py_uf1D_double; +} BPy_GetProjectedXF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETPROJECTEDXF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp new file mode 100644 index 00000000000..ce655172778 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp @@ -0,0 +1,92 @@ +#include "BPy_GetProjectedYF1D.h" + +#include "../../../view_map/Functions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetProjectedYF1D___doc__[] = +".. method:: __init__(iType=IntegrationType.MEAN)\n" +"\n" +" Builds a GetProjectedYF1D object.\n" +"\n" +" :arg iType: The integration method used to compute a single value\n" +" from a set of values. \n" +" :type iType: :class:`IntegrationType`\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns the projected Y 3D coordinate of an Interface1D.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: The projected Y 3D coordinate of an Interface1D.\n" +" :rtype: float\n"; + +static int GetProjectedYF1D___init__( BPy_GetProjectedYF1D* self, PyObject *args ) +{ + PyObject *obj = 0; + + if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) ) + return -1; + + IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN; + self->py_uf1D_double.uf1D_double = new Functions1D::GetProjectedYF1D(t); + return 0; +} + +/*-----------------------BPy_GetProjectedYF1D type definition ------------------------------*/ + +PyTypeObject GetProjectedYF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetProjectedYF1D", /* tp_name */ + sizeof(BPy_GetProjectedYF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetProjectedYF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetProjectedYF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.h new file mode 100644 index 00000000000..1b7fe6c6b5f --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETPROJECTEDYF1D_H +#define FREESTYLE_PYTHON_GETPROJECTEDYF1D_H + +#include "../BPy_UnaryFunction1DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetProjectedYF1D_Type; + +#define BPy_GetProjectedYF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetProjectedYF1D_Type) ) + +/*---------------------------Python BPy_GetProjectedYF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DDouble py_uf1D_double; +} BPy_GetProjectedYF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETPROJECTEDYF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp new file mode 100644 index 00000000000..df1cefeab4c --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp @@ -0,0 +1,92 @@ +#include "BPy_GetProjectedZF1D.h" + +#include "../../../view_map/Functions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetProjectedZF1D___doc__[] = +".. method:: __init__(iType=IntegrationType.MEAN)\n" +"\n" +" Builds a GetProjectedZF1D object.\n" +"\n" +" :arg iType: The integration method used to compute a single value\n" +" from a set of values. \n" +" :type iType: :class:`IntegrationType`\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns the projected Z 3D coordinate of an Interface1D.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: The projected Z 3D coordinate of an Interface1D.\n" +" :rtype: float\n"; + +static int GetProjectedZF1D___init__( BPy_GetProjectedZF1D* self, PyObject *args ) +{ + PyObject *obj = 0; + + if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) ) + return -1; + + IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN; + self->py_uf1D_double.uf1D_double = new Functions1D::GetProjectedZF1D(t); + return 0; +} + +/*-----------------------BPy_GetProjectedZF1D type definition ------------------------------*/ + +PyTypeObject GetProjectedZF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetProjectedZF1D", /* tp_name */ + sizeof(BPy_GetProjectedZF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetProjectedZF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetProjectedZF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.h new file mode 100644 index 00000000000..a87ac6f8c5e --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETPROJECTEDZF1D_H +#define FREESTYLE_PYTHON_GETPROJECTEDZF1D_H + +#include "../BPy_UnaryFunction1DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetProjectedZF1D_Type; + +#define BPy_GetProjectedZF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetProjectedZF1D_Type) ) + +/*---------------------------Python BPy_GetProjectedZF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DDouble py_uf1D_double; +} BPy_GetProjectedZF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETPROJECTEDZF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp new file mode 100644 index 00000000000..7cd08a2da0b --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp @@ -0,0 +1,105 @@ +#include "BPy_GetSteerableViewMapDensityF1D.h" + +#include "../../../stroke/AdvancedFunctions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetSteerableViewMapDensityF1D___doc__[] = +".. method:: __init__(level, iType=IntegrationType.MEAN, sampling=2.0)\n" +"\n" +" Builds a GetSteerableViewMapDensityF1D object.\n" +"\n" +" :arg level: The level of the pyramid from which the pixel must be\n" +" read.\n" +" :type level: int\n" +" :arg iType: The integration method used to compute a single value\n" +" from a set of values.\n" +" :type iType: :class:`IntegrationType`\n" +" :arg sampling: The resolution used to sample the chain: the\n" +" corresponding 0D function is evaluated at each sample point and\n" +" the result is obtained by combining the resulting values into a\n" +" single one, following the method specified by iType.\n" +" :type sampling: float\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns the density of the ViewMap for a given Interface1D. The\n" +" density of each :class:`FEdge` is evaluated in the proper steerable\n" +" :class:`ViewMap` depending on its orientation.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: The density of the ViewMap for a given Interface1D.\n" +" :rtype: float\n"; + +static int GetSteerableViewMapDensityF1D___init__( BPy_GetSteerableViewMapDensityF1D* self, PyObject *args) +{ + PyObject *obj = 0; + int i; + float f = 2.0; + + if( !PyArg_ParseTuple(args, "i|O!f", &i, &IntegrationType_Type, &obj, &f) ) + return -1; + + IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN; + self->py_uf1D_double.uf1D_double = new Functions1D::GetSteerableViewMapDensityF1D(i,t,f); + return 0; + +} + +/*-----------------------BPy_GetSteerableViewMapDensityF1D type definition ------------------------------*/ + +PyTypeObject GetSteerableViewMapDensityF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetSteerableViewMapDensityF1D", /* tp_name */ + sizeof(BPy_GetSteerableViewMapDensityF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetSteerableViewMapDensityF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetSteerableViewMapDensityF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.h new file mode 100644 index 00000000000..29880c7e9a7 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.h @@ -0,0 +1,29 @@ +#ifndef FREESTYLE_PYTHON_GETSTEERABLEVIEWMAPDENSITYF1D_H +#define FREESTYLE_PYTHON_GETSTEERABLEVIEWMAPDENSITYF1D_H + +#include "../BPy_UnaryFunction1DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetSteerableViewMapDensityF1D_Type; + +#define BPy_GetSteerableViewMapDensityF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetSteerableViewMapDensityF1D_Type) ) +/*---------------------------Python BPy_GetSteerableViewMapDensityF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DDouble py_uf1D_double; +} BPy_GetSteerableViewMapDensityF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETSTEERABLEVIEWMAPDENSITYF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp new file mode 100644 index 00000000000..b34d56b37d3 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp @@ -0,0 +1,105 @@ +#include "BPy_GetViewMapGradientNormF1D.h" + +#include "../../../stroke/AdvancedFunctions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetViewMapGradientNormF1D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a GetViewMapGradientNormF1D object.\n" +"\n" +" :arg level: The level of the pyramid from which the pixel must be\n" +" read.\n" +" :type level: int\n" +" :arg iType: The integration method used to compute a single value\n" +" from a set of values.\n" +" :type iType: :class:`IntegrationType`\n" +" :arg sampling: The resolution used to sample the chain: the\n" +" corresponding 0D function is evaluated at each sample point and\n" +" the result is obtained by combining the resulting values into a\n" +" single one, following the method specified by iType.\n" +" :type sampling: float\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns the density of the ViewMap for a given Interface1D. The\n" +" density of each :class:`FEdge` is evaluated in the proper steerable\n" +" :class:`ViewMap` depending on its orientation.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: The density of the ViewMap for a given Interface1D.\n" +" :rtype: float\n"; + +static int GetViewMapGradientNormF1D___init__( BPy_GetViewMapGradientNormF1D* self, PyObject *args) +{ + PyObject *obj = 0; + int i; + float f = 2.0; + + if( !PyArg_ParseTuple(args, "i|O!f", &i, &IntegrationType_Type, &obj, &f) ) + return -1; + + IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN; + self->py_uf1D_double.uf1D_double = new Functions1D::GetViewMapGradientNormF1D(i,t,f); + return 0; + +} + +/*-----------------------BPy_GetViewMapGradientNormF1D type definition ------------------------------*/ + +PyTypeObject GetViewMapGradientNormF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetViewMapGradientNormF1D", /* tp_name */ + sizeof(BPy_GetViewMapGradientNormF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetViewMapGradientNormF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetViewMapGradientNormF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.h new file mode 100644 index 00000000000..4f07629870f --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF1D_H +#define FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF1D_H + +#include "../BPy_UnaryFunction1DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetViewMapGradientNormF1D_Type; + +#define BPy_GetViewMapGradientNormF1D_Check(v) ( ((PyObject *) v)->ob_type == PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetViewMapGradientNormF1D_Type) ) + +/*---------------------------Python BPy_GetViewMapGradientNormF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DDouble py_uf1D_double; +} BPy_GetViewMapGradientNormF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp new file mode 100644 index 00000000000..6bbf15c0af2 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp @@ -0,0 +1,93 @@ +#include "BPy_GetXF1D.h" + +#include "../../../view_map/Functions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetXF1D___doc__[] = +".. method:: __init__(iType)\n" +"\n" +" Builds a GetXF1D object.\n" +"\n" +" :arg iType: The integration method used to compute a single value\n" +" from a set of values.\n" +" :type iType: :class:`IntegrationType`\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns the X 3D coordinate of an Interface1D.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: The X 3D coordinate of the Interface1D.\n" +" :rtype: float\n"; + +static int GetXF1D___init__( BPy_GetXF1D* self, PyObject *args ) +{ + PyObject *obj = 0; + + if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) ) + return -1; + + IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN; + self->py_uf1D_double.uf1D_double = new Functions1D::GetXF1D(t); + return 0; +} + + +/*-----------------------BPy_GetXF1D type definition ------------------------------*/ + +PyTypeObject GetXF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetXF1D", /* tp_name */ + sizeof(BPy_GetXF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetXF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetXF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.h new file mode 100644 index 00000000000..5eae107daae --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETXF1D_H +#define FREESTYLE_PYTHON_GETXF1D_H + +#include "../BPy_UnaryFunction1DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetXF1D_Type; + +#define BPy_GetXF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetXF1D_Type) ) + +/*---------------------------Python BPy_GetXF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DDouble py_uf1D_double; +} BPy_GetXF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETXF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp new file mode 100644 index 00000000000..7275ea3dcf2 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp @@ -0,0 +1,91 @@ +#include "BPy_GetYF1D.h" + +#include "../../../view_map/Functions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetYF1D___doc__[] = +".. method:: __init__(iType)\n" +"\n" +" Builds a GetYF1D object.\n" +"\n" +" :arg iType: The integration method used to compute a single value\n" +" from a set of values.\n" +" :type iType: :class:`IntegrationType`\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns the Y 3D coordinate of an Interface1D.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: The Y 3D coordinate of the Interface1D.\n" +" :rtype: float\n"; + +static int GetYF1D___init__( BPy_GetYF1D* self, PyObject *args ) +{ + PyObject *obj = 0; + + if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) ) + return -1; + + IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN; + self->py_uf1D_double.uf1D_double = new Functions1D::GetYF1D(t); + return 0; +} +/*-----------------------BPy_GetYF1D type definition ------------------------------*/ + +PyTypeObject GetYF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetYF1D", /* tp_name */ + sizeof(BPy_GetYF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetYF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetYF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.h new file mode 100644 index 00000000000..5864c245776 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETYF1D_H +#define FREESTYLE_PYTHON_GETYF1D_H + +#include "../BPy_UnaryFunction1DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetYF1D_Type; + +#define BPy_GetYF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetYF1D_Type) ) + +/*---------------------------Python BPy_GetYF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DDouble py_uf1D_double; +} BPy_GetYF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETYF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp new file mode 100644 index 00000000000..68f4f5e4300 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp @@ -0,0 +1,92 @@ +#include "BPy_GetZF1D.h" + +#include "../../../view_map/Functions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetZF1D___doc__[] = +".. method:: __init__(iType)\n" +"\n" +" Builds a GetZF1D object.\n" +"\n" +" :arg iType: The integration method used to compute a single value\n" +" from a set of values.\n" +" :type iType: :class:`IntegrationType`\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns the Z 3D coordinate of an Interface1D.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: The Z 3D coordinate of the Interface1D.\n" +" :rtype: float\n"; + +static int GetZF1D___init__( BPy_GetZF1D* self, PyObject *args ) +{ + PyObject *obj = 0; + + if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) ) + return -1; + + IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN; + self->py_uf1D_double.uf1D_double = new Functions1D::GetZF1D(t); + return 0; +} + +/*-----------------------BPy_GetZF1D type definition ------------------------------*/ + +PyTypeObject GetZF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetZF1D", /* tp_name */ + sizeof(BPy_GetZF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetZF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetZF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.h new file mode 100644 index 00000000000..4b91a567eef --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETZF1D_H +#define FREESTYLE_PYTHON_GETZF1D_H + +#include "../BPy_UnaryFunction1DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetZF1D_Type; + +#define BPy_GetZF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetZF1D_Type) ) + +/*---------------------------Python BPy_GetZF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DDouble py_uf1D_double; +} BPy_GetZF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETZF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp new file mode 100644 index 00000000000..be262632466 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp @@ -0,0 +1,99 @@ +#include "BPy_LocalAverageDepthF1D.h" + +#include "../../../stroke/AdvancedFunctions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char LocalAverageDepthF1D___doc__[] = +".. method:: __init__(sigma, iType=IntegrationType.MEAN)\n" +"\n" +" Builds a LocalAverageDepthF1D object.\n" +"\n" +" :arg sigma: The sigma used in DensityF0D and determining the window\n" +" size used in each density query.\n" +" :type sigma: float\n" +" :arg iType: The integration method used to compute a single value\n" +" from a set of values.\n" +" :type iType: :class:`IntegrationType`\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns the average depth evaluated for an Interface1D. The\n" +" average depth is evaluated for a set of points along the\n" +" Interface1D (using the :class:`LocalAverageDepthF0D` functor) with\n" +" a user-defined sampling and then integrated into a single value\n" +" using a user-defined integration method.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: The average depth evaluated for the Interface1D.\n" +" :rtype: float\n"; + +static int LocalAverageDepthF1D___init__( BPy_LocalAverageDepthF1D* self, PyObject *args) +{ + PyObject *obj = 0; + double d; + + if( !PyArg_ParseTuple(args, "d|O!", &d, &IntegrationType_Type, &obj) ) + return -1; + + IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN; + self->py_uf1D_double.uf1D_double = new Functions1D::LocalAverageDepthF1D(d,t); + return 0; +} +/*-----------------------BPy_LocalAverageDepthF1D type definition ------------------------------*/ + +PyTypeObject LocalAverageDepthF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "LocalAverageDepthF1D", /* tp_name */ + sizeof(BPy_LocalAverageDepthF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + LocalAverageDepthF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)LocalAverageDepthF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.h new file mode 100644 index 00000000000..627d10b6414 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF1D_H +#define FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF1D_H + +#include "../BPy_UnaryFunction1DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject LocalAverageDepthF1D_Type; + +#define BPy_LocalAverageDepthF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &LocalAverageDepthF1D_Type) ) + +/*---------------------------Python BPy_LocalAverageDepthF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DDouble py_uf1D_double; +} BPy_LocalAverageDepthF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp new file mode 100644 index 00000000000..0640644ea1e --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp @@ -0,0 +1,97 @@ +#include "BPy_ZDiscontinuityF1D.h" + +#include "../../../view_map/Functions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ZDiscontinuityF1D___doc__[] = +".. method:: __init__(iType=IntegrationType.MEAN)\n" +"\n" +" Builds a ZDiscontinuityF1D object.\n" +"\n" +" :arg iType: The integration method used to compute a single value\n" +" from a set of values.\n" +" :type iType: :class:`IntegrationType`\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns a real value giving the distance between an Interface1D\n" +" and the shape that lies behind (occludee). This distance is\n" +" evaluated in the camera space and normalized between 0 and 1.\n" +" Therefore, if no oject is occluded by the shape to which the\n" +" Interface1D belongs to, 1 is returned.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: The normalized distance between the Interface1D and the occludee.\n" +" :rtype: float\n"; + +static int ZDiscontinuityF1D___init__( BPy_ZDiscontinuityF1D* self, PyObject *args ) +{ + PyObject *obj = 0; + + if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) ) + return -1; + + IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN; + self->py_uf1D_double.uf1D_double = new Functions1D::ZDiscontinuityF1D(t); + return 0; +} + + +/*-----------------------BPy_ZDiscontinuityF1D type definition ------------------------------*/ + +PyTypeObject ZDiscontinuityF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ZDiscontinuityF1D", /* tp_name */ + sizeof(BPy_ZDiscontinuityF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ZDiscontinuityF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DDouble_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ZDiscontinuityF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.h new file mode 100644 index 00000000000..e6b4be556d7 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_ZDISCONTINUITYF1D_H +#define FREESTYLE_PYTHON_ZDISCONTINUITYF1D_H + +#include "../BPy_UnaryFunction1DDouble.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ZDiscontinuityF1D_Type; + +#define BPy_ZDiscontinuityF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ZDiscontinuityF1D_Type) ) + +/*---------------------------Python BPy_ZDiscontinuityF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DDouble py_uf1D_double; +} BPy_ZDiscontinuityF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_ZDISCONTINUITYF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp new file mode 100644 index 00000000000..4ffa3437c69 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp @@ -0,0 +1,97 @@ +#include "BPy_QuantitativeInvisibilityF1D.h" + +#include "../../../view_map/Functions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char QuantitativeInvisibilityF1D___doc__[] = +".. method:: __init__(iType=IntegrationType.MEAN)\n" +"\n" +" Builds a QuantitativeInvisibilityF1D object.\n" +"\n" +" :arg iType: The integration method used to compute a single value\n" +" from a set of values.\n" +" :type iType: :class:`IntegrationType`\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns the Quantitative Invisibility of an Interface1D element.\n" +" If the Interface1D is a :class:`ViewEdge`, then there is no\n" +" ambiguity concerning the result. But, if the Interface1D results\n" +" of a chaining (chain, stroke), then it might be made of several 1D\n" +" elements of different Quantitative Invisibilities.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: The Quantitative Invisibility of the Interface1D.\n" +" :rtype: int\n"; + +static int QuantitativeInvisibilityF1D___init__( BPy_QuantitativeInvisibilityF1D* self, PyObject *args) +{ + PyObject *obj = 0; + + if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) ) + return -1; + + IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN; + self->py_uf1D_unsigned.uf1D_unsigned = new Functions1D::QuantitativeInvisibilityF1D(t); + return 0; + +} + +/*-----------------------BPy_QuantitativeInvisibilityF1D type definition ------------------------------*/ + +PyTypeObject QuantitativeInvisibilityF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "QuantitativeInvisibilityF1D", /* tp_name */ + sizeof(BPy_QuantitativeInvisibilityF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + QuantitativeInvisibilityF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DUnsigned_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)QuantitativeInvisibilityF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h new file mode 100644 index 00000000000..5bcf5fcc0a2 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF1D_H +#define FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF1D_H + +#include "../BPy_UnaryFunction1DUnsigned.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject QuantitativeInvisibilityF1D_Type; + +#define BPy_QuantitativeInvisibilityF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &QuantitativeInvisibilityF1D_Type) ) + +/*---------------------------Python BPy_QuantitativeInvisibilityF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DUnsigned py_uf1D_unsigned; +} BPy_QuantitativeInvisibilityF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp new file mode 100644 index 00000000000..a4f49922e01 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp @@ -0,0 +1,84 @@ +#include "BPy_GetOccludeeF1D.h" + +#include "../../../view_map/Functions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetOccludeeF1D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a GetOccludeeF1D object.\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns a list of occluded shapes covered by this Interface1D.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: A list of occluded shapes covered by the Interface1D.\n" +" :rtype: list of :class:`ViewShape` objects\n"; + +static int GetOccludeeF1D___init__( BPy_GetOccludeeF1D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf1D_vectorviewshape.uf1D_vectorviewshape = new Functions1D::GetOccludeeF1D(); + return 0; +} + +/*-----------------------BPy_GetOccludeeF1D type definition ------------------------------*/ + +PyTypeObject GetOccludeeF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetOccludeeF1D", /* tp_name */ + sizeof(BPy_GetOccludeeF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetOccludeeF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DVectorViewShape_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetOccludeeF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.h new file mode 100644 index 00000000000..c8d5e99a6a7 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETOCCLUDEEF1D_H +#define FREESTYLE_PYTHON_GETOCCLUDEEF1D_H + +#include "../BPy_UnaryFunction1DVectorViewShape.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetOccludeeF1D_Type; + +#define BPy_GetOccludeeF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetOccludeeF1D_Type) ) + +/*---------------------------Python BPy_GetOccludeeF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DVectorViewShape py_uf1D_vectorviewshape; +} BPy_GetOccludeeF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETOCCLUDEEF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp new file mode 100644 index 00000000000..f4030b5b25e --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp @@ -0,0 +1,84 @@ +#include "BPy_GetOccludersF1D.h" + +#include "../../../view_map/Functions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetOccludersF1D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a GetOccludersF1D object.\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns a list of occluding shapes that cover this Interface1D.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: A list of occluding shapes that cover the Interface1D.\n" +" :rtype: list of :class:`ViewShape` objects\n"; + +static int GetOccludersF1D___init__( BPy_GetOccludersF1D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf1D_vectorviewshape.uf1D_vectorviewshape = new Functions1D::GetOccludersF1D(); + return 0; +} + +/*-----------------------BPy_GetOccludersF1D type definition ------------------------------*/ + +PyTypeObject GetOccludersF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetOccludersF1D", /* tp_name */ + sizeof(BPy_GetOccludersF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetOccludersF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DVectorViewShape_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetOccludersF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h new file mode 100644 index 00000000000..ad39ad25c3d --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETOCCLUDERSF1D_H +#define FREESTYLE_PYTHON_GETOCCLUDERSF1D_H + +#include "../BPy_UnaryFunction1DVectorViewShape.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetOccludersF1D_Type; + +#define BPy_GetOccludersF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetOccludersF1D_Type) ) + +/*---------------------------Python BPy_GetOccludersF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DVectorViewShape py_uf1D_vectorviewshape; +} BPy_GetOccludersF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETOCCLUDERSF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp new file mode 100644 index 00000000000..017dbc3436d --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp @@ -0,0 +1,84 @@ +#include "BPy_GetShapeF1D.h" + +#include "../../../view_map/Functions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char GetShapeF1D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a GetShapeF1D object.\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns a list of shapes covered by this Interface1D.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: A list of shapes covered by the Interface1D.\n" +" :rtype: list of :class:`ViewShape` objects\n"; + +static int GetShapeF1D___init__( BPy_GetShapeF1D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf1D_vectorviewshape.uf1D_vectorviewshape = new Functions1D::GetShapeF1D(); + return 0; +} + +/*-----------------------BPy_GetShapeF1D type definition ------------------------------*/ + +PyTypeObject GetShapeF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "GetShapeF1D", /* tp_name */ + sizeof(BPy_GetShapeF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + GetShapeF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DVectorViewShape_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)GetShapeF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h new file mode 100644 index 00000000000..39d1268c03f --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_GETSHAPEF1D_H +#define FREESTYLE_PYTHON_GETSHAPEF1D_H + +#include "../BPy_UnaryFunction1DVectorViewShape.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject GetShapeF1D_Type; + +#define BPy_GetShapeF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetShapeF1D_Type) ) + +/*---------------------------Python BPy_GetShapeF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DVectorViewShape py_uf1D_vectorviewshape; +} BPy_GetShapeF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_GETSHAPEF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp new file mode 100644 index 00000000000..848e0c92843 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp @@ -0,0 +1,82 @@ +#include "BPy_ChainingTimeStampF1D.h" + +#include "../../../view_map/Functions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ChainingTimeStampF1D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a ChainingTimeStampF1D object.\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Sets the chaining time stamp of the Interface1D.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n"; + +static int ChainingTimeStampF1D___init__( BPy_ChainingTimeStampF1D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf1D_void.uf1D_void = new Functions1D::ChainingTimeStampF1D(); + return 0; +} + +/*-----------------------BPy_ChainingTimeStampF1D type definition ------------------------------*/ + +PyTypeObject ChainingTimeStampF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ChainingTimeStampF1D", /* tp_name */ + sizeof(BPy_ChainingTimeStampF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ChainingTimeStampF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DVoid_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ChainingTimeStampF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.h new file mode 100644 index 00000000000..6855ddaf14b --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_CHAININGTIMESTAMPF1D_H +#define FREESTYLE_PYTHON_CHAININGTIMESTAMPF1D_H + +#include "../BPy_UnaryFunction1DVoid.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ChainingTimeStampF1D_Type; + +#define BPy_ChainingTimeStampF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ChainingTimeStampF1D_Type) ) + +/*---------------------------Python BPy_ChainingTimeStampF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DVoid py_uf1D_void; +} BPy_ChainingTimeStampF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_CHAININGTIMESTAMPF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp new file mode 100644 index 00000000000..c1bcaacffb7 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp @@ -0,0 +1,82 @@ +#include "BPy_IncrementChainingTimeStampF1D.h" + +#include "../../../view_map/Functions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char IncrementChainingTimeStampF1D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds an IncrementChainingTimeStampF1D object.\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Increments the chaining time stamp of the Interface1D.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n"; + +static int IncrementChainingTimeStampF1D___init__( BPy_IncrementChainingTimeStampF1D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf1D_void.uf1D_void = new Functions1D::IncrementChainingTimeStampF1D(); + return 0; +} + +/*-----------------------BPy_IncrementChainingTimeStampF1D type definition ------------------------------*/ + +PyTypeObject IncrementChainingTimeStampF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "IncrementChainingTimeStampF1D", /* tp_name */ + sizeof(BPy_IncrementChainingTimeStampF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + IncrementChainingTimeStampF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DVoid_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)IncrementChainingTimeStampF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.h new file mode 100644 index 00000000000..a1d5714ab63 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_INCREMENTCHAININGTIMESTAMPF1D_H +#define FREESTYLE_PYTHON_INCREMENTCHAININGTIMESTAMPF1D_H + +#include "../BPy_UnaryFunction1DVoid.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject IncrementChainingTimeStampF1D_Type; + +#define BPy_IncrementChainingTimeStampF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &IncrementChainingTimeStampF1D_Type) ) + +/*---------------------------Python BPy_IncrementChainingTimeStampF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DVoid py_uf1D_void; +} BPy_IncrementChainingTimeStampF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_INCREMENTCHAININGTIMESTAMPF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp new file mode 100644 index 00000000000..e9a7f2095bb --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp @@ -0,0 +1,82 @@ +#include "BPy_TimeStampF1D.h" + +#include "../../../view_map/Functions1D.h" +#include "../../BPy_Convert.h" +#include "../../BPy_IntegrationType.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char TimeStampF1D___doc__[] = +".. method:: __init__()\n" +"\n" +" Builds a TimeStampF1D object.\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns the time stamp of the Interface1D.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n"; + +static int TimeStampF1D___init__( BPy_TimeStampF1D* self, PyObject *args ) +{ + if( !PyArg_ParseTuple(args, "") ) + return -1; + self->py_uf1D_void.uf1D_void = new Functions1D::TimeStampF1D(); + return 0; +} + +/*-----------------------BPy_TimeStampF1D type definition ------------------------------*/ + +PyTypeObject TimeStampF1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "TimeStampF1D", /* tp_name */ + sizeof(BPy_TimeStampF1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + TimeStampF1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryFunction1DVoid_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)TimeStampF1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.h new file mode 100644 index 00000000000..d9bee247c09 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.h @@ -0,0 +1,30 @@ +#ifndef FREESTYLE_PYTHON_TIMESTAMPF1D_H +#define FREESTYLE_PYTHON_TIMESTAMPF1D_H + +#include "../BPy_UnaryFunction1DVoid.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject TimeStampF1D_Type; + +#define BPy_TimeStampF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TimeStampF1D_Type) ) + +/*---------------------------Python BPy_TimeStampF1D structure definition----------*/ +typedef struct { + BPy_UnaryFunction1DVoid py_uf1D_void; +} BPy_TimeStampF1D; + + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_CHAININGTIMESTAMPF1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp new file mode 100644 index 00000000000..c2c956e3eab --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp @@ -0,0 +1,76 @@ +#include "BPy_FalseUP0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char FalseUP0D___doc__[] = +".. method:: __call__(it)\n" +"\n" +" Always returns false.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: False.\n" +" :rtype: bool\n"; + +static int FalseUP0D___init__( BPy_FalseUP0D* self, PyObject *args) +{ + if(!( PyArg_ParseTuple(args, "") )) + return -1; + self->py_up0D.up0D = new Predicates0D::FalseUP0D(); + return 0; +} + +/*-----------------------BPy_FalseUP0D type definition ------------------------------*/ + +PyTypeObject FalseUP0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "FalseUP0D", /* tp_name */ + sizeof(BPy_FalseUP0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + FalseUP0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryPredicate0D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)FalseUP0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.h b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.h new file mode 100644 index 00000000000..399941d442d --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.h @@ -0,0 +1,29 @@ +#ifndef FREESTYLE_PYTHON_FALSEUP0D_H +#define FREESTYLE_PYTHON_FALSEUP0D_H + +#include "../BPy_UnaryPredicate0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject FalseUP0D_Type; + +#define BPy_FalseUP0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FalseUP0D_Type) ) + +/*---------------------------Python BPy_FalseUP0D structure definition----------*/ +typedef struct { + BPy_UnaryPredicate0D py_up0D; +} BPy_FalseUP0D; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_FALSEUP0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp new file mode 100644 index 00000000000..9097f4e38bc --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp @@ -0,0 +1,76 @@ +#include "BPy_TrueUP0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char TrueUP0D___doc__[] = +".. method:: __call__(it)\n" +"\n" +" Always returns true.\n" +"\n" +" :arg it: An Interface0DIterator object.\n" +" :type it: :class:`Interface0DIterator`\n" +" :return: True.\n" +" :rtype: bool\n"; + +static int TrueUP0D___init__( BPy_TrueUP0D* self, PyObject *args ) +{ + if(!( PyArg_ParseTuple(args, "") )) + return -1; + self->py_up0D.up0D = new Predicates0D::TrueUP0D(); + return 0; +} + +/*-----------------------BPy_TrueUP0D type definition ------------------------------*/ + +PyTypeObject TrueUP0D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "TrueUP0D", /* tp_name */ + sizeof(BPy_TrueUP0D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + TrueUP0D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryPredicate0D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)TrueUP0D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.h b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.h new file mode 100644 index 00000000000..24976aaa5c9 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.h @@ -0,0 +1,29 @@ +#ifndef FREESTYLE_PYTHON_TRUEUP0D_H +#define FREESTYLE_PYTHON_TRUEUP0D_H + +#include "../BPy_UnaryPredicate0D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject TrueUP0D_Type; + +#define BPy_TrueUP0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TrueUP0D_Type) ) + +/*---------------------------Python BPy_TrueUP0D structure definition----------*/ +typedef struct { + BPy_UnaryPredicate0D py_up0D; +} BPy_TrueUP0D; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_TRUEUP0D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp new file mode 100644 index 00000000000..b5a16c3c238 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp @@ -0,0 +1,77 @@ +#include "BPy_ContourUP1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ContourUP1D___doc__[] = +".. method:: __call__(inter)\n" +"\n" +" Returns true if the Interface1D is a contour. An Interface1D is a\n" +" contour if it is borded by a different shape on each of its sides.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: True if the Interface1D is a contour, false otherwise.\n" +" :rtype: bool\n"; + +static int ContourUP1D___init__( BPy_ContourUP1D* self, PyObject *args ) +{ + if(!( PyArg_ParseTuple(args, "") )) + return -1; + self->py_up1D.up1D = new Predicates1D::ContourUP1D(); + return 0; +} + +/*-----------------------BPy_ContourUP1D type definition ------------------------------*/ + +PyTypeObject ContourUP1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ContourUP1D", /* tp_name */ + sizeof(BPy_ContourUP1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ContourUP1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryPredicate1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ContourUP1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.h new file mode 100644 index 00000000000..a24261a60de --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.h @@ -0,0 +1,29 @@ +#ifndef FREESTYLE_PYTHON_CONTOURUP1D_H +#define FREESTYLE_PYTHON_CONTOURUP1D_H + +#include "../BPy_UnaryPredicate1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ContourUP1D_Type; + +#define BPy_ContourUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ContourUP1D_Type) ) + +/*---------------------------Python BPy_ContourUP1D structure definition----------*/ +typedef struct { + BPy_UnaryPredicate1D py_up1D; +} BPy_ContourUP1D; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_CONTOURUP1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp new file mode 100644 index 00000000000..97bd6409bf2 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp @@ -0,0 +1,93 @@ +#include "BPy_DensityLowerThanUP1D.h" + +#include "../../stroke/AdvancedPredicates1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char DensityLowerThanUP1D___doc__[] = +".. method:: __init__(threshold, sigma=2.0)\n" +"\n" +" Builds a DensityLowerThanUP1D object.\n" +"\n" +" :arg threshold: The value of the threshold density. Any Interface1D\n" +" having a density lower than this threshold will match.\n" +" :type threshold: float\n" +" :arg sigma: The sigma value defining the density evaluation window\n" +" size used in the :class:`DensityF0D` functor.\n" +" :type sigma: float\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns true if the density evaluated for the Interface1D is less\n" +" than a user-defined density value.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: True if the density is lower than a threshold.\n" +" :rtype: bool\n"; + +static int DensityLowerThanUP1D___init__( BPy_DensityLowerThanUP1D* self, PyObject *args ) +{ + double d1, d2 = 2.0; + + if( !PyArg_ParseTuple(args, "d|d", &d1, &d2) ) + return -1; + + self->py_up1D.up1D = new Predicates1D::DensityLowerThanUP1D(d1,d2); + return 0; +} + +/*-----------------------BPy_DensityLowerThanUP1D type definition ------------------------------*/ + +PyTypeObject DensityLowerThanUP1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "DensityLowerThanUP1D", /* tp_name */ + sizeof(BPy_DensityLowerThanUP1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + DensityLowerThanUP1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryPredicate1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)DensityLowerThanUP1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.h new file mode 100644 index 00000000000..2862b060a0a --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.h @@ -0,0 +1,29 @@ +#ifndef FREESTYLE_PYTHON_DENSITYLOWERTHANUP1D_H +#define FREESTYLE_PYTHON_DENSITYLOWERTHANUP1D_H + +#include "../BPy_UnaryPredicate1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject DensityLowerThanUP1D_Type; + +#define BPy_DensityLowerThanUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &DensityLowerThanUP1D_Type) ) + +/*---------------------------Python BPy_DensityLowerThanUP1D structure definition----------*/ +typedef struct { + BPy_UnaryPredicate1D py_up1D; +} BPy_DensityLowerThanUP1D; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_DENSITYLOWERTHANUP1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp new file mode 100644 index 00000000000..3a5c66aef59 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp @@ -0,0 +1,87 @@ +#include "BPy_EqualToChainingTimeStampUP1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char EqualToChainingTimeStampUP1D___doc__[] = +".. method:: __init__(ts)\n" +"\n" +" Builds a EqualToChainingTimeStampUP1D object.\n" +"\n" +" :arg ts: A time stamp value.\n" +" :type ts: int\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns true if the Interface1D's time stamp is equal to a certain\n" +" user-defined value.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: True if the time stamp is equal to a user-defined value.\n" +" :rtype: bool\n"; + +static int EqualToChainingTimeStampUP1D___init__( BPy_EqualToChainingTimeStampUP1D* self, PyObject *args ) +{ + unsigned u; + + if( !PyArg_ParseTuple(args, "I", &u) ) + return -1; + + self->py_up1D.up1D = new Predicates1D::EqualToChainingTimeStampUP1D(u); + return 0; +} + +/*-----------------------BPy_EqualToChainingTimeStampUP1D type definition ------------------------------*/ + +PyTypeObject EqualToChainingTimeStampUP1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "EqualToChainingTimeStampUP1D", /* tp_name */ + sizeof(BPy_EqualToChainingTimeStampUP1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + EqualToChainingTimeStampUP1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryPredicate1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)EqualToChainingTimeStampUP1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.h new file mode 100644 index 00000000000..39423423b8e --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.h @@ -0,0 +1,29 @@ +#ifndef FREESTYLE_PYTHON_EQUALTOCHAININGTIMESTAMPUP1D_H +#define FREESTYLE_PYTHON_EQUALTOCHAININGTIMESTAMPUP1D_H + +#include "../BPy_UnaryPredicate1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject EqualToChainingTimeStampUP1D_Type; + +#define BPy_EqualToChainingTimeStampUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &EqualToChainingTimeStampUP1D_Type) ) + +/*---------------------------Python BPy_EqualToChainingTimeStampUP1D structure definition----------*/ +typedef struct { + BPy_UnaryPredicate1D py_up1D; +} BPy_EqualToChainingTimeStampUP1D; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_EQUALTOCHAININGTIMESTAMPUP1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp new file mode 100644 index 00000000000..2427f6d0169 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp @@ -0,0 +1,87 @@ +#include "BPy_EqualToTimeStampUP1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char EqualToTimeStampUP1D___doc__[] = +".. method:: __init__(ts)\n" +"\n" +" Builds a EqualToTimeStampUP1D object.\n" +"\n" +" :arg ts: A time stamp value.\n" +" :type ts: int\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns true if the Interface1D's time stamp is equal to a certain\n" +" user-defined value.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: True if the time stamp is equal to a user-defined value.\n" +" :rtype: bool\n"; + +static int EqualToTimeStampUP1D___init__( BPy_EqualToTimeStampUP1D* self, PyObject *args ) +{ + unsigned u; + + if( !PyArg_ParseTuple(args, "I", &u) ) + return -1; + + self->py_up1D.up1D = new Predicates1D::EqualToTimeStampUP1D(u); + return 0; +} + +/*-----------------------BPy_EqualToTimeStampUP1D type definition ------------------------------*/ + +PyTypeObject EqualToTimeStampUP1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "EqualToTimeStampUP1D", /* tp_name */ + sizeof(BPy_EqualToTimeStampUP1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + EqualToTimeStampUP1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryPredicate1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)EqualToTimeStampUP1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.h new file mode 100644 index 00000000000..538dc400dc2 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.h @@ -0,0 +1,29 @@ +#ifndef FREESTYLE_PYTHON_EQUALTOTIMESTAMPUP1D_H +#define FREESTYLE_PYTHON_EQUALTOTIMESTAMPUP1D_H + +#include "../BPy_UnaryPredicate1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject EqualToTimeStampUP1D_Type; + +#define BPy_EqualToTimeStampUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &EqualToTimeStampUP1D_Type) ) + +/*---------------------------Python BPy_EqualToTimeStampUP1D structure definition----------*/ +typedef struct { + BPy_UnaryPredicate1D py_up1D; +} BPy_EqualToTimeStampUP1D; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_EQUALTOTIMESTAMPUP1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp new file mode 100644 index 00000000000..f94b6653c7e --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp @@ -0,0 +1,79 @@ +#include "BPy_ExternalContourUP1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ExternalContourUP1D___doc__[] = +".. method:: __call__(inter)\n" +"\n" +" Returns true if the Interface1D is an external contour. An\n" +" Interface1D is an external contour if it is borded by no shape on\n" +" one of its sides.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: True if the Interface1D is an external contour, false\n" +" otherwise.\n" +" :rtype: bool\n"; + +static int ExternalContourUP1D___init__( BPy_ExternalContourUP1D* self, PyObject *args ) +{ + if(!( PyArg_ParseTuple(args, "") )) + return -1; + self->py_up1D.up1D = new Predicates1D::ExternalContourUP1D(); + return 0; +} + +/*-----------------------BPy_ExternalContourUP1D type definition ------------------------------*/ + +PyTypeObject ExternalContourUP1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ExternalContourUP1D", /* tp_name */ + sizeof(BPy_ExternalContourUP1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ExternalContourUP1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryPredicate1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ExternalContourUP1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.h new file mode 100644 index 00000000000..31300f04dfe --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.h @@ -0,0 +1,29 @@ +#ifndef FREESTYLE_PYTHON_EXTERNALCONTOURUP1D_H +#define FREESTYLE_PYTHON_EXTERNALCONTOURUP1D_H + +#include "../BPy_UnaryPredicate1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ExternalContourUP1D_Type; + +#define BPy_ExternalContourUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ExternalContourUP1D_Type) ) + +/*---------------------------Python BPy_ExternalContourUP1D structure definition----------*/ +typedef struct { + BPy_UnaryPredicate1D py_up1D; +} BPy_ExternalContourUP1D; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_EXTERNALCONTOURUP1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp new file mode 100644 index 00000000000..fa8b145f83a --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp @@ -0,0 +1,76 @@ +#include "BPy_FalseUP1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char FalseUP1D___doc__[] = +".. method:: __call__(inter)\n" +"\n" +" Always returns false.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: False.\n" +" :rtype: bool\n"; + +static int FalseUP1D___init__( BPy_FalseUP1D* self, PyObject *args ) +{ + if(!( PyArg_ParseTuple(args, "") )) + return -1; + self->py_up1D.up1D = new Predicates1D::FalseUP1D(); + return 0; +} + +/*-----------------------BPy_FalseUP1D type definition ------------------------------*/ + +PyTypeObject FalseUP1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "FalseUP1D", /* tp_name */ + sizeof(BPy_FalseUP1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + FalseUP1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryPredicate1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)FalseUP1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.h new file mode 100644 index 00000000000..273e4962db9 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.h @@ -0,0 +1,29 @@ +#ifndef FREESTYLE_PYTHON_FALSEUP1D_H +#define FREESTYLE_PYTHON_FALSEUP1D_H + +#include "../BPy_UnaryPredicate1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject FalseUP1D_Type; + +#define BPy_FalseUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FalseUP1D_Type) ) + +/*---------------------------Python BPy_FalseUP1D structure definition----------*/ +typedef struct { + BPy_UnaryPredicate1D py_up1D; +} BPy_FalseUP1D; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_FALSEUP1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp new file mode 100644 index 00000000000..ebc27787776 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp @@ -0,0 +1,90 @@ +#include "BPy_QuantitativeInvisibilityUP1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char QuantitativeInvisibilityUP1D___doc__[] = +".. method:: __init__(qi=0)\n" +"\n" +" Builds a QuantitativeInvisibilityUP1D object.\n" +"\n" +" :arg qi: The Quantitative Invisibility you want the Interface1D to\n" +" have.\n" +" :type qi: int\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns true if the Quantitative Invisibility evaluated at an\n" +" Interface1D, using the :class:`QuantitativeInvisibilityF1D`\n" +" functor, equals a certain user-defined value.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: True if Quantitative Invisibility equals a user-defined\n" +" value.\n" +" :rtype: bool\n"; + +static int QuantitativeInvisibilityUP1D___init__( BPy_QuantitativeInvisibilityUP1D* self, PyObject *args ) +{ + int i = 0; + + if( !PyArg_ParseTuple(args, "|i", &i) ) + return -1; + + self->py_up1D.up1D = new Predicates1D::QuantitativeInvisibilityUP1D(i); + return 0; +} + +/*-----------------------BPy_QuantitativeInvisibilityUP1D type definition ------------------------------*/ + +PyTypeObject QuantitativeInvisibilityUP1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "QuantitativeInvisibilityUP1D", /* tp_name */ + sizeof(BPy_QuantitativeInvisibilityUP1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + QuantitativeInvisibilityUP1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryPredicate1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)QuantitativeInvisibilityUP1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h new file mode 100644 index 00000000000..f120ecb9778 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h @@ -0,0 +1,29 @@ +#ifndef FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYUP1D_H +#define FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYUP1D_H + +#include "../BPy_UnaryPredicate1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject QuantitativeInvisibilityUP1D_Type; + +#define BPy_QuantitativeInvisibilityUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &QuantitativeInvisibilityUP1D_Type) ) + +/*---------------------------Python BPy_QuantitativeInvisibilityUP1D structure definition----------*/ +typedef struct { + BPy_UnaryPredicate1D py_up1D; +} BPy_QuantitativeInvisibilityUP1D; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYUP1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp new file mode 100644 index 00000000000..50a1de751fb --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp @@ -0,0 +1,90 @@ +#include "BPy_ShapeUP1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char ShapeUP1D___doc__[] = +".. method:: __init__(idFirst, idSecond=0)\n" +"\n" +" Builds a ShapeUP1D object.\n" +"\n" +" :arg idFirst: The first Id component.\n" +" :type idFirst: int\n" +" :arg idSecond: The second Id component.\n" +" :type idSecond: int\n" +"\n" +".. method:: __call__(inter)\n" +"\n" +" Returns true if the shape to which the Interface1D belongs to has\n" +" the same :class:`Id` as the one specified by the user.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: True if Interface1D belongs to the shape of the\n" +" user-specified Id.\n" +" :rtype: bool\n"; + +static int ShapeUP1D___init__( BPy_ShapeUP1D* self, PyObject *args ) +{ + unsigned u1, u2 = 0; + + if( !PyArg_ParseTuple(args, "I|I", &u1, &u2) ) + return -1; + + self->py_up1D.up1D = new Predicates1D::ShapeUP1D(u1,u2); + return 0; +} + +/*-----------------------BPy_ShapeUP1D type definition ------------------------------*/ + +PyTypeObject ShapeUP1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ShapeUP1D", /* tp_name */ + sizeof(BPy_ShapeUP1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + ShapeUP1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryPredicate1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)ShapeUP1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.h new file mode 100644 index 00000000000..ce6d0276edd --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.h @@ -0,0 +1,29 @@ +#ifndef FREESTYLE_PYTHON_SHAPEUP1D_H +#define FREESTYLE_PYTHON_SHAPEUP1D_H + +#include "../BPy_UnaryPredicate1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject ShapeUP1D_Type; + +#define BPy_ShapeUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ShapeUP1D_Type) ) + +/*---------------------------Python BPy_ShapeUP1D structure definition----------*/ +typedef struct { + BPy_UnaryPredicate1D py_up1D; +} BPy_ShapeUP1D; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_SHAPEUP1D_H */ diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp new file mode 100644 index 00000000000..320b1eb1c31 --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp @@ -0,0 +1,76 @@ +#include "BPy_TrueUP1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +//------------------------INSTANCE METHODS ---------------------------------- + +static char TrueUP1D___doc__[] = +".. method:: __call__(inter)\n" +"\n" +" Always returns true.\n" +"\n" +" :arg inter: An Interface1D object.\n" +" :type inter: :class:`Interface1D`\n" +" :return: True.\n" +" :rtype: bool\n"; + +static int TrueUP1D___init__( BPy_TrueUP1D* self, PyObject *args ) +{ + if(!( PyArg_ParseTuple(args, "") )) + return -1; + self->py_up1D.up1D = new Predicates1D::TrueUP1D(); + return 0; +} + +/*-----------------------BPy_TrueUP1D type definition ------------------------------*/ + +PyTypeObject TrueUP1D_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "TrueUP1D", /* tp_name */ + sizeof(BPy_TrueUP1D), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + TrueUP1D___doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &UnaryPredicate1D_Type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)TrueUP1D___init__, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.h new file mode 100644 index 00000000000..5a01ad42d2a --- /dev/null +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.h @@ -0,0 +1,29 @@ +#ifndef FREESTYLE_PYTHON_TRUEUP1D_H +#define FREESTYLE_PYTHON_TRUEUP1D_H + +#include "../BPy_UnaryPredicate1D.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////////////// + +#include <Python.h> + +extern PyTypeObject TrueUP1D_Type; + +#define BPy_TrueUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TrueUP1D_Type) ) + +/*---------------------------Python BPy_TrueUP1D structure definition----------*/ +typedef struct { + BPy_UnaryPredicate1D py_up1D; +} BPy_TrueUP1D; + +/////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif /* FREESTYLE_PYTHON_TRUEUP1D_H */ diff --git a/source/blender/freestyle/intern/scene_graph/DrawingStyle.h b/source/blender/freestyle/intern/scene_graph/DrawingStyle.h new file mode 100755 index 00000000000..58dcf4fede9 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/DrawingStyle.h @@ -0,0 +1,82 @@ +// +// Filename : DrawingStyle.h +// Author(s) : Stephane Grabli +// Purpose : Class to define the drawing style of a node +// Date of creation : 10/10/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef DRAWINGSTYLE_H +# define DRAWINGSTYLE_H + +class DrawingStyle +{ +public: + enum STYLE + {FILLED, LINES, POINTS, INVISIBLE}; + + inline DrawingStyle() {Style = FILLED; LineWidth = 2.f; PointSize = 2.f; LightingEnabled = true;} + inline explicit DrawingStyle(const DrawingStyle& iBrother); + + virtual ~DrawingStyle() {} + + /*! operators */ + inline DrawingStyle& operator=(const DrawingStyle& ds); + + inline void setStyle(const STYLE iStyle) {Style = iStyle;} + inline void setLineWidth(const float iLineWidth) {LineWidth = iLineWidth;} + inline void setPointSize(const float iPointSize) {PointSize = iPointSize;} + inline void setLightingEnabled(const bool on) {LightingEnabled = on;} + + inline STYLE style() const {return Style;} + inline float lineWidth() const {return LineWidth;} + inline float pointSize() const {return PointSize;} + inline bool lightingEnabled() const {return LightingEnabled;} + +private: + STYLE Style; + float LineWidth; + float PointSize; + bool LightingEnabled; +}; + +DrawingStyle::DrawingStyle(const DrawingStyle& iBrother) +{ + Style = iBrother.Style; + LineWidth = iBrother.LineWidth; + PointSize = iBrother.PointSize; + LightingEnabled = iBrother.LightingEnabled; +} + +DrawingStyle& DrawingStyle::operator=(const DrawingStyle& ds) +{ + Style = ds.Style; + LineWidth = ds.LineWidth; + PointSize = ds.PointSize; + LightingEnabled = ds.LightingEnabled; + + return *this; +} + +#endif // DRAWINGSTYLE_H diff --git a/source/blender/freestyle/intern/scene_graph/FrsMaterial.h b/source/blender/freestyle/intern/scene_graph/FrsMaterial.h new file mode 100755 index 00000000000..1cbadab2bd3 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/FrsMaterial.h @@ -0,0 +1,304 @@ +// +// Filename : FrsMaterial.h +// Author(s) : Stephane Grabli +// Purpose : Class used to handle materials. +// Date of creation : 10/10/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef FRS_MATERIAL_H +# define FRS_MATERIAL_H + +# include "../system/FreestyleConfig.h" + +/*! Class defining a material */ +class FrsMaterial +{ +public: + /*! Default constructor */ + inline FrsMaterial(); + /*! Builds a Material from its diffuse, ambiant, specular, emissive + * colors and a shininess coefficient. + * \param iDiffuse + * A 4 element float-array containing the diffuse color. + * \param iAmbiant + * A 4 element float-array containing the ambiant color. + * \param iSpecular + * A 4 element float-array containing the specular color. + * \param iEmission + * A 4 element float-array containing the emissive color. + * \param iShininess + * The shininess coefficient. + */ + inline FrsMaterial(const float *iDiffuse, + const float *iAmbiant, + const float *iSpecular, + const float *iEmission, + const float iShininess); + + /*! Copy constructor */ + inline FrsMaterial(const FrsMaterial& m); + /*! Destructor */ + virtual ~FrsMaterial() {} + + + /*! Returns the diffuse color as a 4 float array */ + inline const float * diffuse() const { return Diffuse; } + /*! Returns the red component of the diffuse color */ + inline const float diffuseR() const { return Diffuse[0]; } + /*! Returns the green component of the diffuse color */ + inline const float diffuseG() const { return Diffuse[1]; } + /*! Returns the blue component of the diffuse color */ + inline const float diffuseB() const { return Diffuse[2]; } + /*! Returns the alpha component of the diffuse color */ + inline const float diffuseA() const { return Diffuse[3]; } + + /*! Returns the specular color as a 4 float array */ + inline const float * specular() const { return Specular; } + /*! Returns the red component of the specular color */ + inline const float specularR() const { return Specular[0]; } + /*! Returns the green component of the specular color */ + inline const float specularG() const { return Specular[1]; } + /*! Returns the blue component of the specular color */ + inline const float specularB() const { return Specular[2]; } + /*! Returns the alpha component of the specular color */ + inline const float specularA() const { return Specular[3]; } + + /*! Returns the ambiant color as a 4 float array */ + inline const float * ambient() const { return Ambient; } + /*! Returns the red component of the ambiant color */ + inline const float ambientR() const { return Ambient[0]; } + /*! Returns the green component of the ambiant color */ + inline const float ambientG() const { return Ambient[1]; } + /*! Returns the blue component of the ambiant color */ + inline const float ambientB() const { return Ambient[2]; } + /*! Returns the alpha component of the ambiant color */ + inline const float ambientA() const { return Ambient[3]; } + + /*! Returns the emissive color as a 4 float array */ + inline const float * emission() const { return Emission; } + /*! Returns the red component of the emissive color */ + inline const float emissionR() const { return Emission[0]; } + /*! Returns the green component of the emissive color */ + inline const float emissionG() const { return Emission[1]; } + /*! Returns the blue component of the emissive color */ + inline const float emissionB() const { return Emission[2]; } + /*! Returns the alpha component of the emissive color */ + inline const float emissionA() const { return Emission[3]; } + + /*! Returns the shininess coefficient */ + inline const float shininess() const { return Shininess; } + + /*! Sets the diffuse color. + * \param r + * Red component + * \param g + * Green component + * \param b + * Blue component + * \param a + * Alpha component + */ + inline void setDiffuse(const float r, const float g, const float b, const float a); + /*! Sets the specular color. + * \param r + * Red component + * \param g + * Green component + * \param b + * Blue component + * \param a + * Alpha component + */ + inline void setSpecular(const float r, const float g, const float b, const float a); + /*! Sets the ambiant color. + * \param r + * Red component + * \param g + * Green component + * \param b + * Blue component + * \param a + * Alpha component + */ + inline void setAmbient(const float r, const float g, const float b, const float a); + + /*! Sets the emissive color. + * \param r + * Red component + * \param g + * Green component + * \param b + * Blue component + * \param a + * Alpha component + */ + inline void setEmission(const float r, const float g, const float b, const float a); + + /*! Sets the shininess. + * \param s + * Shininess + */ + inline void setShininess(const float s); + + /* operators */ + inline FrsMaterial& operator=(const FrsMaterial& m); + inline bool operator!=(const FrsMaterial& m) const; + inline bool operator==(const FrsMaterial& m) const; + +private: + + /*! Material properties */ + float Diffuse[4]; + float Specular[4]; + float Ambient[4]; + float Emission[4]; + float Shininess; + +}; + +FrsMaterial::FrsMaterial() +{ + Ambient[0] = Ambient[1] = Ambient[2] = 0.2f; + Ambient[3] = 1.f; + + Diffuse[0] = Diffuse[1] = Diffuse[2] = 0.8f; + Diffuse[3] = 1.f; + + Emission[0] = Emission[1] = Emission[2] = 0.f; + Emission[3] = 1.f; + + Specular[0] = Specular[1] = Specular[2] = 0.f; + Specular[3] = 1.f; + + Shininess = 0.f; +} + +FrsMaterial::FrsMaterial(const float *iDiffuse, + const float *iAmbiant, + const float *iSpecular, + const float *iEmission, + const float iShininess) +{ + for(int i=0; i<4; i++) + { + Diffuse[i] = iDiffuse[i]; + Specular[i] = iSpecular[i]; + Ambient[i] = iAmbiant[i]; + Emission[i] = iEmission[i]; + } + + Shininess = iShininess; +} + +FrsMaterial::FrsMaterial(const FrsMaterial& m) +{ + for(int i=0; i<4; i++) + { + Diffuse[i] = m.diffuse()[i]; + Specular[i] = m.specular()[i]; + Ambient[i] = m.ambient()[i]; + Emission[i] = m.emission()[i]; + } + + Shininess = m.shininess(); +} + +void FrsMaterial::setDiffuse(const float r, const float g, const float b, const float a) +{ + Diffuse[0] = r; + Diffuse[1] = g; + Diffuse[2] = b; + Diffuse[3] = a; +} + +void FrsMaterial::setSpecular(const float r, const float g, const float b, const float a) +{ + Specular[0] = r; + Specular[1] = g; + Specular[2] = b; + Specular[3] = a; +} + +void FrsMaterial::setAmbient(const float r, const float g, const float b, const float a) +{ + Ambient[0] = r; + Ambient[1] = g; + Ambient[2] = b; + Ambient[3] = a; +} + +void FrsMaterial::setEmission(const float r, const float g, const float b, const float a) +{ + Emission[0] = r; + Emission[1] = g; + Emission[2] = b; + Emission[3] = a; +} + +void FrsMaterial::setShininess(const float s) +{ + Shininess = s; +} + +FrsMaterial& FrsMaterial::operator=(const FrsMaterial& m) +{ + for(int i=0; i<4; i++) + { + Diffuse[i] = m.diffuse()[i]; + Specular[i] = m.specular()[i]; + Ambient[i] = m.ambient()[i]; + Emission[i] = m.emission()[i]; + } + + Shininess = m.shininess(); + + return *this; +} + +bool FrsMaterial::operator!=(const FrsMaterial& m) const +{ + if(Shininess != m.shininess()) + return true; + for(int i=0; i<4; i++) + { + if(Diffuse[i] != m.diffuse()[i]) + return true; + if(Specular[i] != m.specular()[i]) + return true; + if(Ambient[i] != m.ambient()[i]) + return true; + if(Emission[i] != m.emission()[i]) + return true; + } + + return false; +} + +bool FrsMaterial::operator==(const FrsMaterial& m) const +{ + return (!((*this)!=m)); +} + +#endif // FRS_MATERIAL_H diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp new file mode 100755 index 00000000000..98872c6c8ea --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp @@ -0,0 +1,321 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "IndexedFaceSet.h" + +IndexedFaceSet::IndexedFaceSet() +: Rep() +{ + _Vertices = NULL; + _Normals = NULL; + _FrsMaterials = 0; + _TexCoords = 0; + _VSize = 0; + _NSize = 0; + _MSize = 0; + _TSize = 0; + _NumFaces = 0; + _NumVertexPerFace = NULL; + _FaceStyle = NULL; + _VIndices = NULL; + _VISize = 0; + _NIndices = NULL; + _NISize = 0; + _MIndices = NULL; + _MISize = 0; + _TIndices = NULL; + _TISize = 0; + _displayList = 0; +} + +IndexedFaceSet::IndexedFaceSet( real *iVertices, unsigned iVSize, + real *iNormals, unsigned iNSize, + FrsMaterial **iMaterials, unsigned iMSize, + real *iTexCoords, unsigned iTSize, + unsigned iNumFaces, unsigned *iNumVertexPerFace, TRIANGLES_STYLE *iFaceStyle, + unsigned *iVIndices, unsigned iVISize, + unsigned *iNIndices, unsigned iNISize, + unsigned *iMIndices, unsigned iMISize, + unsigned *iTIndices, unsigned iTISize, + unsigned iCopy) + : Rep() +{ + if(1 == iCopy) + { + _VSize = iVSize; + _Vertices = new real[_VSize]; + memcpy(_Vertices, iVertices, iVSize*sizeof(real)); + + _NSize = iNSize; + _Normals = new real[_NSize]; + memcpy(_Normals, iNormals, iNSize*sizeof(real)); + + _MSize = iMSize; + _FrsMaterials = 0; + if(iMaterials){ + _FrsMaterials = new FrsMaterial*[_MSize]; + for(unsigned i=0; i<_MSize; ++i) + _FrsMaterials[i] = new FrsMaterial(*(iMaterials[i])); + } + _TSize = iTSize; + _TexCoords = 0; + if(_TSize){ + _TexCoords = new real[_TSize]; + memcpy(_TexCoords, iTexCoords, iTSize*sizeof(real)); + } + + _NumFaces = iNumFaces; + _NumVertexPerFace = new unsigned[_NumFaces]; + memcpy(_NumVertexPerFace, iNumVertexPerFace, _NumFaces*sizeof(unsigned)); + + _FaceStyle = new TRIANGLES_STYLE[_NumFaces]; + memcpy(_FaceStyle, iFaceStyle, _NumFaces*sizeof(TRIANGLES_STYLE)); + + _VISize = iVISize; + _VIndices = new unsigned[_VISize]; + memcpy(_VIndices, iVIndices, _VISize*sizeof(unsigned)); + + _NISize = iNISize; + _NIndices = new unsigned[_NISize]; + memcpy(_NIndices, iNIndices, _NISize*sizeof(unsigned)); + + _MISize = iMISize; + _MIndices = 0; + if(iMIndices){ + _MIndices = new unsigned[_MISize]; + memcpy(_MIndices, iMIndices, _MISize*sizeof(unsigned)); + } + _TISize = iTISize; + _TIndices = 0; + if(_TISize){ + _TIndices = new unsigned[_TISize]; + memcpy(_TIndices, iTIndices, _TISize*sizeof(unsigned)); + } + } + else + { + _VSize = iVSize; + _Vertices = iVertices; + + _NSize = iNSize; + _Normals = iNormals; + + _MSize = iMSize; + _FrsMaterials = 0; + if(iMaterials) + _FrsMaterials = iMaterials; + + _TSize = iTSize; + _TexCoords = iTexCoords; + + _NumFaces = iNumFaces; + _NumVertexPerFace = iNumVertexPerFace; + _FaceStyle = iFaceStyle; + + _VISize = iVISize; + _VIndices = iVIndices; + + _NISize = iNISize; + _NIndices = iNIndices; + + _MISize = iMISize; + _MIndices = 0; + if(iMISize) + _MIndices = iMIndices; + + _TISize = iTISize; + _TIndices = iTIndices; + } + + _displayList = 0; +} + +IndexedFaceSet::IndexedFaceSet( const IndexedFaceSet& iBrother) +:Rep(iBrother) +{ + _VSize = iBrother.vsize(); + _Vertices = new real[_VSize]; + memcpy(_Vertices, iBrother.vertices(), _VSize*sizeof(real)); + + _NSize = iBrother.nsize(); + _Normals = new real[_NSize]; + memcpy(_Normals, iBrother.normals(), _NSize*sizeof(real)); + + _MSize = iBrother.msize(); + if(_MSize){ + _FrsMaterials = new FrsMaterial*[_MSize]; + for(unsigned i=0; i<_MSize; ++i){ + _FrsMaterials[i] = new FrsMaterial(*(iBrother._FrsMaterials[i])); + } + }else{ + _FrsMaterials = 0; + } + + _TSize = iBrother.tsize(); + _TexCoords = 0; + if(_TSize){ + _TexCoords = new real[_TSize]; + memcpy(_TexCoords, iBrother.texCoords(), _TSize*sizeof(real)); + } + + _NumFaces = iBrother.numFaces(); + _NumVertexPerFace = new unsigned[_NumFaces]; + memcpy(_NumVertexPerFace, iBrother.numVertexPerFaces(), _NumFaces*sizeof(unsigned)); + + _FaceStyle = new TRIANGLES_STYLE[_NumFaces]; + memcpy(_FaceStyle, iBrother.trianglesStyle(), _NumFaces*sizeof(TRIANGLES_STYLE)); + + _VISize = iBrother.visize(); + _VIndices = new unsigned[_VISize]; + memcpy(_VIndices, iBrother.vindices(), _VISize*sizeof(unsigned)); + + _NISize = iBrother.nisize(); + _NIndices = new unsigned[_NISize]; + memcpy(_NIndices, iBrother.nindices(), _NISize*sizeof(unsigned)); + + _MISize = iBrother.misize(); + if(_MISize){ + _MIndices = new unsigned[_MISize]; + memcpy(_MIndices, iBrother.mindices(), _MISize*sizeof(unsigned)); + }else{ + _MIndices=0; + } + + _TISize = iBrother.tisize(); + _TIndices = 0; + if(_TISize){ + _TIndices = new unsigned[_TISize]; + memcpy(_TIndices, iBrother.tindices(), _TISize*sizeof(unsigned)); + } + + _displayList = 0; +} + +IndexedFaceSet::~IndexedFaceSet() +{ + if(NULL != _Vertices) + { + delete [] _Vertices; + _Vertices = NULL; + } + + if(NULL != _Normals) + { + delete [] _Normals; + _Normals = NULL; + } + + if(NULL != _FrsMaterials) + { + for(unsigned i=0; i<_MSize; ++i) + delete _FrsMaterials[i]; + delete [] _FrsMaterials; + _FrsMaterials = NULL; + } + + if(NULL != _TexCoords) + { + delete [] _TexCoords; + _TexCoords = NULL; + } + + if(NULL != _NumVertexPerFace) + { + delete [] _NumVertexPerFace; + _NumVertexPerFace = NULL; + } + + if(NULL != _FaceStyle) + { + delete [] _FaceStyle; + _FaceStyle = NULL; + } + + if(NULL != _VIndices) + { + delete [] _VIndices; + _VIndices = NULL; + } + + if(NULL != _NIndices) + { + delete [] _NIndices; + _NIndices = NULL; + } + + if(NULL != _MIndices) + { + delete [] _MIndices; + _MIndices = NULL; + } + if(NULL != _TIndices) + { + delete [] _TIndices; + _TIndices = NULL; + } + // should find a way to deallocates the displayList + // glDeleteLists(GLuint list, GLSizei range) + _displayList = 0; +} + +void IndexedFaceSet::accept(SceneVisitor& v) { + Rep::accept(v); + v.visitIndexedFaceSet(*this); +} + +void IndexedFaceSet::ComputeBBox() +{ + real XMax = _Vertices[0]; + real YMax = _Vertices[1]; + real ZMax = _Vertices[2]; + + real XMin = _Vertices[0]; + real YMin = _Vertices[1]; + real ZMin = _Vertices[2]; + + // parse all the coordinates to find + // the Xmax, YMax, ZMax + real *v = _Vertices; + + for(unsigned i=0; i<_VSize/3; i++) + { + // X + if(*v > XMax) + XMax = *v; + if(*v < XMin) + XMin = *v; + v++; + + if(*v > YMax) + YMax = *v; + if(*v < YMin) + YMin = *v; + v++; + + if(*v > ZMax) + ZMax = *v; + if(*v < ZMin) + ZMin = *v; + v++; + } + + setBBox(BBox<Vec3r>(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax))); +} diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h new file mode 100755 index 00000000000..41db4db4c42 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h @@ -0,0 +1,222 @@ +// +// Filename : IndexedFaceSet.h +// Author(s) : Stephane Grabli +// Purpose : A Set of indexed faces to represent a surfacic object +// Date of creation : 22/01/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef INDEXEDFACESET_H +# define INDEXEDFACESET_H + +# include <stdio.h> +# include <memory.h> + +//! inherits from class Rep +# include "Rep.h" + +# include "../system/FreestyleConfig.h" + +class LIB_SCENE_GRAPH_EXPORT IndexedFaceSet : public Rep + { +public: + + /*! Triangles description style:*/ + enum TRIANGLES_STYLE{TRIANGLE_STRIP, TRIANGLE_FAN, TRIANGLES}; + + /*! Builds an empty indexed face set + */ + IndexedFaceSet(); + /*! Builds an indexed face set + iVertices + The array of object vertices 3D coordinates (for all faces). + If iCopy != 0, the array is copied; you must desallocate iVertices. Else you must not. + iVSize + The size of iVertices (must be a multiple of 3) + iNormals + The array of object normals 3D coordinates. + If iCopy != 0, the array is copied; you must desallocate iNormals. Else you must not. + iNSize + The size of iNormals + iMaterials + The array of materials + iMSize + The size of iMaterials + iTexCoords + The array of texture coordinates. + iTSize + The size of iTexCoords (must be multiple of 2) + iNumFaces + The number of faces + iNumVertexPerFace + Array containing the number of vertices per face. + iFaceStyle + Array containing the description style of each faces. + The style belongs to: + - TRIANGLE_STRIP: the face indices describe a triangle strip + - TRIANGLE_FAN : the face indices describe a triangle fan + - TRIANGLES : the face indices describe single triangles + If iCopy != 0, the array is copied; you must desallocate iFaceStyle. Else you must not. + iVIndices, + Array of vertices indices. + The integers contained in this array must be multiple of 3. + If iCopy != 0, the array is copied; you must desallocate iVIndices. Else you must not. + iVISize + The size of iVIndices. + iNIndices + Array of normals indices. + The integers contained in this array must be multiple of 3. + If iCopy != 0, the array is copied; you must desallocate iNIndices. Else you must not. + iNISize + The size of iNIndices + iMIndices + The Material indices (per vertex) + iMISize + The size of iMIndices + iTIndices + The Texture coordinates indices (per vertex). The integers contained in this array must be multiple of 2. + iTISize + The size of iMIndices + iCopy + 0 : the arrays are not copied. The pointers passed as arguments are used. + IndexedFaceSet takes these arrays desallocation in charge. + 1 : the arrays are copied. The caller is in charge of the arrays, passed + as arguments desallocation. + */ + IndexedFaceSet( real *iVertices, unsigned iVSize, + real *iNormals, unsigned iNSize, + FrsMaterial **iMaterials, unsigned iMSize, + real *iTexCoords, unsigned iTSize, + unsigned iNumFaces, unsigned *iNumVertexPerFace, TRIANGLES_STYLE *iFaceStyle, + unsigned *iVIndices, unsigned iVISize, + unsigned *iNIndices, unsigned iNISize, + unsigned *iMIndices, unsigned iMISize, + unsigned *iTIndices, unsigned iTISize, + unsigned iCopy = 1 + ); + + /*! Builds an indexed face set from an other indexed face set */ + IndexedFaceSet(const IndexedFaceSet& iBrother); + + void swap(IndexedFaceSet& ioOther){ + std::swap(_Vertices, ioOther._Vertices); + std::swap(_Normals, ioOther._Normals); + std::swap(_FrsMaterials, ioOther._FrsMaterials); + std::swap(_TexCoords, ioOther._TexCoords); + + std::swap(_VSize, ioOther._VSize); + std::swap(_NSize, ioOther._NSize); + std::swap(_MSize, ioOther._MSize); + std::swap(_TSize, ioOther._TSize); + + std::swap(_NumFaces, ioOther._NumFaces); + std::swap(_NumVertexPerFace, ioOther._NumVertexPerFace); + std::swap(_FaceStyle, ioOther._FaceStyle); + + std::swap(_VIndices, ioOther._VIndices); + std::swap(_NIndices, ioOther._NIndices); + std::swap(_MIndices, ioOther._MIndices); // Material Indices + std::swap(_TIndices, ioOther._TIndices); + + std::swap(_VISize, ioOther._VISize); + std::swap(_NISize, ioOther._NISize); + std::swap(_MISize, ioOther._MISize); + std::swap(_TISize, ioOther._TISize); + + std::swap(_displayList, ioOther._displayList); + + Rep::swap(ioOther); + } + + IndexedFaceSet& operator=(const IndexedFaceSet& iBrother){ + IndexedFaceSet tmp(iBrother); + swap(tmp); + return *this; + } + + /*! Desctructor + desallocates all the ressources */ + virtual ~IndexedFaceSet(); + + /*! Accept the corresponding visitor */ + virtual void accept(SceneVisitor& v); + + /*! Compute the Bounding Box */ + virtual void ComputeBBox(); + + /*! modifiers */ + inline void setDisplayList(unsigned int index) {_displayList = index;} + + /*! Accessors */ + virtual const real * vertices() const {return _Vertices;} + virtual const real * normals() const {return _Normals;} + virtual const FrsMaterial*const* frs_materials() const {return _FrsMaterials;} + virtual const real* texCoords() const {return _TexCoords;} + virtual const unsigned vsize() const {return _VSize;} + virtual const unsigned nsize() const {return _NSize;} + virtual const unsigned msize() const {return _MSize;} + virtual const unsigned tsize() const {return _TSize;} + virtual const unsigned numFaces() const {return _NumFaces;} + virtual const unsigned * numVertexPerFaces() const {return _NumVertexPerFace;} + virtual const TRIANGLES_STYLE * trianglesStyle() const {return _FaceStyle;} + virtual const unsigned* vindices() const {return _VIndices;} + virtual const unsigned* nindices() const {return _NIndices;} + virtual const unsigned* mindices() const {return _MIndices;} + virtual const unsigned* tindices() const {return _TIndices;} + virtual const unsigned visize() const {return _VISize;} + virtual const unsigned nisize() const {return _NISize;} + virtual const unsigned misize() const {return _MISize;} + virtual const unsigned tisize() const {return _TISize;} + inline unsigned int displayList() const {return _displayList;} + +protected: + real *_Vertices; + real *_Normals; + FrsMaterial** _FrsMaterials; + real *_TexCoords; + + unsigned _VSize; + unsigned _NSize; + unsigned _MSize; + unsigned _TSize; + + unsigned _NumFaces; + unsigned *_NumVertexPerFace; + TRIANGLES_STYLE *_FaceStyle; + + unsigned *_VIndices; + unsigned *_NIndices; + unsigned *_MIndices; // Material Indices + unsigned *_TIndices; // Texture coordinates Indices + + unsigned _VISize; + unsigned _NISize; + unsigned _MISize; + unsigned _TISize; + + unsigned int _displayList; + +}; + +#endif // INDEXEDFACESET_H diff --git a/source/blender/freestyle/intern/scene_graph/LineRep.cpp b/source/blender/freestyle/intern/scene_graph/LineRep.cpp new file mode 100755 index 00000000000..504db06acf4 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/LineRep.cpp @@ -0,0 +1,58 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "LineRep.h" + +void LineRep::ComputeBBox() +{ + real XMax = _vertices.front()[0]; + real YMax = _vertices.front()[1]; + real ZMax = _vertices.front()[2]; + + real XMin = _vertices.front()[0]; + real YMin = _vertices.front()[1]; + real ZMin = _vertices.front()[2]; + + // parse all the coordinates to find + // the XMax, YMax, ZMax + vector<Vec3r>::iterator v; + for(v=_vertices.begin(); v!=_vertices.end(); v++) { + // X + if((*v)[0] > XMax) + XMax = (*v)[0]; + if((*v)[0] < XMin) + XMin = (*v)[0]; + + // Y + if((*v)[1] > YMax) + YMax = (*v)[1]; + if((*v)[1] < YMin) + YMin = (*v)[1]; + + // Z + if((*v)[2] > ZMax) + ZMax = (*v)[2]; + if((*v)[2] < ZMin) + ZMin = (*v)[2]; + } + + setBBox(BBox<Vec3r>(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax))); +} diff --git a/source/blender/freestyle/intern/scene_graph/LineRep.h b/source/blender/freestyle/intern/scene_graph/LineRep.h new file mode 100755 index 00000000000..232557af857 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/LineRep.h @@ -0,0 +1,130 @@ +// +// Filename : LineRep.h +// Author(s) : Stephane Grabli +// Purpose : Class to define the representation of 3D Line. +// Date of creation : 26/03/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LINEREP_H +# define LINEREP_H + +# include <vector> +# include <list> +# include "Rep.h" +# include "../system/FreestyleConfig.h" + +using namespace std; + +/*! Base class for all lines objects */ +class LIB_SCENE_GRAPH_EXPORT LineRep : public Rep +{ +public: + + /*! Line description style */ + enum LINES_STYLE{LINES, LINE_STRIP, LINE_LOOP}; + inline LineRep() : Rep() {_width = 0.f;} + + /*! Builds a single line from 2 vertices + * v1 + * first vertex + * v2 + * second vertex + */ + inline LineRep(const Vec3r& v1, const Vec3r& v2) + : Rep() + { + setStyle(LINES); + AddVertex(v1); + AddVertex(v2); + _width = 0.f; + } + + /*! Builds a line rep from a vertex chain */ + inline LineRep(const vector<Vec3r>& vertices) + : Rep() + { + _vertices = vertices; + setStyle(LINE_STRIP); + _width = 0.f; + } + + /*! Builds a line rep from a vertex chain */ + inline LineRep(const list<Vec3r>& vertices) + : Rep() + { + for(list<Vec3r>::const_iterator v=vertices.begin(), end=vertices.end(); + v!=end; + v++) + { + _vertices.push_back(*v); + } + setStyle(LINE_STRIP); + _width = 0.f; + } + + virtual ~LineRep() + { + _vertices.clear(); + } + + /*! accessors */ + inline const LINES_STYLE style() const {return _Style;} + inline const vector<Vec3r>& vertices() const {return _vertices;} + inline float width() const {return _width;} + + /*! modifiers */ + inline void setStyle(const LINES_STYLE iStyle) {_Style = iStyle;} + inline void AddVertex(const Vec3r& iVertex) {_vertices.push_back(iVertex);} + inline void setVertices(const vector<Vec3r>& iVertices) + { + if(0 != _vertices.size()) + { + _vertices.clear(); + } + for(vector<Vec3r>::const_iterator v=iVertices.begin(), end=iVertices.end(); + v!=end; + v++) + { + _vertices.push_back(*v); + } + } + inline void setWidth(float iWidth) {_width=iWidth;} + + /*! Accept the corresponding visitor */ + virtual void accept(SceneVisitor& v) { + Rep::accept(v); + v.visitLineRep(*this); + } + + /*! Computes the line bounding box.*/ + virtual void ComputeBBox(); + +private: + LINES_STYLE _Style; + vector<Vec3r> _vertices; + float _width; +}; + +#endif // LINEREP_H diff --git a/source/blender/freestyle/intern/scene_graph/Node.h b/source/blender/freestyle/intern/scene_graph/Node.h new file mode 100755 index 00000000000..41afaa353be --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/Node.h @@ -0,0 +1,97 @@ +// +// Filename : Node.h +// Author(s) : Stephane Grabli +// Purpose : Abstract class for scene graph nodes. Inherits from +// BaseObject which defines the addRef release mechanism. +// Date of creation : 24/01/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef NODE_H +# define NODE_H + +# include "../system/FreestyleConfig.h" +# include "../system/BaseObject.h" +# include "SceneVisitor.h" +# include "../geometry/BBox.h" +# include "../geometry/Geom.h" +# include "../system/Precision.h" + +using namespace std; +using namespace Geometry; + +class LIB_SCENE_GRAPH_EXPORT Node : public BaseObject +{ +public: + + inline Node() : BaseObject() {} + inline Node(const Node& iBrother) : BaseObject() + { + _BBox = iBrother.bbox(); + } + virtual ~Node(){} + + /*! Accept the corresponding visitor + * Each inherited node + * must overload this method + */ + virtual void accept(SceneVisitor& v) { + v.visitNode(*this); + } + + /*! bounding box management */ + /*! Returns the node bounding box + * If no bounding box exists, an empty bbox + * is returned + */ + virtual const BBox<Vec3r>& bbox() const {return _BBox;} + + /*! Sets the Node bounding box */ + virtual void setBBox(const BBox<Vec3r>& iBox) {_BBox = iBox;} + + /*! Makes the union of _BBox and iBox */ + virtual void AddBBox(const BBox<Vec3r>& iBox) + { + if(iBox.empty()) + return; + + if(_BBox.empty()) + _BBox = iBox; + else + _BBox += iBox; + } + + /*! Updates the BBox */ + virtual const BBox<Vec3r>& UpdateBBox() {return _BBox;} + + /*! Clears the bounding box */ + virtual void clearBBox() { _BBox.clear(); } + +protected: + +private: + BBox<Vec3r> _BBox; +}; + +#endif // NODE_H diff --git a/source/blender/freestyle/intern/scene_graph/NodeCamera.cpp b/source/blender/freestyle/intern/scene_graph/NodeCamera.cpp new file mode 100644 index 00000000000..1d095b35a0d --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/NodeCamera.cpp @@ -0,0 +1,120 @@ +#include <string.h> // for memcpy +#include "NodeCamera.h" +#include <math.h> + +void loadIdentity(double * matrix){ + int i; + + // Build Identity matrix + for(i=0;i<16;++i){ + double value ; + if((i % 5) == 0) + value = 1.0; + else + value = 0; + matrix[i] = value; + } +} + +NodeCamera::NodeCamera(CameraType camera_type) +:camera_type_(camera_type){ + loadIdentity(modelview_matrix_); + loadIdentity(projection_matrix_); +} + +NodeCamera::NodeCamera(const NodeCamera& iBrother) +:camera_type_(iBrother.camera_type_){ + memcpy(modelview_matrix_, iBrother.modelview_matrix_, 16*sizeof(double)); + memcpy(projection_matrix_, iBrother.projection_matrix_, 16*sizeof(double)); +} + +void NodeCamera::accept(SceneVisitor& v){ + v.visitNodeCamera(*this) ; +} + +void NodeCamera::setModelViewMatrix(double modelview_matrix[16]){ + memcpy(modelview_matrix_, modelview_matrix,16*sizeof(double)); +} + +void NodeCamera::setProjectionMatrix(double projection_matrix[16]){ + memcpy(projection_matrix_, projection_matrix,16*sizeof(double)); +} + +NodeOrthographicCamera::NodeOrthographicCamera() +:NodeCamera(NodeCamera::ORTHOGRAPHIC), +left_(0),right_(0),bottom_(0),top_(0),zNear_(0),zFar_(0){ + loadIdentity(projection_matrix_); + loadIdentity(modelview_matrix_); +} + +NodeOrthographicCamera::NodeOrthographicCamera(double left + , double right + , double bottom + , double top + , double zNear + , double zFar + ) +:NodeCamera(NodeCamera::ORTHOGRAPHIC), +left_(left), +right_(right), +bottom_(bottom), +top_(top), +zNear_(zNear), +zFar_(zFar){ + + loadIdentity(projection_matrix_); + + projection_matrix_[0] = 2.0/(right-left); + projection_matrix_[3] = -(right + left) / (right - left) ; + projection_matrix_[5] = 2.0/(top-bottom); + projection_matrix_[7] = -(top + bottom) / (top - bottom) ; + projection_matrix_[10] = -2.0/(zFar-zNear); + projection_matrix_[11] = -(zFar + zNear) / (zFar - zNear); + +} + +NodeOrthographicCamera::NodeOrthographicCamera(const NodeOrthographicCamera& iBrother) +:NodeCamera(iBrother),left_(iBrother.left_),right_(iBrother.right_),bottom_(iBrother.bottom_),top_(iBrother.top_),zNear_(iBrother.zNear_),zFar_(iBrother.zFar_){ +} + +NodePerspectiveCamera::NodePerspectiveCamera() +:NodeCamera(NodeCamera::PERSPECTIVE){ +} + +NodePerspectiveCamera::NodePerspectiveCamera(double fovy + , double aspect + , double zNear + , double zFar) +:NodeCamera(NodeCamera::PERSPECTIVE){ + loadIdentity(projection_matrix_); + + double f = cos(fovy/2.0)/sin(fovy/2.0); // cotangent + + projection_matrix_[0] = f/aspect; + projection_matrix_[5] = f; + projection_matrix_[10] = (zNear+zFar)/(zNear-zFar); + projection_matrix_[11] = (2.0*zNear*zFar)/(zNear-zFar); + projection_matrix_[14] = -1.0; + projection_matrix_[15] = 0; + +} + +NodePerspectiveCamera::NodePerspectiveCamera(double left, + double right, + double bottom, + double top, + double zNear, + double zFar) +:NodeCamera(NodeCamera::PERSPECTIVE){ + loadIdentity(projection_matrix_); + + projection_matrix_[0] = (2.0*zNear)/(right-left); + projection_matrix_[2] = (right+left)/(right-left); + projection_matrix_[5] = (2.0*zNear)/(top-bottom); + projection_matrix_[6] = (top+bottom)/(top-bottom); + projection_matrix_[10] = - (zFar+zNear)/(zFar-zNear); + projection_matrix_[11] = - (2.0*zFar*zNear)/(zFar-zNear); + projection_matrix_[14] = -1.0; + projection_matrix_[15] = 0; +} + diff --git a/source/blender/freestyle/intern/scene_graph/NodeCamera.h b/source/blender/freestyle/intern/scene_graph/NodeCamera.h new file mode 100644 index 00000000000..cdd6fa83048 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/NodeCamera.h @@ -0,0 +1,192 @@ +// +// Filename : NodeCamera.h +// Author(s) : Stephane Grabli +// Purpose : Class to represent a light node +// Date of creation : 25/01/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + + +#ifndef NODE_CAMERA_H_ +#define NODE_CAMERA_H_ + +# include "../geometry/Geom.h" +# include "../system/FreestyleConfig.h" +# include "Node.h" + +using namespace Geometry; + +class NodeOrthographicCamera; +class NodePerspectiveCamera; +class LIB_SCENE_GRAPH_EXPORT NodeCamera : public Node +{ +public: + typedef enum {PERSPECTIVE,ORTHOGRAPHIC,GENERIC} CameraType; + + /*! Default matrices: Identity for both projection and modelview. */ + NodeCamera(CameraType camera_type = GENERIC); + NodeCamera(const NodeCamera& iBrother); + + virtual ~NodeCamera() {} + + /*! Accept the corresponding visitor */ + virtual void accept(SceneVisitor& v); + + /*! Matrix is copied */ + void setModelViewMatrix(double modelview_matrix[16]); + /*! Matrix is copied */ + void setProjectionMatrix(double projection_matrix[16]); + + double * modelViewMatrix() {return modelview_matrix_;} + double * projectionMatrix() {return projection_matrix_;} + +protected: + // row major right handed matrix + double modelview_matrix_[16]; + // row major right handed matrix + double projection_matrix_[16]; + + CameraType camera_type_; +}; + +class LIB_SCENE_GRAPH_EXPORT NodeOrthographicCamera : public NodeCamera{ +public: + NodeOrthographicCamera(); + /*! Builds a parallel projection matrix a la glOrtho. + A 0 0 tx + 0 B 0 ty + 0 0 C tz + 0 0 0 1 + + where + + A = + 2 / (right - left) + B = + 2 / (top - bottom) + C = + -2 / (far - near) + tx = + -(right + left) / (right - left) + ty = + -(top + bottom) / (top - bottom) + tz = + -(zFar + zNear) / (zFar - zNear) + */ + NodeOrthographicCamera(double left + , double right + , double bottom + , double top + , double zNear + , double zFar + ); + + double left() const {return left_;} + double right() const {return right_;} + double bottom() const {return bottom_;} + double top() const {return top_;} + double zNear() const {return zNear_;} + double zFar() const {return zFar_;} + + NodeOrthographicCamera(const NodeOrthographicCamera& iBrother); + +private: + double left_; + double right_; + double bottom_; + double top_; + double zNear_; + double zFar_; +}; + +class LIB_SCENE_GRAPH_EXPORT NodePerspectiveCamera : public NodeCamera { +public: + NodePerspectiveCamera(); + /*! Builds a perspective projection matrix a la gluPerspective. + Given f defined as follows: + fovy + f = cotangent(____) + 2 + The generated matrix is + + + ( f ) + | ______ | + | aspect 0 0 0 | + | | + | 0 f 0 0 | + | | + | zNear+zFar 2*zNear*zFar | + | __________ ____________ | + | 0 0 zNear-zFar zNear-zFar | + | | + ( 0 0 -1 0 ) + \param fovy + Field of View specified in radians. + */ + NodePerspectiveCamera(double fovy + , double aspect + , double zNear + , double zFar); + + /*! Builds a perspective projection matrix a la glFrustum. + ( 2*zNear ) + | __________ | + | right-left 0 A 0 | + | | + | 2*zNear | + | 0 __________ B 0 | + | top-bottom | + | | + | 0 0 C D | + | | + | 0 0 -1 0 | + ( ) + + right+left + A = __________ + right-left + + top+bottom + B = __________ + top-bottom + + zFar+zNear + C = - __________ + zFar-zNear + + 2*zFar*zNear + D = - ____________ + zFar-zNear + */ + NodePerspectiveCamera(double left, + double right, + double bottom, + double top, + double zNear, + double zFar); +}; + + +#endif // NODE_CAMERA_H_ diff --git a/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.cpp b/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.cpp new file mode 100755 index 00000000000..acd740ee055 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.cpp @@ -0,0 +1,34 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "NodeDrawingStyle.h" + +void NodeDrawingStyle::accept(SceneVisitor& v) { + v.visitNodeDrawingStyle(*this); + + v.visitNodeDrawingStyleBefore(*this); + v.visitDrawingStyle(_DrawingStyle); + for(vector<Node*>::iterator node=_Children.begin(), end=_Children.end(); + node!=end; + node++) + (*node)->accept(v); + v.visitNodeDrawingStyleAfter(*this); +} diff --git a/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.h b/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.h new file mode 100755 index 00000000000..012f963ea8c --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.h @@ -0,0 +1,70 @@ +// +// Filename : NodeDrawingStyle.h +// Author(s) : Stephane Grabli +// Purpose : Class to define a Drawing Style to be applied +// to the underlying children. Inherits from NodeGroup. +// Date of creation : 06/02/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef NODEDRAWINGSTYLE_H +# define NODEDRAWINGSTYLE_H + +# include "../system/FreestyleConfig.h" +# include "NodeGroup.h" +# include "DrawingStyle.h" + +class LIB_SCENE_GRAPH_EXPORT NodeDrawingStyle : public NodeGroup +{ +public: + + inline NodeDrawingStyle() : NodeGroup() {} + virtual ~NodeDrawingStyle() {} + + inline const DrawingStyle& drawingStyle() const { return _DrawingStyle; } + inline void setDrawingStyle(const DrawingStyle& iDrawingStyle) { _DrawingStyle = iDrawingStyle; } + + /*! Sets the style. Must be one of FILLED, LINES, POINTS, INVISIBLE. */ + inline void setStyle(const DrawingStyle::STYLE iStyle) { _DrawingStyle.setStyle(iStyle); } + /*! Sets the line width in the LINES style case */ + inline void setLineWidth(const float iLineWidth) { _DrawingStyle.setLineWidth(iLineWidth); } + /*! Sets the Point size in the POINTS style case */ + inline void setPointSize(const float iPointSize) { _DrawingStyle.setPointSize(iPointSize); } + /*! Enables or disables the lighting. TRUE = enable */ + inline void setLightingEnabled(const bool iEnableLighting) { _DrawingStyle.setLightingEnabled(iEnableLighting); } + + /*! Accept the corresponding visitor */ + virtual void accept(SceneVisitor& v); + + /*! accessors */ + inline DrawingStyle::STYLE style() const {return _DrawingStyle.style();} + inline float lineWidth() const {return _DrawingStyle.lineWidth();} + inline float pointSize() const {return _DrawingStyle.pointSize();} + inline bool lightingEnabled() const {return _DrawingStyle.lightingEnabled();} + +private: + DrawingStyle _DrawingStyle; +}; + +#endif // NODEDRAWINGSTYLE_H diff --git a/source/blender/freestyle/intern/scene_graph/NodeGroup.cpp b/source/blender/freestyle/intern/scene_graph/NodeGroup.cpp new file mode 100755 index 00000000000..3d2aa2c8694 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/NodeGroup.cpp @@ -0,0 +1,122 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "NodeGroup.h" + +void NodeGroup::AddChild(Node *iChild) +{ + if(NULL == iChild) + return; + + _Children.push_back(iChild); + iChild->addRef(); +} + +int NodeGroup::destroy() +{ + /*! Node::destroy makes a release on the object + * and then returns the reference counter. + * If the reference counter is equal to 0, + * that means that nobody else is linking + * this node group and that we can destroy the whole + * underlying tree. + * Else, one or several Node link this node group, + * and we only returns the reference counter + * decremented by Node::destroy(); + */ + int refThis = Node::destroy(); + + // if refThis != 0, we can't destroy the tree + if(0 != refThis) + return refThis; + + // If we are here, that means that nobody else + // needs our NodeGroup and we can destroy it. + int refCount = 0; + vector<Node *>::iterator node; + + for(node=_Children.begin(); node!=_Children.end(); node++) + { + refCount = (*node)->destroy(); + if(0 == refCount) + delete (*node); + } + + _Children.clear(); + + return refThis; +} + +void NodeGroup::accept(SceneVisitor& v) { + v.visitNodeGroup(*this); + + v.visitNodeGroupBefore(*this); + for(vector<Node *>::iterator node=_Children.begin(), end=_Children.end(); + node!=end; + node++) + (*node)->accept(v); + v.visitNodeGroupAfter(*this); +} + +void NodeGroup::DetachChildren() +{ + vector<Node *>::iterator node; + + for(node=_Children.begin(); node!=_Children.end(); node++) + { + (*node)->release(); + } + + _Children.clear(); +} + +void NodeGroup::DetachChild(Node *iChild) +{ + int found = 0; + vector<Node*>::iterator node; + + for(node=_Children.begin(); node!=_Children.end(); node++) + { + if((*node) == iChild) + { + (*node)->release(); + _Children.erase(node); + found = 1; + break; + } + } +} + +void NodeGroup::RetrieveChildren(vector<Node*>& oNodes){ + oNodes = _Children; +} + +const BBox<Vec3r>& NodeGroup::UpdateBBox() +{ + vector<Node *>::iterator node; + clearBBox(); + for(node=_Children.begin(); node!=_Children.end(); node++) + { + AddBBox((*node)->UpdateBBox()); + } + + return Node::UpdateBBox(); +} diff --git a/source/blender/freestyle/intern/scene_graph/NodeGroup.h b/source/blender/freestyle/intern/scene_graph/NodeGroup.h new file mode 100755 index 00000000000..a1bd2b57e56 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/NodeGroup.h @@ -0,0 +1,84 @@ +// +// Filename : NodeGroup.h +// Author(s) : Stephane Grabli +// Purpose : Class to represent a group node. This node can contains +// several children. It also contains a transform matrix +// indicating the transform state of the underlying +// children. +// Date of creation : 24/01/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef NODEGROUP_H +# define NODEGROUP_H + +# include <vector> +# include "../system/FreestyleConfig.h" +# include "Node.h" + +using namespace std; + +class LIB_SCENE_GRAPH_EXPORT NodeGroup : public Node +{ +public: + + inline NodeGroup(): Node() {} + virtual ~NodeGroup(){} + + /*! Adds a child. Makes a addRef on the + * iChild reference counter */ + virtual void AddChild(Node *iChild); + + /*! destroys all the underlying nodes + * Returns the reference counter + * after having done a release() */ + virtual int destroy(); + + /*! Detaches all the children */ + virtual void DetachChildren(); + + /*! Detached the sepcified child */ + virtual void DetachChild(Node *iChild); + + /*! Retrieve children */ + virtual void RetrieveChildren(vector<Node*>& oNodes); + + + /*! Renders every children */ + // virtual void Render(Renderer *iRenderer); + + /*! Accept the corresponding visitor */ + virtual void accept(SceneVisitor& v); + + /*! Updates the BBox */ + virtual const BBox<Vec3r>& UpdateBBox(); + + /*! Returns the number of children */ + virtual int numberOfChildren() {return _Children.size();} + +protected: + vector<Node*> _Children; +}; + +#endif // NODEGROUP_H diff --git a/source/blender/freestyle/intern/scene_graph/NodeLight.cpp b/source/blender/freestyle/intern/scene_graph/NodeLight.cpp new file mode 100755 index 00000000000..61a46155cfa --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/NodeLight.cpp @@ -0,0 +1,80 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "NodeLight.h" + +int NodeLight::numberOfLights = 0; + +NodeLight::NodeLight() +: Node() +{ + if(numberOfLights > 7) + { + _number = 7; + } + else + { + _number = numberOfLights; + numberOfLights++; + } + + Ambient[0] = Ambient[1] = Ambient[2] = 0.f; + Ambient[3] = 1.f; + + for(int i=0; i<4; i++) + { + Diffuse[i] = 1.f; + Specular[i] = 1.f; + } + + Position[0] = Position[1] = Position[3] = 0.f; + Position[2] = 1.f; + + on = true; +} + +NodeLight::NodeLight(NodeLight& iBrother) +: Node(iBrother) +{ + if(numberOfLights > 7) + { + _number = 7; + } + else + { + _number = numberOfLights; + numberOfLights++; + } + + for(int i=0; i<4; i++) + { + Ambient[i] = iBrother.ambient()[i]; + Diffuse[i] = iBrother.diffuse()[i]; + Specular[i] = iBrother.specular()[i]; + Position[i] = iBrother.position()[i]; + } + + on = iBrother.isOn(); +} + +void NodeLight::accept(SceneVisitor& v) { + v.visitNodeLight(*this); +} diff --git a/source/blender/freestyle/intern/scene_graph/NodeLight.h b/source/blender/freestyle/intern/scene_graph/NodeLight.h new file mode 100755 index 00000000000..0689505fb24 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/NodeLight.h @@ -0,0 +1,86 @@ +// +// Filename : NodeLight.h +// Author(s) : Stephane Grabli +// Purpose : Class to represent a light node +// Date of creation : 25/01/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef NODELIGHT_H +# define NODELIGHT_H + +# include "../geometry/Geom.h" +# include "../system/FreestyleConfig.h" +# include "Node.h" + +using namespace Geometry; + +class LIB_SCENE_GRAPH_EXPORT NodeLight : public Node +{ +public: + + NodeLight(); + NodeLight(NodeLight& iBrother); + + virtual ~NodeLight() {} + + /*! Accept the corresponding visitor */ + virtual void accept(SceneVisitor& v); + + /*! Accessors for the light properties */ + inline const float * ambient() const {return Ambient;} + inline const float * diffuse() const {return Diffuse;} + inline const float * specular() const {return Specular;} + inline const float * position() const {return Position;} + inline bool isOn() const {return on;} + inline int number() const {return _number;} + +private: + // Data members + // ============ + + /*! on=true, the light is on */ + bool on; + + /*! The color definition */ + float Ambient[4]; + float Diffuse[4]; + float Specular[4]; + + /*! Light position. if w = 0, the light is + * placed at infinite. + */ + float Position[4]; + + /*! used to manage the number of lights */ + /*! numberOfLights + * the number of lights in the scene. + * Initially, 0. + */ + static int numberOfLights; + /*! The current lignt number */ + int _number; +}; + +#endif // NODELIGHT_H diff --git a/source/blender/freestyle/intern/scene_graph/NodeShape.cpp b/source/blender/freestyle/intern/scene_graph/NodeShape.cpp new file mode 100755 index 00000000000..9083c852d36 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/NodeShape.cpp @@ -0,0 +1,51 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "NodeShape.h" + +NodeShape::~NodeShape() +{ + vector<Rep *>::iterator rep; + + if(0 != _Shapes.size()) + { + for(rep=_Shapes.begin(); rep!=_Shapes.end(); rep++) + { + int refCount = (*rep)->destroy(); + if(0 == refCount) + delete (*rep); + } + + _Shapes.clear(); + } +} + +void NodeShape::accept(SceneVisitor& v) { + v.visitNodeShape(*this); + + v.visitFrsMaterial(_FrsMaterial); + + v.visitNodeShapeBefore(*this); + vector<Rep *>::iterator rep; + for(rep = _Shapes.begin(); rep != _Shapes.end(); rep++) + (*rep)->accept(v); + v.visitNodeShapeAfter(*this); +} diff --git a/source/blender/freestyle/intern/scene_graph/NodeShape.h b/source/blender/freestyle/intern/scene_graph/NodeShape.h new file mode 100755 index 00000000000..9849d4661b8 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/NodeShape.h @@ -0,0 +1,89 @@ +// +// Filename : NodeShape.h +// Author(s) : Stephane Grabli +// Purpose : Class to build a shape node. It contains a Rep, +// which is the shape geometry +// Date of creation : 25/01/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef NODESHAPE_H +# define NODESHAPE_H + +# include <vector> +# include "../system/FreestyleConfig.h" +# include "Node.h" +# include "Rep.h" +# include "../geometry/BBox.h" +# include "../geometry/Geom.h" +# include "FrsMaterial.h" + +using namespace std; +using namespace Geometry; + +class LIB_SCENE_GRAPH_EXPORT NodeShape : public Node +{ +public: + + inline NodeShape() : Node() {} + + virtual ~NodeShape(); + + /*! Adds a Rep to the _Shapes list + * The delete of the rep is done + * when it is not used any more by + * the Scene Manager. So, it must not + * be deleted by the caller + */ + virtual void AddRep(Rep *iRep) + { + if(NULL == iRep) + return; + _Shapes.push_back(iRep); + iRep->addRef(); + + // updates bbox: + AddBBox(iRep->bbox()); + } + + /*! Accept the corresponding visitor */ + virtual void accept(SceneVisitor& v); + + /*! Sets the shape material */ + inline void setFrsMaterial(const FrsMaterial& iMaterial) { _FrsMaterial = iMaterial; } + + /*! accessors */ + /*! returns the shape's material */ + inline FrsMaterial& frs_material() { return _FrsMaterial; } + inline const vector<Rep*>& shapes() {return _Shapes;} + +private: + /*! list of shapes */ + vector<Rep*> _Shapes; + + /*! Shape Material */ + FrsMaterial _FrsMaterial; +}; + +#endif // NODESHAPE_H diff --git a/source/blender/freestyle/intern/scene_graph/NodeTransform.cpp b/source/blender/freestyle/intern/scene_graph/NodeTransform.cpp new file mode 100755 index 00000000000..8f706c78259 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/NodeTransform.cpp @@ -0,0 +1,166 @@ +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + + +#include "../system/FreestyleConfig.h" +#include "NodeTransform.h" + +void NodeTransform::Translate(real x, real y, real z) +{ + _Matrix(0, 3) += x; + _Matrix(1, 3) += y; + _Matrix(2, 3) += z; +} + +void NodeTransform::Rotate(real iAngle, real x, real y, real z) +{ + //Normalize the x,y,z vector; + real norm = (real)sqrt(x*x+y*y+z*z); + if(0 == norm) + return; + + x /= norm; + y /= norm; + z /= norm; + + // find the corresponding matrix with the Rodrigues formula: + // R = I + sin(iAngle)*Ntilda + (1-cos(iAngle))*Ntilda*Ntilda + Matrix33r Ntilda; + Ntilda(0,0) = Ntilda(1,1) = Ntilda(2,2) = 0.f; + Ntilda(0,1) = -z; + Ntilda(0,2) = y; + Ntilda(1,0) = z; + Ntilda(1,2) = -x; + Ntilda(2,0) = -y; + Ntilda(2,1) = x; + + const Matrix33r Ntilda2(Ntilda * Ntilda); + + + const real sinAngle = (real)sin((iAngle/180.f)*M_PI); + const real cosAngle = (real)cos((iAngle/180.f)*M_PI); + + Matrix33r NS(Ntilda*sinAngle); + Matrix33r NC(Ntilda2*(1.f-cosAngle)); + Matrix33r R; + R = Matrix33r::identity(); + R += NS + NC; + + //R4 is the corresponding 4x4 matrix + Matrix44r R4; + R4 = Matrix44r::identity(); + + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + R4(i,j) = R(i,j); + + // Finally, we multiply our current matrix by R4: + Matrix44r mat_tmp(_Matrix); + _Matrix = mat_tmp * R4; +} + +void NodeTransform::Scale(real x, real y, real z) +{ + _Matrix(0,0) *= x; + _Matrix(1,1) *= y; + _Matrix(2,2) *= z; + + _Scaled = true; +} + +void NodeTransform::MultiplyMatrix(const Matrix44r &iMatrix) +{ + Matrix44r mat_tmp(_Matrix); + _Matrix = mat_tmp * iMatrix; +} + +void NodeTransform::setMatrix(const Matrix44r &iMatrix) +{ + _Matrix = iMatrix; + if(isScaled(iMatrix)) + _Scaled = true; +} + +void NodeTransform::accept(SceneVisitor& v) { + v.visitNodeTransform(*this); + + v.visitNodeTransformBefore(*this); + for(vector<Node *>::iterator node=_Children.begin(), end=_Children.end(); + node!=end; + node++) + (*node)->accept(v); + v.visitNodeTransformAfter(*this); +} + +void NodeTransform::AddBBox(const BBox<Vec3r>& iBBox) +{ + Vec3r oldMin(iBBox.getMin()); + Vec3r oldMax(iBBox.getMax()); + + // compute the 8 corners of the bbox + HVec3r box[8]; + box[0] = HVec3r(iBBox.getMin()); + box[1] = HVec3r(oldMax[0], oldMin[1], oldMin[2]); + box[2] = HVec3r(oldMax[0], oldMax[1], oldMin[2]); + box[3] = HVec3r(oldMin[0], oldMax[1], oldMin[2]); + box[4] = HVec3r(oldMin[0], oldMin[1], oldMax[2]); + box[5] = HVec3r(oldMax[0], oldMin[1], oldMax[2]); + box[6] = HVec3r(oldMax[0], oldMax[1], oldMax[2]); + box[7] = HVec3r(oldMin[0], oldMax[1], oldMax[2]); + + // Computes the transform iBBox + HVec3r tbox[8]; + unsigned i; + for(i = 0; i < 8; i++) + tbox[i] = _Matrix * box[i]; + + Vec3r newMin(tbox[0]); + Vec3r newMax(tbox[0]); + for (i=0; i<8; i++) + { + for (unsigned int j=0; j<3; j++) + { + if (newMin[j] > tbox[i][j]) + newMin[j] = tbox[i][j]; + if (newMax[j] < tbox[i][j]) + newMax[j] = tbox[i][j]; + } + } + + BBox<Vec3r> transformBox(newMin, newMax); + + Node::AddBBox(transformBox); +} + +bool NodeTransform::isScaled(const Matrix44r &M) +{ + for(unsigned int j=0; j<3; j++) + { + real norm = 0; + for(unsigned int i=0; i<3; i++) + { + norm += M(i,j)*M(i,j); + } + if((norm > 1.01) || (norm < 0.99)) + return true; + } + + return false; +} diff --git a/source/blender/freestyle/intern/scene_graph/NodeTransform.h b/source/blender/freestyle/intern/scene_graph/NodeTransform.h new file mode 100755 index 00000000000..e75132466f0 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/NodeTransform.h @@ -0,0 +1,107 @@ +// +// Filename : NodeTransform.h +// Author(s) : Stephane Grabli +// Purpose : Class to represent a transform node. A Transform node +// contains one or several children, all affected by the +// transformation. +// Date of creation : 06/02/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef NODETRANSFORM_H +# define NODETRANSFORM_H + +# include "../geometry/Geom.h" +# include "../system/FreestyleConfig.h" +# include "NodeGroup.h" + +using namespace Geometry; + +class LIB_SCENE_GRAPH_EXPORT NodeTransform : public NodeGroup +{ +public: + + inline NodeTransform() : NodeGroup() { + _Matrix = Matrix44r::identity(); + _Scaled=false; + } + + virtual ~NodeTransform() {} + + /*! multiplys the current matrix by the + * x, y, z translation matrix. + */ + void Translate(real x, real y, real z); + + /*! multiplys the current matrix by a + * rotation matrix + * iAngle + * The rotation angle + * x, y, z + * The rotation axis + */ + void Rotate(real iAngle, real x, real y, real z); + + /*! multiplys the current matrix by a + * scaling matrix. + * x, y, z + * The scaling coefficients + * with respect to the x,y,z axis + */ + void Scale(real x, real y, real z); + + /*! Multiplys the current matrix + * by iMatrix + */ + void MultiplyMatrix(const Matrix44r &iMatrix); + + /*! Sets the current matrix to iMatrix */ + void setMatrix(const Matrix44r &iMatrix); + + /*! Accept the corresponding visitor */ + virtual void accept(SceneVisitor& v); + + /*! Overloads the Node::AddBBox in order to take care + * about the transformation + */ + virtual void AddBBox(const BBox<Vec3r>& iBBox); + + /*! Checks whether a matrix contains a scale factor + * or not. + * Returns true if yes. + * iMatrix + * The matrix to check + */ + bool isScaled(const Matrix44r &M); + + /*! accessors */ + inline const Matrix44r& matrix() const { return _Matrix; } + inline bool scaled() const {return _Scaled;} + +private: + Matrix44r _Matrix; + bool _Scaled; +}; + +#endif // NODETRANSFORM_H diff --git a/source/blender/freestyle/intern/scene_graph/OrientedLineRep.cpp b/source/blender/freestyle/intern/scene_graph/OrientedLineRep.cpp new file mode 100755 index 00000000000..94068983596 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/OrientedLineRep.cpp @@ -0,0 +1,31 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "OrientedLineRep.h" +#include "../system/BaseObject.h" + +void OrientedLineRep::accept(SceneVisitor& v) { + Rep::accept(v); + if(!frs_material()) + v.visitOrientedLineRep(*this); + else + v.visitLineRep(*this); +} diff --git a/source/blender/freestyle/intern/scene_graph/OrientedLineRep.h b/source/blender/freestyle/intern/scene_graph/OrientedLineRep.h new file mode 100755 index 00000000000..4274581e39a --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/OrientedLineRep.h @@ -0,0 +1,67 @@ +// +// Filename : OrientedLineRep.h +// Author(s) : Stephane Grabli +// Purpose : Class to display an oriented line representation. +// Date of creation : 24/10/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef VIEWEDGEREP_H +# define VIEWEDGEREP_H + +# include "../system/FreestyleConfig.h" +# include "LineRep.h" + +class LIB_SCENE_GRAPH_EXPORT OrientedLineRep : public LineRep +{ +public: + + OrientedLineRep() : LineRep() {} + /*! Builds a single line from 2 vertices + * v1 + * first vertex + * v2 + * second vertex + */ + inline OrientedLineRep(const Vec3r& v1, const Vec3r& v2) + : LineRep(v1,v2) + {} + + /*! Builds a line rep from a vertex chain */ + inline OrientedLineRep(const vector<Vec3r>& vertices) + : LineRep(vertices) + {} + + /*! Builds a line rep from a vertex chain */ + inline OrientedLineRep(const list<Vec3r>& vertices) + : LineRep(vertices) + {} + + virtual ~OrientedLineRep() {} + + /*! Accept the corresponding visitor */ + virtual void accept(SceneVisitor& v); +}; + +#endif // VIEWEDGEREP_H diff --git a/source/blender/freestyle/intern/scene_graph/Rep.cpp b/source/blender/freestyle/intern/scene_graph/Rep.cpp new file mode 100755 index 00000000000..84ad2c2a966 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/Rep.cpp @@ -0,0 +1 @@ +#include "Rep.h" diff --git a/source/blender/freestyle/intern/scene_graph/Rep.h b/source/blender/freestyle/intern/scene_graph/Rep.h new file mode 100755 index 00000000000..58be0374ae4 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/Rep.h @@ -0,0 +1,133 @@ +// +// Filename : Rep.h +// Author(s) : Stephane Grabli +// Purpose : Base class for all shapes. Inherits from BasicObjects +// for references counter management (addRef, release). +// Date of creation : 25/01/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef REP_H +# define REP_H + +# include "../system/BaseObject.h" +# include "SceneVisitor.h" +# include "../geometry/BBox.h" +# include "../geometry/Geom.h" +# include "../system/Precision.h" +# include "FrsMaterial.h" +# include "../system/Id.h" + +using namespace Geometry; + +class LIB_SCENE_GRAPH_EXPORT Rep : public BaseObject +{ +public: + + inline Rep() : BaseObject() {_Id = 0; _FrsMaterial=0;} + inline Rep(const Rep& iBrother) + : BaseObject() + { + _Id = iBrother._Id; + _Name = iBrother._Name; + if(0 == iBrother._FrsMaterial) + _FrsMaterial = 0; + else + _FrsMaterial = new FrsMaterial(*(iBrother._FrsMaterial)); + + _BBox = iBrother.bbox(); + } + inline void swap(Rep& ioOther){ + std::swap(_BBox,ioOther._BBox); + std::swap(_Id, ioOther._Id); + std::swap(_Name, ioOther._Name); + std::swap(_FrsMaterial,ioOther._FrsMaterial); + } + Rep& operator=(const Rep& iBrother){ + if(&iBrother != this){ + _Id = iBrother._Id; + _Name = iBrother._Name; + if(0 == iBrother._FrsMaterial) + _FrsMaterial = 0; + else{ + if(_FrsMaterial == 0){ + _FrsMaterial = new FrsMaterial(*iBrother._FrsMaterial); + }else{ + (*_FrsMaterial)=(*(iBrother._FrsMaterial)); + } + _BBox = iBrother.bbox(); + } + } + return *this; + } + virtual ~Rep() + { + if(0 != _FrsMaterial) + { + delete _FrsMaterial; + _FrsMaterial = 0; + } + } + + /*! Accept the corresponding visitor + * Must be overload by + * inherited classes + */ + virtual void accept(SceneVisitor& v) { + if(_FrsMaterial) + v.visitFrsMaterial(*_FrsMaterial); + v.visitRep(*this); + } + + /*! Computes the rep bounding box. + * Each Inherited rep must compute + * its bbox depending on the way the data + * are stored. So, each inherited class + * must overload this method + */ + virtual void ComputeBBox() = 0; + + /*! Returns the rep bounding box */ + virtual const BBox<Vec3r>& bbox() const {return _BBox;} + inline Id getId() const {return _Id;} + inline const string& getName() const {return _Name;} + inline const FrsMaterial * frs_material() const {return _FrsMaterial;} + + /*! Sets the Rep bounding box */ + virtual void setBBox(const BBox<Vec3r>& iBox) {_BBox = iBox;} + inline void setId(const Id& id) {_Id = id;} + inline void setName(const string& name) {_Name = name;} + inline void setFrsMaterial(const FrsMaterial& iMaterial) + { + _FrsMaterial = new FrsMaterial(iMaterial); + } + +private: + BBox<Vec3r> _BBox; + Id _Id; + string _Name; + FrsMaterial *_FrsMaterial; +}; + +#endif // REP_H diff --git a/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp new file mode 100755 index 00000000000..aeee87f8222 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp @@ -0,0 +1,86 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include <iomanip> +#include "ScenePrettyPrinter.h" +#include "IndexedFaceSet.h" + +#define VISIT(CLASS) \ + void ScenePrettyPrinter::visit##CLASS(CLASS&) { \ + _ofs << _space << #CLASS << endl; \ + } + +VISIT(Node) +VISIT(NodeShape) +VISIT(NodeGroup) +VISIT(NodeLight) +VISIT(NodeDrawingStyle) +VISIT(NodeTransform) + +void ScenePrettyPrinter::visitNodeShapeBefore(NodeShape&) { + increaseSpace(); +} + +void ScenePrettyPrinter::visitNodeShapeAfter(NodeShape&) { + decreaseSpace(); +} + +void ScenePrettyPrinter::visitNodeGroupBefore(NodeGroup&) { + increaseSpace(); +} + +void ScenePrettyPrinter::visitNodeGroupAfter(NodeGroup&) { + decreaseSpace(); +} + +void ScenePrettyPrinter::visitNodeDrawingStyleBefore(NodeDrawingStyle&) { + increaseSpace(); +} + +void ScenePrettyPrinter::visitNodeDrawingStyleAfter(NodeDrawingStyle&) { + decreaseSpace(); +} + +void ScenePrettyPrinter::visitNodeTransformBefore(NodeTransform&) { + increaseSpace(); +} + +void ScenePrettyPrinter::visitNodeTransformAfter(NodeTransform&) { + decreaseSpace(); +} + +VISIT(LineRep) +VISIT(OrientedLineRep) +VISIT(TriangleRep) +VISIT(VertexRep) + +void ScenePrettyPrinter::visitIndexedFaceSet(IndexedFaceSet& ifs) { + const real* vertices = ifs.vertices(); + unsigned vsize = ifs.vsize(); + + _ofs << _space << "IndexedFaceSet" << endl; + const real *p = vertices; + for (unsigned i = 0; i < vsize / 3; i++) { + _ofs << _space << " " << setw(3) << setfill('0') << i << ": " + << p[0] << ", " << p[1] << ", " << p[2] << endl; + p += 3; + } +} diff --git a/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.h b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.h new file mode 100755 index 00000000000..4e83825ff55 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.h @@ -0,0 +1,105 @@ +// +// Filename : ScenePrettyPrinter.h +// Author(s) : Stephane Grabli, Emmanuel Turquin +// Purpose : Class to display textual information +// about a scene graph. +// Date of creation : 26/04/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef SCENE_PRETTY_PRINTER_H +# define SCENE_PRETTY_PRINTER_H + +# include <iostream> +# include <fstream> +# include <string> +# include "SceneVisitor.h" + +using namespace std; + +class ScenePrettyPrinter : public SceneVisitor +{ +public: + + ScenePrettyPrinter(const string filename = "SceneLog.txt") + : SceneVisitor() { + if (!filename.empty()) + _ofs.open(filename.c_str()); + if (!_ofs.is_open()) + cerr << "Warning, unable to open file \"" << filename << "\"" << endl; + _space = ""; + } + + virtual ~ScenePrettyPrinter() { + if (_ofs.is_open()) + _ofs.close(); + } + + + // + // visitClass methods + // + ////////////////////////////////////////////// + + VISIT_DECL(Node) + VISIT_DECL(NodeShape) + VISIT_DECL(NodeGroup) + VISIT_DECL(NodeLight) + VISIT_DECL(NodeDrawingStyle) + VISIT_DECL(NodeTransform) + + VISIT_DECL(LineRep) + VISIT_DECL(OrientedLineRep) + VISIT_DECL(TriangleRep) + VISIT_DECL(VertexRep) + VISIT_DECL(IndexedFaceSet) + + virtual void visitNodeShapeBefore(NodeShape&); + virtual void visitNodeShapeAfter(NodeShape&); + virtual void visitNodeGroupBefore(NodeGroup&); + virtual void visitNodeGroupAfter(NodeGroup&); + virtual void visitNodeDrawingStyleBefore(NodeDrawingStyle&); + virtual void visitNodeDrawingStyleAfter(NodeDrawingStyle&); + virtual void visitNodeTransformBefore(NodeTransform&); + virtual void visitNodeTransformAfter(NodeTransform&); + + protected: + + void increaseSpace() + { + _space += " "; + } + + void decreaseSpace() + { + _space.erase(0, 2); + } + + private: + + ofstream _ofs; + string _space; +}; + +#endif // SCENE_PRETTY_PRINTER_H diff --git a/source/blender/freestyle/intern/scene_graph/SceneVisitor.cpp b/source/blender/freestyle/intern/scene_graph/SceneVisitor.cpp new file mode 100755 index 00000000000..da9c94930bd --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/SceneVisitor.cpp @@ -0,0 +1 @@ +#include "SceneVisitor.h" diff --git a/source/blender/freestyle/intern/scene_graph/SceneVisitor.h b/source/blender/freestyle/intern/scene_graph/SceneVisitor.h new file mode 100755 index 00000000000..5f67b4b44aa --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/SceneVisitor.h @@ -0,0 +1,98 @@ +// +// Filename : SceneVisitor.h +// Author(s) : Emmanuel Turquin +// Purpose : Class to visit (without doing anything) +// a scene graph structure +// Date of creation : 26/04/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef SCENE_VISITOR_H +# define SCENE_VISITOR_H + +# define VISIT_COMPLETE_DEF(type) \ +virtual void visit##type(type&) {} \ +virtual void visit##type##Before(type&) {} \ +virtual void visit##type##After(type&) {} + +# define VISIT_DECL(type) virtual void visit##type(type&); + +# define VISIT_COMPLETE_DECL(type) \ + virtual void visit##type##Before(type&); \ + virtual void visit##type(type&); \ + virtual void visit##type##After(type&); + +#include "../system/FreestyleConfig.h" + +class Node; +class NodeShape; +class NodeGroup; +class NodeLight; +class NodeCamera; +class NodeDrawingStyle; +class NodeTransform; + +class Rep; +class LineRep; +class OrientedLineRep; +class TriangleRep; +class VertexRep; +class IndexedFaceSet; +class DrawingStyle; +class FrsMaterial; + +class LIB_SCENE_GRAPH_EXPORT SceneVisitor +{ +public: + + SceneVisitor() {} + virtual ~SceneVisitor() {} + + virtual void beginScene() {} + virtual void endScene() {} + + // + // visitClass methods + // + ////////////////////////////////////////////// + + VISIT_COMPLETE_DEF(Node) + VISIT_COMPLETE_DEF(NodeShape) + VISIT_COMPLETE_DEF(NodeGroup) + VISIT_COMPLETE_DEF(NodeLight) + VISIT_COMPLETE_DEF(NodeCamera) + VISIT_COMPLETE_DEF(NodeDrawingStyle) + VISIT_COMPLETE_DEF(NodeTransform) + + VISIT_COMPLETE_DEF(Rep) + VISIT_COMPLETE_DEF(LineRep) + VISIT_COMPLETE_DEF(OrientedLineRep) + VISIT_COMPLETE_DEF(TriangleRep) + VISIT_COMPLETE_DEF(VertexRep) + VISIT_COMPLETE_DEF(IndexedFaceSet) + VISIT_COMPLETE_DEF(DrawingStyle) + VISIT_COMPLETE_DEF(FrsMaterial) +}; + +#endif // SCENEVISITOR_H diff --git a/source/blender/freestyle/intern/scene_graph/TriangleRep.cpp b/source/blender/freestyle/intern/scene_graph/TriangleRep.cpp new file mode 100755 index 00000000000..f73a8498714 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/TriangleRep.cpp @@ -0,0 +1,59 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "TriangleRep.h" + +void TriangleRep::ComputeBBox() +{ + real XMax = _vertices[0][0]; + real YMax = _vertices[0][1]; + real ZMax = _vertices[0][2]; + + real XMin = _vertices[0][0]; + real YMin = _vertices[0][1]; + real ZMin = _vertices[0][2]; + + // parse all the coordinates to find + // the XMax, YMax, ZMax + for(int i=0; i<3; ++i) + { + // X + if(_vertices[i][0] > XMax) + XMax = _vertices[i][0]; + if(_vertices[i][0] < XMin) + XMin = _vertices[i][0]; + + // Y + if(_vertices[i][1] > YMax) + YMax = _vertices[i][1]; + if(_vertices[i][1] < YMin) + YMin = _vertices[i][1]; + + // Z + if(_vertices[i][2] > ZMax) + ZMax = _vertices[i][2]; + if(_vertices[i][2] < ZMin) + ZMin = _vertices[i][2]; + + } + + setBBox(BBox<Vec3r>(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax))); +} diff --git a/source/blender/freestyle/intern/scene_graph/TriangleRep.h b/source/blender/freestyle/intern/scene_graph/TriangleRep.h new file mode 100755 index 00000000000..9d986857060 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/TriangleRep.h @@ -0,0 +1,106 @@ +// +// Filename : TriangleRep.h +// Author(s) : Stephane Grabli +// Purpose : Class to define the represenation of a triangle +// Date of creation : 16/12/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef TRIANGLEREP_H +# define TRIANGLEREP_H + +//! inherits from class Rep +#include "Rep.h" + +/*! Base class for all lines objects */ +class LIB_SCENE_GRAPH_EXPORT TriangleRep : public Rep +{ +public: + + /*! Line description style */ + enum TRIANGLE_STYLE{FILL, LINES}; +private: + TRIANGLE_STYLE _Style; + Vec3r _vertices[3]; + Vec3r _colors[3]; +public: + inline TriangleRep() : Rep() {_Style = FILL;} + + /*! Builds a triangle from 3 vertices + * v0 + * first vertex + * v1 + * second vertex + * v2 + * third vertex + */ + inline TriangleRep(const Vec3r& v0, const Vec3r& v1, const Vec3r& v2) + : Rep() + { + _vertices[0] = v0; + _vertices[1] = v1; + _vertices[2] = v2; + _Style = FILL; + } + inline TriangleRep( const Vec3r& v0, const Vec3r& c0, + const Vec3r& v1, const Vec3r& c1, + const Vec3r& v2, const Vec3r& c2) + : Rep() + { + _vertices[0] = v0; + _vertices[1] = v1; + _vertices[2] = v2; + _colors[0] = c0; + _colors[1] = c1; + _colors[2] = c2; + _Style = FILL; + } + + virtual ~TriangleRep() + {} + + /*! accessors */ + inline const TRIANGLE_STYLE style() const {return _Style;} + inline const Vec3r& vertex(int index) const {return _vertices[index];} + inline const Vec3r& color(int index) const {return _colors[index];} + /*! modifiers */ + inline void setStyle(const TRIANGLE_STYLE iStyle) {_Style = iStyle;} + inline void setVertex(int index, const Vec3r& iVertex) {_vertices[index] = iVertex;} + inline void setColor(int index, const Vec3r& iColor) {_colors[index] = iColor;} + inline void setVertices(const Vec3r& v0, const Vec3r& v1, const Vec3r& v2) {_vertices[0] = v0; _vertices[1] = v1; _vertices[2] = v2;} + inline void setColors(const Vec3r& c0, const Vec3r& c1, const Vec3r& c2) {_colors[0] = c0; _colors[1] = c1; _colors[2] = c2;} + + /*! Accept the corresponding visitor */ + virtual void accept(SceneVisitor& v) { + Rep::accept(v); + v.visitTriangleRep(*this); + } + + /*! Computes the triangle bounding box.*/ + virtual void ComputeBBox(); + + +}; + +#endif diff --git a/source/blender/freestyle/intern/scene_graph/VertexRep.cpp b/source/blender/freestyle/intern/scene_graph/VertexRep.cpp new file mode 100755 index 00000000000..e4f774bfb84 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/VertexRep.cpp @@ -0,0 +1,29 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "VertexRep.h" + +void VertexRep::ComputeBBox() +{ + + setBBox(BBox<Vec3r>(Vec3r(_coordinates[0], _coordinates[1], _coordinates[2]), + Vec3r(_coordinates[0], _coordinates[1], _coordinates[2]))); +} diff --git a/source/blender/freestyle/intern/scene_graph/VertexRep.h b/source/blender/freestyle/intern/scene_graph/VertexRep.h new file mode 100755 index 00000000000..9e31b4b8ef9 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/VertexRep.h @@ -0,0 +1,87 @@ +// +// Filename : VertexRep.h +// Author(s) : Stephane Grabli +// Purpose : Class to define the representation of a vertex for +// displaying purpose. +// Date of creation : 03/04/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef VERTEXREP_H +# define VERTEXREP_H + +#include "Rep.h" + +class LIB_SCENE_GRAPH_EXPORT VertexRep : public Rep +{ +public: + + inline VertexRep() : Rep() {_vid = 0;_PointSize = 0.f;} + inline VertexRep(real x, real y, real z, int id = 0) + : Rep() + { + _coordinates[0] = x; + _coordinates[1] = y; + _coordinates[2] = z; + + _vid = id; + _PointSize = 0.f; + } + + inline ~VertexRep() {} + + /*! Accept the corresponding visitor */ + + virtual void accept(SceneVisitor& v) { + Rep::accept(v); + v.visitVertexRep(*this); + } + + /*! Computes the rep bounding box. + */ + virtual void ComputeBBox(); + + /*! accessors */ + inline const int vid() const {return _vid;} + inline const real * coordinates() const {return _coordinates;} + inline real x() const {return _coordinates[0];} + inline real y() const {return _coordinates[1];} + inline real z() const {return _coordinates[2];} + inline float pointSize() const {return _PointSize;} + + /*! modifiers */ + inline void setVid(int id) {_vid = id;} + inline void setX(real x) {_coordinates[0] = x;} + inline void setY(real y) {_coordinates[1] = y;} + inline void setZ(real z) {_coordinates[2] = z;} + inline void setCoordinates(real x, real y, real z) {_coordinates[0] = x;_coordinates[1] = y; _coordinates[2] = z;} + inline void setPointSize(float iPointSize) {_PointSize = iPointSize;} + +private: + int _vid; // vertex id + real _coordinates[3]; + float _PointSize; +}; + +#endif // VERTEXREP_H diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp new file mode 100755 index 00000000000..7a51a1a78df --- /dev/null +++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp @@ -0,0 +1,92 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +# include "../view_map/Functions0D.h" +# include "AdvancedFunctions0D.h" +# include "../view_map/SteerableViewMap.h" +# include "Canvas.h" + +namespace Functions0D { + + int DensityF0D::operator()(Interface0DIterator& iter) { + Canvas* canvas = Canvas::getInstance(); + int bound = _filter.getBound(); + if( (iter->getProjectedX()-bound < 0) || (iter->getProjectedX()+bound>canvas->width()) + || (iter->getProjectedY()-bound < 0) || (iter->getProjectedY()+bound>canvas->height())) { + result = 0.0; + return 0; + } + RGBImage image; + canvas->readColorPixels((int)iter->getProjectedX() - bound, + (int)iter->getProjectedY() - bound, + _filter.maskSize(), + _filter.maskSize(), + image); + result = _filter.getSmoothedPixel<RGBImage>(&image, (int)iter->getProjectedX(), + (int)iter->getProjectedY()); + return 0; + } + + + int LocalAverageDepthF0D::operator()(Interface0DIterator& iter) { + Canvas * iViewer = Canvas::getInstance(); + int bound = _filter.getBound(); + + if( (iter->getProjectedX()-bound < 0) || (iter->getProjectedX()+bound>iViewer->width()) + || (iter->getProjectedY()-bound < 0) || (iter->getProjectedY()+bound>iViewer->height())) { + result = 0.0; + return 0; + } + GrayImage image ; + iViewer->readDepthPixels((int)iter->getProjectedX()-bound,(int)iter->getProjectedY()-bound,_filter.maskSize(),_filter.maskSize(),image); + result = _filter.getSmoothedPixel(&image, (int)iter->getProjectedX(), (int)iter->getProjectedY()); + return 0; + } + + int ReadMapPixelF0D::operator()(Interface0DIterator& iter) { + Canvas * canvas = Canvas::getInstance(); + result = canvas->readMapPixel(_mapName, _level, (int)iter->getProjectedX(), (int)iter->getProjectedY()); + return 0; + } + + int ReadSteerableViewMapPixelF0D::operator()(Interface0DIterator& iter) { + SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap(); + result = svm->readSteerableViewMapPixel(_orientation, _level,(int)iter->getProjectedX(), (int)iter->getProjectedY()); + return 0; + } + + int ReadCompleteViewMapPixelF0D::operator()(Interface0DIterator& iter) { + SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap(); + result = svm->readCompleteViewMapPixel(_level,(int)iter->getProjectedX(), (int)iter->getProjectedY()); + return 0; + } + + int GetViewMapGradientNormF0D::operator()(Interface0DIterator& iter){ + SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap(); + float pxy = svm->readCompleteViewMapPixel(_level,(int)iter->getProjectedX(), (int)iter->getProjectedY()); + float gx = svm->readCompleteViewMapPixel(_level,(int)iter->getProjectedX()+_step, (int)iter->getProjectedY()) + - pxy; + float gy = svm->readCompleteViewMapPixel(_level,(int)iter->getProjectedX(), (int)iter->getProjectedY()+_step) + - pxy; + result = Vec2f(gx,gy).norm(); + return 0; + } +} // end of namespace Functions0D diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.h b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.h new file mode 100755 index 00000000000..5d62ea8d9eb --- /dev/null +++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.h @@ -0,0 +1,209 @@ +// +// Filename : AdvancedFunctions0D.h +// Author(s) : Stephane Grabli +// Emmanuel Turquin +// Purpose : Functions taking 0D input +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef ADVANCED_FUNCTIONS0D_HPP +# define ADVANCED_FUNCTIONS0D_HPP + + +# include "../image/Image.h" +# include "../image/GaussianFilter.h" +# include "../view_map/Functions0D.h" + +// +// Functions definitions +// +/////////////////////////////////////////////////////////// + +namespace Functions0D { + + // DensityF0D + /*! Returns the density of the (result) image evaluated at an Interface0D. + * This density is evaluated using a pixels square window around the + * evaluation point and integrating these values using + * a gaussian. + */ + class LIB_STROKE_EXPORT DensityF0D : public UnaryFunction0D<double> + { + public: + /*! Builds the functor from the gaussian sigma value. + * \param sigma + * sigma indicates the x value for which the gaussian + * function is 0.5. It leads to the window size + * value. (the larger, the smoother) + */ + DensityF0D(double sigma = 2) : UnaryFunction0D<double>() { + _filter.setSigma((float)sigma); + } + /*! Returns the string "DensityF0D"*/ + string getName() const { + return "DensityF0D"; + } + /*! The () operator. */ + int operator()(Interface0DIterator& iter); + + private: + + GaussianFilter _filter; + }; + + // LocalAverageDepthF0D + /*! Returns the average depth around a point. + * The result is obtained by querying the + * depth buffer on a window around that point. + */ + class LIB_STROKE_EXPORT LocalAverageDepthF0D : public UnaryFunction0D<double> + { + private: + GaussianFilter _filter; + public: + /*! Builds the functor from the size of the mask that + * will be used. + */ + LocalAverageDepthF0D(real maskSize=5.f) : UnaryFunction0D<double>() { + _filter.setSigma((float)maskSize/2.f); + } + /*! Returns the string "LocalAverageDepthF0D"*/ + string getName() const { + return "LocalAverageDepthF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter); + }; + + // ReadMapPixel + /*! Reads a pixel in a map. + */ + class LIB_STROKE_EXPORT ReadMapPixelF0D : public UnaryFunction0D<float> + { + private: + const char * _mapName; + int _level; + public: + /*! Builds the functor from name of the + * Map that must be read. + * \param iMapName + * The name of the map. + * \param level + * The level of the pyramid from which + * the pixel must be read. + */ + ReadMapPixelF0D(const char *iMapName, int level) : UnaryFunction0D<float>() { + _mapName = iMapName; + _level = level; + } + /*! Returns the string "ReadMapPixelF0D"*/ + string getName() const { + return "ReadMapPixelF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter); + }; + + // ReadSteerableViewMapPixel + /*! Reads a pixel in one of the level of one of the steerable viewmaps. + */ + class LIB_STROKE_EXPORT ReadSteerableViewMapPixelF0D : public UnaryFunction0D<float> + { + private: + unsigned _orientation; + int _level; + public: + /*! Builds the functor + * \param nOrientation + * The integer belonging to [0,4] indicating the orientation (E,NE,N,NW) + * we are interested in. + * \param level + * The level of the pyramid from which + * the pixel must be read. + */ + ReadSteerableViewMapPixelF0D(unsigned nOrientation, int level) : UnaryFunction0D<float>() { + _orientation = nOrientation; + _level = level; + } + /*! Returns the string "ReadSteerableViewMapPixelF0D"*/ + string getName() const { + return "ReadSteerableViewMapPixelF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter); + }; + + // ReadCompleteViewMapPixel + /*! Reads a pixel in one of the level of the complete viewmap. + */ + class LIB_STROKE_EXPORT ReadCompleteViewMapPixelF0D : public UnaryFunction0D<float> + { + private: + int _level; + public: + /*! Builds the functor + * \param level + * The level of the pyramid from which + * the pixel must be read. + */ + ReadCompleteViewMapPixelF0D(int level) : UnaryFunction0D<float>() { + _level = level; + } + /*! Returns the string "ReadCompleteViewMapPixelF0D"*/ + string getName() const { + return "ReadCompleteViewMapPixelF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter); + }; + + // GetViewMapGradientNormF0D + /*! Returns the norm of the gradient of the global viewmap density image. + */ + class LIB_STROKE_EXPORT GetViewMapGradientNormF0D: public UnaryFunction0D< float> + { + private: + int _level; + float _step; + public: + /*! Builds the functor + * \param level + * The level of the pyramid from which + * the pixel must be read. + */ + GetViewMapGradientNormF0D(int level) : UnaryFunction0D<float>() { + _level = level; + _step = (float)pow(2.0,_level); + } + /*! Returns the string "GetOccludeeF0D"*/ + string getName() const { + return "GetViewMapGradientNormF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter); + }; +} // end of namespace Functions0D + +#endif // ADVANCED_FUNCTIONS0D_HPP diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp new file mode 100755 index 00000000000..2548ce38659 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp @@ -0,0 +1,110 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +# include "AdvancedFunctions1D.h" +# include "../view_map/SteerableViewMap.h" +# include "Canvas.h" + +// FIXME +namespace Functions1D { + + int GetSteerableViewMapDensityF1D::operator()(Interface1D& inter) { + SteerableViewMap * svm = Canvas::getInstance()->getSteerableViewMap(); + Interface0DIterator it = inter.pointsBegin(_sampling); + Interface0DIterator itnext = it;++itnext; + FEdge *fe; + unsigned nSVM; + vector<float> values; + while(!itnext.isEnd()){ + Interface0D& i0D = (*it); + Interface0D& i0Dnext = (*itnext); + fe = i0D.getFEdge(i0Dnext); + if(fe == 0){ + cerr << "GetSteerableViewMapDensityF1D warning: no FEdge between " << i0D.getId() << " and " << i0Dnext.getId() << endl; + // compute the direction between these two ??? + Vec2f dir = i0Dnext.getPoint2D()-i0D.getPoint2D(); + nSVM = svm->getSVMNumber(dir); + }else{ + nSVM = svm->getSVMNumber(fe->getId().getFirst()); + } + Vec2r m((i0D.getProjectedX()+i0Dnext.getProjectedX())/2.0, + (i0D.getProjectedY()+i0Dnext.getProjectedY())/2.0); + values.push_back(svm->readSteerableViewMapPixel(nSVM,_level,(int)m[0],(int)m[1])); + ++it;++itnext; + } + float res, res_tmp; + vector<float>::iterator v = values.begin(), vend=values.end(); + unsigned size = 1; + switch(_integration) { + case MIN: + res = *v;++v; + for (; v!=vend; ++v) { + res_tmp = *v; + if (res_tmp < res) + res = res_tmp; + } + break; + case MAX: + res = *v;++v; + for (; v!=vend; ++v) { + res_tmp = *v; + if (res_tmp > res) + res = res_tmp; + } + break; + case FIRST: + res = *v; + break; + case LAST: + --vend; + res = *vend; + break; + case MEAN: + default: + res = *v;++v; + for (; v!=vend; ++v, ++size) + res += *v; + res /= (size ? size : 1); + break; + } + result = res; + return 0; + } + + int GetDirectionalViewMapDensityF1D::operator()(Interface1D& inter) { + //soc unsigned size; + result = integrate(_fun, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration); + return 0; + } + + int GetCompleteViewMapDensityF1D::operator()(Interface1D& inter) { + //soc unsigned size; + Id id = inter.getId(); + result = integrate(_fun, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration); + return 0; + } + + int GetViewMapGradientNormF1D::operator()(Interface1D& inter){ + result = integrate(_func, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration); + return 0; + } +} + diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h new file mode 100755 index 00000000000..ab963c68034 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h @@ -0,0 +1,288 @@ +// +// Filename : AdvancedFunctions1D.h +// Author(s) : Stephane Grabli, Emmanuel Turquin +// Purpose : Functions taking 1D input +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef ADVANCED_FUNCTIONS1D_HPP +# define ADVANCED_FUNCTIONS1D_HPP + + +# include "../view_map/Functions1D.h" +# include "AdvancedFunctions0D.h" + +// +// Functions definitions +// +/////////////////////////////////////////////////////////// + +namespace Functions1D { + + // DensityF1D + /*! Returns the density evaluated for an Interface1D. + * The density is evaluated for a set of points along + * the Interface1D (using the DensityF0D functor) + * with a user-defined sampling and + * then integrated into a single value using + * a user-defined integration method. + */ + class DensityF1D : public UnaryFunction1D<double> + { + private: + float _sampling; + public: + /*! Builds the functor. + * \param sigma + * Thesigma used in DensityF0D and determining + * the window size used in each density query. + * \param iType + * The integration method used to compute + * a single value from a set of values. + * \param sampling + * The resolution used to sample the chain: the corresponding 0D function + * is evaluated at each sample point and the result is obtained by + * combining the resulting values into a single one, following the + * method specified by iType. + */ + DensityF1D(double sigma = 2, IntegrationType iType = MEAN, float sampling=2.f) : UnaryFunction1D<double>(iType), _fun(sigma) { + _sampling = sampling; + } + /*! Destructor */ + virtual ~DensityF1D(){} + + /*! Returns the string "DensityF1D"*/ + string getName() const { + return "DensityF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter) { + result = integrate(_fun, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration); + return 0; + } + private: + Functions0D::DensityF0D _fun; + }; + + // LocalAverageDepthF1D + /*! Returns the average depth evaluated for an Interface1D. + * The average depth is evaluated for a set of points along + * the Interface1D (using the LocalAverageDepthF0D functor) + * with a user-defined sampling and + * then integrated into a single value using + * a user-defined integration method. + */ + class LocalAverageDepthF1D : public UnaryFunction1D<double> + { + public: + /*! Builds the functor. + * \param sigma + * The sigma used in DensityF0D and determining + * the window size used in each density query. + * \param iType + * The integration method used to compute + * a single value from a set of values. + */ + LocalAverageDepthF1D(real sigma, IntegrationType iType = MEAN) + : UnaryFunction1D<double>(iType), _fun(sigma){ + } + /*! Returns the string "LocalAverageDepthF1D"*/ + string getName() const { + return "LocalAverageDepthF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter) { + result = integrate(_fun, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; + } + private: + Functions0D::LocalAverageDepthF0D _fun; + }; + + // GetCompleteViewMapDensity + /*! Returns the density evaluated for an Interface1D in the + * complete viewmap image. + * The density is evaluated for a set of points along + * the Interface1D (using the ReadCompleteViewMapPixelF0D functor) + * and then integrated into a single value using + * a user-defined integration method. + */ + class LIB_STROKE_EXPORT GetCompleteViewMapDensityF1D : public UnaryFunction1D<double> + { + public: + /*! Builds the functor. + * \param level + * The level of the pyramid from which + * the pixel must be read. + * \param iType + * The integration method used to compute + * a single value from a set of values. + * \param sampling + * The resolution used to sample the chain: the corresponding 0D function + * is evaluated at each sample point and the result is obtained by + * combining the resulting values into a single one, following the + * method specified by iType. + */ + GetCompleteViewMapDensityF1D(unsigned level, IntegrationType iType = MEAN, float sampling=2.f) + : UnaryFunction1D<double>(iType), _fun(level){_sampling = sampling;} + /*! Returns the string "GetCompleteViewMapDensityF1D"*/ + string getName() const { + return "GetCompleteViewMapDensityF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter); + + private: + Functions0D::ReadCompleteViewMapPixelF0D _fun; + float _sampling; + }; + + // GetDirectionalViewMapDensity + /*! Returns the density evaluated for an Interface1D in of the + * steerable viewmaps image. + * The direction telling which Directional map to choose + * is explicitely specified by the user. + * The density is evaluated for a set of points along + * the Interface1D (using the ReadSteerableViewMapPixelF0D functor) + * and then integrated into a single value using + * a user-defined integration method. + */ + class LIB_STROKE_EXPORT GetDirectionalViewMapDensityF1D : public UnaryFunction1D<double> + { + public: + /*! Builds the functor. + * \param iOrientation + * The number of the directional map + * we must work with. + * \param level + * The level of the pyramid from which + * the pixel must be read. + * \param iType + * The integration method used to compute + * a single value from a set of values. + * \param sampling + * The resolution used to sample the chain: the corresponding 0D function + * is evaluated at each sample point and the result is obtained by + * combining the resulting values into a single one, following the + * method specified by iType. + */ + GetDirectionalViewMapDensityF1D(unsigned iOrientation, unsigned level, IntegrationType iType = MEAN, float sampling=2.f) + : UnaryFunction1D<double>(iType), _fun(iOrientation,level){_sampling = sampling;} + /*! Returns the string "GetDirectionalViewMapDensityF1D"*/ + string getName() const { + return "GetDirectionalViewMapDensityF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter); + + private: + Functions0D::ReadSteerableViewMapPixelF0D _fun; + float _sampling; + }; + + // GetSteerableViewMapDensityF1D + /*! Returns the density of the viewmap + * for a given Interface1D. The density of each + * FEdge is evaluated in the proper steerable + * ViewMap depending on its oorientation. + */ + class LIB_STROKE_EXPORT GetSteerableViewMapDensityF1D : public UnaryFunction1D<real> + { + private: + int _level; + float _sampling; + public: + /*! Builds the functor from the level + * of the pyramid from which the pixel must be read. + * \param level + * The level of the pyramid from which + * the pixel must be read. + * \param iType + * The integration method used to compute + * a single value from a set of values. + * \param sampling + * The resolution used to sample the chain: the corresponding 0D function + * is evaluated at each sample point and the result is obtained by + * combining the resulting values into a single one, following the + * method specified by iType. + */ + GetSteerableViewMapDensityF1D(int level,IntegrationType iType = MEAN, float sampling=2.f) : UnaryFunction1D<real>(iType) { + _level = level; + _sampling = sampling; + } + /*! Destructor */ + virtual ~GetSteerableViewMapDensityF1D(){} + + /*! Returns the string "GetSteerableViewMapDensityF1D"*/ + string getName() const { + return "GetSteerableViewMapDensityF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter); + }; + + // GetViewMapGradientNormF1D + /*! Returns the density of the viewmap + * for a given Interface1D. The density of each + * FEdge is evaluated in the proper steerable + * ViewMap depending on its oorientation. + */ + class LIB_STROKE_EXPORT GetViewMapGradientNormF1D : public UnaryFunction1D<real> + { + private: + int _level; + float _sampling; + Functions0D::GetViewMapGradientNormF0D _func; + public: + /*! Builds the functor from the level + * of the pyramid from which the pixel must be read. + * \param level + * The level of the pyramid from which + * the pixel must be read. + * \param iType + * The integration method used to compute + * a single value from a set of values. + * \param sampling + * The resolution used to sample the chain: the corresponding 0D function + * is evaluated at each sample point and the result is obtained by + * combining the resulting values into a single one, following the + * method specified by iType. + */ + GetViewMapGradientNormF1D(int level,IntegrationType iType = MEAN, float sampling=2.f) + : UnaryFunction1D<real>(iType), _func(level) { + _level = level; + _sampling = sampling; + } + + /*! Returns the string "GetSteerableViewMapDensityF1D"*/ + string getName() const { + return "GetViewMapGradientNormF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter); + }; +} // end of namespace Functions1D + +#endif // ADVANCED_FUNCTIONS1D_HPP diff --git a/source/blender/freestyle/intern/stroke/AdvancedPredicates1D.h b/source/blender/freestyle/intern/stroke/AdvancedPredicates1D.h new file mode 100755 index 00000000000..91b63168aa9 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/AdvancedPredicates1D.h @@ -0,0 +1,84 @@ +// +// Filename : AdvancedPredicates1D.h +// Author(s) : Stephane Grabli +// Purpose : Class gathering stroke creation algorithms +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef ADVANCED_PREDICATES1D_H +# define ADVANCED_PREDICATES1D_H + +# include <string> +# include "../view_map/Interface1D.h" +# include "AdvancedFunctions1D.h" +# include "Predicates1D.h" + +// +// Predicates definitions +// +/////////////////////////////////////////////////////////// + +namespace Predicates1D { + + // DensityLowerThanUP1D + /*! Returns true if the density evaluated for the + * Interface1D is less than a user-defined density value. + */ + class DensityLowerThanUP1D : public UnaryPredicate1D + { + public: + /*! Builds the functor. + * \param threshold + * The value of the threshold density. + * Any Interface1D having a density lower than + * this threshold will match. + * \param sigma + * The sigma value defining the density evaluation window size + * used in the DensityF0D functor. + */ + DensityLowerThanUP1D(double threshold, double sigma = 2) { + _threshold = threshold; + _sigma = sigma; + } + /*! Returns the string "DensityLowerThanUP1D"*/ + string getName() const { + return "DensityLowerThanUP1D"; + } + /*! The () operator. */ + int operator()(Interface1D& inter) { + Functions1D::DensityF1D fun(_sigma); + if (fun(inter) < 0) + return -1; + result = (fun.result < _threshold); + return 0; + } + private: + double _sigma; + double _threshold; + }; + +} // end of namespace Predicates1D + +#endif // ADVANCED_PREDICATES1D_H diff --git a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp new file mode 100755 index 00000000000..05da47914f3 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp @@ -0,0 +1,431 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "AdvancedStrokeShaders.h" +#include "../system/PseudoNoise.h" +#include "../system/RandGen.h" +#include "StrokeIterators.h" + +///////////////////////////////////////// +// +// CALLIGRAPHICS SHADER +// +///////////////////////////////////////// + + +CalligraphicShader::CalligraphicShader (real iMinThickness, real iMaxThickness, + const Vec2f &iOrientation, bool clamp) + : StrokeShader() +{ + _minThickness=iMinThickness; + _maxThickness=iMaxThickness; + _orientation = iOrientation; + _orientation.normalize(); + _clamp = clamp; +} + +float ksinToto=0; + +int +CalligraphicShader::shade(Stroke &ioStroke) const +{ + Interface0DIterator v; + Functions0D::VertexOrientation2DF0D fun; + StrokeVertex* sv; + for(v=ioStroke.verticesBegin(); + !v.isEnd(); + ++v) + { + real thickness; + if (fun(v) < 0) + return -1; + Vec2f vertexOri(fun.result); + Vec2r ori2d(-vertexOri[1], vertexOri[0]); + ori2d.normalizeSafe(); + real scal = ori2d * _orientation; + sv = dynamic_cast<StrokeVertex*>(&(*v)); + if (_clamp && (scal<0)) { + scal=0.0; + sv->attribute().setColor(1,1,1); + } + else { + scal=fabs(scal); + sv->attribute().setColor(0,0,0); + } + thickness=_minThickness+scal*(_maxThickness-_minThickness); + if (thickness<0.0) + thickness=0.0; + sv->attribute().setThickness(thickness/2.0,thickness/2.0); + } + + return 0; +} + +//void +//TipRemoverShader::shade(Stroke &ioStroke) const +//{ +// +// StrokeInternal::StrokeVertexIterator v, vend; +// for(v=ioStroke.strokeVerticesBegin(), vend=ioStroke.strokeVerticesEnd(); +// v!=vend; +// ++v) +// { +// if (((*v)->curvilinearAbscissa()<_tipLength) || +// ((*v)->strokeLength()-(*v)->curvilinearAbscissa()<_tipLength)) +// { +// (*v)->attribute().setThickness(0.0, 0.0); +// (*v)->attribute().setColor(1,1,1); +// } +// } +// +//} + + + +///////////////////////////////////////// +// +// SPATIAL NOISE SHADER +// +///////////////////////////////////////// + +static const unsigned NB_VALUE_NOISE = 512; + +SpatialNoiseShader::SpatialNoiseShader (float ioamount, float ixScale, int nbOctave, + bool smooth, bool pureRandom) + : StrokeShader() +{ + _amount = ioamount; + if (ixScale==0) _xScale=0; + else _xScale=1.0/ixScale/real(NB_VALUE_NOISE); + _nbOctave=nbOctave; + _smooth=smooth; + _pureRandom=pureRandom; +} +int +SpatialNoiseShader::shade(Stroke &ioStroke) const +{ + Interface0DIterator v, v2; + v=ioStroke.verticesBegin(); + Vec2r p(v->getProjectedX(), v->getProjectedY()); + v2=v; ++v2; + Vec2r p0(v2->getProjectedX(), v2->getProjectedY()); + p0=p+2*(p-p0); + StrokeVertex* sv; + sv = dynamic_cast<StrokeVertex*>(&(*v)); + real initU = sv->strokeLength()*real(NB_VALUE_NOISE); + if (_pureRandom) initU+=RandGen::drand48()*real(NB_VALUE_NOISE); + + Functions0D::VertexOrientation2DF0D fun; + while (!v.isEnd()) + { + sv = dynamic_cast<StrokeVertex*>(&(*v)); + Vec2r p(sv->getPoint()); + if (fun(v) < 0) + return -1; + Vec2r vertexOri(fun.result); + Vec2r ori2d(vertexOri[0], vertexOri[1]); + ori2d = Vec2r(p-p0); + ori2d.normalizeSafe(); + + PseudoNoise mynoise; + real bruit; + + if (_smooth) + bruit=mynoise.turbulenceSmooth(_xScale*sv->curvilinearAbscissa()+initU, + _nbOctave); + else + bruit=mynoise.turbulenceLinear(_xScale*sv->curvilinearAbscissa()+initU, + _nbOctave); + + Vec2r noise(-ori2d[1]*_amount*bruit, + ori2d[0]*_amount*bruit); + + sv->setPoint(p[0]+noise[0], p[1]+noise[1]); + p0=p; + + ++v; + } + + return 0; +} + + + +///////////////////////////////////////// +// +// SMOOTHING SHADER +// +///////////////////////////////////////// + + +SmoothingShader::SmoothingShader (int ionbIteration, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference, + real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real iCarricatureFactor) + : StrokeShader() +{ + _nbIterations=ionbIteration; + _factorCurvature=ifactorCurvature; + _factorCurvatureDifference=iFactorCurvatureDifference; + _anisoNormal=iAnisoNormal; + _anisoCurvature=iAnisoCurvature; + _carricatureFactor=iCarricatureFactor; + _factorPoint=iFactorPoint; + _anisoPoint=iAnisoPoint; +} + + + +int +SmoothingShader::shade(Stroke &ioStroke) const +{ + //cerr<<" Smoothing a stroke "<<endl; + + Smoother smoother(ioStroke); + smoother.smooth(_nbIterations, _factorPoint, _factorCurvature, _factorCurvatureDifference, + _anisoPoint, _anisoNormal, _anisoCurvature, _carricatureFactor); + return 0; +} + +// SMOOTHER +//////////////////////////// + +Smoother::Smoother(Stroke &ioStroke) +{ + _stroke=&ioStroke; + + _nbVertices=ioStroke.vertices_size(); + _vertex=new Vec2r[_nbVertices]; + _curvature=new real[_nbVertices]; + _normal=new Vec2r[_nbVertices]; + StrokeInternal::StrokeVertexIterator v, vend; + int i=0; + for(v = ioStroke.strokeVerticesBegin(), vend = ioStroke.strokeVerticesEnd(); + v != vend; + ++v) + { + _vertex[i]=(v)->getPoint(); + i++; + } + Vec2r vec_tmp(_vertex[0]-_vertex[_nbVertices-1]); + _isClosedCurve = (vec_tmp.norm() < M_EPSILON); + + _safeTest=(_nbVertices>4); +} + +void Smoother::smooth(int nbIteration, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference, + real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real iCarricatureFactor) +{ + _factorCurvature=ifactorCurvature; + _factorCurvatureDifference=iFactorCurvatureDifference; + _anisoNormal=iAnisoNormal; + _anisoCurvature=iAnisoCurvature; + _carricatureFactor=iCarricatureFactor; + _factorPoint=iFactorPoint; + _anisoPoint=iAnisoPoint; + + for (int i=0; i<nbIteration; i++) + iteration (); + copyVertices(); +} + +real edgeStopping (real x, real sigma) +{ + if (sigma==0.0) return 1.0; + return exp(-x*x/(sigma*sigma)); +} + +void +Smoother::iteration () +{ + computeCurvature(); + for (int i=1; i<_nbVertices-1; i++) + { + real motionNormal=_factorCurvature*_curvature[i]* + edgeStopping(_curvature[i], _anisoNormal); + + real diffC1=_curvature[i]-_curvature[i-1]; + real diffC2=_curvature[i]-_curvature[i+1]; + real motionCurvature=edgeStopping(diffC1, _anisoCurvature)*diffC1 + + edgeStopping(diffC2, _anisoCurvature)*diffC2;//_factorCurvatureDifference; + motionCurvature*=_factorCurvatureDifference; + //motionCurvature=_factorCurvatureDifference*(diffC1+diffC2); + if (_safeTest) + _vertex[i]=Vec2r(_vertex[i]+(motionNormal+motionCurvature)*_normal[i]); + Vec2r v1(_vertex[i-1]-_vertex[i]); + Vec2r v2(_vertex[i+1]-_vertex[i]); + real d1 = v1.norm(); + real d2 = v2.norm(); + _vertex[i]=Vec2r(_vertex[i]+ + _factorPoint*edgeStopping(d2, _anisoPoint)*(_vertex[i-1]-_vertex[i]) + + _factorPoint*edgeStopping(d1, _anisoPoint)*(_vertex[i+1]-_vertex[i]) ); + } + + if (_isClosedCurve) + { + real motionNormal=_factorCurvature*_curvature[0]* + edgeStopping(_curvature[0], _anisoNormal); + + real diffC1=_curvature[0]-_curvature[_nbVertices-2]; + real diffC2=_curvature[0]-_curvature[1]; + real motionCurvature=edgeStopping(diffC1, _anisoCurvature)*diffC1 + + edgeStopping(diffC2, _anisoCurvature)*diffC2;//_factorCurvatureDifference; + motionCurvature*=_factorCurvatureDifference; + //motionCurvature=_factorCurvatureDifference*(diffC1+diffC2); + _vertex[0]=Vec2r(_vertex[0]+(motionNormal+motionCurvature)*_normal[0]); + _vertex[_nbVertices-1]=_vertex[0]; + } +} + + +void +Smoother::computeCurvature () +{ + int i; + Vec2r BA, BC, normalCurvature; + for (i = 1; i < _nbVertices - 1; i++) + { + BA=_vertex[i-1]-_vertex[i]; + BC=_vertex[i+1]-_vertex[i]; + real lba=BA.norm(), lbc=BC.norm(); + BA.normalizeSafe(); + BC.normalizeSafe(); + normalCurvature = BA + BC; + + _normal[i]=Vec2r(-(BC-BA)[1], (BC-BA)[0]); + _normal[i].normalizeSafe(); + + _curvature[i] = normalCurvature * _normal[i]; + if (lba+lbc > M_EPSILON) + _curvature[i]/=(0.5*lba+lbc); + } + _curvature[0]=_curvature[1]; + _curvature[_nbVertices-1]=_curvature[_nbVertices-2]; + Vec2r di(_vertex[1]-_vertex[0]); + _normal[0] = Vec2r(-di[1], di[0]); + _normal[0].normalizeSafe(); + di=_vertex[_nbVertices-1]-_vertex[_nbVertices-2]; + _normal[_nbVertices-1]=Vec2r(-di[1], di[0]); + _normal[_nbVertices-1].normalizeSafe(); + + if (_isClosedCurve) + { + BA=_vertex[_nbVertices-2]-_vertex[0]; + BC=_vertex[1]-_vertex[0]; + real lba=BA.norm(), lbc=BC.norm(); + BA.normalizeSafe(); + BC.normalizeSafe(); + normalCurvature = BA + BC; + + _normal[i]=Vec2r(-(BC-BA)[1], (BC-BA)[0]); + _normal[i].normalizeSafe(); + + _curvature[i] = normalCurvature * _normal[i]; + if (lba+lbc > M_EPSILON) + _curvature[i]/=(0.5*lba+lbc); + + _normal[_nbVertices-1]=_normal[0]; + _curvature[_nbVertices-1]=_curvature[0]; + } +} + +void +Smoother::copyVertices () +{ + int i=0; + StrokeInternal::StrokeVertexIterator v, vend; + for(v=_stroke->strokeVerticesBegin(), vend=_stroke->strokeVerticesEnd(); + v!=vend; + ++v) + { + const Vec2r p0((v)->getPoint()); + const Vec2r p1(_vertex[i]); + Vec2r p(p0 + _carricatureFactor * (p1 - p0)); + + (v)->setPoint(p[0], p[1]); + i++; + } + +} + + +///////////////////////////////////////// +// +// OMISSION SHADER +// +///////////////////////////////////////// + +OmissionShader::OmissionShader (real sizeWindow, real thrVari, real thrFlat, real lFlat) +{ + _sizeWindow=sizeWindow; + _thresholdVariation=thrVari; + _thresholdFlat=thrFlat; + _lengthFlat=lFlat; +} + +int +OmissionShader::shade(Stroke &ioStroke) const +{ + Omitter omi(ioStroke); + omi.omit(_sizeWindow, _thresholdVariation, _thresholdFlat, _lengthFlat); + + return 0; +} + + +// OMITTER +/////////////////////////// + +Omitter::Omitter (Stroke &ioStroke) + :Smoother (ioStroke) +{ + StrokeInternal::StrokeVertexIterator v, vend; + int i=0; + for(v=ioStroke.strokeVerticesBegin(), vend=ioStroke.strokeVerticesEnd(); + v!=vend; + ++v) + { + _u[i]=(v)->curvilinearAbscissa(); + i++; + } + +} + +void +Omitter::omit (real sizeWindow, real thrVari, real thrFlat, real lFlat) +{ + _sizeWindow=sizeWindow; + _thresholdVariation=thrVari; + _thresholdFlat=thrFlat; + _lengthFlat=lFlat; + + for (int i=1; i<_nbVertices-1; i++) + { + if (_u[i]<_lengthFlat) continue; + // is the previous segment flat? + int j=i-1; + while ((j>=0) && (_u[i]-_u[j]<_lengthFlat)) + { + if ((_normal[j] * _normal[i]) < _thresholdFlat) + ; // FIXME + j--; + } + + } +} diff --git a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h new file mode 100755 index 00000000000..f2e56222cc0 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h @@ -0,0 +1,222 @@ +// +// Filename : AdvancedStrokeShaders.h +// Author : Fredo Durand +// Purpose : Fredo's stroke shaders +// Date of creation : 17/12/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef ADVANCEDSTROKESHADERS_H +# define ADVANCEDSTROKESHADERS_H + +# include "BasicStrokeShaders.h" + +/*! [ Thickness Shader ]. + * Assigns thicknesses to the stroke vertices + * so that the stroke looks like made with a calligraphic tool. + * i.e. The stroke will be the thickest in a main direction, + * the thinest in the direction perpendicular to this one, + * and an interpolation inbetween. + */ +class LIB_STROKE_EXPORT CalligraphicShader : public StrokeShader +{ + +public: + /*! Builds the shader. + * \param iMinThickness + * The minimum thickness in the direction perpandicular + * to the main direction. + * \param iMaxThickness + * The maximum thickness in the main direction. + * \param iOrientation + * The 2D vector giving the main direction. + * \param clamp + * Tells ??? + */ + CalligraphicShader (real iMinThickness, real iMaxThickness, + const Vec2f &iOrientation, bool clamp); + /*! Destructor. */ + virtual ~CalligraphicShader () {} + /*! The shading method */ + virtual int shade(Stroke &ioStroke) const; +protected: + real _maxThickness; + real _minThickness; + Vec2f _orientation; + bool _clamp; +}; + +/*! [ Geometry Shader ]. + * Spatial Noise stroke shader. + * Moves the vertices to make the stroke more noisy. + * @see \htmlonly <a href=noise/noise.html>noise/noise.html</a> \endhtmlonly + */ +class LIB_STROKE_EXPORT SpatialNoiseShader : public StrokeShader +{ +public: + /*! Builds the shader. + * \param iAmount + * The amplitude of the noise. + * \param ixScale + * The noise frequency + * \param nbOctave + * The number of octaves + * \param smooth + * If you want the noise to be smooth + * \param pureRandom + * If you don't want any coherence + */ + SpatialNoiseShader (float iAmount, float ixScale, int nbOctave, bool smooth, bool pureRandom); + /*! Destructor. */ + virtual ~SpatialNoiseShader () {} + /*! The shading method. */ + virtual int shade(Stroke &ioStroke) const; + +protected: + + float _amount; + float _xScale; + int _nbOctave; + bool _smooth; + bool _pureRandom; +}; + +/*! [ Geometry Shader ]. + * Smoothes the stroke. + * (Moves the vertices to make the stroke smoother). + * Uses curvature flow to converge towards a curve of constant + * curvature. The diffusion method we use is anisotropic + * to prevent the diffusion accross corners. + * @see \htmlonly <a href=/smoothing/smoothing.html>smoothing/smoothing.html</a> endhtmlonly + */ +class LIB_STROKE_EXPORT SmoothingShader : public StrokeShader +{ +public: + /*! Builds the shader. + * \param iNbIteration + * The number of iterations. (400) + * \param iFactorPoint + * 0 + * \param ifactorCurvature + * 0 + * \param iFactorCurvatureDifference + * 0.2 + * \param iAnisoPoint + * 0 + * \param iAnisNormal + * 0 + * \param iAnisoCurvature + * 0 + * \param icarricatureFactor + * 1 + */ + SmoothingShader (int iNbIteration, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference, + real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real icarricatureFactor); + /*! Destructor. */ + virtual ~SmoothingShader () {} + + /*! The shading method. */ + virtual int shade(Stroke &ioStroke) const; + +protected: + + int _nbIterations; + real _factorPoint; + real _factorCurvature; + real _factorCurvatureDifference; + real _anisoPoint; + real _anisoNormal; + real _anisoCurvature; + real _carricatureFactor; +}; + +class LIB_STROKE_EXPORT Smoother +{ +public: + Smoother (Stroke &ioStroke); + + virtual ~Smoother () {} + + void smooth (int nbIterations, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference, + real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real icarricatureFactor); + void computeCurvature (); + +protected: + real _factorPoint; + real _factorCurvature; + real _factorCurvatureDifference; + real _anisoPoint; + real _anisoNormal; + real _anisoCurvature; + real _carricatureFactor; + + void iteration(); + void copyVertices (); + + Stroke *_stroke; + int _nbVertices; + Vec2r *_vertex; + Vec2r *_normal; + real *_curvature; + bool *_isFixedVertex; + + bool _isClosedCurve; + bool _safeTest; +}; + +class LIB_STROKE_EXPORT Omitter : public Smoother +{ +public: + Omitter (Stroke &ioStroke); + virtual ~Omitter () {} + + void omit (real sizeWindow, real thrVari, real thrFlat, real lFlat); +protected: + real *_u; + + real _sizeWindow; + real _thresholdVariation; + real _thresholdFlat; + real _lengthFlat; +}; + +/*! Omission shader + */ +class LIB_STROKE_EXPORT OmissionShader : public StrokeShader +{ +public: + OmissionShader (real sizeWindow, real thrVari, real thrFlat, real lFlat); + virtual ~OmissionShader () {} + + virtual int shade(Stroke &ioStroke) const; + +protected: + + real _sizeWindow; + real _thresholdVariation; + real _thresholdFlat; + real _lengthFlat; +}; + +#endif // ADVANCEDSTROKESHADERS_H diff --git a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp new file mode 100755 index 00000000000..bc9edcef057 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp @@ -0,0 +1,1160 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "StrokeRenderer.h" +#include <fstream> +#include "BasicStrokeShaders.h" +#include "../system/PseudoNoise.h" +#include "../system/RandGen.h" +#include "../view_map/Functions0D.h" +#include "../view_map/Functions1D.h" +#include "AdvancedFunctions0D.h" +#include "AdvancedFunctions1D.h" +#include "StrokeIterators.h" +#include "../system/StringUtils.h" +#include "StrokeIO.h" + +//soc #include <qimage.h> +//soc #include <QString> +extern "C" { +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" +} + +// Internal function + +// soc +// void convert(const QImage& iImage, float **oArray, unsigned &oSize) { +// oSize = iImage.width(); +// *oArray = new float[oSize]; +// for(unsigned i=0; i<oSize; ++i) { +// QRgb rgb = iImage.pixel(i,0); +// (*oArray)[i] = ((float)qBlue(rgb))/255.f; +// } +// } +void convert(ImBuf *imBuf, float **oArray, unsigned &oSize) { + oSize = imBuf->x; + *oArray = new float[oSize]; + + char *pix; + for(unsigned i=0; i < oSize; ++i) { + pix = (char*) imBuf->rect + i*4; + (*oArray)[i] = ((float) pix[2] )/255.f; + } +} + +namespace StrokeShaders { + + // + // Thickness modifiers + // + ////////////////////////////////////////////////////////// + + int ConstantThicknessShader::shade(Stroke& stroke) const + { + StrokeInternal::StrokeVertexIterator v, vend; + int i=0; + int size = stroke.strokeVerticesSize(); + for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd(); + v!=vend; + ++v) + { + if((1 == i) || (size-2 == i)) + v->attribute().setThickness(_thickness/4.0,_thickness/4.0); + if((0 == i) || (size-1 == i)) + v->attribute().setThickness(0,0); + + v->attribute().setThickness(_thickness/2.0, _thickness/2.0); + } + return 0; + } + + int ConstantExternThicknessShader::shade(Stroke& stroke) const + { + StrokeInternal::StrokeVertexIterator v, vend; + int i=0; + int size = stroke.strokeVerticesSize(); + for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd(); + v!=vend; + ++v) + { + if((1 == i) || (size-2 == i)) + v->attribute().setThickness(_thickness/2.0,0); + if((0 == i) || (size-1 == i)) + v->attribute().setThickness(0,0); + + v->attribute().setThickness(_thickness, 0); + } + return 0; + } + + int IncreasingThicknessShader::shade(Stroke& stroke) const + { + + int n=stroke.strokeVerticesSize()-1; + StrokeInternal::StrokeVertexIterator v, vend; + int i=0; + for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd(); + v!=vend; + + ++v) + { + float t; + if(i < (float)n/2.f) + t = (1.0-(float)i/(float)n)*_ThicknessMin + (float)i/(float)n*_ThicknessMax; + else + t = (1.0-(float)i/(float)n)*_ThicknessMax + (float)i/(float)n*_ThicknessMin; + v->attribute().setThickness(t/2.0, t/2.0); + ++i; + } + return 0; + } + + int ConstrainedIncreasingThicknessShader::shade(Stroke& stroke) const + { + float slength = stroke.getLength2D(); + float maxT = min(_ratio*slength,_ThicknessMax); + int n=stroke.strokeVerticesSize()-1; + StrokeInternal::StrokeVertexIterator v, vend; + int i=0; + for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd(); + v!=vend; + + ++v) + { + float t; + if(i < (float)n/2.f) + t = (1.0-(float)i/(float)n)*_ThicknessMin + (float)i/(float)n*maxT; + else + t = (1.0-(float)i/(float)n)*maxT + (float)i/(float)n*_ThicknessMin; + v->attribute().setThickness(t/2.0, t/2.0); + if(i == n-1) + v->attribute().setThickness(_ThicknessMin/2.0, _ThicknessMin/2.0); + ++i; + } + return 0; + } + + + int LengthDependingThicknessShader::shade(Stroke& stroke) const + { + float step = (_maxThickness-_minThickness)/3.f; + float l = stroke.getLength2D(); + float thickness = 0.0; + if(l>300.f) + thickness = _minThickness+3.f*step; + else if((l< 300.f) && (l>100.f)) + thickness = _minThickness+2.f*step; + else if((l<100.f) && (l>50.f)) + thickness = _minThickness+1.f*step; + else if(l< 50.f) + thickness = _minThickness; + + StrokeInternal::StrokeVertexIterator v, vend; + int i=0; + int size = stroke.strokeVerticesSize(); + for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd(); + v!=vend; + ++v) + { + if((1 == i) || (size-2 == i)) + v->attribute().setThickness(thickness/4.0,thickness/4.0); + if((0 == i) || (size-1 == i)) + v->attribute().setThickness(0,0); + + v->attribute().setThickness(thickness/2.0, thickness/2.0); + } + return 0; + } + + + ThicknessVariationPatternShader::ThicknessVariationPatternShader(const string pattern_name, + float iMinThickness, + float iMaxThickness, + bool stretch) + : StrokeShader() { + _stretch = stretch; + _minThickness = iMinThickness; + _maxThickness = iMaxThickness; + ImBuf *image = 0; //soc + vector<string> pathnames; + StringUtils::getPathName(TextureManager::Options::getPatternsPath(), + pattern_name, + pathnames); + for (vector<string>::const_iterator j = pathnames.begin(); j != pathnames.end(); j++) { + ifstream ifs(j->c_str()); + if (ifs.is_open()) { + //soc image.load(j->c_str()); + image = IMB_loadiffname(j->c_str(), 0); + break; + } + } + if (image == 0) //soc + cerr << "Error: cannot find pattern \"" << pattern_name + << "\" - check the path in the Options" << endl; + else + convert(image, &_aThickness, _size); + } + + int ThicknessVariationPatternShader::shade(Stroke& stroke) const + { + StrokeInternal::StrokeVertexIterator v, vend; + float *array = 0; + int size; + array = _aThickness; + size = _size; + // } + int vert_size = stroke.strokeVerticesSize(); + int sig = 0; + unsigned index; + const float* originalThickness; + for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd(); + v!=vend; + ++v) + { + originalThickness = v->attribute().getThickness(); + if (_stretch) { + float tmp = v->u()*(_size-1); + index = (unsigned)floor(tmp); + if((tmp-index) > (index+1-tmp)) + ++index; + } + else + index = (unsigned)floor(v->curvilinearAbscissa()); + index %= _size; + float thicknessR = array[index]*originalThickness[0]; + float thicknessL = array[index]*originalThickness[1]; + if(thicknessR+thicknessL < _minThickness) + { + thicknessL = _minThickness/2.f; + thicknessR = _minThickness/2.f; + } + if(thicknessR+thicknessL > _maxThickness) + { + thicknessL = _maxThickness/2.f; + thicknessR = _maxThickness/2.f; + } + if((sig==0) || (sig==vert_size-1)) + v->attribute().setThickness(1, 1); + else + v->attribute().setThickness(thicknessR, thicknessL); + ++sig; + } + return 0; + } + + + static const unsigned NB_VALUE_NOISE = 512; + ThicknessNoiseShader::ThicknessNoiseShader() + :StrokeShader() + {_amplitude=1.f;_scale=1.f/2.f/(float)NB_VALUE_NOISE;} + + ThicknessNoiseShader::ThicknessNoiseShader(float iAmplitude, float iPeriod) + :StrokeShader() + {_amplitude=iAmplitude;_scale=1.f/iPeriod/(float)NB_VALUE_NOISE;} + + + int ThicknessNoiseShader::shade(Stroke& stroke) const + { + StrokeInternal::StrokeVertexIterator v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd(); + real initU1=v->strokeLength()*real(NB_VALUE_NOISE)+RandGen::drand48()*real(NB_VALUE_NOISE); + real initU2=v->strokeLength()*real(NB_VALUE_NOISE)+RandGen::drand48()*real(NB_VALUE_NOISE); + + real bruit, bruit2; + PseudoNoise mynoise, mynoise2; + for(; + v!=vend; + ++v) + { + + bruit=mynoise.turbulenceSmooth(_scale*v->curvilinearAbscissa()+initU1, + 2); //2 : nbOctaves + bruit2=mynoise2.turbulenceSmooth(_scale*v->curvilinearAbscissa()+initU2, + 2); //2 : nbOctaves + const float *originalThickness = v->attribute().getThickness(); + float r = bruit*_amplitude+originalThickness[0]; + float l = bruit2*_amplitude+originalThickness[1]; + v->attribute().setThickness(r,l); + } + + return 0; + } + + // + // Color shaders + // + /////////////////////////////////////////////////////////////////////////////// + + int ConstantColorShader::shade(Stroke& stroke) const + { + StrokeInternal::StrokeVertexIterator v, vend; + for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd(); + v!=vend; + ++v) + { + v->attribute().setColor(_color[0], _color[1], _color[2]); + v->attribute().setAlpha(_color[3]); + } + return 0; + } + + int IncreasingColorShader::shade(Stroke& stroke) const + { + StrokeInternal::StrokeVertexIterator v, vend; + int n=stroke.strokeVerticesSize()-1; + int yo=0; + float newcolor[4]; + for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd(); + v!=vend; + + ++v) + { + for(int i=0; i<4; ++i) + { + newcolor[i] = (1.0-(float)yo/(float)n)*_colorMin[i] + (float)yo/(float)n*_colorMax[i]; + } + v->attribute().setColor(newcolor[0], newcolor[1], newcolor[2]); + v->attribute().setAlpha(newcolor[3]); + ++yo; + } + return 0; + } + + ColorVariationPatternShader::ColorVariationPatternShader(const string pattern_name, + bool stretch) + : StrokeShader() { + _stretch = stretch; + ImBuf *image = 0; //soc + vector<string> pathnames; + StringUtils::getPathName(TextureManager::Options::getPatternsPath(), + pattern_name, + pathnames); + for (vector<string>::const_iterator j = pathnames.begin(); j != pathnames.end(); j++) { + ifstream ifs(j->c_str()); + if (ifs.is_open()) { + image = IMB_loadiffname(j->c_str(), 0); //soc + break; + } + } + if (image == 0) //soc + cerr << "Error: cannot find pattern \"" << pattern_name + << "\" - check the path in the Options" << endl; + else + convert(image, &_aVariation, _size); + } + + int ColorVariationPatternShader::shade(Stroke& stroke) const + { + StrokeInternal::StrokeVertexIterator v, vend; + unsigned index; + for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd(); + v!=vend; + ++v) + { + const float *originalColor = v->attribute().getColor(); + if (_stretch) { + float tmp = v->u()*(_size-1); + index = (unsigned)floor(tmp); + if((tmp-index) > (index+1-tmp)) + ++index; + } + else + index = (unsigned)floor(v->curvilinearAbscissa()); + index %= _size; + float r = _aVariation[index]*originalColor[0]; + float g = _aVariation[index]*originalColor[1]; + float b = _aVariation[index]*originalColor[2]; + v->attribute().setColor(r,g,b); + } + return 0; + } + + int MaterialColorShader::shade(Stroke& stroke) const + { + Interface0DIterator v, vend; + Functions0D::MaterialF0D fun; + StrokeVertex *sv; + for(v=stroke.verticesBegin(), vend=stroke.verticesEnd(); + v!=vend; + ++v) + { + if (fun(v) < 0) + return -1; + const float *diffuse = fun.result.diffuse(); + sv = dynamic_cast<StrokeVertex*>(&(*v)); + sv->attribute().setColor(diffuse[0]*_coefficient, diffuse[1]*_coefficient, diffuse[2]*_coefficient); + sv->attribute().setAlpha(diffuse[3]); + } + return 0; + } + + + int CalligraphicColorShader::shade(Stroke& stroke) const + { + Interface0DIterator v; + Functions0D::VertexOrientation2DF0D fun; + StrokeVertex* sv; + for(v=stroke.verticesBegin(); + !v.isEnd(); + ++v) + { + if (fun(v) < 0) + return -1; + Vec2f vertexOri(fun.result); + Vec2d ori2d(-vertexOri[1], vertexOri[0]); + ori2d.normalizeSafe(); + real scal = ori2d * _orientation; + sv = dynamic_cast<StrokeVertex*>(&(*v)); + if ((scal<0)) + sv->attribute().setColor(0,0,0); + else + sv->attribute().setColor(1,1,1); + } + return 0; + } + + + ColorNoiseShader::ColorNoiseShader() + :StrokeShader() + {_amplitude=1.f;_scale=1.f/2.f/(float)NB_VALUE_NOISE;} + + ColorNoiseShader::ColorNoiseShader(float iAmplitude, float iPeriod) + :StrokeShader() + {_amplitude=iAmplitude;_scale=1.f/iPeriod/(float)NB_VALUE_NOISE;} + + + int ColorNoiseShader::shade(Stroke& stroke) const + { + StrokeInternal::StrokeVertexIterator v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd(); + real initU=v->strokeLength()*real(NB_VALUE_NOISE)+RandGen::drand48()*real(NB_VALUE_NOISE); + + real bruit; + PseudoNoise mynoise; + for(; + v!=vend; + ++v) + { + + bruit=mynoise.turbulenceSmooth(_scale*v->curvilinearAbscissa()+initU, + 2); //2 : nbOctaves + const float *originalColor = v->attribute().getColor(); + float r = bruit*_amplitude+originalColor[0]; + float g = bruit*_amplitude+originalColor[1]; + float b = bruit*_amplitude+originalColor[2]; + v->attribute().setColor(r,g,b); + } + + return 0; + } + + + // + // Texture Shaders + // + /////////////////////////////////////////////////////////////////////////////// + + int TextureAssignerShader::shade(Stroke& stroke) const + { + // getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::HUMID_MEDIUM); + // getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::HUMID_MEDIUM); + // getBrushTextureIndex(TEXTURES_DIR "/brushes/oil.bmp", Stroke::HUMID_MEDIUM); + // getBrushTextureIndex(TEXTURES_DIR "/brushes/oilnoblend.bmp", Stroke::HUMID_MEDIUM); + // getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::DRY_MEDIUM); + // getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::DRY_MEDIUM); + // getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueDryBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM); + // getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM); + + TextureManager * instance = TextureManager::getInstance(); + if(!instance) + return 0; + string pathname; + Stroke::MediumType mediumType; + bool hasTips = false; + switch(_textureId) + { + case 0: + //pathname = TextureManager::Options::getBrushesPath() + "/charcoalAlpha.bmp"; + pathname = "/charcoalAlpha.bmp"; + mediumType = Stroke::HUMID_MEDIUM; + hasTips = false; + break; + case 1: + pathname = "/washbrushAlpha.bmp"; + mediumType = Stroke::HUMID_MEDIUM; + hasTips = true; + break; + case 2: + pathname = "/oil.bmp"; + mediumType = Stroke::HUMID_MEDIUM; + hasTips = true; + break; + case 3: + pathname = "/oilnoblend.bmp"; + mediumType = Stroke::HUMID_MEDIUM; + hasTips = true; + break; + case 4: + pathname = "/charcoalAlpha.bmp"; + mediumType = Stroke::DRY_MEDIUM; + hasTips = false; + break; + case 5: + mediumType = Stroke::DRY_MEDIUM; + hasTips = true; + break; + case 6: + pathname = "/opaqueDryBrushAlpha.bmp"; + mediumType = Stroke::OPAQUE_MEDIUM; + hasTips = true; + break; + case 7: + pathname = "/opaqueBrushAlpha.bmp"; + mediumType = Stroke::OPAQUE_MEDIUM; + hasTips = true; + break; + default: + pathname = "/smoothAlpha.bmp"; + mediumType = Stroke::OPAQUE_MEDIUM; + hasTips = false; + break; + } + unsigned int texId = instance->getBrushTextureIndex(pathname, mediumType); + stroke.setMediumType(mediumType); + stroke.setTips(hasTips); + stroke.setTextureId(texId); + return 0; + } + + // FIXME + int StrokeTextureShader::shade(Stroke& stroke) const + { + TextureManager * instance = TextureManager::getInstance(); + if(!instance) + return 0; + string pathname = TextureManager::Options::getBrushesPath() + "/" + _texturePath; + unsigned int texId = instance->getBrushTextureIndex(pathname, _mediumType); + stroke.setMediumType(_mediumType); + stroke.setTips(_tips); + stroke.setTextureId(texId); + return 0; + } + + // + // Geometry Shaders + // + /////////////////////////////////////////////////////////////////////////////// + + int BackboneStretcherShader::shade(Stroke& stroke) const + { + float l=stroke.getLength2D(); + if(l <= 50) + return 0; + + StrokeInternal::StrokeVertexIterator v0=stroke.strokeVerticesBegin(); + StrokeInternal::StrokeVertexIterator v1=v0;++v1; + StrokeInternal::StrokeVertexIterator vn=stroke.strokeVerticesEnd();--vn; + StrokeInternal::StrokeVertexIterator vn_1=vn;--vn_1; + + + Vec2d first((v0)->x(), (v0)->y()); + Vec2d last((vn)->x(), (vn)->y()); + + Vec2d d1(first-Vec2d((v1)->x(), (v1)->y())); + d1.normalize(); + Vec2d dn(last-Vec2d((vn_1)->x(), (vn_1)->y())); + dn.normalize(); + + Vec2d newFirst(first+_amount*d1); + (v0)->setPoint(newFirst[0], newFirst[1]); + Vec2d newLast(last+_amount*dn); + (vn)->setPoint(newLast[0], newLast[1]); + return 0; + } + + int SamplingShader::shade(Stroke& stroke) const + { + stroke.Resample(_sampling); + return 0; + } + + int ExternalContourStretcherShader::shade(Stroke& stroke) const + { + //float l=stroke.getLength2D(); + Interface0DIterator it=stroke.verticesBegin(); + Functions0D::Normal2DF0D fun; + StrokeVertex* sv; + while (!it.isEnd()) + { + if (fun(it) < 0) + return -1; + Vec2f n(fun.result); + sv = dynamic_cast<StrokeVertex*>(&(*it)); + Vec2d newPoint(sv->x()+_amount*n.x(), sv->y()+_amount*n.y()); + sv->setPoint(newPoint[0], newPoint[1]); + ++it; + } + return 0; + } + + int BSplineShader::shade(Stroke& stroke) const + { + if(stroke.strokeVerticesSize() < 4) + return 0; + + // Find the new vertices + vector<Vec2d> newVertices; + double t=0.f; + float _sampling = 5.f; + + StrokeInternal::StrokeVertexIterator p0,p1,p2,p3, end; + p0 = stroke.strokeVerticesBegin(); + p1 = p0; + p2 = p1; + p3 = p2; + end = stroke.strokeVerticesEnd(); + double a[4],b[4]; + int n=0; + while(p1 != end) + { + // if(p1 == end) + // p1 = p0; + if(p2 == end) + p2 = p1; + if(p3 == end) + p3 = p2; + // compute new matrix + a[0] = (-(p0)->x()+3*(p1)->x()-3*(p2)->x()+(p3)->x())/6.0; + a[1] = (3*(p0)->x()-6*(p1)->x()+3*(p2)->x())/6.0; + a[2] = (-3*(p0)->x()+3*(p2)->x())/6.0; + a[3] = ((p0)->x()+4*(p1)->x()+(p2)->x())/6.0; + + b[0] = (-(p0)->y()+3*(p1)->y()-3*(p2)->y()+(p3)->y())/6.0; + b[1] = (3*(p0)->y()-6*(p1)->y()+3*(p2)->y())/6.0; + b[2] = (-3*(p0)->y()+3*(p2)->y())/6.0; + b[3] = ((p0)->y()+4*(p1)->y()+(p2)->y())/6.0; + + + // draw the spline depending on resolution: + Vec2d p1p2((p2)->x()-(p1)->x(), (p2)->y()-(p1)->y()); + double norm = p1p2.norm(); + //t = _sampling/norm; + t=0; + while(t<1) + { + newVertices.push_back(Vec2d((a[3] + t*(a[2] + t*(a[1] + t*a[0]))), + (b[3] + t*(b[2] + t*(b[1] + t*b[0]))))); + t = t + _sampling/norm; + } + if(n > 2) + { + ++p0; + ++p1; + ++p2; + ++p3; + } + else + { + if(n==0) + ++p3; + if(n==1) + {++p2;++p3;} + if(n==2) + {++p1;++p2;++p3;} + ++n; + } + } + //last point: + newVertices.push_back(Vec2d((p0)->x(), (p0)->y())); + + int originalSize = newVertices.size(); + _sampling = stroke.ComputeSampling(originalSize); + + // Resample and set x,y coordinates + stroke.Resample(_sampling); + int newsize = stroke.strokeVerticesSize(); + + int nExtraVertex=0; + if(newsize < originalSize) + cerr << "Warning: unsufficient resampling" << endl; + else + { + nExtraVertex = newsize - originalSize; + } + + // assigns the new coordinates: + vector<Vec2d>::iterator p,pend; + p=newVertices.begin();pend=newVertices.end(); + vector<Vec2d>::iterator last = p; + n=0; + StrokeInternal::StrokeVertexIterator it=stroke.strokeVerticesBegin(), itend=stroke.strokeVerticesEnd(); + it=stroke.strokeVerticesBegin(); + for(; + ((it!=itend) && (p!=pend)); + ++it) + { + it->setX(p->x()); + it->setY(p->y()); + last = p; + ++p; + ++n; + } + // nExtraVertex should stay unassigned + for(int i=0; i< nExtraVertex; ++i) + { + it->setX(last->x()); + it->setY(last->y()); + if(it.isEnd()) + cerr << "Warning: Problem encountered while creating B-spline" << endl; + ++it; + ++n; + } + return 0; + } + + //!! Bezier curve stroke shader + int BezierCurveShader::shade(Stroke& stroke) const + { + if(stroke.strokeVerticesSize() < 4) + return 0; + + // Build the Bezier curve from this set of data points: + vector<Vec2d> data; + StrokeInternal::StrokeVertexIterator v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd(); + data.push_back(Vec2d(v->x(), v->y()));//first one + StrokeInternal::StrokeVertexIterator previous = v;++v; + for(; + v!=vend; + ++v) + { + if(!((fabs(v->x() -(previous)->x())<M_EPSILON) && ((fabs(v->y() - (previous)->y())<M_EPSILON)))) + data.push_back(Vec2d(v->x(), v->y())); + previous = v; + } + + // Vec2d tmp;bool equal=false; + // if(data.front() == data.back()) + // { + // tmp = data.back(); + // data.pop_back(); + // equal=true; + // } + // here we build the bezier curve + BezierCurve bcurve(data, _error); + + // bad performances are here !!! // FIXME + vector<Vec2d> CurveVertices; + vector<BezierCurveSegment*>& bsegments = bcurve.segments(); + vector<BezierCurveSegment*>::iterator s=bsegments.begin(),send=bsegments.end(); + vector<Vec2d>& segmentsVertices = (*s)->vertices(); + vector<Vec2d>::iterator p,pend; + // first point + CurveVertices.push_back(segmentsVertices[0]); + for(; + s!=send; + ++s) + { + segmentsVertices = (*s)->vertices(); + p=segmentsVertices.begin(); pend=segmentsVertices.end(); + ++p; + for(; + p!=pend; + ++p) + { + CurveVertices.push_back((*p)); + } + } + + //if(equal) + // if(data.back() == data.front()) + // { + // vector<Vec2d>::iterator d=data.begin(), dend=data.end(); + // cout << "ending point = starting point" << endl; + // cout << "---------------DATA----------" << endl; + // for(; + // d!=dend; + // ++d) + // { + // cout << d->x() << "-" << d->y() << endl; + // } + // cout << "--------------BEZIER RESULT----------" << endl; + // d=CurveVertices.begin(), dend=CurveVertices.end(); + // for(;d!=dend;++d) + // { + // cout << d->x() << "-" << d->y() << endl; + // } + // } + + // Resample the Stroke depending on the number of + // vertices of the bezier curve: + int originalSize = CurveVertices.size(); + //float sampling = stroke.ComputeSampling(originalSize); + //stroke.Resample(sampling); + stroke.Resample(originalSize); + int newsize = stroke.strokeVerticesSize(); + int nExtraVertex=0; + if(newsize < originalSize) + cerr << "Warning: unsufficient resampling" << endl; + else + { + //cout << "Oversampling" << endl; + nExtraVertex = newsize - originalSize; + if(nExtraVertex != 0) + cout << "Bezier Shader : Stroke " << stroke.getId() << " have not been resampled" << endl; + } + + // assigns the new coordinates: + p=CurveVertices.begin();pend=CurveVertices.end(); + vector<Vec2d>::iterator last = p; + int n=0; + StrokeInternal::StrokeVertexIterator it=stroke.strokeVerticesBegin(), itend=stroke.strokeVerticesEnd(); + // while(p!=pend) + // { + // ++n; + // ++p; + // } + it=stroke.strokeVerticesBegin(); + for(; + ((it!=itend) && (p!=pend)); + ++it) + { + it->setX(p->x()); + it->setY(p->y()); + // double x = p->x(); + // double y = p->y(); + // cout << "x = " << x << "-" << "y = " << y << endl; + last = p; + ++p; + ++n; + } + + // Deal with extra vertices: + if(nExtraVertex == 0) + return 0; + + // nExtraVertex should stay unassigned + vector<StrokeAttribute> attributes; + vector<StrokeVertex*> verticesToRemove; + for(int i=0; i< nExtraVertex; ++i) + { + verticesToRemove.push_back(&(*it)); + if(it.isEnd()) + cout << "fucked up" << endl; + ++it; + ++n; + } + it=stroke.strokeVerticesBegin(); + for(; + it!=itend; + ++it) + { + attributes.push_back(it->attribute()); + } + + for(vector<StrokeVertex*>::iterator vr=verticesToRemove.begin(), vrend=verticesToRemove.end(); + vr!=vrend; + ++vr) + { + stroke.RemoveVertex(*vr); + } + it=stroke.strokeVerticesBegin(); + itend=stroke.strokeVerticesEnd(); + vector<StrokeAttribute>::iterator a=attributes.begin(), aend=attributes.end(); + int index = 0; + int index1 = (int)floor((float)originalSize/2.0); + int index2 = index1+nExtraVertex; + for(; + (it!=itend) && (a!=aend); + ++it) + { + (it)->setAttribute(*a); + if((index <= index1)||(index>index2)) + ++a; + ++index; + } + return 0; + } + + int InflateShader::shade(Stroke& stroke) const + { + // we're computing the curvature variance of the stroke.(Combo 5) + // If it's too high, forget about it + Functions1D::Curvature2DAngleF1D fun; + if (fun(stroke) < 0) + return -1; + if (fun.result > _curvatureThreshold) + return 0; + + Functions0D::VertexOrientation2DF0D ori_fun; + Functions0D::Curvature2DAngleF0D curv_fun; + Functions1D::Normal2DF1D norm_fun; + Interface0DIterator it=stroke.verticesBegin(); + StrokeVertex* sv; + while (!it.isEnd()) + { + if (ori_fun(it) < 0) + return -1; + Vec2f ntmp(ori_fun.result); + Vec2f n(ntmp.y(), -ntmp.x()); + if (norm_fun(stroke) < 0) + return -1; + Vec2f strokeN(norm_fun.result); + if(n*strokeN < 0) + { + n[0] = -n[0]; + n[1] = -n[1]; + } + sv = dynamic_cast<StrokeVertex*>(&(*it)); + float u=sv->u(); + float t = 4.f*(0.25f - (u-0.5)*(u-0.5)); + if (curv_fun(it) < 0) + return -1; + float curvature_coeff = (M_PI-curv_fun.result)/M_PI; + Vec2d newPoint(sv->x()+curvature_coeff*t*_amount*n.x(), sv->y()+curvature_coeff*t*_amount*n.y()); + sv->setPoint(newPoint[0], newPoint[1]); + ++it; + } + return 0; + } + + class CurvePiece + { + public: + StrokeInternal::StrokeVertexIterator _begin; + StrokeInternal::StrokeVertexIterator _last; + Vec2d A; + Vec2d B; + int size; + float _error; + + CurvePiece(StrokeInternal::StrokeVertexIterator b, StrokeInternal::StrokeVertexIterator l, int iSize) + { + _begin = b; + _last = l; + A = Vec2d((_begin)->x(),(_begin)->y()); + B = Vec2d((_last)->x(),(_last)->y()); + size = iSize; + } + + float error() + { + float maxE = 0.f; + for(StrokeInternal::StrokeVertexIterator it=_begin; + it!=_last; + ++it) + { + Vec2d P(it->x(), it->y()); + float d = GeomUtils::distPointSegment(P,A,B); + if(d > maxE) + maxE = d; + } + _error = maxE; + return maxE; + } + //! Subdivides the curve into two pieces. + // The first piece is this same object (modified) + // the second piece is returned by the method + CurvePiece * subdivide() + { + StrokeInternal::StrokeVertexIterator it=_begin; + int actualSize = 1; + for(int i=0; i<size/2; ++i) + { + ++it; + ++actualSize; + } + CurvePiece * second = new CurvePiece(it, _last, size-actualSize+1); + size = actualSize; + _last = it; + B = Vec2d((_last)->x(), (_last)->y()); + return second; + } + }; + + int PolygonalizationShader::shade(Stroke& stroke) const + { + vector<CurvePiece*> _pieces; + vector<CurvePiece*> _results; + vector<CurvePiece*>::iterator cp,cpend; + + // Compute first approx: + StrokeInternal::StrokeVertexIterator a=stroke.strokeVerticesBegin(); + StrokeInternal::StrokeVertexIterator b=stroke.strokeVerticesEnd();--b; + int size = stroke.strokeVerticesSize(); + + CurvePiece * piece = new CurvePiece(a,b,size); + _pieces.push_back(piece); + + while(!_pieces.empty()) + { + piece = _pieces.back();_pieces.pop_back(); + if(piece->error() > _error) + { + CurvePiece * second = piece->subdivide(); + _pieces.push_back(second); + _pieces.push_back(piece); + } + else + { + _results.push_back(piece); + } + } + + // actually modify the geometry for each piece: + for(cp=_results.begin(), cpend=_results.end(); + cp!=cpend; + ++cp) + { + a = (*cp)->_begin; + b = (*cp)->_last; + Vec2d u = (*cp)->B-(*cp)->A; + Vec2d n(u[1], -u[0]);n.normalize(); + //Vec2d n(0,0); + float offset = ((*cp)->_error); + StrokeInternal::StrokeVertexIterator v,vlast; + for(v=a; + v!=b; + ++v) + { + v->setPoint((*cp)->A.x()+v->u()*u.x()+n.x()*offset, (*cp)->A.y()+v->u()*u.y()+n.y()*offset); + } + // u.normalize(); + // (*a)->setPoint((*a)->x()-u.x()*10, (*a)->y()-u.y()*10); + } + + // delete stuff + for(cp=_results.begin(), cpend=_results.end(); + cp!=cpend; + ++cp) + { + delete (*cp); + } + _results.clear(); + return 0; + } + + int GuidingLinesShader::shade(Stroke& stroke) const + { + Functions1D::Normal2DF1D norm_fun; + StrokeInternal::StrokeVertexIterator a=stroke.strokeVerticesBegin(); + StrokeInternal::StrokeVertexIterator b=stroke.strokeVerticesEnd();--b; + int size = stroke.strokeVerticesSize(); + CurvePiece piece(a,b,size); + + Vec2d u = piece.B-piece.A; + Vec2f n(u[1], -u[0]);n.normalize(); + if (norm_fun(stroke) < 0) + return -1; + Vec2f strokeN(norm_fun.result); + if(n*strokeN < 0) + { + n[0] = -n[0]; + n[1] = -n[1]; + } + float offset = (piece.error())/2.f*_offset; + StrokeInternal::StrokeVertexIterator v=a,vend=stroke.strokeVerticesEnd(); + for(; + v!=vend; + ++v) + { + v->setPoint(piece.A.x()+v->u()*u.x()+n.x()*offset, piece.A.y()+v->u()*u.y()+n.y()*offset); + } + return 0; + } + + ///////////////////////////////////////// + // + // Tip Remover + // + ///////////////////////////////////////// + + + TipRemoverShader::TipRemoverShader(real tipLength) + : StrokeShader() + { + _tipLength = tipLength; + } + + int + TipRemoverShader::shade(Stroke& stroke) const + { + int originalSize = stroke.strokeVerticesSize(); + + if(originalSize<4) + return 0; + + StrokeInternal::StrokeVertexIterator v, vend; + vector<StrokeVertex*> verticesToRemove; + vector<StrokeAttribute> oldAttributes; + v=stroke.strokeVerticesBegin(); vend=stroke.strokeVerticesEnd(); + for(; + v!=vend; + ++v) + { + if ((v->curvilinearAbscissa()<_tipLength) || + (v->strokeLength()-v->curvilinearAbscissa()<_tipLength)) + { + verticesToRemove.push_back(&(*v)); + } + oldAttributes.push_back(v->attribute()); + } + + if(originalSize-verticesToRemove.size() < 2) + return 0; + + vector<StrokeVertex*>::iterator sv=verticesToRemove.begin(), svend=verticesToRemove.end(); + for(; + sv!=svend; + ++sv) + { + stroke.RemoveVertex((*sv)); + } + + // Resample so that our new stroke have the same + // number of vertices than before + stroke.Resample(originalSize); + + if((int)stroke.strokeVerticesSize() != originalSize) //soc + cerr << "Warning: resampling problem" << endl; + + // assign old attributes to new stroke vertices: + v=stroke.strokeVerticesBegin(); vend=stroke.strokeVerticesEnd(); + vector<StrokeAttribute>::iterator a=oldAttributes.begin(), aend=oldAttributes.end(); + //cout << "-----------------------------------------------" << endl; + for(;(v!=vend)&&(a!=aend);++v,++a) + { + v->setAttribute(*a); + //cout << "thickness = " << (*a).getThickness()[0] << "-" << (*a).getThickness()[1] << endl; + } + // we're done! + return 0; + } + + int streamShader::shade(Stroke& stroke) const{ + cout << stroke << endl; + return 0; + } + int fstreamShader::shade(Stroke& stroke) const{ + _stream << stroke << endl; + return 0; + } + +} // end of namespace StrokeShaders + diff --git a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h new file mode 100755 index 00000000000..a0c0a44c9b6 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h @@ -0,0 +1,890 @@ +// +// Filename : BasicStrokeShaders.h +// Author : Stephane Grabli +// Purpose : Class gathering basic stroke shaders +// Date of creation : 17/12/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef BASIC_STROKE_SHADERS_H +# define BASIC_STROKE_SHADERS_H + +# include "Stroke.h" +# include "../geometry/Geom.h" +# include "../geometry/Bezier.h" +# include "StrokeShader.h" +# include <fstream> + +using namespace std; +using namespace Geometry; + +namespace StrokeShaders { + + // + // Thickness modifiers + // + ////////////////////////////////////////////////////// + /*! [ Thickness Shader ]. + * Assigns an absolute constant thickness to every + * vertices of the Stroke. + */ + class LIB_STROKE_EXPORT ConstantThicknessShader : public StrokeShader + { + public: + /*! Builds the shader. + * \param thickness + * The thickness that must be assigned + * to the stroke. + */ + ConstantThicknessShader(float thickness) : StrokeShader() { + _thickness = thickness; + } + /*! Destructor. */ + virtual ~ConstantThicknessShader() {} + /*! Returns the string "ConstantThicknessShader".*/ + virtual string getName() const { + return "ConstantThicknessShader"; + } + /*! The shading method. */ + virtual int shade(Stroke& stroke) const; + + private: + float _thickness; + }; + + /* [ Thickness Shader ]. + * Assigns an absolute constant external thickness to every + * vertices of the Stroke. The external thickness of a point + * is its thickness from the point to the strip border + * in the direction pointing outside the object the + * Stroke delimitates. + */ + class LIB_STROKE_EXPORT ConstantExternThicknessShader : public StrokeShader + { + public: + + ConstantExternThicknessShader(float thickness) : StrokeShader() { + _thickness = thickness; + } + + virtual ~ConstantExternThicknessShader() {} + + virtual string getName() const { + return "ConstantExternThicknessShader"; + } + + virtual int shade(Stroke& stroke) const; + + private: + + float _thickness; + }; + + /*! [ Thickness Shader ]. + * Assigns thicknesses values such as the thickness + * increases from a thickness value A to a thickness value B + * between the first vertex to the midpoint vertex and + * then decreases from B to a A between this midpoint vertex + * and the last vertex. + * The thickness is linearly interpolated from A to B. + */ + class LIB_STROKE_EXPORT IncreasingThicknessShader : public StrokeShader + { + public: + /*! Builds the shader. + * \param iThicknessMin + * The first thickness value. + * \param iThicknessMax + * The second thickness value. + */ + IncreasingThicknessShader(float iThicknessMin, float iThicknessMax) + : StrokeShader() + { + _ThicknessMin = iThicknessMin; + _ThicknessMax = iThicknessMax; + } + /*! Destructor.*/ + virtual ~IncreasingThicknessShader() {} + + virtual string getName() const { + return "IncreasingThicknessShader"; + } + + /*! The shading method. */ + virtual int shade(Stroke& stroke) const; + + private: + + float _ThicknessMin; + float _ThicknessMax; + }; + + /*! [ Thickness shader ]. + * Same as previous but + * here we allow the user to control the ratio thickness/length so that + * we don't get fat short lines + */ + class LIB_STROKE_EXPORT ConstrainedIncreasingThicknessShader : public StrokeShader + { + private: + float _ThicknessMin; + float _ThicknessMax; + float _ratio; + public: + /*! Builds the shader. + * \param iThicknessMin + * The first thickness value. + * \param iThicknessMax + * The second thickness value. + * \param iRatio + * The ration thickness/length we don't want to + * exceed. + */ + ConstrainedIncreasingThicknessShader(float iThicknessMin, float iThicknessMax, float iRatio) + : StrokeShader() + { + _ThicknessMin = iThicknessMin; + _ThicknessMax = iThicknessMax; + _ratio = iRatio; + } + /*! Destructor.*/ + virtual ~ConstrainedIncreasingThicknessShader() {} + + virtual string getName() const { + return "ConstrainedIncreasingThicknessShader"; + } + + /*! The shading method. */ + virtual int shade(Stroke& stroke) const; + }; + + /* [ Thickness Shader ]. + * Modifys the thickness in a relative way + * depending on its length. + */ + class LIB_STROKE_EXPORT LengthDependingThicknessShader : public StrokeShader + { + private: + float _minThickness; + float _maxThickness; + // We divide the strokes in 4 categories: + // l > 300 + // 100 < l < 300 + // 50 < l < 100 + // l < 50 + public: + LengthDependingThicknessShader(float iMinThickness, float iMaxThickness) + : StrokeShader() + { + _minThickness = iMinThickness; + _maxThickness = iMaxThickness; + } + virtual ~LengthDependingThicknessShader() {} + + virtual string getName() const { + return "LengthDependingThicknessShader"; + } + + virtual int shade(Stroke& stroke) const; + }; + + /*! [ Thickness Shader ]. + * Applys a pattern (texture) to vary thickness. + * The new thicknesses are the result of the multiplication + * of the pattern and the original thickness + */ + class LIB_STROKE_EXPORT ThicknessVariationPatternShader : public StrokeShader + { + public: + + /*! Builds the shader. + * \param pattern_name + * The texture file name. + * \param iMinThickness + * The minimum thickness we don't want to exceed. + * \param iMaxThickness + * The maximum thickness we don't want to exceed. + * \param stretch + * Tells whether the pattern texture must + * be stretched or repeted to fit the stroke. + */ + ThicknessVariationPatternShader(const string pattern_name, + float iMinThickness = 1.f, + float iMaxThickness = 5.f, + bool stretch = true); + /*! Destructor.*/ + virtual ~ThicknessVariationPatternShader() + { + if(0 != _aThickness) + { + delete [] _aThickness; + _aThickness = 0; + } + } + + virtual string getName() const { + return "ThicknessVariationPatternShader"; + } + + /*! The shading method. */ + virtual int shade(Stroke& stroke) const; + + private: + + float* _aThickness; // array of thickness values, in % of the max (i.e comprised between 0 and 1) + unsigned _size; + float _minThickness; + float _maxThickness; + bool _stretch; + }; + + /*! [ Thickness Shader ]. + * Adds some noise to the stroke thickness. + * \see \htmlonly <a href=noise/noise.html>noise/noise.html</a>\endhtmlonly + */ + class LIB_STROKE_EXPORT ThicknessNoiseShader : public StrokeShader + { + private: + float _amplitude; + float _scale; + public: + ThicknessNoiseShader(); + /*! Builds a Thickness Noise Shader + * \param iAmplitude + * The amplitude of the noise signal + * \param iPeriod + * The period of the noise signal + */ + ThicknessNoiseShader(float iAmplitude, float iPeriod); + + virtual string getName() const { + return "ThicknessNoiseShader"; + } + + /*! The shading method. */ + virtual int shade(Stroke& stroke) const; + }; + + + // + // Color shaders + // + ///////////////////////////////////////////////////////// + /*! [ Color Shader ]. + * Assigns a constant color to every vertices of the Stroke. + */ + class LIB_STROKE_EXPORT ConstantColorShader : public StrokeShader + { + public: + /*! Builds the shader from a user-specified color. + * \param iR + * The red component + * \param iG + * The green component + * \param iB + * The blue component + * \param iAlpha + * The alpha value + */ + ConstantColorShader(float iR, float iG, float iB, float iAlpha=1.f) + : StrokeShader() + { + _color[0] = iR; + _color[1] = iG; + _color[2] = iB; + _color[3] = iAlpha; + } + + virtual string getName() const { + return "ConstantColorShader"; + } + /*! The shading method. */ + virtual int shade(Stroke& stroke) const; + + private: + + float _color[4]; + }; + + /*! [ Color Shader ]. + * Assigns a varying color to the stroke. + * The user specifies 2 colors A and B. The stroke + * color will change linearly from A to B between the + * first and the last vertex. + */ + class LIB_STROKE_EXPORT IncreasingColorShader : public StrokeShader + { + private: + float _colorMin[4]; + float _colorMax[4]; + public: + /*! Builds the shader from 2 user-specified colors. + * \param iRm + * The first color red component + * \param iGm + * The first color green component + * \param iBm + * The first color blue component + * \param iAlpham + * The first color alpha value + * \param iRM + * The second color red component + * \param iGM + * The second color green component + * \param iBM + * The second color blue component + * \param iAlphaM + * The second color alpha value + */ + IncreasingColorShader(float iRm, float iGm, float iBm, float iAlpham, + float iRM, float iGM, float iBM, float iAlphaM) + : StrokeShader() + { + _colorMin[0] = iRm; + _colorMin[1] = iGm; + _colorMin[2] = iBm; + _colorMin[3] = iAlpham; + + _colorMax[0] = iRM; + _colorMax[1] = iGM; + _colorMax[2] = iBM; + _colorMax[3] = iAlphaM; + } + + virtual string getName() const { + return "IncreasingColorShader"; + } + + /*! The shading method. */ + virtual int shade(Stroke& stroke) const; + }; + + /*! [ Color Shader ]. + * Applys a pattern to vary original color. + * The new color is the result of the multiplication + * of the pattern and the original color + */ + class LIB_STROKE_EXPORT ColorVariationPatternShader : public StrokeShader + { + public: + /*! Builds the shader from the pattern texture file name. + * \param pattern_name + * The file name of the texture file to use as pattern + * \param stretch + * Tells whether the texture must be strecthed or repeted + * to fit the stroke. + */ + ColorVariationPatternShader(const string pattern_name, bool stretch = true); + /*! Destructor */ + virtual ~ColorVariationPatternShader() + { + if(0 != _aVariation) + { + delete [] _aVariation; + _aVariation = 0; + } + } + + virtual string getName() const { + return "ColorVariationPatternShader"; + } + + /*! The shading method. */ + virtual int shade(Stroke& stroke) const; + + private: + + float* _aVariation; // array of coef values, in % of the max (i.e comprised between 0 and 1) + unsigned _size; + bool _stretch; + }; + + /* [ Color Shader ]. + * Assigns a color to the stroke depending + * on the material of the shape to which ot belongs + * to. (Disney shader) + */ + class LIB_STROKE_EXPORT MaterialColorShader : public StrokeShader + { + private: + float _coefficient; + public: + MaterialColorShader(float coeff=1.f) + : StrokeShader() + {_coefficient=coeff;} + + virtual string getName() const { + return "MaterialColorShader"; + } + + virtual int shade(Stroke& stroke) const; + }; + + class LIB_STROKE_EXPORT CalligraphicColorShader : public StrokeShader + { + private: + int _textureId; + Vec2d _orientation; + public: + CalligraphicColorShader( + const Vec2d &iOrientation) + : StrokeShader() + { + _orientation=iOrientation; + _orientation.normalize(); + } + + virtual string getName() const { + return "CalligraphicColorShader"; + } + + virtual int shade(Stroke& stroke) const; + + }; + + /*! [ Color Shader ]. + * Shader to add noise to the stroke colors. + */ + class LIB_STROKE_EXPORT ColorNoiseShader : public StrokeShader + { + private: + float _amplitude; + float _scale; + + public: + ColorNoiseShader(); + /*! Builds a Color Noise Shader + * \param iAmplitude + * The amplitude of the noise signal + * \param iPeriod + * The period of the noise signal + */ + ColorNoiseShader(float iAmplitude, float iPeriod); + + virtual string getName() const { + return "ColorNoiseShader"; + } + + /*! The shading method. */ + virtual int shade(Stroke& stroke) const; + }; + + // + // Texture Shaders + // + /////////////////////////////////////////////////////////////////////////////// + /*! [ Texture Shader ]. + * Assigns a texture to the stroke in order to simulate + * its marks system. This shader takes as input an integer value + * telling which texture and blending mode to use among a set of + * predefined textures. + * Here are the different presets: + * 0) -> /brushes/charcoalAlpha.bmp, HUMID_MEDIUM + * 1) -> /brushes/washbrushAlpha.bmp, HUMID_MEDIUM + * 2) -> /brushes/oil.bmp, HUMID_MEDIUM + * 3) -> /brushes/oilnoblend.bmp, HUMID_MEDIUM + * 4) -> /brushes/charcoalAlpha.bmp, DRY_MEDIUM + * 5) -> /brushes/washbrushAlpha.bmp, DRY_MEDIUM + * 6) -> /brushes/opaqueDryBrushAlpha.bmp, OPAQUE_MEDIUM + * 7) -> /brushes/opaqueBrushAlpha.bmp, Stroke::OPAQUE_MEDIUM + * Any other value will lead to the following preset: + * default) -> /brushes/smoothAlpha.bmp, OPAQUE_MEDIUM. + */ + class LIB_STROKE_EXPORT TextureAssignerShader : public StrokeShader // FIXME + { + private: + int _textureId; + public: + /*! Builds the shader. + * \param id + * The number of the preset to use. + */ + TextureAssignerShader(int id) + : StrokeShader() + { + _textureId = id; + } + + virtual string getName() const { + return "TextureAssignerShader"; + } + + /*! The shading method */ + virtual int shade(Stroke& stroke) const; + + }; + /*! [ Texture Shader ]. + * Assigns a texture and a blending mode to the stroke + * in order to simulate its marks system. + */ + class LIB_STROKE_EXPORT StrokeTextureShader : public StrokeShader + { + private: + string _texturePath; + Stroke::MediumType _mediumType; + bool _tips; // 0 or 1 + + public: + /*! Builds the shader from the texture file name and the blending mode to use. + * \param textureFile + * The the texture file name. + * \attention The textures must be placed in the $FREESTYLE_DIR/data/textures/brushes + * directory. + * \param mediumType + * The medium type and therefore, the blending mode that must + * be used for the rendering of this stroke. + * \param iTips + * Tells whether the texture includes tips or not. + * If it is the case, the texture image must respect the following + * format: + * \verbatim + * __________ + * | | + * | A | + * |__________| + * | | | + * | B | C | + * |_____|____| + * + * \endverbatim + * - A : The stroke's corpus texture + * - B : The stroke's left extremity texture + * - C : The stroke's right extremity texture + */ + StrokeTextureShader(const string textureFile, Stroke::MediumType mediumType = Stroke::OPAQUE_MEDIUM, bool iTips = false) + : StrokeShader() + { + _texturePath = textureFile; + _mediumType = mediumType; + _tips = iTips; + } + + virtual string getName() const { + return "StrokeTextureShader"; + } + + /*! The shading method */ + virtual int shade(Stroke& stroke) const; + + }; + + + // + // Geometry Shaders + // + /////////////////////////////////////////////////////////////////////////////// + /*! [ Geometry Shader ]. + * Stretches the stroke at its two extremities and following the + * respective directions: v(1)v(0) and v(n-1)v(n). + */ + class LIB_STROKE_EXPORT BackboneStretcherShader : public StrokeShader + { + private: + float _amount; + public: + /*! Builds the shader. + * \param iAmount + * The stretching amount value. + */ + BackboneStretcherShader(float iAmount=2.f) + : StrokeShader() + { + _amount = iAmount; + } + + virtual string getName() const { + return "BackboneStretcherShader"; + } + + /*! The shading method */ + virtual int shade(Stroke& stroke) const; + }; + + /*! [ Geometry Shader. ] + * Resamples the stroke. + * @see Stroke::Resample(float). + */ + class LIB_STROKE_EXPORT SamplingShader: public StrokeShader + { + private: + float _sampling; + public: + /*! Builds the shader. + * \param sampling + * The sampling to use for the + * stroke resampling + */ + SamplingShader(float sampling) + : StrokeShader() + { + _sampling = sampling; + } + + virtual string getName() const { + return "SamplingShader"; + } + + /*! The shading method */ + virtual int shade(Stroke& stroke) const; + }; + + + class LIB_STROKE_EXPORT ExternalContourStretcherShader : public StrokeShader + { + private: + float _amount; + public: + ExternalContourStretcherShader(float iAmount=2.f) + : StrokeShader() + { + _amount = iAmount; + } + + virtual string getName() const { + return "ExternalContourStretcherShader"; + } + + virtual int shade(Stroke& stroke) const; + }; + + // B-Spline stroke shader + class LIB_STROKE_EXPORT BSplineShader: public StrokeShader + { + public: + BSplineShader() + : StrokeShader() + {} + + virtual string getName() const { + return "BSplineShader"; + } + + virtual int shade(Stroke& stroke) const; + }; + + + // Bezier curve stroke shader + /*! [ Geometry Shader ]. + * Transforms the stroke backbone geometry + * so that it corresponds to a Bezier Curve + * approximation of the original backbone geometry. + * @see \htmlonly <a href=bezier/bezier.html>bezier/bezier.html</a> \endhtmlonly + */ + class LIB_STROKE_EXPORT BezierCurveShader : public StrokeShader + { + private: + float _error; + public: + /*! Builds the shader. + * \param error + * The error we're allowing for the approximation. + * This error is the max distance allowed between + * the new curve and the original geometry. + */ + BezierCurveShader(float error = 4.0) + : StrokeShader() + {_error=error;} + + virtual string getName() const { + return "BezierCurveShader"; + } + + /*! The shading method */ + virtual int shade(Stroke& stroke) const; + }; + + /* Shader to inflate the curves. It keeps the extreme + * points positions and moves the other ones along + * the 2D normal. The displacement value is proportional + * to the 2d curvature at the considered point (the higher + * the curvature, the smaller the displacement) and to a value + * specified by the user. + */ + class LIB_STROKE_EXPORT InflateShader : public StrokeShader + { + private: + float _amount; + float _curvatureThreshold; + public: + /*! Builds an inflate shader + * \param iAmount + * A multiplicative coefficient that + * acts on the amount and direction of displacement + * \param iThreshold + * The curves having a 2d curvature > iThreshold + * at one of their points is not inflated + */ + InflateShader(float iAmount,float iThreshold) + : StrokeShader() + { + _amount = iAmount; + _curvatureThreshold = iThreshold; + } + + virtual string getName() const { + return "InflateShader"; + } + + /*! The shading method */ + virtual int shade(Stroke& stroke) const; + }; + + /*! [ Geometry Shader ]. + * Shader to modify the Stroke geometry so that + * it looks more "polygonal". + * The basic idea is to start from the + * minimal stroke approximation consisting in + * a line joining the first vertex to the last one and + * to subdivide using the original stroke vertices + * until a certain error is reached. + */ + class LIB_STROKE_EXPORT PolygonalizationShader : public StrokeShader + { + private: + float _error; + public: + /*! Builds the shader. + * \param iError + * The error we want our polygonal approximation + * to have with respect to the original geometry. + * The smaller, the closer the new stroke to + * the orinal one. + * This error corresponds to the maximum distance + * between the new stroke and the old one. + */ + PolygonalizationShader(float iError) : StrokeShader() + {_error = iError;} + + virtual string getName() const { + return "PolygonalizationShader"; + } + + /*! The shading method */ + virtual int shade(Stroke& stroke) const; + }; + + + /*! [ Geometry Shader ]. + * Shader to modify the Stroke geometry so that + * it corresponds to its main direction line. + * This shader must be used together with the + * splitting operator using the curvature criterion. + * Indeed, the precision of the approximation + * will depend on the size of the stroke's pieces. + * The bigger the pieces, the rougher the approximation. + */ + class LIB_STROKE_EXPORT GuidingLinesShader : public StrokeShader + { + private: + float _offset; + public: + /*! Builds a Guiding Lines shader + * \param iOffset + * The line that replaces the stroke + * is initially in the middle + * of the initial stroke "bbox". + * iOffset is the value of the displacement + * which is applied to this line along its + * normal. + */ + GuidingLinesShader(float iOffset) : StrokeShader() + {_offset = iOffset;} + + virtual string getName() const { + return "GuidingLinesShader"; + } + + /*! The shading method */ + virtual int shade(Stroke& stroke) const; + }; + + /*! [ Geometry Shader ]. + * Removes the stroke's extremities. + */ + class LIB_STROKE_EXPORT TipRemoverShader : public StrokeShader + { + public: + /*! Builds the shader. + * \param tipLength + * The length of the piece of stroke + * we want to remove at each extremity. + */ + TipRemoverShader (real tipLength); + /*! Destructor. */ + virtual ~TipRemoverShader () {} + /*! The shading method */ + virtual string getName() const { + return "TipRemoverShader"; + } + + virtual int shade(Stroke &stroke) const; + + protected: + + real _tipLength; + }; + + /*! [ output Shader ]. + * streams the Stroke + */ + class LIB_STROKE_EXPORT streamShader : public StrokeShader + { + public: + /*! Destructor. */ + virtual ~streamShader() {} + /*! Returns the string "streamShader".*/ + virtual string getName() const { + return "streamShader"; + } + /*! The shading method. */ + virtual int shade(Stroke& stroke) const; + }; + + /*! [ output Shader ]. + * streams the Stroke in a file + */ + class LIB_STROKE_EXPORT fstreamShader : public StrokeShader + { + protected: + mutable ofstream _stream; + public: + /*! Builds the shader from the output file name */ + fstreamShader(const char *iFileName) : StrokeShader(){ + _stream .open(iFileName); + if(!_stream.is_open()){ + cout << "couldn't open file " << iFileName << endl; + } + } + /*! Destructor. */ + virtual ~fstreamShader() {_stream.close();} + /*! Returns the string "fstreamShader".*/ + virtual string getName() const { + return "fstreamShader"; + } + /*! The shading method. */ + virtual int shade(Stroke& stroke) const; + }; +} // end of namespace StrokeShaders + +#endif // BASIC_STROKE_SHADERS_H diff --git a/source/blender/freestyle/intern/stroke/Canvas.cpp b/source/blender/freestyle/intern/stroke/Canvas.cpp new file mode 100755 index 00000000000..d536bd7f5b4 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/Canvas.cpp @@ -0,0 +1,454 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "StrokeRenderer.h" +#include <vector> +#include "../system/FreestyleConfig.h" +#include "../system/TimeStamp.h" +#include "../system/PseudoNoise.h" +#include "Canvas.h" +#include "../image/Image.h" +#include "../image/GaussianFilter.h" +#include "../image/ImagePyramid.h" +#include "../view_map/SteerableViewMap.h" +#include "StyleModule.h" + +//soc #include <qimage.h> +//soc #include <QString> +#include <sstream> + +extern "C" { +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" +} + +using namespace std; + +LIB_STROKE_EXPORT +Canvas * Canvas::_pInstance = 0; + +LIB_STROKE_EXPORT +const char * Canvas::_MapsPath = 0; + +using namespace std; + +Canvas::Canvas() +{ + _SelectedFEdge = 0; + _pInstance = this; + PseudoNoise::init(42); + _Renderer = 0; + _current_sm = NULL; + _steerableViewMap = new SteerableViewMap(NB_STEERABLE_VIEWMAP-1); + _basic = false; +} + +Canvas::Canvas(const Canvas& iBrother) +{ + _SelectedFEdge = iBrother._SelectedFEdge; + _pInstance = this; + PseudoNoise::init(42); + _Renderer = iBrother._Renderer; + _current_sm = iBrother._current_sm; + _steerableViewMap = new SteerableViewMap(*(iBrother._steerableViewMap)); + _basic = iBrother._basic; +} + +Canvas::~Canvas() +{ + _pInstance = 0; + + Clear(); + if(_Renderer) + { + delete _Renderer; + _Renderer = 0; + } + // FIXME: think about an easy control + // for the maps memory management... + if(!_maps.empty()){ + for(mapsMap::iterator m=_maps.begin(), mend=_maps.end(); + m!=mend; + ++m){ + delete ((*m).second); + } + _maps.clear(); + } + if(_steerableViewMap) + delete _steerableViewMap; +} + +void Canvas::preDraw() {} + +void Canvas::Draw() +{ + if(_StyleModules.empty()) + return; + preDraw(); + TimeStamp *timestamp = TimeStamp::instance(); + + for(unsigned i = 0; i < _StyleModules.size(); i++) { + _current_sm = _StyleModules[i]; + + if (i < _Layers.size() && _Layers[i]) + delete _Layers[i]; + + _Layers[i] = _StyleModules[i]->execute(); + if (!_Layers[i]) + continue; + + stroke_count += _Layers[i]->strokes_size(); + + timestamp->increment(); + } + postDraw(); +} + +void Canvas::postDraw() +{ + update(); +} + + +void Canvas::Clear() +{ + if(!_Layers.empty()) { + for (deque<StrokeLayer*>::iterator sl=_Layers.begin(), slend=_Layers.end(); + sl != slend; + ++sl) + if (*sl) + delete (*sl); + _Layers.clear(); + } + + if(!_StyleModules.empty()) { + for (deque<StyleModule*>::iterator s=_StyleModules.begin(), send=_StyleModules.end(); + s != send; + ++s) + if (*s) + delete (*s); + _StyleModules.clear(); + } + if(_steerableViewMap) + _steerableViewMap->Reset(); + + stroke_count = 0; +} + +void Canvas::Erase() +{ + if(!_Layers.empty()) + { + for (deque<StrokeLayer*>::iterator sl=_Layers.begin(), slend=_Layers.end(); + sl != slend; + ++sl) + if (*sl) + (*sl)->clear(); + } + if(_steerableViewMap) + _steerableViewMap->Reset(); + update(); + +stroke_count = 0; +} + +void Canvas::PushBackStyleModule(StyleModule *iStyleModule) { + StrokeLayer* layer = new StrokeLayer(); + _StyleModules.push_back(iStyleModule); + _Layers.push_back(layer); +} + +void Canvas::InsertStyleModule(unsigned index, StyleModule *iStyleModule) { + unsigned size = _StyleModules.size(); + StrokeLayer* layer = new StrokeLayer(); + if((_StyleModules.empty()) || (index == size)) { + _StyleModules.push_back(iStyleModule); + _Layers.push_back(layer); + return; + } + _StyleModules.insert(_StyleModules.begin() + index, iStyleModule); + _Layers.insert(_Layers.begin()+index, layer); +} + +void Canvas::RemoveStyleModule(unsigned index) +{ + unsigned i=0; + if (!_StyleModules.empty()) + { + for(deque<StyleModule*>::iterator s=_StyleModules.begin(), send=_StyleModules.end(); + s!=send; + ++s) + { + if(i == index) + { + // remove shader + if (*s) + delete *s; + _StyleModules.erase(s); + break; + } + ++i; + } + } + i=0; + if(!_Layers.empty()) + { + for(deque<StrokeLayer*>::iterator sl=_Layers.begin(), slend=_Layers.end(); + sl!=slend; + ++sl) + { + if(i == index) + { + // remove layer + if (*sl) + delete *sl; + _Layers.erase(sl); + break; + } + ++i; + } + } +} + + +void Canvas::SwapStyleModules(unsigned i1, unsigned i2) +{ + StyleModule* tmp; + tmp = _StyleModules[i1]; + _StyleModules[i1] = _StyleModules[i2]; + _StyleModules[i2] = tmp; + + StrokeLayer* tmp2; + tmp2 = _Layers[i1]; + _Layers[i1] = _Layers[i2]; + _Layers[i2] = tmp2; +} + +void Canvas::ReplaceStyleModule(unsigned index, StyleModule *iStyleModule) +{ + unsigned i=0; + for(deque<StyleModule*>::iterator s=_StyleModules.begin(), send=_StyleModules.end(); + s != send; + ++s) + { + if(i == index) + { + if (*s) + delete *s; + *s = iStyleModule; + break; + } + ++i; + } +} + +void Canvas::setVisible(unsigned index, bool iVisible) { + _StyleModules[index]->setDisplayed(iVisible); +} + +void Canvas::setModified(unsigned index, bool iMod) +{ + _StyleModules[index]->setModified(iMod); +} + +void Canvas::resetModified(bool iMod/* =false */) +{ + unsigned size = _StyleModules.size(); + for(unsigned i = 0; i < size; ++i) + setModified(i,iMod); +} + +void Canvas::causalStyleModules(vector<unsigned>& vec, unsigned index) { + unsigned size = _StyleModules.size(); + + for(unsigned i = index; i < size; ++i) + if (_StyleModules[i]->getCausal()) + vec.push_back(i); +} + +void Canvas::Render(const StrokeRenderer *iRenderer) +{ + for (unsigned i = 0; i < _StyleModules.size(); i++) { + if(!_StyleModules[i]->getDisplayed() || !_Layers[i]) + continue; + _Layers[i]->Render(iRenderer); + } +} + +void Canvas::RenderBasic(const StrokeRenderer *iRenderer) + +{ + for (unsigned i = 0; i < _StyleModules.size(); i++) { + if(!_StyleModules[i]->getDisplayed() || !_Layers[i]) + continue; + _Layers[i]->RenderBasic(iRenderer); + } +} + +void Canvas::loadMap(const char *iFileName, const char *iMapName, unsigned int iNbLevels, float iSigma){ + // check whether this map was already loaded: + if(!_maps.empty()){ + mapsMap::iterator m = _maps.find(iMapName); + if(m!=_maps.end()){ + // lazy check for size changes + ImagePyramid * pyramid = (*m).second; + if((pyramid->width() != width()) || (pyramid->height() != height())){ + delete pyramid; + }else{ + return; + } + } + } + string filePath; + if(_MapsPath){ + filePath = _MapsPath; + filePath += iFileName; + }else{ + filePath = iFileName; + } + + //soc + // QImage *qimg; + // QImage newMap(filePath.c_str()); + // if(newMap.isNull()){ + // cout << "Could not load image file " << filePath << endl; + // return; + // } + // qimg = &newMap; + ImBuf *qimg = IMB_loadiffname(filePath.c_str(), 0);; + if( qimg == 0 ){ + cout << "Could not load image file " << filePath << endl; + return; + } + + // soc + //resize + // QImage scaledImg; + // if((newMap.width()!=width()) || (newMap.height()!=height())){ + // scaledImg = newMap.scaled(width(), height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + // qimg = &scaledImg; + // } + ImBuf *scaledImg; + if( ( qimg->x != width() ) || ( qimg->y != height() ) ){ + scaledImg = IMB_dupImBuf(qimg); + IMB_scaleImBuf(scaledImg, width(), height()); + } + + + // deal with color image + // if(newMap->depth() != 8){ + // int w = newMap->width(); + // int h = newMap->height(); + // QImage *tmp = new QImage(w, h, 8); + // for(unsigned y=0;y<h;++y){ + // for(unsigned x=0;x<w;++x){ + // int c = qGray(newMap->pixel(x,y)); + // tmp->setPixel(x,y,c); + // } + // } + // delete newMap; + // newMap = tmp; + // } + + int x,y; + int w = qimg->x; + int h = qimg->y; +int rowbytes = w*4; + GrayImage tmp(w,h); + char *pix; + + for(y=0; y<h;++y){ + for(x=0;x<w;++x){ + pix = (char*)qimg->rect + y*rowbytes + x*4; + float c = (pix[0]*11 + pix[1]*16 + pix[2]*5)/32; + tmp.setPixel(x,y,c); + } + } + + // GrayImage blur(w,h); + // GaussianFilter gf(4.f); + // //int bound = gf.getBound(); + // for(y=0; y<h;++y){ + // for(x=0;x<w;++x){ + // int c = gf.getSmoothedPixel<GrayImage>(&tmp, x,y); + // blur.setPixel(x,y,c); + // } + // } + + GaussianPyramid *pyramid = new GaussianPyramid(tmp, iNbLevels, iSigma); + int ow = pyramid->width(0); + int oh = pyramid->height(0); + string base(iMapName); //soc + for(int i=0; i<pyramid->getNumberOfLevels(); ++i){ + // save each image: + // w = pyramid.width(i); + // h = pyramid.height(i); + + //soc QImage qtmp(ow, oh, QImage::Format_RGB32); + ImBuf *qtmp = IMB_allocImBuf(ow, oh, 32, IB_rect, 0); + +//int k = (1<<i); + for(y=0;y<oh;++y){ + for(x=0;x<ow;++x){ + int c = pyramid->pixel(x,y,i);//255*pyramid->pixel(x,y,i); + //soc qtmp.setPixel(x,y,qRgb(c,c,c)); + pix = (char*)qtmp->rect + y*rowbytes + x*4; + pix[0] = pix [1] = pix[2] = c; + } + } + //soc qtmp.save(base+QString::number(i)+".bmp", "BMP"); + stringstream filename; + filename << base; + filename << i << ".bmp"; + qtmp->ftype= BMP; + IMB_saveiff(qtmp, const_cast<char *>(filename.str().c_str()), 0); + + } + // QImage *qtmp = new QImage(w, h, 32); + // for(y=0;y<h;++y){ + // for(x=0;x<w;++x){ + // int c = (int)blur.pixel(x,y); + // qtmp->setPixel(x,y,qRgb(c,c,c)); + // } + // } + // delete newMap; + // newMap = qtmp; + // + _maps[iMapName] = pyramid; + // newMap->save("toto.bmp", "BMP"); +} + +float Canvas::readMapPixel(const char *iMapName, int level, int x, int y){ + if(_maps.empty()){ + cout << "readMapPixel warning: no map was loaded "<< endl; + return -1; + } + mapsMap::iterator m = _maps.find(iMapName); + if(m==_maps.end()){ + cout << "readMapPixel warning: no map was loaded with the name " << iMapName << endl; + return -1; + } + ImagePyramid *pyramid = (*m).second; + if((x<0) || (x>=pyramid->width()) || (y<0) || (y>=pyramid->height())) + return 0; + + return pyramid->pixel(x,height()-1-y,level); +} diff --git a/source/blender/freestyle/intern/stroke/Canvas.h b/source/blender/freestyle/intern/stroke/Canvas.h new file mode 100755 index 00000000000..707455c87f6 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/Canvas.h @@ -0,0 +1,196 @@ +// +// Filename : Canvas.h +// Author(s) : Stephane Grabli +// Purpose : Class to define a canvas designed to draw style modules +// Date of creation : 20/10/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef CANVAS_H +# define CANVAS_H + +# include <cstring> +# include <deque> +# include <vector> +# include <map> +# include "../system/FreestyleConfig.h" +# include "StrokeLayer.h" +# include "../geometry/BBox.h" +# include "../geometry/Geom.h" + +using namespace Geometry; + +struct ltstr +{ + bool operator()(const char* s1, const char* s2) const + { + return strcmp(s1, s2) < 0; + } +}; + +class InformationMap; +class StrokeRenderer; +class ViewMap; +class ViewEdge; +class FEdge; +class RGBImage; +class GrayImage; +class QImage; +class ImagePyramid; +class SteerableViewMap; +class StyleModule; + +/*! Class to define the canvas on which strokes are drawn. + * It's used to store state information about the drawing. + */ +class LIB_STROKE_EXPORT Canvas +{ +public: + /*! Returns a pointer on the Canvas instance */ + static Canvas * getInstance() {return _pInstance;} + typedef std::map<const char*, ImagePyramid*, ltstr> mapsMap ; + static const int NB_STEERABLE_VIEWMAP = 5; +protected: + static Canvas *_pInstance; + std::deque<StrokeLayer*> _Layers; + std::deque<StyleModule*> _StyleModules; + FEdge *_SelectedFEdge; + + StrokeRenderer *_Renderer; + StyleModule* _current_sm; + mapsMap _maps; + static const char * _MapsPath; + SteerableViewMap *_steerableViewMap; + bool _basic; + +public: + /* Builds the Canvas */ + Canvas(); + /* Copy constructor */ + Canvas(const Canvas& iBrother); + /* Destructor */ + virtual ~Canvas(); + + /* operations that need to be done before a draw */ + virtual void preDraw(); + + /* Draw the canvas using the current shader */ + virtual void Draw(); + + /* operations that need to be done after a draw */ + virtual void postDraw(); + + /* Renders the created strokes */ + virtual void Render(const StrokeRenderer *iRenderer); + /* Basic Renders the created strokes */ + virtual void RenderBasic(const StrokeRenderer *iRenderer); + /* Renders a stroke */ + virtual void RenderStroke(Stroke *iStroke) = 0; + + /* init the canvas */ + virtual void init() = 0; + + /* Clears the Canvas (shaders stack, layers stack...)*/ + void Clear(); + + /* Erases the layers */ + virtual void Erase(); + + /* Reads a pixel area from the canvas */ + virtual void readColorPixels(int x, int y,int w, int h, RGBImage& oImage) const = 0; + /* Reads a depth pixel area from the canvas */ + virtual void readDepthPixels(int x, int y,int w, int h, GrayImage& oImage) const = 0; + + /* update the canvas (display) */ + virtual void update() = 0; + + /* checks whether the canvas is empty or not */ + bool isEmpty() const {return (_Layers.empty());} + + /* Maps management */ + /*! Loads an image map. The map will be scaled + * (without preserving the ratio in order + * to fit the actual canvas size.) + * The image must be a gray values image... + * \param iFileName + * The name of the image file + * \param iMapName + * The name that will be used to access + * this image + * \param iNbLevels + * The number of levels in the map pyramid. (default = 4). + * If iNbLevels == 0, the complete pyramid is built. + */ + void loadMap(const char *iFileName, const char *iMapName, unsigned iNbLevels=4, float iSigma = 1.f); + + /*! Reads a pixel value in a map. + * Returns a value between 0 and 1. + * \param iMapName + * The name of the map + * \param level + * The level of the pyramid from which the pixel must + * be read. + * \param x + * The abscissa of the desired pixel specified in level0 coordinate + * system. The origin is the lower left corner. + * \param y + * The ordinate of the desired pixel specified in level0 coordinate + * system. The origin is the lower left corner. + */ + float readMapPixel(const char *iMapName, int level, int x, int y); + + /*! Sets the steerable viewmap */ + void loadSteerableViewMap(SteerableViewMap * iSVM) {_steerableViewMap = iSVM;} + + /*! Returns the steerable VM */ + SteerableViewMap * getSteerableViewMap() {return _steerableViewMap;} + + /*! accessors */ + inline const FEdge * selectedFEdge() const {return _SelectedFEdge;} + inline FEdge * selectedFEdge() {return _SelectedFEdge;} + virtual int width() const = 0; + virtual int height() const = 0; + virtual BBox<Vec3r> scene3DBBox() const = 0; + inline const StrokeRenderer * renderer() const {return _Renderer;} + inline StyleModule* getCurrentStyleModule() { return _current_sm; } + virtual bool getRecordFlag() const {return false;} + int stroke_count; + + /*! modifiers */ + inline void setSelectedFEdge(FEdge *iFEdge) {_SelectedFEdge = iFEdge;} + /*! inserts a shader at pos index+1 */ + void PushBackStyleModule(StyleModule *iStyleModule); + void InsertStyleModule(unsigned index, StyleModule *iStyleModule); + void RemoveStyleModule(unsigned index); + void SwapStyleModules(unsigned i1, unsigned i2); + void ReplaceStyleModule(unsigned index, StyleModule *iStyleModule); + void setVisible(unsigned index, bool iVisible) ; + //inline void setDensityMap(InformationMap<RGBImage>* iMap) {_DensityMap = iMap;} + inline void AddLayer(StrokeLayer *iLayer) {_Layers.push_back(iLayer);} + void resetModified(bool iMod=false); + void causalStyleModules(std::vector<unsigned>& vec, unsigned index = 0); + void setModified(unsigned index, bool b); +}; + +#endif // CANVAS_H diff --git a/source/blender/freestyle/intern/stroke/Chain.cpp b/source/blender/freestyle/intern/stroke/Chain.cpp new file mode 100755 index 00000000000..3776cd58a03 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/Chain.cpp @@ -0,0 +1,126 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "Chain.h" +#include "../view_map/ViewMapIterators.h" +#include "../view_map/ViewMapAdvancedIterators.h" + +void Chain::push_viewedge_back(ViewEdge *iViewEdge, bool orientation) +{ + ViewEdge::vertex_iterator v; + ViewEdge::vertex_iterator vend; + ViewEdge::vertex_iterator vfirst; + Vec3r previous, current; + if(true == orientation) + { + v=iViewEdge->vertices_begin(); + vfirst = v; + vend=iViewEdge->vertices_end(); + } + else + { + v=iViewEdge->vertices_last(); + vfirst = v; + vend=iViewEdge->vertices_end(); + } + + if(!_Vertices.empty()) + { + previous = _Vertices.back()->point2d(); + if(orientation) + ++v; + else + --v; + } + else + previous = (*v)->point2d(); + do{ + current = (*v)->point2d(); + Curve::push_vertex_back(*v); + //_Length += (current-previous).norm(); + previous = current; + if(orientation) + ++v; + else + --v; + }while((v!=vend) && (v!=vfirst)); + + if(v==vfirst) + { + //Add last one: + current = (*v)->point2d(); + Curve::push_vertex_back(*v); + //_Length += (current-previous).norm(); + } +} + +void Chain::push_viewedge_front(ViewEdge *iViewEdge, bool orientation) +{ + orientation = !orientation; + ViewEdge::vertex_iterator v; + ViewEdge::vertex_iterator vend; + ViewEdge::vertex_iterator vfirst; + Vec3r previous, current; + if(true == orientation) + { + v=iViewEdge->vertices_begin(); + vfirst = v; + vend=iViewEdge->vertices_end(); + } + else + { + v=iViewEdge->vertices_last(); + vfirst = v; + vend=iViewEdge->vertices_end(); + } + + if(!_Vertices.empty()) + { + previous = _Vertices.front()->point2d(); + if(orientation) + ++v; + else + --v; + } + else + previous = (*v)->point2d(); + do{ + current = (*v)->point2d(); + Curve::push_vertex_front((*v)); + //_Length += (current-previous).norm(); + previous = current; + if(orientation) + ++v; + else + --v; + }while((v!=vend) && (v!=vfirst)); + + if(v==vfirst) + { + //Add last one: + current = (*v)->point2d(); + Curve::push_vertex_front(*v); + //_Length += (current-previous).norm(); + } +} + + + diff --git a/source/blender/freestyle/intern/stroke/Chain.h b/source/blender/freestyle/intern/stroke/Chain.h new file mode 100755 index 00000000000..711ae16a1a0 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/Chain.h @@ -0,0 +1,86 @@ +// +// Filename : Chain.h +// Author(s) : Stephane Grabli +// Purpose : Class to define a chain of viewedges. +// Date of creation : 09/01/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef CHAIN_H +# define CHAIN_H + +# include "../view_map/ViewMap.h" +# include "Curve.h" +/*! Class to represent a 1D elements issued + * from the chaining process. + * A Chain is the last step before the Stroke and + * is used in the Splitting and Creation processes. + */ +class Chain : public Curve +{ +protected: + // tmp + Id * _splittingId; +public: + /*! Defult constructor. */ + Chain() : Curve() {_splittingId=0;} + /*! Builds a chain from its Id. */ + Chain(const Id& id) : Curve(id) {_splittingId=0;} + /*! Copy Constructor */ + Chain(const Chain& iBrother) : Curve(iBrother) {_splittingId=iBrother._splittingId;} + /*! Destructor. */ + virtual ~Chain() { + // only the last splitted deletes this id + if(_splittingId){ + if(*_splittingId == _Id) + delete _splittingId; + } + } + /*! Returns the string "Chain" */ + virtual string getExactTypeName() const { + return "Chain"; + } + + /*! Adds a ViewEdge at the end of the chain + * \param iViewEdge + * The ViewEdge that must be added. + * \param orientation + * The orientation with which this ViewEdge + * must be processed. + */ + void push_viewedge_back(ViewEdge *iViewEdge, bool orientation) ; + /*! Adds a ViewEdge at the beginning of the chain + * \param iViewEdge + * The ViewEdge that must be added. + * \param orientation + * The orientation with which this ViewEdge + * must be processed. + */ + void push_viewedge_front(ViewEdge *iViewEdge, bool orientation) ; + + inline void setSplittingId(Id * sid){_splittingId = sid;} + inline Id* getSplittingId() {return _splittingId;} +}; + +#endif // CHAIN_H diff --git a/source/blender/freestyle/intern/stroke/ChainingIterators.cpp b/source/blender/freestyle/intern/stroke/ChainingIterators.cpp new file mode 100755 index 00000000000..c54ee6ea1ee --- /dev/null +++ b/source/blender/freestyle/intern/stroke/ChainingIterators.cpp @@ -0,0 +1,170 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// +#include "ChainingIterators.h" +#include "../system/TimeStamp.h" + +ViewEdge* AdjacencyIterator::operator*() { + return (*_internalIterator).first; +} +bool AdjacencyIterator::isIncoming() const{ + return (*_internalIterator).second; +} + +int AdjacencyIterator::increment(){ + ++_internalIterator; + while((!_internalIterator.isEnd()) && (!isValid((*_internalIterator).first))) + ++_internalIterator; + return 0; +} + +bool AdjacencyIterator::isValid(ViewEdge* edge){ + if(_restrictToSelection) + if(edge->getTimeStamp() != TimeStamp::instance()->getTimeStamp()) + return false; + if(_restrictToUnvisited) + if(edge->getChainingTimeStamp() > TimeStamp::instance()->getTimeStamp()) + return false; + return true; +} + +int ChainingIterator::increment() { + _increment = true; + ViewVertex * vertex = getVertex(); + if(!vertex){ + _edge = 0; + return 0; + } + AdjacencyIterator it = AdjacencyIterator(vertex, _restrictToSelection, _restrictToUnvisited); + if(it.isEnd()) { + _edge = 0; + return 0; + } + if (traverse(it) < 0) + return -1; + _edge = result; + if(_edge == 0) + return 0; + if(_edge->A() == vertex) + _orientation = true; + else + _orientation = false; + return 0; +} + +int ChainingIterator::decrement() { + _increment = false; + ViewVertex * vertex = getVertex(); + if(!vertex){ + _edge = 0; + return 0; + } + AdjacencyIterator it = AdjacencyIterator(vertex, _restrictToSelection, _restrictToUnvisited); + if(it.isEnd()) { + _edge = 0; + return 0; + } + if (traverse(it) < 0) + return -1; + _edge = result; + if(_edge == 0) + return 0; + if(_edge->B() == vertex) + _orientation = true; + else + _orientation = false; + return 0; +} + +// +// ChainSilhouetteIterators +// +/////////////////////////////////////////////////////////// + +int ChainSilhouetteIterator::traverse(const AdjacencyIterator& ait){ + AdjacencyIterator it(ait); + ViewVertex* nextVertex = getVertex(); + // we can't get a NULL nextVertex here, it was intercepted + // before + if(nextVertex->getNature() & Nature::T_VERTEX){ + TVertex * tvertex = (TVertex*)nextVertex; + ViewEdge *mate = (tvertex)->mate(getCurrentEdge()); + while(!it.isEnd()){ + ViewEdge *ve = *it; + if(ve == mate) { + result = ve; + return 0; + } + ++it; + } + result = 0; + return 0; + } + if(nextVertex->getNature() & Nature::NON_T_VERTEX){ + //soc NonTVertex * nontvertex = (NonTVertex*)nextVertex; + ViewEdge * newEdge(0); + // we'll try to chain the edges by keeping the same nature... + // the preseance order is : SILHOUETTE, BORDER, CREASE, SUGGESTIVE, VALLEY, RIDGE + Nature::EdgeNature natures[6] = {Nature::SILHOUETTE, Nature::BORDER, Nature::CREASE, Nature::SUGGESTIVE_CONTOUR, Nature::VALLEY, Nature::RIDGE}; + for(unsigned i=0; i<6; ++i){ + if(getCurrentEdge()->getNature() & natures[i]){ + int n = 0; + while(!it.isEnd()){ + ViewEdge *ve = *it; + if(ve->getNature() & natures[i]){ + ++n; + newEdge = ve; + } + ++it; + } + if(n == 1){ + result = newEdge; + }else{ + result = 0; + } + return 0; + } + } + } + result = 0; + return 0; +} + +int ChainPredicateIterator::traverse(const AdjacencyIterator& ait){ + AdjacencyIterator it(ait); + // Iterates over next edges to see if one of them + // respects the predicate: + while(!it.isEnd()) { + ViewEdge *ve = *it; + if (_unary_predicate->operator()(*ve) < 0) + return -1; + if (_unary_predicate->result) { + if (_binary_predicate->operator()(*(getCurrentEdge()), *(ve)) < 0) + return -1; + if (_binary_predicate->result) { + result = ve; + return 0; + } + } + ++it; + } + result = 0; + return 0; +} diff --git a/source/blender/freestyle/intern/stroke/ChainingIterators.h b/source/blender/freestyle/intern/stroke/ChainingIterators.h new file mode 100755 index 00000000000..fec8d5ab6dc --- /dev/null +++ b/source/blender/freestyle/intern/stroke/ChainingIterators.h @@ -0,0 +1,394 @@ +// +// Filename : ChainingIterators +// Author : Stephane Grabli +// Purpose : Chaining iterators +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// +#ifndef CHAININGITERATORS_H +# define CHAININGITERATORS_H + +# include "../view_map/ViewMap.h" +# include "../view_map/ViewMapIterators.h" +# include "../view_map/ViewMapAdvancedIterators.h" +# include <iostream> +# include "Predicates1D.h" + +#include "../system/Iterator.h" //soc + +# include "../python/Director.h" + +//using namespace ViewEdgeInternal; + +// +// Adjacency iterator used in the chaining process +// +/////////////////////////////////////////////////////////// +class LIB_STROKE_EXPORT AdjacencyIterator : public Iterator { +protected: + ViewVertexInternal::orientedViewEdgeIterator _internalIterator; + bool _restrictToSelection; + bool _restrictToUnvisited; +public: + AdjacencyIterator(){ + _restrictToSelection = true; + _restrictToUnvisited = true; + } + AdjacencyIterator(ViewVertex *iVertex, bool iRestrictToSelection = true, bool iRestrictToUnvisited = true){ + _restrictToSelection = iRestrictToSelection; + _restrictToUnvisited = iRestrictToUnvisited; + _internalIterator = iVertex->edgesBegin(); + while((!_internalIterator.isEnd()) && (!isValid((*_internalIterator).first))) + ++_internalIterator; + } + AdjacencyIterator(const AdjacencyIterator& iBrother){ + _internalIterator = iBrother._internalIterator; + _restrictToSelection = iBrother._restrictToSelection; + _restrictToUnvisited = iBrother._restrictToUnvisited; + } + AdjacencyIterator& operator=(const AdjacencyIterator& iBrother) { + _internalIterator = iBrother._internalIterator; + _restrictToSelection = iBrother._restrictToSelection; + _restrictToUnvisited = iBrother._restrictToUnvisited; + return *this; + } + virtual ~AdjacencyIterator(){ + } + + virtual string getExactTypeName() const { + return "AdjacencyIterator"; + } + + virtual inline bool isEnd() const { + return _internalIterator.isEnd(); + } + virtual inline bool isBegin() const { + return _internalIterator.isBegin(); + } + /*! Returns true if the current ViewEdge is is coming + * towards the iteration vertex. False otherwise. + */ + bool isIncoming() const ; + + /*! Returns a *pointer* to the pointed ViewEdge. */ + virtual ViewEdge* operator*() ; + virtual ViewEdge* operator->() {return operator*();} + virtual AdjacencyIterator& operator++() { + increment(); + return *this; + } + virtual AdjacencyIterator operator++(int) { + AdjacencyIterator tmp(*this); + increment(); + return tmp; + } + virtual int increment(); + + virtual int decrement(){ + cerr << "Warning: method decrement() not implemented" << endl; + return 0; + } + +protected: + bool isValid(ViewEdge* edge); +}; + +// +// Base class for Chaining Iterators +// +/////////////////////////////////////////////////////////// + +/*! Base class for chaining iterators. + * This class is designed to be overloaded + * in order to describe chaining rules. + * It makes the works of chaining rules description + * easier. + * The two main methods that need to overloaded are + * traverse() and init(). + * traverse() tells which ViewEdge to follow, among the adjacent ones. + * If you specify restriction rules (such as "Chain only + * ViewEdges of the selection"), they will be included + * in the adjacency iterator. (i.e, the adjacent iterator + * will only stop on "valid" edges). + */ +class LIB_STROKE_EXPORT ChainingIterator : public ViewEdgeInternal::ViewEdgeIterator{ +protected: + bool _restrictToSelection; + bool _restrictToUnvisited; + bool _increment; //true if we're currently incrementing, false when decrementing + +public: + + ViewEdge *result; + PyObject *py_c_it; + + /*! Builds a Chaining Iterator from the first ViewEdge used for iteration + * and its orientation. + * \param iRestrictToSelection + * Indicates whether to force the chaining to stay within + * the set of selected ViewEdges or not. + * \param iRestrictToUnvisited + * Indicates whether a ViewEdge that has already been chained + * must be ignored ot not. + * \param begin + * The ViewEdge from which to start the chain. + * \param orientation + * The direction to follow to explore the graph. If true, + * the direction indicated by the first ViewEdge is used. + */ + ChainingIterator(bool iRestrictToSelection = true, bool iRestrictToUnvisited = true, ViewEdge* begin = 0, bool orientation = true) + : ViewEdgeIterator(begin, orientation) { + _restrictToSelection = iRestrictToSelection; + _restrictToUnvisited = iRestrictToUnvisited; + _increment = true; + py_c_it = 0; + } + + /*! Copy constructor */ + ChainingIterator(const ChainingIterator& brother) + : ViewEdgeIterator(brother) { + _restrictToSelection = brother._restrictToSelection; + _restrictToUnvisited = brother._restrictToUnvisited; + _increment = brother._increment; + py_c_it = brother.py_c_it; + } + + /*! Returns the string "ChainingIterator" */ + virtual string getExactTypeName() const { + return "ChainingIterator"; + } + + /*! Inits the iterator context. + * This method is called each time + * a new chain is started. + * It can be used to reset some + * history information that you + * might want to keep. + */ + virtual int init() { + return Director_BPy_ChainingIterator_init( this ); + } + + /*! This method iterates over the potential next + * ViewEdges and returns the one that will be + * followed next. + * returns the next ViewEdge to follow or + * 0 when the end of the chain is reached. + * \param it + * The iterator over the ViewEdges adjacent to + * the end vertex of the current ViewEdge. + * The Adjacency iterator reflects the restriction + * rules by only iterating over the valid ViewEdges. + */ + virtual int traverse(const AdjacencyIterator &it){ + return Director_BPy_ChainingIterator_traverse( this, const_cast<AdjacencyIterator &>(it) ); + } + + /* accessors */ + /*! Returns true if the orientation of the current ViewEdge + * corresponds to its natural orientation + */ + //inline bool getOrientation() const {} + /*! Returns the vertex which is the next crossing */ + inline ViewVertex * getVertex() { + if(_increment){ + if(_orientation){ + return _edge->B(); + }else{ + return _edge->A(); + } + }else{ + if(_orientation){ + return _edge->A(); + }else{ + return _edge->B(); + } + } + } + + /*! Returns true if the current iteration is an incrementation */ + inline bool isIncrementing() const{ + return _increment; + } + + /* increments.*/ + virtual int increment() ; + virtual int decrement() ; +}; + +// +// Chaining iterators definitions +// +/////////////////////////////////////////////////////////// + +/*! A ViewEdge Iterator used to follow ViewEdges the most naturally. + * For example, it will follow visible ViewEdges of same nature. + * As soon, as the nature or the visibility changes, the iteration + * stops (by setting the pointed ViewEdge to 0). + * In the case of an iteration over a set of ViewEdge that are both + * Silhouette and Crease, there will be a precedence of the silhouette + * over the crease criterion. + */ +class LIB_STROKE_EXPORT ChainSilhouetteIterator : public ChainingIterator +{ +public: + /*! Builds a ChainSilhouetteIterator from the first ViewEdge used for iteration + * and its orientation. + * \param iRestrictToSelection + * Indicates whether to force the chaining to stay within + * the set of selected ViewEdges or not. + * \param begin + * The ViewEdge from where to start the iteration. + * \param orientation + * If true, we'll look for the next ViewEdge among the + * ViewEdges that surround the ending ViewVertex of begin. + * If false, we'll search over the ViewEdges surrounding + * the ending ViewVertex of begin. + */ + ChainSilhouetteIterator(bool iRestrictToSelection = true, ViewEdge* begin = NULL, bool orientation = true) + : ChainingIterator(iRestrictToSelection, true, begin, orientation) {} + + /*! Copy constructor */ + ChainSilhouetteIterator(const ChainSilhouetteIterator& brother) + : ChainingIterator(brother) {} + + /*! Returns the string "ChainSilhouetteIterator" */ + virtual string getExactTypeName() const { + return "ChainSilhouetteIterator"; + } + + /*! This method iterates over the potential next + * ViewEdges and returns the one that will be + * followed next. + * When reaching the end of a chain, 0 is returned. + */ + virtual int traverse(const AdjacencyIterator& it); + + /*! Inits the iterator context */ + virtual int init() { + return 0; + } +}; + +// +// ChainPredicateIterator +// +/////////////////////////////////////////////////////////// + +/*! A "generic" user-controlled ViewEdge iterator. This iterator + * is in particular built from a unary predicate and a binary predicate. + * First, the unary predicate is evaluated for all potential next ViewEdges + * in order to only keep the ones respecting a certain constraint. + * Then, the binary predicate is evaluated on the current ViewEdge + * together with each ViewEdge of the previous selection. The first + * ViewEdge respecting both the unary predicate and the binary predicate + * is kept as the next one. If none of the potential next ViewEdge respects + * these 2 predicates, 0 is returned. + */ +class LIB_STROKE_EXPORT ChainPredicateIterator : public ChainingIterator +{ +protected: + BinaryPredicate1D *_binary_predicate; // the caller is responsible for the deletion of this object + UnaryPredicate1D *_unary_predicate; // the caller is responsible for the deletion of this object +public: + + /*! Builds a ChainPredicateIterator from a starting ViewEdge and its orientation. + * \param iRestrictToSelection + * Indicates whether to force the chaining to stay within + * the set of selected ViewEdges or not. + * \param iRestrictToUnvisited + * Indicates whether a ViewEdge that has already been chained + * must be ignored ot not. + * \param begin + * The ViewEdge from where to start the iteration. + * \param orientation + * If true, we'll look for the next ViewEdge among the + * ViewEdges that surround the ending ViewVertex of begin. + * If false, we'll search over the ViewEdges surrounding + * the ending ViewVertex of begin. + */ + ChainPredicateIterator(bool iRestrictToSelection = true, bool iRestrictToUnvisited = true, ViewEdge* begin = NULL, bool orientation = true) + : ChainingIterator(iRestrictToSelection, iRestrictToUnvisited, begin, orientation) { + _binary_predicate = 0; + _unary_predicate = 0; + } + + /*! Builds a ChainPredicateIterator from a unary predicate, a binary predicate, a starting ViewEdge and its orientation. + * \param iRestrictToSelection + * Indicates whether to force the chaining to stay within + * the set of selected ViewEdges or not. + * \param iRestrictToUnvisited + * Indicates whether a ViewEdge that has already been chained + * must be ignored ot not. + * \param upred + * The unary predicate that the next ViewEdge must satisfy. + * \param bpred + * The binary predicate that the next ViewEdge must satisfy + * together with the actual pointed ViewEdge. + * \param begin + * The ViewEdge from where to start the iteration. + * \param orientation + * If true, we'll look for the next ViewEdge among the + * ViewEdges that surround the ending ViewVertex of begin. + * If false, we'll search over the ViewEdges surrounding + * the ending ViewVertex of begin. + */ + ChainPredicateIterator(UnaryPredicate1D& upred, BinaryPredicate1D& bpred, bool iRestrictToSelection = true, bool iRestrictToUnvisited = true, ViewEdge* begin = NULL, bool orientation = true) + : ChainingIterator(iRestrictToSelection, iRestrictToUnvisited, begin, orientation) { + _unary_predicate = &upred; + _binary_predicate = &bpred; + } + + /*! Copy constructor */ + ChainPredicateIterator(const ChainPredicateIterator& brother) + : ChainingIterator(brother){ + _unary_predicate = brother._unary_predicate; + _binary_predicate = brother._binary_predicate; + } + + /*! Destructor. */ + virtual ~ChainPredicateIterator(){ + _unary_predicate = 0; + _binary_predicate = 0; + } + + /*! Returns the string "ChainPredicateIterator" */ + virtual string getExactTypeName() const { + return "ChainPredicateIterator"; + } + + /*! This method iterates over the potential next + * ViewEdges and returns the one that will be + * followed next. + * When reaching the end of a chain, 0 is returned. + */ + virtual int traverse(const AdjacencyIterator &it); + + /*! Inits the iterator context */ + virtual int init() { + return 0; + } + +}; + +#endif // CHAININGITERATORS_H diff --git a/source/blender/freestyle/intern/stroke/ContextFunctions.cpp b/source/blender/freestyle/intern/stroke/ContextFunctions.cpp new file mode 100755 index 00000000000..b55da1fb0f8 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/ContextFunctions.cpp @@ -0,0 +1,60 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "ContextFunctions.h" +#include "../view_map/SteerableViewMap.h" +#include "../system/TimeStamp.h" +namespace ContextFunctions { + + unsigned GetTimeStampCF(){ + return TimeStamp::instance()->getTimeStamp(); + } + + unsigned GetCanvasWidthCF(){ + return Canvas::getInstance()->width(); + } + + unsigned GetCanvasHeightCF(){ + return Canvas::getInstance()->height(); + } + void LoadMapCF(const char *iFileName, const char *iMapName, unsigned iNbLevels, float iSigma ){ + return Canvas::getInstance()->loadMap(iFileName, iMapName, iNbLevels,iSigma); + } + + float ReadMapPixelCF(const char *iMapName, int level, unsigned x, unsigned y){ + Canvas * canvas = Canvas::getInstance(); + return canvas->readMapPixel(iMapName, level, x,y); + } + + float ReadCompleteViewMapPixelCF(int level, unsigned x, unsigned y){ + SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap(); + return svm->readCompleteViewMapPixel(level,x,y); + } + + float ReadDirectionalViewMapPixelCF(int iOrientation, int level, unsigned x, unsigned y){ + SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap(); + return svm->readSteerableViewMapPixel(iOrientation, level,x,y); + } + + FEdge * GetSelectedFEdgeCF(){ + return Canvas::getInstance()->selectedFEdge(); + } +} diff --git a/source/blender/freestyle/intern/stroke/ContextFunctions.h b/source/blender/freestyle/intern/stroke/ContextFunctions.h new file mode 100755 index 00000000000..37c98656fa7 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/ContextFunctions.h @@ -0,0 +1,124 @@ +// +// Filename : AdvancedFunctions0D.h +// Author(s) : Stephane Grabli +// Purpose : Functions related to context queries +// Date of creation : 20/12/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef CONTEXT_FUNCTIONS_HPP +# define CONTEXT_FUNCTIONS_HPP + +# include "Canvas.h" +# include "../image/Image.h" +# include "../image/GaussianFilter.h" + +/*! \file ContextFunctions.h + * Interface to access the context related + * information. + */ +// +// Context Functions definitions +// +/////////////////////////////////////////////////////////// +/*! namespace containing all the Context related functions */ +namespace ContextFunctions { + + // GetTimeStamp + LIB_STROKE_EXPORT + /*! Returns the system time stamp */ + unsigned GetTimeStampCF(); + + // GetCanvasWidth + /*! Returns the canvas width */ + LIB_STROKE_EXPORT + unsigned GetCanvasWidthCF(); + + // GetCanvasHeight + /*! Returns the canvas width */ + LIB_STROKE_EXPORT + unsigned GetCanvasHeightCF(); + + // Load map + /*! Loads an image map for further reading */ + LIB_STROKE_EXPORT + void LoadMapCF(const char *iFileName, const char *iMapName, unsigned iNbLevels=4, float iSigma=1.f); + + // ReadMapPixel + /*! Reads a pixel in a user-defined map + * \return the floating value stored for that pixel + * \param iMapName + * The name of the map + * \param level + * The level of the pyramid in which we wish to read the pixel + * \param x + * The x-coordinate of the pixel we wish to read. The origin is + * in the lower-left corner. + * \param y + * The y-coordinate of the pixel we wish to read. The origin is + * in the lower-left corner. + */ + LIB_STROKE_EXPORT + float ReadMapPixelCF(const char *iMapName, int level, unsigned x, unsigned y); + + // ReadCompleteViewMapPixel + /*! Reads a pixel in the complete view map + * \return the floating value stored for that pixel + * \param level + * The level of the pyramid in which we wish to read the pixel + * \param x + * The x-coordinate of the pixel we wish to read. The origin is + * in the lower-left corner. + * \param y + * The y-coordinate of the pixel we wish to read. The origin is + * in the lower-left corner. + */ + LIB_STROKE_EXPORT + float ReadCompleteViewMapPixelCF(int level, unsigned x, unsigned y); + + // ReadOrientedViewMapPixel + /*! Reads a pixel in one of the oriented view map images + * \return the floating value stored for that pixel + * \param iOrientation + * The number telling which orientation we want to check + * \param level + * The level of the pyramid in which we wish to read the pixel + * \param x + * The x-coordinate of the pixel we wish to read. The origin is + * in the lower-left corner. + * \param y + * The y-coordinate of the pixel we wish to read. The origin is + * in the lower-left corner. + */ + LIB_STROKE_EXPORT + float ReadDirectionalViewMapPixelCF(int iOrientation, int level, unsigned x, unsigned y); + + // DEBUG + LIB_STROKE_EXPORT + FEdge * GetSelectedFEdgeCF(); + +} // end of namespace ContextFunctions + +#endif // CONTEXT_FUNCTIONS_HPP + diff --git a/source/blender/freestyle/intern/stroke/Curve.cpp b/source/blender/freestyle/intern/stroke/Curve.cpp new file mode 100755 index 00000000000..f7b255c3ef4 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/Curve.cpp @@ -0,0 +1,818 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "Curve.h" +#include "CurveIterators.h" +#include "CurveAdvancedIterators.h" + + /**********************************/ + /* */ + /* */ + /* CurvePoint */ + /* */ + /* */ + /**********************************/ + +CurvePoint::CurvePoint() +{ + __A=0; + __B=0; + _t2d=0; +} + +CurvePoint::CurvePoint(SVertex *iA, SVertex *iB, float t) +{ + __A=iA; + __B=iB; + _t2d=t; + if((iA == 0) && (t == 1.f)) + { + _Point2d=__B->point2d(); + _Point3d=__B->point3d(); + } + else if((iB == 0) && (t == 0.f)) + { + _Point2d=__A->point2d(); + _Point3d=__A->point3d(); + } + else + { + _Point2d=__A->point2d()+_t2d*(__B->point2d()-__A->point2d()); + _Point3d=__A->point3d()+_t2d*(__B->point3d()-__A->point3d()); + } +} + +CurvePoint::CurvePoint(CurvePoint *iA, CurvePoint *iB, float t3) +{ + float t1=iA->t2d(); + float t2=iB->t2d(); + if((iA->A() == iB->A()) && (iA->B() == iB->B()) && (iA->A() != 0) && (iA->B() != 0) && (iB->A() != 0) && (iB->B() != 0)) + { + __A=iA->A(); + __B=iB->B(); + _t2d=t1+t2*t3-t1*t3; + } + else if((iA->B() == 0) && (iB->B() == 0)) + { + __A = iA->A(); + __B = iB->A(); + _t2d = t3; + } + else if((iA->t2d() == 0) && (iB->t2d() == 0)) + { + __A = iA->A(); + __B = iB->A(); + _t2d = t3; + } + else if(iA->A() == iB->A()){ + if(iA->t2d() == 0){ + __A = iB->A(); + __B = iB->B(); + _t2d = t3; + }else if(iB->t2d() == 0){ + __A = iA->A(); + __B = iA->B(); + _t2d = t3; + } + }else if(iA->B() == iB->B()){ + if(iA->t2d() == 1){ + __A = iB->A(); + __B = iB->B(); + _t2d = t3; + }else if(iB->t2d() == 1){ + __A = iA->A(); + __B = iA->B(); + _t2d = t3; + } + } + else if(iA->B() == iB->A()) + { + if((iA->t2d() != 1.f) && (iB->t2d() == 0.f)) + { + __A = iA->A(); + __B = iA->B(); + _t2d=t1+t3-t1*t3; + //_t2d = t3; + } + else if((iA->t2d() == 1.f) && (iB->t2d() != 0.f)) + { + __A = iB->A(); + __B = iB->B(); + //_t2d = t3; + _t2d=t2*t3; + } + + } + //_Point2d=__A->point2d()+_t2d*(__B->point2d()-__A->point2d()); + //_Point3d=__A->point3d()+_t2d*(__B->point3d()-__A->point3d()); + + _Point2d= iA->point2d()+t3*(iB->point2d()-iA->point2d()); + _Point3d=__A->point3d()+_t2d*(__B->point3d()-__A->point3d()); +} + +CurvePoint::CurvePoint(const CurvePoint& iBrother) +{ + __A=iBrother.__A; + __B=iBrother.__B; + _t2d=iBrother._t2d; + _Point2d=iBrother._Point2d; + _Point3d=iBrother._Point3d; +} + +CurvePoint& CurvePoint::operator=(const CurvePoint& iBrother) +{ + __A=iBrother.__A; + __B=iBrother.__B; + _t2d=iBrother._t2d; + _Point2d=iBrother._Point2d; + _Point3d=iBrother._Point3d; + return *this; +} + + +FEdge *CurvePoint::fedge() +{ + if(getNature() & Nature::T_VERTEX) + return 0; + return __A->fedge(); +} + + +FEdge* CurvePoint::getFEdge(Interface0D& inter) +{ + CurvePoint* iVertexB = dynamic_cast<CurvePoint*>(&inter); + if (!iVertexB) + return 0; + if(((__A == iVertexB->__A) && (__B == iVertexB->__B)) + || + ((__A == iVertexB->__B) && (__B == iVertexB->__A))) + return __A->getFEdge(*__B); + else if(__B == 0) + { + if(iVertexB->__B == 0) + return __A->getFEdge(*(iVertexB->__A)); + else if(iVertexB->__A == __A) + return __A->getFEdge(*(iVertexB->__B)); + else if(iVertexB->__B == __A) + return __A->getFEdge(*(iVertexB->__A)); + } + else if(iVertexB->__B == 0) + { + if(iVertexB->__A == __A) + return __B->getFEdge(*(iVertexB->__A)); + else if(iVertexB->__A == __B) + return __A->getFEdge(*(iVertexB->__A)); + } + else if(__B == iVertexB->__A) + { + if((_t2d != 1) && (iVertexB->_t2d == 0)) + return __A->getFEdge(*__B); + if((_t2d == 1) && (iVertexB->_t2d != 0)) + return iVertexB->__A->getFEdge(*(iVertexB->__B)); + } + else if(__B == iVertexB->__B) + { + if((_t2d != 1) && (iVertexB->_t2d == 1)) + return __A->getFEdge(*__B); + if((_t2d == 1) && (iVertexB->_t2d != 1)) + return iVertexB->__A->getFEdge(*(iVertexB->__B)); + } + else if(__A == iVertexB->__A) + { + if((_t2d == 0) && (iVertexB->_t2d != 0)) + return iVertexB->__A->getFEdge(*(iVertexB->__B)); + if((_t2d != 0) && (iVertexB->_t2d == 0)) + return __A->getFEdge(*__B); + } + else if(__A == iVertexB->__B) + { + if((_t2d == 0) && (iVertexB->_t2d != 1)) + return iVertexB->__A->getFEdge(*(iVertexB->__B)); + if((_t2d != 0) && (iVertexB->_t2d == 1)) + return __A->getFEdge(*__B); + } + + cerr << "Warning: you should not be there..." << endl; + + return 0; +} + + + Vec3r CurvePoint::normal() const +{ + if(__B == 0) + return __A->normal(); + if(__A == 0) + return __B->normal(); + Vec3r Na = __A->normal(); + if(Exception::getException()) + Na = Vec3r(0,0,0); + Vec3r Nb = __B->normal(); + if(Exception::getException()) + Nb = Vec3r(0,0,0); + // compute t3d: + real t3d = SilhouetteGeomEngine::ImageToWorldParameter(__A->getFEdge(*__B),_t2d); + return ((1-t3d)*Na+t3d*Nb); +} + + + // Material CurvePoint::material() const + //{ + // if(__A == 0) + // return __B->material(); + // return __A->material(); + //} + + +// Id CurvePoint::shape_id() const +// { +// if(__A == 0) +// return __B->shape_id(); +// return __A->shape_id(); +// } + + + const SShape * CurvePoint::shape() const +{ + if(__A == 0) + return __B->shape(); + return __A->shape(); +} + + + +// float CurvePoint::shape_importance() const +// { + +// if(__A == 0) + +// return __B->shape_importance(); +// return __A->shape_importance(); +// } + + + // const unsigned CurvePoint::qi() const + //{ + // if(__A == 0) + // return __B->qi(); + // if(__B == 0) + // return __A->qi(); + // return __A->getFEdge(*__B)->qi(); + //} + + + occluder_container::const_iterator CurvePoint::occluders_begin() const +{ + if(__A == 0) + return __B->occluders_begin(); + if(__B == 0) + return __A->occluders_begin(); + return __A->getFEdge(*__B)->occluders_begin(); +} + + occluder_container::const_iterator CurvePoint::occluders_end() const +{ + if(__A == 0) + return __B->occluders_end(); + if(__B == 0) + return __A->occluders_end(); + return __A->getFEdge(*__B)->occluders_end(); +} + + bool CurvePoint::occluders_empty() const +{ + if(__A == 0) + return __B->occluders_empty(); + if(__B == 0) + return __A->occluders_empty(); + return __A->getFEdge(*__B)->occluders_empty(); +} + + int CurvePoint::occluders_size() const +{ + if(__A == 0) + return __B->occluders_size(); + if(__B == 0) + return __A->occluders_size(); + return __A->getFEdge(*__B)->occluders_size(); +} + + const SShape * CurvePoint::occluded_shape() const +{ + if(__A == 0) + return __B->occluded_shape(); + if(__B == 0) + return __A->occluded_shape(); + return __A->getFEdge(*__B)->occluded_shape(); +} + + const Polygon3r& CurvePoint::occludee() const +{ + if(__A == 0) + return __B->occludee(); + if(__B == 0) + return __A->occludee(); + return __A->getFEdge(*__B)->occludee(); +} + + const bool CurvePoint::occludee_empty() const +{ + if(__A == 0) + return __B->occludee_empty(); + if(__B == 0) + return __A->occludee_empty(); + return __A->getFEdge(*__B)->occludee_empty(); +} + + real CurvePoint::z_discontinuity() const +{ + if(__A == 0) + return __B->z_discontinuity(); + if(__B == 0) + return __A->z_discontinuity(); + if(__A->getFEdge(*__B) == 0) + return 0.0; + + return __A->getFEdge(*__B)->z_discontinuity(); +} +// +// float CurvePoint::local_average_depth() const +//{ +// return local_average_depth_function<CurvePoint >(this); +//} +// +// float CurvePoint::local_depth_variance() const +//{ +// return local_depth_variance_function<CurvePoint >(this); +//} +// +// real CurvePoint::local_average_density(float sigma) const +//{ +// //return local_average_density<CurvePoint >(this); +// +// return density_function<CurvePoint >(this); +//} +// Vec3r shaded_color() const ; +// +// Vec3r CurvePoint::orientation2d() const +// { +// if(__A == 0) +// return __B->orientation2d(); +// if(__B == 0) +// return __A->orientation2d(); +// return __B->point2d()-__A->point2d(); +// } +// +// Vec3r CurvePoint::orientation3d() const +// { +// if(__A == 0) +// return __B->orientation3d(); +// if(__B == 0) +// return __A->orientation3d(); +// return __B->point3d()-__A->point3d(); +// } + +// real curvature2d() const {return viewedge()->curvature2d((_VertexA->point2d()+_VertexB->point2d())/2.0);} +// +// Vec3r CurvePoint::curvature2d_as_vector() const +//{ +// // Vec3r edgeA = (_FEdges[0])->orientation2d().normalize(); +// // Vec3r edgeB = (_FEdges[1])->orientation2d().normalize(); +// // return edgeA+edgeB; +// // +// if(__A == 0) +// return __B->curvature2d_as_vector(); +// if(__B == 0) +// return __A->curvature2d_as_vector(); +// return ((1-_t2d)*__A->curvature2d_as_vector()+_t2d*__B->curvature2d_as_vector()); +//} +// +// real CurvePoint::curvature2d_as_angle() const +//{ +// // Vec3r edgeA = (_FEdges[0])->orientation2d(); +// // Vec3r edgeB = (_FEdges[1])->orientation2d(); +// // Vec2d N1(-edgeA.y(), edgeA.x());N1.normalize(); +// // Vec2d N2(-edgeB.y(), edgeB.x());N2.normalize(); +// // return acos((N1*N2)); +// +// if(__A == 0) +// return __B->curvature2d_as_angle(); +// if(__B == 0) +// return __A->curvature2d_as_angle(); +// return ((1-_t2d)*__A->curvature2d_as_angle()+_t2d*__B->curvature2d_as_angle()); +//} + + +real CurvePoint::curvatureFredo() const +{ + if(__A == 0) + return __B->curvatureFredo(); + if(__B == 0) + return __A->curvatureFredo(); + return ((1-_t2d)*__A->curvatureFredo()+_t2d*__B->curvatureFredo()); +} + +Vec2d CurvePoint::directionFredo () const +{ + if(__A == 0) + return __B->directionFredo(); + if(__B == 0) + return __A->directionFredo(); + return ((1-_t2d)*__A->directionFredo()+_t2d*__B->directionFredo()); +} + + /**********************************/ + /* */ + /* */ + /* Curve */ + /* */ + /* */ + /**********************************/ + +/* for functions */ + + +Curve::~Curve() +{ + if(!_Vertices.empty()) + { + for(vertex_container::iterator it=_Vertices.begin(), itend =_Vertices.end(); + it!=itend; + ++it) + { + delete (*it); + } + _Vertices.clear(); + } +} + +/*! iterators access */ +Curve::point_iterator Curve::points_begin(float step) +{ + vertex_container::iterator second = _Vertices.begin();++second; + return point_iterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), _nSegments, step, 0.f, 0.f); + //return point_iterator(_Vertices.begin(), second, _nSegments, step, 0.f, 0.f); +} +Curve::const_point_iterator Curve::points_begin(float step) const +{ + vertex_container::const_iterator second = _Vertices.begin();++second; + return const_point_iterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), _nSegments, step, 0.f, 0.f); + //return const_point_iterator(_Vertices.begin(), second, _nSegments, step, 0.f, 0.f); +} +Curve::point_iterator Curve::points_end(float step) +{ + return point_iterator(_Vertices.end(), _Vertices.end(), _Vertices.begin(), _Vertices.end(), _nSegments, step, 1.f, _Length); + //return point_iterator(_Vertices.end(), _Vertices.end(), _nSegments, step, 1.f, _Length); +} +Curve::const_point_iterator Curve::points_end(float step) const +{ + return const_point_iterator(_Vertices.end(), _Vertices.end(), _Vertices.begin(), _Vertices.end(), _nSegments, step, 1.f, _Length); + //return const_point_iterator(_Vertices.end(), _Vertices.end(), _nSegments, step, 1.f, _Length); +} + +// Adavnced Iterators access +Curve::point_iterator Curve::vertices_begin(){return points_begin(0);} +Curve::const_point_iterator Curve::vertices_begin() const {return points_begin(0);} +Curve::point_iterator Curve::vertices_end(){return points_end(0);} +Curve::const_point_iterator Curve::vertices_end() const {return points_end(0);} + +// specialized iterators access +CurveInternal::CurvePointIterator Curve::curvePointsBegin(float t){ + vertex_container::iterator second = _Vertices.begin();++second; + return CurveInternal::CurvePointIterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), 0, _nSegments, _Length, t, 0.f, 0.f); +} + +CurveInternal::CurvePointIterator Curve::curvePointsEnd(float t){ + vertex_container::iterator last = _Vertices.end();--last; + return CurveInternal::CurvePointIterator(last, _Vertices.end(), _Vertices.begin(), _Vertices.end(), _nSegments, _nSegments, _Length, t, 0.f, _Length); +} + +CurveInternal::CurvePointIterator Curve::curveVerticesBegin(){ + return curvePointsBegin(0); +} + +CurveInternal::CurvePointIterator Curve::curveVerticesEnd(){ + return curvePointsEnd(0); +} + +Interface0DIterator Curve::pointsBegin(float t){ + vertex_container::iterator second = _Vertices.begin();++second; + Interface0DIterator ret(new CurveInternal::CurvePointIterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), 0, _nSegments, _Length, t, 0.f, 0.f)); + return ret; +} + +Interface0DIterator Curve::pointsEnd(float t){ + vertex_container::iterator last = _Vertices.end();--last; + Interface0DIterator ret(new CurveInternal::CurvePointIterator(last, _Vertices.end(), _Vertices.begin(), _Vertices.end(), _nSegments, _nSegments, _Length, t, 0.f, _Length)); + return ret; +} + +Interface0DIterator Curve::verticesBegin(){ + return pointsBegin(0); +} + +Interface0DIterator Curve::verticesEnd(){ + return pointsEnd(0); +} + + +// Vec3r shaded_color(int iCombination = 0) const ; +// +// Vec3r Curve::orientation2d(point_iterator it) const +//{ +// return (*it)->orientation2d(); +//} +/* template <class BaseVertex> */ +/* Vec3r Curve::orientation2d(int iCombination) const */ +/* { */ +/* return edge_orientation2d_function<Curve >(this, iCombination); */ +/* } */ +// +// Vec3r Curve::orientation3d(point_iterator it) const +//{ +// return (*it)->orientation3d(); +//} +/* */ +/* Vec3r Curve::orientation3d(int iCombination) const */ +/* { */ +/* return edge_orientation3d_function<Curve >(this, iCombination); */ +/* } */ +// real curvature2d(point_iterator it) const {return (*it)->curvature2d();} +// real curvature2d(int iCombination = 0) const ; + +// Material Curve::material() const +//{ +// const_vertex_iterator v=vertices_begin(), vend=vertices_end(); +// const Material& mat = (*v)->material(); +// for(;v!=vend;++v) +// { +// if((*v)->material() != mat) +// Exception::raiseException(); +// } +// return mat; +//} + +// int Curve::qi() const +//{ +// const_vertex_iterator v=vertices_begin(), vend=vertices_end(); +// int qi_= (*v)->qi(); +// for(;v!=vend;++v) +// { +// if((*v)->qi() != qi_) +// Exception::raiseException(); +// } +// return qi_; +//} +// occluder_container::const_iterator occluders_begin() const {return _FEdgeA->occluders().begin();} +// occluder_container::const_iterator occluders_end() const {return _FEdgeA->occluders().end();} + +//int Curve::occluders_size() const +//{ +// return qi(); +//} + +// bool Curve::occluders_empty() const +//{ +// const_vertex_iterator v=vertices_begin(), vend=vertices_end(); +// bool empty = (*v)->occluders_empty(); +// for(;v!=vend;++v) +// { +// if((*v)->occluders_empty() != empty) +// Exception::raiseException(); +// } +// return empty; +//} +// const Polygon3r& occludee() const {return *(_FEdgeA->aFace());} + +// const SShape * Curve::occluded_shape() const +//{ +// const_vertex_iterator v=vertices_begin(), vend=vertices_end(); +// const SShape *sshape = (*v)->occluded_shape(); +// for(;v!=vend;++v) +// { +// if((*v)->occluded_shape() != sshape) +// Exception::raiseException(); +// } +// return sshape; +//} + + +// const bool Curve::occludee_empty() const +//{ +// const_vertex_iterator v=vertices_begin(), vend=vertices_end(); +// bool empty = (*v)->occludee_empty(); +// for(;v!=vend;++v) +// { +// if((*v)->occludee_empty() != empty) +// Exception::raiseException(); +// } +// return empty; +//} +/* */ +/* real Curve::z_discontinuity(int iCombination) const */ +/* { */ +/* return z_discontinuity_edge_function<Curve >(this, iCombination); */ +/* } */ + +// int Curve::shape_id() const +// { +// const_vertex_iterator v=vertices_begin(), vend=vertices_end(); +// Id id = (*v)->shape_id(); +// for(;v!=vend;++v) +// { +// if((*v)->shape_id() != id) +// Exception::raiseException(); +// } +// return id.first; +// } + + +// const SShape * Curve::shape() const +//{ +// const_vertex_iterator v=vertices_begin(), vend=vertices_end(); +// const SShape *sshape = (*v)->shape(); +// for(;v!=vend;++v) +// { +// if((*v)->shape() != sshape) +// Exception::raiseException(); +// } +// return sshape; +//} + + +// occluder_container::const_iterator Curve::occluders_begin() const +//{ +// const_vertex_iterator v=vertices_begin(); +// return (*v)->occluders_begin(); +//} +// +// +// occluder_container::const_iterator Curve::occluders_end() const +//{ +// const_vertex_iterator v=vertices_end(); +// return (*v)->occluders_end(); +//} + +/* */ +/* Vec3r Curve::curvature2d_as_vector(int iCombination) const */ +/* { */ +/* return curvature2d_as_vector_edge_function<Curve >(this, iCombination); */ +/* } */ +/* */ +/* real Curve::curvature2d_as_angle(int iCombination) const */ +/* { */ +/* return curvature2d_as_angle_edge_function<Curve >(this, iCombination); */ +/* } */ + +/* */ +/* float Curve::shape_importance(int iCombination) const */ +/* { */ +/* return shape_importance_edge_function<Curve >(this, iCombination); */ +/* } */ + +/* */ +/* float Curve::local_average_depth(int iCombination) const */ +/* { */ +/* return local_average_depth_edge_function<Curve >(this, iCombination); */ +/* } */ +/* */ +/* float Curve::local_depth_variance(int iCombination ) const */ +/* { */ +/* return local_depth_variance_edge_function<Curve >(this, iCombination); */ +/* // local_depth_variance_functor<Point> functor; */ +/* // float result; */ +/* // Evaluate<float, local_depth_variance_functor<Point> >(&functor, iCombination, result); */ +/* // return result; */ +/* } */ + +/* */ +/* real Curve::local_average_density(float sigma, int iCombination ) const */ +/* { */ +/* return density_edge_function<Curve >(this, iCombination); */ +/* // density_functor<Point> functor; */ +/* // real result; */ +/* // Evaluate<real, density_functor<Point> >(&functor, iCombination, result); */ +/* // return result; */ +/* } */ + +#define EPS_CURVA_DIR 0.01 + + +void Curve::computeCurvatureAndOrientation () +{ +// const_vertex_iterator v=vertices_begin(), vend=vertices_end(), v2, prevV, v0; +// Vec2d p0, p1, p2; +// Vec3r p; + +// p=(*v)->point2d(); +// p0=Vec2d(p[0], p[1]); +// prevV=v; ++v; +// p=(*v)->point2d(); +// p1=Vec2d(p[0], p[1]); +// Vec2d prevDir(p1-p0); + +// for(;v!=vend;++v) +// { +// v2=v; ++v2; +// if (v2==vend) break; +// Vec3r p2=(*v2)->point2d(); + +// Vec2d BA=p0-p1; +// Vec2d BC=p2-p1; +// real lba=BA.norm(), lbc=BC.norm(); +// BA.normalizeSafe(); +// BC.normalizeSafe(); +// Vec2d normalCurvature=BA+BC; +// Vec2d dir=Vec2d(BC-BA); +// Vec2d normal=Vec2d(-dir[1], dir[0]); + +// normal.normalizeSafe(); +// real curvature=normalCurvature*normal; +// if (lba+lbc > MY_EPSILON) +// curvature/=(0.5*lba+lbc); +// if (dir.norm() < MY_EPSILON) +// dir=0.1*prevDir; +// (*v)->setCurvatureFredo(curvature); +// (*v)->setDirectionFredo(dir); + +// prevV=v; p0=p1; p1=p2; prevDir=dir; prevDir.normalize(); +// } +// (*v)->setCurvatureFredo((*prevV)->curvatureFredo()); +// (*v)->setDirectionFredo((*v)->point2d()-(*prevV)->point2d()); +// v0=vertices_begin(); v2=v0; ++v2; +// (*v0)->setCurvatureFredo((*v2)->curvatureFredo()); +// (*v0)->setDirectionFredo((*v2)->point2d()-(*v0)->point2d()); + +// //closed curve case one day... + +// // +// return; + +// //numerical degeneracy verification.. we'll see later +// const_vertex_iterator vLastReliable=vertices_begin(); + +// v=vertices_begin(); +// p=(*v)->point2d(); +// p0=Vec2d(p[0], p[1]); +// prevV=v; ++v; +// p=(*v)->point2d(); +// p1=Vec2d(p[0], p[1]); +// bool isReliable=false; +// if ((p1-p0).norm>EPS_CURVA) +// { +// vLastReliable=v; +// isReliable=true; +// } + +// for(;v!=vend;++v) +// { +// v2=v; ++v2; +// if (v2==vend) break; +// Vec3r p2=(*v2)->point2d(); + +// Vec2d BA=p0-p1; +// Vec2d BC=p2-p1; +// real lba=BA.norm(), lbc=BC.norm(); + +// if ((lba+lbc)<EPS_CURVA) +// { +// isReliable=false; +// cerr<<"/"; +// } +// else +// { +// if (!isReliable)//previous points were not reliable +// { +// const_vertex_iterator vfix=vLastReliable; +// vfix++; +// for (; vfix!=v; ++vfix) +// { +// (*vfix)->setCurvatureFredo((*v)->curvatureFredo()); +// (*vfix)->setDirectionFredo((*v)->directionFredo()); +// } +// } +// isReliable=true; +// vLastReliable=v; +// } +// prevV=v; p0=p1; p1=p2; +// } + +} diff --git a/source/blender/freestyle/intern/stroke/Curve.h b/source/blender/freestyle/intern/stroke/Curve.h new file mode 100755 index 00000000000..60bc9815cb4 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/Curve.h @@ -0,0 +1,467 @@ +// +// Filename : Curve.h +// Author(s) : Stephane Grabli +// Purpose : Class to define a container for curves +// Date of creation : 11/01/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef CURVE_H +# define CURVE_H + +# include "../view_map/Silhouette.h" +# include <deque> +# include "../system/BaseIterator.h" +# include "../geometry/Geom.h" +//# include "../scene_graph/FrsMaterial.h" +# include "../view_map/SilhouetteGeomEngine.h" +# include "../view_map/Interface0D.h" +# include "../view_map/Interface1D.h" + +using namespace std; +using namespace Geometry; + + /**********************************/ + /* */ + /* */ + /* CurvePoint */ + /* */ + /* */ + /**********************************/ + +/*! Class to represent a point of a curve. + * A CurvePoint can be any point of a 1D curve + * (it doesn't have to be a vertex of the curve). + * Any Interface1D is built upon ViewEdges, themselves + * built upon FEdges. Therefore, a curve is basically + * a polyline made of a list SVertex. + * Thus, a CurvePoint is built by lineraly interpolating + * two SVertex. + * CurvePoint can be used as virtual points while + * querying 0D information along a curve at a given resolution. + */ +class LIB_STROKE_EXPORT CurvePoint : public Interface0D +{ +public: // Implementation of Interface0D + /*! Returns the string "CurvePoint"*/ + virtual string getExactTypeName() const { + return "CurvePoint"; + } + + // Data access methods + /*! Returns the 3D X coordinate of the point */ + virtual real getX() const { + return _Point3d.x(); + } + /*! Returns the 3D Y coordinate of the point */ + virtual real getY() const { + return _Point3d.y(); + } + /*! Returns the 3D Z coordinate of the point */ + virtual real getZ() const { + return _Point3d.z(); + } + /*! Returns the 3D point. */ + virtual Vec3f getPoint3D() const { + return _Point3d; + } + /*! Returns the projected 3D X coordinate of the point */ + virtual real getProjectedX() const { + return _Point2d.x(); + } + /*! Returns the projected 3D Y coordinate of the point */ + virtual real getProjectedY() const { + return _Point2d.y(); + } + /*! Returns the projected 3D Z coordinate of the point */ + virtual real getProjectedZ() const { + return _Point2d.z(); + } + /*! Returns the 2D point. */ + virtual Vec2f getPoint2D() const { + return Vec2f((float)_Point2d.x(),(float)_Point2d.y()); + } + + virtual FEdge* getFEdge(Interface0D& inter); + /*! Returns the CurvePoint's Id */ + virtual Id getId() const { + Id id; + if(_t2d == 0) + return __A->getId(); + else if(_t2d == 1) + return __B->getId(); + return id; + } + /*! Returns the CurvePoint's Nature */ + virtual Nature::VertexNature getNature() const { + Nature::VertexNature nature = Nature::POINT; + if(_t2d == 0) + nature |= __A->getNature(); + else if(_t2d == 1) + nature |= __B->getNature(); + return nature; + } + + /*! Cast the Interface0D in SVertex if it can be. */ + virtual SVertex * castToSVertex(){ + if(_t2d == 0) + return __A; + else if(_t2d == 1) + return __B; + return Interface0D::castToSVertex(); + } + + /*! Cast the Interface0D in ViewVertex if it can be. */ + virtual ViewVertex * castToViewVertex(){ + if(_t2d == 0) + return __A->castToViewVertex(); + else if(_t2d == 1) + return __B->castToViewVertex(); + return Interface0D::castToViewVertex(); + } + + /*! Cast the Interface0D in NonTVertex if it can be. */ + virtual NonTVertex * castToNonTVertex(){ + if(_t2d == 0) + return __A->castToNonTVertex(); + else if(_t2d == 1) + return __B->castToNonTVertex(); + return Interface0D::castToNonTVertex(); + } + + /*! Cast the Interface0D in TVertex if it can be. */ + virtual TVertex * castToTVertex(){ + if(_t2d == 0) + return __A->castToTVertex(); + else if(_t2d == 1) + return __B->castToTVertex(); + return Interface0D::castToTVertex(); + } +public: + typedef SVertex vertex_type; +protected: + SVertex *__A; + SVertex *__B; + float _t2d; + //float _t3d; + Vec3r _Point2d; + Vec3r _Point3d; +public: + /*! Defult Constructor. */ + CurvePoint(); + /*! Builds a CurvePoint from two SVertex and an interpolation + * parameter. + * \param iA + * The first SVertex + * \param iB + * The second SVertex + * \param t2d + * A 2D interpolation parameter + * used to linearly interpolate \a iA and \a iB + */ + CurvePoint(SVertex *iA, SVertex *iB, float t2d) ; + /*! Builds a CurvePoint from two CurvePoint and an interpolation parameter. + * \param iA + * The first CurvePoint + * \param iB + * The second CurvePoint + * \param t2d + * The 2D interpolation parameter used + * to linearly interpolate \a iA and \a iB. + */ + CurvePoint(CurvePoint *iA, CurvePoint *iB, float t2d) ; + // CurvePoint(SVertex *iA, SVertex *iB, float t2d, float t3d) ; + /*! Copy Constructor. */ + CurvePoint(const CurvePoint& iBrother) ; + /*! Operator = */ + CurvePoint& operator=(const CurvePoint& iBrother) ; + /*! Destructor */ + virtual ~CurvePoint() {} + /*! Operator == */ + bool operator==(const CurvePoint& b){ + return ((__A==b.__A) && (__B==b.__B) && (_t2d==b._t2d)); + } + + /* accessors */ + /*! Returns the first SVertex upon which + * the CurvePoint is built. */ + inline SVertex * A() {return __A;} + /*! Returns the second SVertex upon which + * the CurvePoint is built. */ + inline SVertex * B() {return __B;} + /*! Returns the interpolation parameter. */ + inline float t2d() const {return _t2d;} + //inline const float t3d() const {return _t3d;} + + /* modifiers */ + /*! Sets the first SVertex upon which to build + * the CurvePoint. + */ + inline void setA(SVertex *iA) {__A = iA;} + /*! Sets the second SVertex upon which to build + * the CurvePoint. + */ + inline void setB(SVertex *iB) {__B = iB;} + /*! Sets the 2D interpolation parameter to use. + */ + inline void setT2d(float t) {_t2d = t;} + //inline void SetT3d(float t) {_t3d = t;} + + /* Information access interface */ + + FEdge *fedge() ; + inline const Vec3r& point2d() const {return _Point2d;} + inline const Vec3r& point3d() const {return _Point3d;} + Vec3r normal() const ; + //FrsMaterial material() const ; + // Id shape_id() const ; + const SShape * shape() const ; + // float shape_importance() const ; + + //const unsigned qi() const ; + occluder_container::const_iterator occluders_begin() const ; + occluder_container::const_iterator occluders_end() const ; + bool occluders_empty() const ; + int occluders_size() const ; + const Polygon3r& occludee() const ; + const SShape * occluded_shape() const ; + const bool occludee_empty() const ; + real z_discontinuity() const ; + // float local_average_depth() const ; + // float local_depth_variance() const ; + // real local_average_density(float sigma = 2.3f) const ; + // Vec3r shaded_color() const ; +// Vec3r orientation2d() const ; +// Vec3r orientation3d() const ; + // // real curvature2d() const {return viewedge()->curvature2d((_VertexA->point2d()+_VertexB->point2d())/2.0);} + // Vec3r curvature2d_as_vector() const ; + // /*! angle in radians */ + // real curvature2d_as_angle() const ; + + real curvatureFredo () const; + Vec2d directionFredo () const; +}; + + + /**********************************/ + /* */ + /* */ + /* Curve */ + /* */ + /* */ + /**********************************/ + +namespace CurveInternal { + class CurvePoint_const_traits; + class CurvePoint_nonconst_traits; + template<class Traits> class __point_iterator; + class CurvePointIterator; +} // end of namespace CurveInternal + +/*! Base class for curves made of CurvePoints. + * SVertex is the type of the initial curve vertices. + * A Chain is a specialization of a Curve. + */ +class LIB_STROKE_EXPORT Curve : public Interface1D +{ +public: + typedef CurvePoint Vertex; + typedef CurvePoint Point; + typedef Point point_type; + typedef Vertex vertex_type; + typedef deque<Vertex*> vertex_container; + + /* Iterator to iterate over a vertex edges */ + + typedef CurveInternal::__point_iterator<CurveInternal::CurvePoint_nonconst_traits > point_iterator; + typedef CurveInternal::__point_iterator<CurveInternal::CurvePoint_const_traits > const_point_iterator; + typedef point_iterator vertex_iterator ; + typedef const_point_iterator const_vertex_iterator ; + +protected: + vertex_container _Vertices; + double _Length; + Id _Id; + unsigned _nSegments; // number of segments + +public: + /*! Default Constructor. */ + Curve() {_Length = 0;_Id = 0;_nSegments=0;} + /*! Builds a Curve from its id */ + Curve(const Id& id) {_Length = 0;_Id = id;_nSegments=0;} + /*! Copy Constructor. */ + Curve(const Curve& iBrother) {_Length = iBrother._Length;_Vertices = iBrother._Vertices;_Id=iBrother._Id;_nSegments=0;} + /*! Destructor. */ + virtual ~Curve() ; + /*! Returns the string "Curve" */ + virtual string getExactTypeName() const { + return "Curve"; + } + + /* + fredo's curvature storage + */ + void computeCurvatureAndOrientation (); + + /*! Adds a single vertex (CurvePoint) at the end of the Curve */ + inline void push_vertex_back(Vertex *iVertex) + { + if(!_Vertices.empty()) + { + Vec3r vec_tmp(iVertex->point2d() - _Vertices.back()->point2d()); + _Length += vec_tmp.norm(); + ++_nSegments; + } + Vertex * new_vertex = new Vertex(*iVertex); + _Vertices.push_back(new_vertex); + } + /*! Adds a single vertex (SVertex) at the end of the Curve */ + inline void push_vertex_back(SVertex *iVertex) + { + if(!_Vertices.empty()) + { + Vec3r vec_tmp(iVertex->point2d() - _Vertices.back()->point2d()); + _Length += vec_tmp.norm(); + ++_nSegments; + } + Vertex *new_vertex = new Vertex(iVertex, 0,0); + _Vertices.push_back(new_vertex); + } + /*! Adds a single vertex (CurvePoint) at the front of the Curve */ + inline void push_vertex_front(Vertex *iVertex) + { + if(!_Vertices.empty()) + { + Vec3r vec_tmp(iVertex->point2d() - _Vertices.front()->point2d()); + _Length += vec_tmp.norm(); + ++_nSegments; + } + Vertex * new_vertex = new Vertex(*iVertex); + _Vertices.push_front(new_vertex); + } + /*! Adds a single vertex (SVertex) at the front of the Curve */ + inline void push_vertex_front(SVertex *iVertex) + { + if(!_Vertices.empty()) + { + Vec3r vec_tmp(iVertex->point2d() - _Vertices.front()->point2d()); + _Length += vec_tmp.norm(); + ++_nSegments; + } + Vertex *new_vertex = new Vertex(iVertex, 0,0); + _Vertices.push_front(new_vertex); + } + /*! Returns true is the Curve doesn't have any Vertex yet. */ + inline bool empty() const {return _Vertices.empty();} + /*! Returns the 2D length of the Curve.*/ + inline real getLength2D() const {return _Length;} + /*! Returns the Id of the 1D element .*/ + virtual Id getId() const { + return _Id; + } + /*! Returns the number of segments in the + * oplyline constituing the Curve. + */ + inline unsigned int nSegments() const {return _nSegments;} + + inline void setId(const Id& id){_Id = id;} + /* Information access interface */ + + + //inline Vec3r shaded_color(int iCombination = 0) const ; + // inline Vec3r orientation2d(point_iterator it) const ; + //Vec3r orientation2d(int iCombination = 0) const ; + // Vec3r orientation3d(point_iterator it) const ; + //Vec3r orientation3d(int iCombination = 0) const ; + // real curvature2d(point_iterator it) const {return (*it)->curvature2d();} + // real curvature2d(int iCombination = 0) const ; + //FrsMaterial material() const ; + //int qi() const ; + // occluder_container::const_iterator occluders_begin() const ; + // occluder_container::const_iterator occluders_end() const ; + //int occluders_size() const; + //bool occluders_empty() const ; + // const Polygon3r& occludee() const {return *(_FEdgeA->aFace());} + //const SShape * occluded_shape() const; + //const bool occludee_empty() const ; + //real z_discontinuity(int iCombination = 0) const ; + // int shape_id() const ; + //const SShape * shape() const ; + //float shape_importance(int iCombination=0) const ; + //float local_average_depth(int iCombination = 0) const; + //float local_depth_variance(int iCombination = 0) const ; + //real local_average_density(float sigma = 2.3f, int iCombination = 0) const ; + //Vec3r curvature2d_as_vector(int iCombination=0) const ; + /*! angle in radians */ + //real curvature2d_as_angle(int iCombination=0) const ; + + /* advanced iterators access */ + point_iterator points_begin(float step = 0); + const_point_iterator points_begin(float step = 0) const; + point_iterator points_end(float step = 0); + const_point_iterator points_end(float step = 0) const; + + // methods given for convenience */ + point_iterator vertices_begin(); + const_point_iterator vertices_begin() const; + point_iterator vertices_end(); + const_point_iterator vertices_end() const; + + // specialized iterators access + CurveInternal::CurvePointIterator curvePointsBegin(float t=0.f); + CurveInternal::CurvePointIterator curvePointsEnd(float t=0.f); + + CurveInternal::CurvePointIterator curveVerticesBegin(); + CurveInternal::CurvePointIterator curveVerticesEnd(); + + // Iterators access + /*! Returns an Interface0DIterator pointing onto + * the first vertex of the Curve and that can iterate + * over the \a vertices of the Curve. + */ + virtual Interface0DIterator verticesBegin(); + /*! Returns an Interface0DIterator pointing after + * the last vertex of the Curve and that can iterate + * over the \a vertices of the Curve. + */ + virtual Interface0DIterator verticesEnd(); + /*! Returns an Interface0DIterator pointing onto + * the first point of the Curve and that can iterate + * over the \a points of the Curve at any resolution. + * At each iteration a virtual temporary CurvePoint + * is created. + */ + virtual Interface0DIterator pointsBegin(float t=0.f); + /*! Returns an Interface0DIterator pointing after + * the last point of the Curve and that can iterate + * over the \a points of the Curve at any resolution. + * At each iteration a virtual temporary CurvePoint + * is created. + */ + virtual Interface0DIterator pointsEnd(float t=0.f); +}; + + + +#endif diff --git a/source/blender/freestyle/intern/stroke/CurveAdvancedIterators.h b/source/blender/freestyle/intern/stroke/CurveAdvancedIterators.h new file mode 100755 index 00000000000..dfc9f2719f8 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/CurveAdvancedIterators.h @@ -0,0 +1,378 @@ +// +// Filename : CurveAdvancedIterators.h +// Author(s) : Stephane Grabli +// Purpose : Iterators used to iterate over the elements of the Curve +// Can't be used in python +// Date of creation : 01/08/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef ADVANCEDCURVEITERATORS_H +# define ADVANCEDCURVEITERATORS_H + +# include "Stroke.h" + +namespace CurveInternal { + + class CurvePoint_const_traits : public Const_traits<CurvePoint*> { + public: + typedef deque<CurvePoint*> vertex_container; + typedef vertex_container::const_iterator vertex_container_iterator; + typedef SVertex vertex_type; + }; + + class CurvePoint_nonconst_traits : public Nonconst_traits<CurvePoint*> { + public: + typedef deque<CurvePoint*> vertex_container; + typedef vertex_container::iterator vertex_container_iterator ; + typedef SVertex vertex_type; + }; + + /**********************************/ + /* */ + /* */ + /* CurvePoint Iterator */ + /* */ + /* */ + /**********************************/ + + + /*! iterator on a curve. Allows an iterating outside + * initial vertices. A CurvePoint is instanciated an returned + * when the iterator is dereferenced. + */ + + template<class Traits> + class __point_iterator : public IteratorBase<Traits, BidirectionalIteratorTag_Traits> + { + public: + typedef __point_iterator <Traits> Self; + typedef typename Traits::vertex_container_iterator vertex_container_iterator; + typedef typename Traits::vertex_type vertex_type; + typedef CurvePoint Point; + typedef Point point_type; + + typedef __point_iterator<CurvePoint_nonconst_traits > iterator; + typedef __point_iterator<CurvePoint_const_traits > const_iterator; + + // public: + // typedef Vertex vertex_type ; + // typedef vertex_container_iterator vertex_iterator_type; + // typedef CurvePoint<Vertex> Point; + // typedef Point point_type; + typedef IteratorBase<Traits,BidirectionalIteratorTag_Traits> parent_class; + //# if defined(__GNUC__) && (__GNUC__ < 3) + // typedef bidirectional_iterator<CurvePoint<Vertex>,ptrdiff_t> bidirectional_point_iterator; + //# else + // typedef iterator<bidirectional_iterator_tag, CurvePoint<Vertex>,ptrdiff_t> bidirectional_point_iterator; + //# endif + friend class Curve; + //friend class Curve::vertex_iterator; + //friend class __point_iterator<CurvePoint_nonconst_traits >; + //friend class iterator; + //protected: + public: + float _CurvilinearLength; + float _step; + vertex_container_iterator __A; + vertex_container_iterator __B; + vertex_container_iterator _begin; + vertex_container_iterator _end; + int _n; + int _currentn; + float _t; + mutable Point *_Point; + + public: + + public: + inline __point_iterator(float step = 0.f) + : parent_class() + { + _step = step; + _CurvilinearLength = 0.f; + _t = 0.f; + _Point = 0; + _n = 0; + _currentn = 0; + } + + inline __point_iterator(const iterator& iBrother) + : parent_class() + { + __A = iBrother.__A; + __B = iBrother.__B; + _begin = iBrother._begin; + _end = iBrother._end; + _CurvilinearLength = iBrother._CurvilinearLength; + _step = iBrother._step; + _t = iBrother._t; + if(iBrother._Point == 0) + _Point = 0; + else + _Point = new Point(*(iBrother._Point)); + _n = iBrother._n; + _currentn = iBrother._currentn; + } + inline __point_iterator(const const_iterator& iBrother) + : parent_class() + { + __A = iBrother.__A; + __B = iBrother.__B; + _begin = iBrother._begin; + _end = iBrother._end; + _CurvilinearLength = iBrother._CurvilinearLength; + _step = iBrother._step; + _t = iBrother._t; + if(iBrother._Point == 0) + _Point = 0; + else + _Point = new Point(*(iBrother._Point)); + _n = iBrother._n; + _currentn = iBrother._currentn; + } + inline Self& operator=(const Self& iBrother) + { + //((bidirectional_point_iterator*)this)->operator=(iBrother); + __A = iBrother.__A; + __B = iBrother.__B; + _begin = iBrother._begin; + _end = iBrother._end; + _CurvilinearLength = iBrother._CurvilinearLength; + _step = iBrother._step; + _t = iBrother._t; + if(iBrother._Point == 0) + _Point = 0; + else + _Point = new Point(*(iBrother._Point)); + _n = iBrother._n; + _currentn = iBrother._currentn; + return *this; + } + virtual ~__point_iterator() + { + if(_Point != 0) + delete _Point; + } + //protected://FIXME + public: + inline __point_iterator(vertex_container_iterator iA, + vertex_container_iterator iB, + vertex_container_iterator ibegin, + vertex_container_iterator iend, + int currentn, + int n, + float step, float t=0.f, float iCurvilinearLength = 0.f) + : parent_class() + { + __A = iA; + __B = iB; + _begin = ibegin; + _end = iend; + _CurvilinearLength = iCurvilinearLength; + _step = step; + _t = t; + _Point = 0; + _n = n; + _currentn = currentn; + } + + public: + + // operators + inline Self& operator++() // operator corresponding to ++i + { + increment(); + return *this; + } + inline Self operator++(int) // opérateur correspondant à i++ + { // c.a.d qui renvoie la valeur *puis* incrémente. + Self tmp = *this; // C'est pour cela qu'on stocke la valeur + increment(); // dans un temporaire. + return tmp; + } + inline Self& operator--() // operator corresponding to ++i + { + decrement(); + return *this; + } + inline Self operator--(int) // opérateur correspondant à i++ + { // c.a.d qui renvoie la valeur *puis* incrémente. + Self tmp = *this; // C'est pour cela qu'on stocke la valeur + decrement(); // dans un temporaire. + return tmp; + } + + // comparibility + virtual bool operator!=(const Self& b) const + { + return ((__A!=b.__A) || (__B!=b.__B) || (_t != b._t)); + } + virtual bool operator==(const Self& b) const + { + return !(*this != b); + } + + // dereferencing + virtual typename Traits::reference operator*() const + { + if(_Point != 0) + { + delete _Point; + _Point = 0; + } + if((_currentn < 0) || (_currentn >= _n)) + return _Point; // 0 in this case + return (_Point = new Point(*__A,*__B,_t)); + } + virtual typename Traits::pointer operator->() const { return &(operator*());} + + public: + virtual bool begin() const + { + if((__A == _begin) && (_t < (float)M_EPSILON)) + return true; + return false; + } + virtual bool end() const + { + if((__B == _end)) + return true; + return false; + } + protected: + virtual void increment() + { + if(_Point != 0) + { + delete _Point; + _Point = 0; + } + if((_currentn == _n-1) && (_t == 1.f)) + { + // we're setting the iterator to end + ++__A; + ++__B; + ++_currentn; + _t = 0.f; + return; + } + + if(0 == _step) // means we iterate over initial vertices + { + Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d()); + _CurvilinearLength += vec_tmp.norm(); + if(_currentn == _n-1) + { + _t = 1.f; + return; + } + ++__B; + ++__A; + ++_currentn; + return; + } + + // compute the new position: + Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d()); + float normAB = vec_tmp2.norm(); + + if(normAB > M_EPSILON) + { + _CurvilinearLength += _step; + _t = _t + _step/normAB; + } + else + _t = 1.f; // AB is a null segment, we're directly at its end + //if normAB ~= 0, we don't change these values + if(_t >= 1) + { + _CurvilinearLength -= normAB*(_t-1); + if(_currentn == _n-1) + _t=1.f; + else + { + _t = 0.f; + ++_currentn; + ++__A;++__B; + } + } + } + virtual void decrement() + { + if(_Point != 0) + { + delete _Point; + _Point = 0; + } + + if(_t == 0.f) //we're at the beginning of the edge + { + _t = 1.f; + --_currentn; + --__A; --__B; + if(_currentn == _n-1) + return; + } + + if(0 == _step) // means we iterate over initial vertices + { + Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d()); + _CurvilinearLength -= vec_tmp.norm(); + _t = 0; + return; + } + + // compute the new position: + Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d()); + float normAB = vec_tmp2.norm(); + + if(normAB >M_EPSILON) + { + _CurvilinearLength -= _step; + _t = _t - _step/normAB; + } + else + _t = -1.f; // We just need a negative value here + + // round value + if(fabs(_t) < (float)M_EPSILON) + _t = 0.0; + if(_t < 0) + { + if(_currentn == 0) + _CurvilinearLength = 0.f; + else + _CurvilinearLength += normAB*(-_t); + _t = 0.f; + } + } + }; + + + +} // end of namespace StrokeInternal + + +#endif // ADVANCEDCURVEITERATORS_H diff --git a/source/blender/freestyle/intern/stroke/CurveIterators.h b/source/blender/freestyle/intern/stroke/CurveIterators.h new file mode 100755 index 00000000000..a45ef4bfdaf --- /dev/null +++ b/source/blender/freestyle/intern/stroke/CurveIterators.h @@ -0,0 +1,299 @@ +// +// Filename : CurveIterators.h +// Author(s) : Stephane Grabli +// Purpose : Iterators used to iterate over the elements of the Curve +// Date of creation : 01/08/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef CURVEITERATORS_H +# define CURVEITERATORS_H + +#include "Stroke.h" +#include "Curve.h" + +namespace CurveInternal { + + /*! iterator on a curve. Allows an iterating outside + * initial vertices. A CurvePoint is instanciated an returned + * when the iterator is dereferenced. + */ + + class CurvePointIterator : public Interface0DIteratorNested + { + public: + friend class ::Curve; + public: + float _CurvilinearLength; + float _step; + ::Curve::vertex_container::iterator __A; + ::Curve::vertex_container::iterator __B; + ::Curve::vertex_container::iterator _begin; + ::Curve::vertex_container::iterator _end; + int _n; + int _currentn; + float _t; + mutable CurvePoint _Point; + float _CurveLength; + + public: + + public: + inline CurvePointIterator(float step = 0.f) + : Interface0DIteratorNested() + { + _step = step; + _CurvilinearLength = 0.f; + _t = 0.f; + //_Point = 0; + _n = 0; + _currentn = 0; + _CurveLength=0; + } + + inline CurvePointIterator(const CurvePointIterator& iBrother) + : Interface0DIteratorNested() + { + __A = iBrother.__A; + __B = iBrother.__B; + _begin = iBrother._begin; + _end = iBrother._end; + _CurvilinearLength = iBrother._CurvilinearLength; + _step = iBrother._step; + _t = iBrother._t; + _Point = iBrother._Point; + _n = iBrother._n; + _currentn = iBrother._currentn; + _CurveLength = iBrother._CurveLength; + } + inline CurvePointIterator& operator=(const CurvePointIterator& iBrother) + { + __A = iBrother.__A; + __B = iBrother.__B; + _begin = iBrother._begin; + _end = iBrother._end; + _CurvilinearLength = iBrother._CurvilinearLength; + _step = iBrother._step; + _t = iBrother._t; + _Point = iBrother._Point; + _n = iBrother._n; + _currentn = iBrother._currentn; + _CurveLength = iBrother._CurveLength; + return *this; + } + virtual ~CurvePointIterator() + { + } + protected: + inline CurvePointIterator(::Curve::vertex_container::iterator iA, + ::Curve::vertex_container::iterator iB, + ::Curve::vertex_container::iterator ibegin, + ::Curve::vertex_container::iterator iend, + int currentn, + int n, + float iCurveLength, + float step, float t=0.f, float iCurvilinearLength = 0.f) + : Interface0DIteratorNested() + { + __A = iA; + __B = iB; + _begin = ibegin; + _end = iend; + _CurvilinearLength = iCurvilinearLength; + _step = step; + _t = t; + _n = n; + _currentn = currentn; + _CurveLength = iCurveLength; + } + + public: + + virtual CurvePointIterator* copy() const { + return new CurvePointIterator(*this); + } + + inline Interface0DIterator castToInterface0DIterator() const{ + Interface0DIterator ret(new CurveInternal::CurvePointIterator(*this)); + return ret; + } + virtual string getExactTypeName() const { + return "CurvePointIterator"; + } + + // operators + inline CurvePointIterator& operator++() // operator corresponding to ++i + { + increment(); + return *this; + } + + inline CurvePointIterator& operator--() // operator corresponding to ++i + { + decrement(); + return *this; + } + + // comparibility + virtual bool operator==(const Interface0DIteratorNested& b) const + { + const CurvePointIterator* it_exact = dynamic_cast<const CurvePointIterator*>(&b); + if (!it_exact) + return false; + return ((__A==it_exact->__A) && (__B==it_exact->__B) && (_t == it_exact->_t)); + } + + // dereferencing + virtual CurvePoint& operator*() + { + return (_Point = CurvePoint(*__A,*__B,_t)); + } + virtual CurvePoint* operator->() { return &(operator*());} + public: + virtual bool isBegin() const + { + if((__A == _begin) && (_t < (float)M_EPSILON)) + return true; + return false; + } + virtual bool isEnd() const + { + if(__B == _end) + return true; + return false; + } + +// protected: + + virtual int increment() + { + if((_currentn == _n-1) && (_t == 1.f)) + { + // we're setting the iterator to end + ++__A; + ++__B; + ++_currentn; + _t = 0.f; + return 0; + } + + if(0 == _step) // means we iterate over initial vertices + { + Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d()); + _CurvilinearLength += (float)vec_tmp.norm(); + if(_currentn == _n-1) + { + _t = 1.f; + return 0; + } + ++__B; + ++__A; + ++_currentn; + return 0; + } + + // compute the new position: + Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d()); + float normAB = (float)vec_tmp2.norm(); + + if(normAB > M_EPSILON) + { + _CurvilinearLength += _step; + _t = _t + _step/normAB; + } + else + _t = 1.f; // AB is a null segment, we're directly at its end + //if normAB ~= 0, we don't change these values + if(_t >= 1) + { + _CurvilinearLength -= normAB*(_t-1); + if(_currentn == _n-1) + _t=1.f; + else + { + _t = 0.f; + ++_currentn; + ++__A;++__B; + } + } + return 0; + } + virtual int decrement() + { + if(_t == 0.f) //we're at the beginning of the edge + { + _t = 1.f; + --_currentn; + --__A; --__B; + if(_currentn == _n-1) + return 0; + } + + if(0 == _step) // means we iterate over initial vertices + { + Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d()); + _CurvilinearLength -= (float)vec_tmp.norm(); + _t = 0; + return 0; + } + + // compute the new position: + Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d()); + float normAB = (float)vec_tmp2.norm(); + + if(normAB >M_EPSILON) + { + _CurvilinearLength -= _step; + _t = _t - _step/normAB; + } + else + _t = -1.f; // We just need a negative value here + + // round value + if(fabs(_t) < (float)M_EPSILON) + _t = 0.0; + if(_t < 0) + { + if(_currentn == 0) + _CurvilinearLength = 0.f; + else + _CurvilinearLength += normAB*(-_t); + _t = 0.f; + } + return 0; + } + + virtual float t() const{ + return _CurvilinearLength; + } + virtual float u() const{ + return _CurvilinearLength/_CurveLength; + } + }; + + + +} // end of namespace StrokeInternal + +#endif // CURVEITERATORS_H diff --git a/source/blender/freestyle/intern/stroke/Modifiers.h b/source/blender/freestyle/intern/stroke/Modifiers.h new file mode 100755 index 00000000000..21bebebc6f8 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/Modifiers.h @@ -0,0 +1,71 @@ +// +// Filename : Modifiers.h +// Author : Stephane Grabli +// Purpose : modifiers... +// Date of creation : 05/01/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef MODIFIERS_H +# define MODIFIERS_H + +# include "TimeStamp.h" + +/* ----------------------------------------- * + * * + * modifiers * + * * + * ----------------------------------------- */ +/*! Base class for modifiers. + * Modifiers are used in the + * Operators in order to "mark" + * the processed Interface1D. + */ +template<class Edge> +struct EdgeModifier : public unary_function<Edge,void> +{ + /*! Default construction */ + EdgeModifier() : unary_function<Edge,void>() {} + /*! the () operator */ + virtual void operator()(Edge& iEdge) {} +}; + +/*! Modifier that sets the time stamp + * of an Interface1D to the time stamp + * of the system. + */ +template<class Edge> +struct TimestampModifier : public EdgeModifier<Edge> +{ + /*! Default constructor */ + TimestampModifier() : EdgeModifier<Edge>() {} + /*! The () operator. */ + virtual void operator()(Edge& iEdge) + { + TimeStamp *timestamp = TimeStamp::instance(); + iEdge.setTimeStamp(timestamp->getTimeStamp()); + } +}; + +#endif // MODIFIERS_H diff --git a/source/blender/freestyle/intern/stroke/Module.h b/source/blender/freestyle/intern/stroke/Module.h new file mode 100755 index 00000000000..591bb157392 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/Module.h @@ -0,0 +1,72 @@ +// +// Filename : Module.h +// Author(s) : Emmanuel Turquin +// Purpose : Set the type of the module +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef MODULE_H +# define MODULE_H + +# include "Canvas.h" +# include "StyleModule.h" + +class Module +{ +public: + + static void setAlwaysRefresh(bool b = true) { + getCurrentStyleModule()->setAlwaysRefresh(b); + } + + static void setCausal(bool b = true) { + getCurrentStyleModule()->setCausal(b); + } + + static void setDrawable(bool b = true) { + getCurrentStyleModule()->setDrawable(b); + } + + static bool getAlwaysRefresh() { + return getCurrentStyleModule()->getAlwaysRefresh(); + } + + static bool getCausal() { + return getCurrentStyleModule()->getCausal(); + } + + static bool getDrawable() { + return getCurrentStyleModule()->getDrawable(); + } + +private: + + static StyleModule* getCurrentStyleModule() { + Canvas* canvas = Canvas::getInstance(); + return canvas->getCurrentStyleModule(); + } +}; + +#endif // MODULE_H diff --git a/source/blender/freestyle/intern/stroke/Operators.cpp b/source/blender/freestyle/intern/stroke/Operators.cpp new file mode 100755 index 00000000000..ea996c67785 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/Operators.cpp @@ -0,0 +1,1040 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "Operators.h" +#include <algorithm> +#include <stdexcept> +#include "Canvas.h" +#include "Stroke.h" + +LIB_STROKE_EXPORT Operators::I1DContainer Operators::_current_view_edges_set; +LIB_STROKE_EXPORT Operators::I1DContainer Operators::_current_chains_set; +LIB_STROKE_EXPORT Operators::I1DContainer* Operators::_current_set = NULL; +LIB_STROKE_EXPORT Operators::StrokesContainer Operators::_current_strokes_set; + +int Operators::select(UnaryPredicate1D& pred) { + if (!_current_set) + return 0; + if(_current_set->empty()) + return 0; + I1DContainer new_set; + I1DContainer rejected; + Functions1D::ChainingTimeStampF1D cts; + Functions1D::TimeStampF1D ts; + I1DContainer::iterator it = _current_set->begin(); + I1DContainer::iterator itbegin = it; + while (it != _current_set->end()) { + Interface1D * i1d = *it; + cts(*i1d); // mark everyone's chaining time stamp anyway + if(pred(*i1d) < 0){ + new_set.clear(); + rejected.clear(); + return -1; + } + if(pred.result){ + new_set.push_back(i1d); + ts(*i1d); + }else{ + rejected.push_back(i1d); + } + ++it; + } + if((*itbegin)->getExactTypeName() != "ViewEdge"){ + for (it = rejected.begin(); + it != rejected.end(); + ++it) + delete *it; + } + rejected.clear(); + _current_set->clear(); + *_current_set = new_set; + return 0; +} + + +int Operators::chain(ViewEdgeInternal::ViewEdgeIterator& it, + UnaryPredicate1D& pred, + UnaryFunction1D_void& modifier) { + if (_current_view_edges_set.empty()) + return 0; + + unsigned id = 0; + ViewEdge* edge; + //soc unused - Chain* new_chain; + + for (I1DContainer::iterator it_edge = _current_view_edges_set.begin(); + it_edge != _current_view_edges_set.end(); + ++it_edge) { + if (pred(**it_edge) < 0) + return -1; + if (pred.result) + continue; + + edge = dynamic_cast<ViewEdge*>(*it_edge); + it.setBegin(edge); + it.setCurrentEdge(edge); + + Chain* new_chain = new Chain(id);++id; + for (;;) { + new_chain->push_viewedge_back(*it, it.getOrientation()); + if (modifier(**it) < 0) { + delete new_chain; + return -1; + } + ++it; + if (it.isEnd()) + break; + if (pred(**it) < 0) { + delete new_chain; + return -1; + } + if (pred.result) + break; + } + + _current_chains_set.push_back(new_chain); + } + + if (!_current_chains_set.empty()) + _current_set = &_current_chains_set; + return 0; +} + + +int Operators::chain(ViewEdgeInternal::ViewEdgeIterator& it, + UnaryPredicate1D& pred) { + if (_current_view_edges_set.empty()) + return 0; + + unsigned id = 0; + Functions1D::IncrementChainingTimeStampF1D ts; + Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp()+1); + + ViewEdge* edge; + //soc Chain* new_chain; + + for (I1DContainer::iterator it_edge = _current_view_edges_set.begin(); + it_edge != _current_view_edges_set.end(); + ++it_edge) { + if (pred(**it_edge) < 0) + return -1; + if (pred.result) + continue; + if (pred_ts(**it_edge) < 0) + return -1; + if (pred_ts.result) + continue; + + edge = dynamic_cast<ViewEdge*>(*it_edge); + it.setBegin(edge); + it.setCurrentEdge(edge); + + Chain* new_chain = new Chain(id);++id; + for (;;) { + new_chain->push_viewedge_back(*it, it.getOrientation()); + ts(**it); + ++it; + if (it.isEnd()) + break; + if (pred(**it) < 0) { + delete new_chain; + return -1; + } + if (pred.result) + break; + if (pred_ts(**it) < 0) { + delete new_chain; + return -1; + } + if (pred_ts.result) + break; + } + + _current_chains_set.push_back(new_chain); + } + + if (!_current_chains_set.empty()) + _current_set = &_current_chains_set; + return 0; +} + + +//void Operators::bidirectionalChain(ViewEdgeIterator& it, +// UnaryPredicate1D& pred, +// UnaryFunction1D_void& modifier) { +// if (_current_view_edges_set.empty()) +// return; +// +// unsigned id = 0; +// ViewEdge* edge; +// Chain* new_chain; +// +// for (I1DContainer::iterator it_edge = _current_view_edges_set.begin(); +// it_edge != _current_view_edges_set.end(); +// ++it_edge) { +// if (pred(**it_edge)) +// continue; +// +// edge = dynamic_cast<ViewEdge*>(*it_edge); +// it.setBegin(edge); +// it.setCurrentEdge(edge); +// +// Chain* new_chain = new Chain(id);++id; +// //ViewEdgeIterator it_back(it);--it_back; // FIXME +// do { +// new_chain->push_viewedge_back(*it, it.getOrientation()); +// modifier(**it); +// ++it; +// } while (!it.isEnd() && !pred(**it)); +// it.setBegin(edge); +// it.setCurrentEdge(edge); +// --it; +// while (!it.isEnd() && !pred(**it)) { +// new_chain->push_viewedge_front(*it, it.getOrientation()); +// modifier(**it); +// --it; +// } +// +// _current_chains_set.push_back(new_chain); +// } +// +// if (!_current_chains_set.empty()) +// _current_set = &_current_chains_set; +//} +// +//void Operators::bidirectionalChain(ViewEdgeIterator& it, +// UnaryPredicate1D& pred) { +// if (_current_view_edges_set.empty()) +// return; +// +// unsigned id = 0; +// Functions1D::IncrementChainingTimeStampF1D ts; +// Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp()+1); +// +// ViewEdge* edge; +// Chain* new_chain; +// +// for (I1DContainer::iterator it_edge = _current_view_edges_set.begin(); +// it_edge != _current_view_edges_set.end(); +// ++it_edge) { +// if (pred(**it_edge) || pred_ts(**it_edge)) +// continue; +// +// edge = dynamic_cast<ViewEdge*>(*it_edge); +// it.setBegin(edge); +// it.setCurrentEdge(edge); + // + // Chain* new_chain = new Chain(id);++id; + // //ViewEdgeIterator it_back(it);--it_back;//FIXME + // do { + // new_chain->push_viewedge_back(*it, it.getOrientation()); + // ts(**it); + // ++it; + // } while (!it.isEnd() && !pred(**it) && !pred_ts(**it)); + // it.setBegin(edge); + // it.setCurrentEdge(edge); + // --it; + // while (!it.isEnd() && !pred(**it) && !pred_ts(**it)) { + // new_chain->push_viewedge_front(*it, it.getOrientation()); + // ts(**it); + // --it; + // } + // + // _current_chains_set.push_back(new_chain); + // } + // + // if (!_current_chains_set.empty()) + // _current_set = &_current_chains_set; + //} + +int Operators::bidirectionalChain(ChainingIterator& it, UnaryPredicate1D& pred) { + if (_current_view_edges_set.empty()) + return 0; + + unsigned id = 0; + Functions1D::IncrementChainingTimeStampF1D ts; + Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp()+1); + + ViewEdge* edge; + //soc unused - Chain* new_chain; + + for (I1DContainer::iterator it_edge = _current_view_edges_set.begin(); + it_edge != _current_view_edges_set.end(); + ++it_edge) { + if (pred(**it_edge) < 0) + return -1; + if (pred.result) + continue; + if (pred_ts(**it_edge) < 0) + return -1; + if (pred_ts.result) + continue; + + edge = dynamic_cast<ViewEdge*>(*it_edge); + // re-init iterator + it.setBegin(edge); + it.setCurrentEdge(edge); + it.setOrientation(true); + if (it.init() < 0) + return -1; + + Chain* new_chain = new Chain(id);++id; + //ViewEdgeIterator it_back(it);--it_back;//FIXME + for (;;) { + new_chain->push_viewedge_back(*it, it.getOrientation()); + ts(**it); + if (it.increment() < 0) { // FIXME + delete new_chain; + return -1; + } + if (it.isEnd()) + break; + if (pred(**it) < 0) { + delete new_chain; + return -1; + } + if (pred.result) + break; + } + it.setBegin(edge); + it.setCurrentEdge(edge); + it.setOrientation(true); + if (it.decrement() < 0) { // FIXME + delete new_chain; + return -1; + } + while (!it.isEnd()) { + if (pred(**it) < 0) { + delete new_chain; + return -1; + } + if (pred.result) + break; + new_chain->push_viewedge_front(*it, it.getOrientation()); + ts(**it); + if (it.decrement() < 0) { // FIXME + delete new_chain; + return -1; + } + } + _current_chains_set.push_back(new_chain); + } + + if (!_current_chains_set.empty()) + _current_set = &_current_chains_set; + return 0; +} + +int Operators::bidirectionalChain(ChainingIterator& it) { + if (_current_view_edges_set.empty()) + return 0; + + unsigned id = 0; + Functions1D::IncrementChainingTimeStampF1D ts; + Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp()+1); + + ViewEdge* edge; + //soc unused - Chain* new_chain; + + for (I1DContainer::iterator it_edge = _current_view_edges_set.begin(); + it_edge != _current_view_edges_set.end(); + ++it_edge) { + if (pred_ts(**it_edge) < 0) + return -1; + if (pred_ts.result) + continue; + + edge = dynamic_cast<ViewEdge*>(*it_edge); + // re-init iterator + it.setBegin(edge); + it.setCurrentEdge(edge); + it.setOrientation(true); + if (it.init() < 0) + return -1; + + Chain* new_chain = new Chain(id);++id; + //ViewEdgeIterator it_back(it);--it_back;//FIXME + do { + new_chain->push_viewedge_back(*it, it.getOrientation()); + ts(**it); + if (it.increment() < 0) { // FIXME + delete new_chain; + return -1; + } + } while (!it.isEnd()); + it.setBegin(edge); + it.setCurrentEdge(edge); + it.setOrientation(true); + if (it.decrement() < 0) { // FIXME + delete new_chain; + return -1; + } + while (!it.isEnd()) { + new_chain->push_viewedge_front(*it, it.getOrientation()); + ts(**it); + if (it.decrement() < 0) { // FIXME + delete new_chain; + return -1; + } + } + _current_chains_set.push_back(new_chain); + } + + if (!_current_chains_set.empty()) + _current_set = &_current_chains_set; + return 0; +} + +int Operators::sequentialSplit(UnaryPredicate0D& pred, + float sampling) +{ + if (_current_chains_set.empty()) { + cerr << "Warning: current set empty" << endl; + return 0; + } + CurvePoint *point; + Chain * new_curve; + I1DContainer splitted_chains; + Interface0DIterator first; + Interface0DIterator end; + Interface0DIterator last; + Interface0DIterator it; + I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end(); + for (; + cit != citend; + ++cit) { + + Id currentId = (*cit)->getId(); + new_curve = new Chain(currentId); + first = (*cit)->pointsBegin(sampling); + end = (*cit)->pointsEnd(sampling); + last = end;--last; + it = first; + + point = dynamic_cast<CurvePoint*>(&(*it)); + new_curve->push_vertex_back(point);++it; + for(; it!= end; ++it) + { + point = dynamic_cast<CurvePoint*>(&(*it)); + new_curve->push_vertex_back(point); + if(pred(it) < 0) + { + delete new_curve; + goto error; + } + if(pred.result && (it!=last)) + { + splitted_chains.push_back(new_curve); + currentId.setSecond(currentId.getSecond()+1); + new_curve = new Chain(currentId); + new_curve->push_vertex_back(point); + } + } + if(new_curve->nSegments() == 0){ + delete new_curve; + return 0; + } + + splitted_chains.push_back(new_curve); + } + + // Update the current set of chains: + cit = _current_chains_set.begin(); + for(; + cit != citend; + ++cit){ + delete (*cit); + } + _current_chains_set.clear(); + _current_chains_set = splitted_chains; + splitted_chains.clear(); + + if (!_current_chains_set.empty()) + _current_set = &_current_chains_set; + return 0; + +error: + cit = splitted_chains.begin(); + citend = splitted_chains.end(); + for(; + cit != citend; + ++cit){ + delete (*cit); + } + splitted_chains.clear(); + return -1; +} + +int Operators::sequentialSplit(UnaryPredicate0D& startingPred, UnaryPredicate0D& stoppingPred, + float sampling) +{ + if (_current_chains_set.empty()) { + cerr << "Warning: current set empty" << endl; + return 0; + } + CurvePoint *point; + Chain * new_curve; + I1DContainer splitted_chains; + Interface0DIterator first; + Interface0DIterator end; + Interface0DIterator last; + Interface0DIterator itStart; + Interface0DIterator itStop; + I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end(); + for (; + cit != citend; + ++cit) { + Id currentId = (*cit)->getId(); + first = (*cit)->pointsBegin(sampling); + end = (*cit)->pointsEnd(sampling); + last = end;--last; + itStart = first; + do{ + itStop = itStart;++itStop; + + new_curve = new Chain(currentId); + currentId.setSecond(currentId.getSecond()+1); + + point = dynamic_cast<CurvePoint*>(&(*itStart)); + new_curve->push_vertex_back(point); + do{ + point = dynamic_cast<CurvePoint*>(&(*itStop)); + new_curve->push_vertex_back(point); + ++itStop; + if(itStop == end) + break; + if(stoppingPred(itStop) < 0){ + delete new_curve; + goto error; + } + }while(!stoppingPred.result); + if(itStop!=end){ + point = dynamic_cast<CurvePoint*>(&(*itStop)); + new_curve->push_vertex_back(point); + } + if(new_curve->nSegments() == 0){ + delete new_curve; + }else{ + splitted_chains.push_back(new_curve); + } + // find next start + do{ + ++itStart; + if(itStart == end) + break; + if(startingPred(itStart) < 0) + goto error; + }while(!startingPred.result); + }while((itStart!=end) && (itStart!=last)); + } + + // Update the current set of chains: + cit = _current_chains_set.begin(); + for(; + cit != citend; + ++cit){ + delete (*cit); + } + _current_chains_set.clear(); + _current_chains_set = splitted_chains; + splitted_chains.clear(); + + if (!_current_chains_set.empty()) + _current_set = &_current_chains_set; + return 0; + +error: + cit = splitted_chains.begin(); + citend = splitted_chains.end(); + for(; + cit != citend; + ++cit){ + delete (*cit); + } + splitted_chains.clear(); + return -1; +} + +#include "CurveIterators.h" + +// Internal function +int __recursiveSplit(Chain *_curve, UnaryFunction0D<double>& func, UnaryPredicate1D& pred, float sampling, + Operators::I1DContainer& newChains, Operators::I1DContainer& splitted_chains) +{ + if(((_curve->nSegments() == 1) && (sampling == 0)) || (_curve->getLength2D() <= sampling)){ + newChains.push_back(_curve); + return 0; + } + + CurveInternal::CurvePointIterator first = _curve->curvePointsBegin(sampling); + CurveInternal::CurvePointIterator second = first; ++second; + CurveInternal::CurvePointIterator end = _curve->curvePointsEnd(sampling); + CurveInternal::CurvePointIterator it = second; + CurveInternal::CurvePointIterator split = second; + Interface0DIterator it0d = it.castToInterface0DIterator(); + real _min = FLT_MAX;++it;//func(it0d);++it; + CurveInternal::CurvePointIterator next = it;++next; + + bool bsplit = false; + for(; ((it != end) && (next != end)); ++it,++next){ + it0d = it.castToInterface0DIterator(); + if (func(it0d) < 0) + return -1; + if(func.result < _min){ + _min = func.result; + split = it; + bsplit = true; + } + } + + if(!bsplit){ // we didn't find any minimum + newChains.push_back(_curve); + return 0; + } + + // retrieves the current splitting id + Id * newId = _curve->getSplittingId(); + if(newId == 0){ + newId = new Id(_curve->getId()); + _curve->setSplittingId(newId); + } + + Chain *new_curve_a = new Chain(*newId); + newId->setSecond(newId->getSecond()+1); + new_curve_a->setSplittingId(newId); + Chain *new_curve_b = new Chain(*newId); + newId->setSecond(newId->getSecond()+1); + new_curve_b->setSplittingId(newId); + + CurveInternal::CurvePointIterator vit = _curve->curveVerticesBegin(), vitend=_curve->curveVerticesEnd(); + CurveInternal::CurvePointIterator vnext = vit; ++vnext; + + + for(; (vit!=vitend)&&(vnext!=vitend)&&(split._CurvilinearLength-vit._CurvilinearLength> 0.001); ++vit,++vnext){ + new_curve_a->push_vertex_back(&(*vit)); + } + if((vit==vitend) || (vnext == vitend)){ + cout << "The split takes place in bad location" << endl; + newChains.push_back(_curve); + delete new_curve_a; + delete new_curve_b; + return 0; + } + + // build the two resulting chains + if(fabs(vit._CurvilinearLength-split._CurvilinearLength) > 0.001){ + new_curve_a->push_vertex_back(&(*split)); + new_curve_b->push_vertex_back(&(*split)); + } + else{ + new_curve_a->push_vertex_back(&(*vit)); + } + + for(;vit!=vitend;++vit) + new_curve_b->push_vertex_back(&(*vit)); + + // let's check whether one or two of the two new curves + // satisfy the stopping condition or not. + // (if one of them satisfies it, we don't split) + if (pred(*new_curve_a) < 0 || (!pred.result && pred(*new_curve_b) < 0)) { + delete new_curve_a; + delete new_curve_b; + return -1; + } + if(pred.result){ + // we don't actually create these two chains + newChains.push_back(_curve); + delete new_curve_a; + delete new_curve_b; + return 0; + } + // here we know we'll split _curve: + splitted_chains.push_back(_curve); + + __recursiveSplit(new_curve_a, func, pred, sampling, newChains, splitted_chains); + __recursiveSplit(new_curve_b, func, pred, sampling, newChains, splitted_chains); + return 0; +} + +int Operators::recursiveSplit(UnaryFunction0D<double>& func, UnaryPredicate1D& pred, float sampling) +{ + if (_current_chains_set.empty()) { + cerr << "Warning: current set empty" << endl; + return 0; + } + + Chain *currentChain = 0; + I1DContainer splitted_chains; + I1DContainer newChains; + I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end(); + for (; + cit != citend; + ++cit) { + currentChain = dynamic_cast<Chain*>(*cit); + if(!currentChain) + continue; + // let's check the first one: + if (pred(*currentChain) < 0) + return -1; + if(!pred.result){ + __recursiveSplit(currentChain, func, pred, sampling, newChains, splitted_chains); + }else{ + newChains.push_back(currentChain); + } + } + // Update the current set of chains: + if(!splitted_chains.empty()){ + for(cit = splitted_chains.begin(), citend = splitted_chains.end(); + cit != citend; + ++cit){ + delete (*cit); + } + splitted_chains.clear(); + } + + _current_chains_set.clear(); + _current_chains_set = newChains; + newChains.clear(); + + if (!_current_chains_set.empty()) + _current_set = &_current_chains_set; + return 0; +} + + +// recursive split with pred 0D +int __recursiveSplit(Chain *_curve, UnaryFunction0D<double>& func, UnaryPredicate0D& pred0d, UnaryPredicate1D& pred, float sampling, + Operators::I1DContainer& newChains, Operators::I1DContainer& splitted_chains) +{ + if(((_curve->nSegments() == 1) && (sampling == 0)) || (_curve->getLength2D() <= sampling)){ + newChains.push_back(_curve); + return 0; + } + + CurveInternal::CurvePointIterator first = _curve->curvePointsBegin(sampling); + CurveInternal::CurvePointIterator second = first; ++second; + CurveInternal::CurvePointIterator end = _curve->curvePointsEnd(sampling); + CurveInternal::CurvePointIterator it = second; + CurveInternal::CurvePointIterator split = second; + Interface0DIterator it0d = it.castToInterface0DIterator(); + //real _min = func(it0d);++it; + real _min = FLT_MAX;++it; + real mean = 0.f; + //soc unused - real variance = 0.f; + unsigned count = 0; + CurveInternal::CurvePointIterator next = it;++next; + + bool bsplit = false; + for(; ((it != end) && (next != end)); ++it,++next){ + ++count; + it0d = it.castToInterface0DIterator(); + if(pred0d(it0d) < 0) + return -1; + if(!pred0d.result) + continue; + if(func(it0d) < 0) + return -1; + mean += func.result; + if(func.result < _min){ + _min = func.result; + split = it; + bsplit = true; + } + } + mean /= (float)count; + + //if((!bsplit) || (mean-_min>mean)){ // we didn't find any minimum + if(!bsplit){ // we didn't find any minimum + newChains.push_back(_curve); + return 0; + } + + // retrieves the current splitting id + Id * newId = _curve->getSplittingId(); + if(newId == 0){ + newId = new Id(_curve->getId()); + _curve->setSplittingId(newId); + } + + Chain *new_curve_a = new Chain(*newId); + newId->setSecond(newId->getSecond()+1); + new_curve_a->setSplittingId(newId); + Chain *new_curve_b = new Chain(*newId); + newId->setSecond(newId->getSecond()+1); + new_curve_b->setSplittingId(newId); + + CurveInternal::CurvePointIterator vit = _curve->curveVerticesBegin(), vitend=_curve->curveVerticesEnd(); + CurveInternal::CurvePointIterator vnext = vit; ++vnext; + + + for(; (vit!=vitend)&&(vnext!=vitend)&&(split._CurvilinearLength-vit._CurvilinearLength> 0.001); ++vit,++vnext){ + new_curve_a->push_vertex_back(&(*vit)); + } + if((vit==vitend) || (vnext == vitend)){ + cout << "The split takes place in bad location" << endl; + newChains.push_back(_curve); + delete new_curve_a; + delete new_curve_b; + return 0; + } + + // build the two resulting chains + if(fabs(vit._CurvilinearLength-split._CurvilinearLength) > 0.001){ + new_curve_a->push_vertex_back(&(*split)); + new_curve_b->push_vertex_back(&(*split)); + } + else{ + new_curve_a->push_vertex_back(&(*vit)); + } + + for(;vit!=vitend;++vit) + new_curve_b->push_vertex_back(&(*vit)); + + // let's check whether one or two of the two new curves + // satisfy the stopping condition or not. + // (if one of them satisfies it, we don't split) + if (pred(*new_curve_a) < 0 || (!pred.result && pred(*new_curve_b) < 0)) { + delete new_curve_a; + delete new_curve_b; + return -1; + } + if(pred.result){ + // we don't actually create these two chains + newChains.push_back(_curve); + delete new_curve_a; + delete new_curve_b; + return 0; + } + // here we know we'll split _curve: + splitted_chains.push_back(_curve); + + __recursiveSplit(new_curve_a, func, pred0d, pred, sampling, newChains, splitted_chains); + __recursiveSplit(new_curve_b, func, pred0d, pred, sampling, newChains, splitted_chains); + return 0; +} + +int Operators::recursiveSplit(UnaryFunction0D<double>& func, UnaryPredicate0D& pred0d, UnaryPredicate1D& pred, float sampling) +{ + if (_current_chains_set.empty()) { + cerr << "Warning: current set empty" << endl; + return 0; + } + + Chain *currentChain = 0; + I1DContainer splitted_chains; + I1DContainer newChains; + I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end(); + for (; + cit != citend; + ++cit) { + currentChain = dynamic_cast<Chain*>(*cit); + if(!currentChain) + continue; + // let's check the first one: + if(pred(*currentChain) < 0) + return -1; + if(!pred.result){ + __recursiveSplit(currentChain, func, pred0d, pred, sampling, newChains, splitted_chains); + }else{ + newChains.push_back(currentChain); + } + } + // Update the current set of chains: + if(!splitted_chains.empty()){ + for(cit = splitted_chains.begin(), citend = splitted_chains.end(); + cit != citend; + ++cit){ + delete (*cit); + } + splitted_chains.clear(); + } + + _current_chains_set.clear(); + _current_chains_set = newChains; + newChains.clear(); + + if (!_current_chains_set.empty()) + _current_set = &_current_chains_set; + return 0; +} +// Internal class +class PredicateWrapper +{ +public: + + inline PredicateWrapper(BinaryPredicate1D& pred) { + _pred = &pred; + } + + inline bool operator()(Interface1D* i1, Interface1D* i2) { + if ((*_pred)(*i1, *i2) < 0) + throw std::runtime_error("comparison failed"); + return _pred->result; + } + +private: + + BinaryPredicate1D* _pred; +}; + +int Operators::sort(BinaryPredicate1D& pred) { + if (!_current_set) + return 0; + PredicateWrapper wrapper(pred); + try { + std::sort(_current_set->begin(), _current_set->end(), wrapper); + } + catch (std::runtime_error &e) { + cerr << "Warning: Operator.sort(): " << e.what() << endl; + return -1; + } + return 0; +} + +Stroke* createStroke(Interface1D& inter) { + Stroke* stroke = new Stroke; + stroke->setId(inter.getId()); + + float currentCurvilignAbscissa = 0.f; + + Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd(); + Interface0DIterator itfirst = it; + + Vec3r current(it->getProjectedX(), it->getProjectedY(), it->getProjectedZ()); + Vec3r previous = current; + SVertex* sv; + CurvePoint* cp; + StrokeVertex* stroke_vertex = NULL; + + do { + cp = dynamic_cast<CurvePoint*>(&(*it)); + if (!cp) { + sv = dynamic_cast<SVertex*>(&(*it)); + if (!sv) { + cerr << "Warning: unexpected Vertex type" << endl; + continue; + } + stroke_vertex = new StrokeVertex(sv); + } + else + stroke_vertex = new StrokeVertex(cp); + current = stroke_vertex->point2d(); + Vec3r vec_tmp(current - previous); + real vec_tmp_norm = vec_tmp.norm(); + if((stroke->strokeVerticesSize() > 0) && (vec_tmp_norm < 1.e-06)){ + // The point we just created is superimposed with the + // previous one. We remove it to avoid having to deal + // with this kind of singularities in the strip creation + delete stroke_vertex; + }else{ + currentCurvilignAbscissa += vec_tmp.norm(); + stroke_vertex->setCurvilinearAbscissa(currentCurvilignAbscissa); + stroke->push_back(stroke_vertex); + previous = current; + } + ++it; + } while((it != itend) && (it != itfirst)); + + if (it == itfirst) { + // Add last vertex: + cp = dynamic_cast<CurvePoint*>(&(*it)); + if (!cp) { + sv = dynamic_cast<SVertex*>(&(*it)); + if (!sv) + cerr << "Warning: unexpected Vertex type" << endl; + else + stroke_vertex = new StrokeVertex(sv); + } + else + stroke_vertex = new StrokeVertex(cp); + current = stroke_vertex->point2d(); + Vec3r vec_tmp(current - previous); + real vec_tmp_norm = vec_tmp.norm(); + if((stroke->strokeVerticesSize() > 0) && (vec_tmp_norm < 1.e-06)){ + // The point we just created is superimposed with the + // previous one. We remove it to avoid having to deal + // with this kind of singularities in the strip creation + delete stroke_vertex; + }else{ + currentCurvilignAbscissa += vec_tmp.norm(); + stroke_vertex->setCurvilinearAbscissa(currentCurvilignAbscissa); + stroke->push_back(stroke_vertex); + } + } + stroke->setLength(currentCurvilignAbscissa); + return stroke; +} + + +inline int applyShading(Stroke& stroke, vector<StrokeShader*>& shaders) { + for (vector<StrokeShader*>::iterator it = shaders.begin(); it != shaders.end(); ++it) { + if ((*it)->shade(stroke) < 0) { + return -1; + } + } + return 0; +} + + +int Operators::create(UnaryPredicate1D& pred, vector<StrokeShader*> shaders) { + //Canvas* canvas = Canvas::getInstance(); + if (!_current_set) { + cerr << "Warning: current set empty" << endl; + return 0; + } + for (Operators::I1DContainer::iterator it = _current_set->begin(); + it != _current_set->end(); + ++it) { + if (pred(**it) < 0) + return -1; + if (!pred.result) + continue; + + Stroke* stroke = createStroke(**it); + if (stroke) { + if (applyShading(*stroke, shaders) < 0) + return -1; + //canvas->RenderStroke(stroke); + _current_strokes_set.push_back(stroke); + } + } + return 0; +} + + +void Operators::reset() { + ViewMap* vm = ViewMap::getInstance(); + if (!vm) { + cerr << "Error: no ViewMap computed yet" << endl; + return; + } + _current_view_edges_set.clear(); + for (I1DContainer::iterator it = _current_chains_set.begin(); + it != _current_chains_set.end(); + ++it) + delete *it; + _current_chains_set.clear(); + _current_view_edges_set.insert(_current_view_edges_set.begin(), + vm->ViewEdges().begin(), + vm->ViewEdges().end()); + _current_set = &_current_view_edges_set; + _current_strokes_set.clear(); +} diff --git a/source/blender/freestyle/intern/stroke/Operators.h b/source/blender/freestyle/intern/stroke/Operators.h new file mode 100755 index 00000000000..d705d5af5b2 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/Operators.h @@ -0,0 +1,311 @@ +// +// Filename : Operators.h +// Author(s) : Stephane Grabli, Emmanuel Turquin +// Purpose : Class gathering stroke creation algorithms +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef OPERATORS_H +# define OPERATORS_H + +# include "../view_map/Interface1D.h" +# include <vector> +# include <iostream> +# include "Predicates1D.h" +# include "Predicates0D.h" +# include "../view_map/ViewMap.h" +# include "Chain.h" +# include "ChainingIterators.h" +# include "../system/TimeStamp.h" +# include "StrokeShader.h" + +/*! Class defining the operators used in a style module. + * There are 4 classes of operators: Selection, Chaining, + * Splitting and Creating. All these operators are user controlled + * in the scripting language through Functors, Predicates and Shaders + * that are taken as arguments. + */ +class LIB_STROKE_EXPORT Operators { + +public: + + typedef vector<Interface1D*> I1DContainer; + typedef vector<Stroke*> StrokesContainer; + + + // + // Operators + // + //////////////////////////////////////////////// + + /*! Selects the ViewEdges of the ViewMap verifying + * a specified condition. + * \param pred The predicate expressing this condition + */ + static int select(UnaryPredicate1D& pred); + + /*! Builds a set of chains from the current set of ViewEdges. + * Each ViewEdge of the current list starts a new chain. The chaining + * operator then iterates over the ViewEdges of the ViewMap using the + * user specified iterator. + * This operator only iterates using the increment operator and is + * therefore unidirectional. + * \param it + * The iterator on the ViewEdges of the ViewMap. It contains + * the chaining rule. + * \param pred + * The predicate on the ViewEdge that expresses the stopping + * condition. + * \param modifier + * A function that takes a ViewEdge as argument and that + * is used to modify the processed ViewEdge state (the timestamp + * incrementation is a typical illustration of such a modifier) + */ + static int chain(ViewEdgeInternal::ViewEdgeIterator& it, + UnaryPredicate1D& pred, + UnaryFunction1D_void& modifier); + + /*! Builds a set of chains from the current set of ViewEdges. + * Each ViewEdge of the current list starts a new chain. The chaining + * operator then iterates over the ViewEdges of the ViewMap using the + * user specified iterator. + * This operator only iterates using the increment operator and is + * therefore unidirectional. + * This chaining operator is different from the previous one because + * it doesn't take any modifier as argument. Indeed, the time stamp (insuring + * that a ViewEdge is processed one time) is automatically managed in this case. + * \param it + * The iterator on the ViewEdges of the ViewMap. It contains + * the chaining rule. + * \param pred + * The predicate on the ViewEdge that expresses the stopping + * condition. + */ + static int chain(ViewEdgeInternal::ViewEdgeIterator& it, + UnaryPredicate1D& pred); + + /*! Builds a set of chains from the current set of ViewEdges. + * Each ViewEdge of the current list potentially starts a new chain. The chaining + * operator then iterates over the ViewEdges of the ViewMap using the + * user specified iterator. + * This operator iterates both using the increment and decrement operators and is + * therefore bidirectional. + * This operator works with a ChainingIterator which contains the + * chaining rules. It is this last one which can be told + * to chain only edges that belong to the selection or not to + * process twice a ViewEdge during the chaining. + * Each time a ViewEdge is added to a chain, its chaining time stamp + * is incremented. This allows you to keep track of + * the number of chains to which a ViewEdge belongs to. + * \param it + * The ChainingIterator on the ViewEdges of the ViewMap. It contains + * the chaining rule. + * \param pred + * The predicate on the ViewEdge that expresses the stopping + * condition. + */ + static int bidirectionalChain(ChainingIterator& it, UnaryPredicate1D& pred); + + /*! The only difference with the above bidirectional chaining algorithm is + * that we don't need to pass a stopping criterion. This might be desirable + * when the stopping criterion is already contained in the iterator + * definition. + * Builds a set of chains from the current set of ViewEdges. + * Each ViewEdge of the current list potentially starts a new chain. The chaining + * operator then iterates over the ViewEdges of the ViewMap using the + * user specified iterator. + * This operator iterates both using the increment and decrement operators and is + * therefore bidirectional. + * This operator works with a ChainingIterator which contains the + * chaining rules. It is this last one which can be told + * to chain only edges that belong to the selection or not to + * process twice a ViewEdge during the chaining. + * Each time a ViewEdge is added to a chain, its chaining time stamp + * is incremented. This allows you to keep track of + * the number of chains to which a ViewEdge belongs to. + * \param it + * The ChainingIterator on the ViewEdges of the ViewMap. It contains + * the chaining rule. + */ + static int bidirectionalChain(ChainingIterator& it); + + /*! Splits each chain of the current set of chains in a sequential way. + * The points of each chain are processed (with a specified sampling) sequentially. + * Each time a user specified starting condition is verified, a new chain begins and + * ends as soon as a user-defined stopping predicate is verified. + * This allows chains overlapping rather than chains partitioning. + * The first point of the initial chain is the first point of one of the + * resulting chains. + * The splitting ends when no more chain can start. + * \param startingPred + * The predicate on a point that expresses the starting + * condition + * \param stoppingPred + * The predicate on a point that expresses the stopping + * condition + * \param sampling + * The resolution used to sample the chain for the predicates + * evaluation. (The chain is not actually resampled, a virtual point + * only progresses along the curve using this resolution) + */ + static int sequentialSplit(UnaryPredicate0D& startingPred, UnaryPredicate0D& stoppingPred, + float sampling = 0.f); + + /*! Splits each chain of the current set of chains in a sequential way. + * The points of each chain are processed (with a specified sampling) sequentially + * and each time a user specified condition is verified, the chain is split into two chains. + * The resulting set of chains is a partition of the initial chain + * \param pred + * The predicate on a point that expresses the splitting + * condition + * \param sampling + * The resolution used to sample the chain for the predicate + * evaluation. (The chain is not actually resampled, a virtual point + * only progresses along the curve using this resolution) + */ + static int sequentialSplit(UnaryPredicate0D& pred, + float sampling = 0.f); + + /*! Splits the current set of chains in a recursive way. + * We process the points of each chain (with a specified sampling) to find + * the point minimizing a specified function. The chain is split in two at this + * point and the two new chains are processed in the same way. + * The recursivity level is controlled through a predicate 1D that expresses a stopping condition + * on the chain that is about to be processed. + * \param func + * The Unary Function evaluated at each point of the chain. + * The splitting point is the point minimizing this function + * \param pred + * The Unary Predicate ex pressing the recursivity stopping condition. + * This predicate is evaluated for each curve before it actually gets + * split. If pred(chain) is true, the curve won't be split anymore. + * \param sampling + * The resolution used to sample the chain for the predicates + * evaluation. (The chain is not actually resampled, a virtual point + * only progresses along the curve using this resolution) + */ + static int recursiveSplit(UnaryFunction0D<double>& func, UnaryPredicate1D& pred, float sampling = 0); + + /*! Splits the current set of chains in a recursive way. + * We process the points of each chain (with a specified sampling) to find + * the point minimizing a specified function. The chain is split in two at this + * point and the two new chains are processed in the same way. + * The user can specify a 0D predicate to make a first selection + * on the points that can potentially be split. + * A point that doesn't verify the 0D predicate won't be candidate + * in realizing the min. + * The recursivity level is controlled through a predicate 1D that expresses a stopping condition + * on the chain that is about to be processed. + * \param func + * The Unary Function evaluated at each point of the chain. + * The splitting point is the point minimizing this function + * \param pred0d + * The Unary Predicate 0D used to select the candidate points + * where the split can occur. + * For example, it is very likely that would rather have + * your chain splitting around its middle point than around + * one of its extremities. A 0D predicate working on + * the curvilinear abscissa allows to add this kind of constraints. + * \param pred + * The Unary Predicate ex pressing the recursivity stopping condition. + * This predicate is evaluated for each curve before it actually gets + * split. If pred(chain) is true, the curve won't be split anymore. + * \param sampling + * The resolution used to sample the chain for the predicates + * evaluation. (The chain is not actually resampled, a virtual point + * only progresses along the curve using this resolution) + * + */ + static int recursiveSplit(UnaryFunction0D<double>& func, UnaryPredicate0D& pred0d, UnaryPredicate1D& pred, float sampling = 0); + + /*! Sorts the current set of chains (or viewedges) according to the + * comparison predicate given as argument. + * \param pred + * The binary predicate used for the comparison + */ + static int sort(BinaryPredicate1D& pred); + + /*! Creates and shades the strokes from the current set of chains. + * A predicate can be specified to make a selection pass on the + * chains. + * \param pred + * The predicate that a chain must verify in order to + * be transform as a stroke + * \param shaders + * The list of shaders used to shade the strokes + */ + static int create(UnaryPredicate1D& pred, vector<StrokeShader*> shaders); + + // + // Data access + // + //////////////////////////////////////////////// + + static ViewEdge* getViewEdgeFromIndex(unsigned i) { + return dynamic_cast<ViewEdge*>(_current_view_edges_set[i]); + } + + static Chain* getChainFromIndex(unsigned i) { + return dynamic_cast<Chain*>(_current_chains_set[i]); + } + + static Stroke* getStrokeFromIndex(unsigned i) { + return _current_strokes_set[i]; + } + + static unsigned getViewEdgesSize() { + return _current_view_edges_set.size(); + } + + static unsigned getChainsSize() { + return _current_chains_set.size(); + } + + static unsigned getStrokesSize() { + return _current_strokes_set.size(); + } + + // + // Not exported in Python + // + ////////////////////////////////////////////////// + + static StrokesContainer* getStrokesSet() { + return &_current_strokes_set; + } + + static void reset(); + +private: + + Operators() {} + + static I1DContainer _current_view_edges_set; + static I1DContainer _current_chains_set; + static I1DContainer* _current_set; + static StrokesContainer _current_strokes_set; +}; + +#endif // OPERATORS_H diff --git a/source/blender/freestyle/intern/stroke/PSStrokeRenderer.cpp b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.cpp new file mode 100755 index 00000000000..dc9c94e0e11 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.cpp @@ -0,0 +1,89 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +# include "PSStrokeRenderer.h" +# include "Canvas.h" + +PSStrokeRenderer::PSStrokeRenderer(const char* iFileName) +:StrokeRenderer(){ + if(!iFileName) + iFileName = "freestyle.ps"; + // open the stream: + _ofstream.open(iFileName, ios::out); + if(!_ofstream.is_open()){ + cerr << "couldn't open the output file " << iFileName << endl; + } + _ofstream << "%!PS-Adobe-2.0 EPSF-2.0" << endl; + _ofstream << "%%Creator: Freestyle (http://artis.imag.fr/Software/Freestyle)" << endl; + _ofstream << "%%BoundingBox: " << 0 << " "<< 0 << " " << Canvas::getInstance()->width() << " " << Canvas::getInstance()->height() << endl; + _ofstream << "%%EndComments" << endl; +} + +PSStrokeRenderer::~PSStrokeRenderer(){ + Close(); +} + +void PSStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const{ + RenderStrokeRepBasic(iStrokeRep); +} + +void PSStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const{ + vector<Strip*>& strips = iStrokeRep->getStrips(); + Strip::vertex_container::iterator v[3]; + StrokeVertexRep *svRep[3]; + Vec3r color[3]; + for(vector<Strip*>::iterator s=strips.begin(), send=strips.end(); + s!=send; + ++s){ + Strip::vertex_container& vertices = (*s)->vertices(); + v[0] = vertices.begin(); + v[1] = v[0];++(v[1]); + v[2] = v[1]; ++(v[2]); + + while(v[2]!=vertices.end()){ + svRep[0] = *(v[0]); + svRep[1] = *(v[1]); + svRep[2] = *(v[2]); + + color[0] = svRep[0]->color(); + //color[1] = svRep[1]->color(); + //color[2] = svRep[2]->color(); + + _ofstream << "newpath" << endl; + _ofstream << (color[0])[0] << " " << (color[0])[1] << " " << (color[0])[2] << " setrgbcolor" <<endl; + _ofstream << svRep[0]->point2d()[0] << " " <<svRep[0]->point2d()[1] << " moveto" << endl; + _ofstream << svRep[1]->point2d()[0] << " " <<svRep[1]->point2d()[1] << " lineto" << endl; + _ofstream << svRep[2]->point2d()[0] << " " <<svRep[2]->point2d()[1] << " lineto" << endl; + _ofstream << "closepath" << endl; + _ofstream << "fill" << endl; + + ++v[0]; + ++v[1]; + ++v[2]; + } + } +} + +void PSStrokeRenderer::Close(){ + if(_ofstream.is_open()) + _ofstream.close(); +} + diff --git a/source/blender/freestyle/intern/stroke/PSStrokeRenderer.h b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.h new file mode 100755 index 00000000000..b30949845ab --- /dev/null +++ b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.h @@ -0,0 +1,63 @@ +// +// Filename : PSStrokeRenderer.h +// Author(s) : Stephane Grabli +// Purpose : Class to define the Postscript rendering of a stroke +// Date of creation : 10/26/2004 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef PSSTROKERENDERER_H +# define PSSTROKERENDERER_H + +# include "StrokeRenderer.h" +# include "../system/FreestyleConfig.h" +# include <fstream> + +/**********************************/ +/* */ +/* */ +/* PSStrokeRenderer */ +/* */ +/* */ +/**********************************/ + +class LIB_STROKE_EXPORT PSStrokeRenderer : public StrokeRenderer +{ +public: + PSStrokeRenderer(const char * iFileName = 0); + virtual ~PSStrokeRenderer(); + + /*! Renders a stroke rep */ + virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const; + virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const; + + /*! Closes the output PS file */ + void Close(); + +protected: + mutable ofstream _ofstream; +}; + +#endif // PSSTROKERENDERER_H + diff --git a/source/blender/freestyle/intern/stroke/Predicates0D.h b/source/blender/freestyle/intern/stroke/Predicates0D.h new file mode 100755 index 00000000000..2f5d9551b3a --- /dev/null +++ b/source/blender/freestyle/intern/stroke/Predicates0D.h @@ -0,0 +1,172 @@ +// +// Filename : Predicates0D.h +// Author(s) : Stephane Grabli, Emmanuel Turquin +// Purpose : Class gathering stroke creation algorithms +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef PREDICATES0D_H +# define PREDICATES0D_H + +# include "../view_map/Functions0D.h" + +# include "../python/Director.h" + +// +// UnaryPredicate0D (base class for predicates in 0D) +// +/////////////////////////////////////////////////////////// +/*! Base class for Unary Predicates that work + * on Interface0DIterator. + * A UnaryPredicate0D is a functor that evaluates + * a condition on a Interface0DIterator and returns + * true or false depending on whether this condition is + * satisfied or not. + * The UnaryPredicate0D is used by calling its () operator. + * Any inherited class must overload the () operator. + */ +class UnaryPredicate0D +{ +public: + + bool result; + PyObject *py_up0D; + + /*! Default constructor. */ + UnaryPredicate0D() { py_up0D = 0; } + /*! Destructor. */ + virtual ~UnaryPredicate0D() {} + /*! Returns the string of the name + * of the UnaryPredicate0D. + */ + virtual string getName() const { + return "UnaryPredicate0D"; + } + /*! The () operator. Must be overload + * by inherited classes. + * \param it + * The Interface0DIterator pointing onto the + * Interface0D at which we wish to evaluate + * the predicate. + * \return true if the condition is satisfied, + * false otherwise. + */ + virtual int operator()(Interface0DIterator& it) { + return Director_BPy_UnaryPredicate0D___call__(this, it); + } + +}; + + +// +// BinaryPredicate0D (base class for predicates in 0D) +// +/////////////////////////////////////////////////////////// +/*! Base class for Binary Predicates working on Interface0D. + * A BinaryPredicate0D is typically an ordering relation + * between two Interface0D. + * It evaluates a relation between 2 Interface0D and + * returns true or false. + * It is used by calling the () operator. + */ +class BinaryPredicate0D +{ +public: + + bool result; + PyObject *py_bp0D; + + /*! Default constructor. */ + BinaryPredicate0D() { py_bp0D = 0; } + /*! Destructor. */ + virtual ~BinaryPredicate0D() {} + /*! Returns the string of the name of the + * binary predicate. + */ + virtual string getName() const { + return "BinaryPredicate0D"; + } + + /*! The () operator. Must be overload by inherited classes. + * It evaluates a relation between 2 Interface0D. + * \param inter1 + * The first Interface0D. + * \param inter2 + * The second Interface0D. + * \return true or false. + */ + virtual int operator()(Interface0D& inter1, Interface0D& inter2) { + return Director_BPy_BinaryPredicate0D___call__(this, inter1, inter2); + } + +}; + + +// +// Predicates definitions +// +/////////////////////////////////////////////////////////// + +namespace Predicates0D { + + // TrueUP0D + /*! Returns true any time */ + class TrueUP0D : public UnaryPredicate0D + { + public: + /*! Default constructor. */ + TrueUP0D() {} + /*! Returns the string "TrueUP0D"*/ + string getName() const { + return "TrueUP0D"; + } + /*! The () operator. */ + int operator()(Interface0DIterator&) { + result = true; + return 0; + } + }; + + // FalseUP0D + /*! Returns false any time */ + class FalseUP0D : public UnaryPredicate0D + { + public: + /*! Default constructor. */ + FalseUP0D() {} + /*! Returns the string "FalseUP0D"*/ + string getName() const { + return "FalseUP0D"; + } + /*! The () operator. */ + int operator()(Interface0DIterator&) { + result = false; + return 0; + } + }; + +} // end of namespace Predicates0D + +#endif // PREDICATES0D_H diff --git a/source/blender/freestyle/intern/stroke/Predicates1D.h b/source/blender/freestyle/intern/stroke/Predicates1D.h new file mode 100755 index 00000000000..6461f6428ab --- /dev/null +++ b/source/blender/freestyle/intern/stroke/Predicates1D.h @@ -0,0 +1,483 @@ +// +// Filename : Predicates1D.h +// Author(s) : Stephane Grabli, Emmanuel Turquin +// Purpose : Class gathering stroke creation algorithms +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef PREDICATES1D_H +# define PREDICATES1D_H + +# include <string> +# include "../system/TimeStamp.h" +# include "../view_map/Interface1D.h" +# include "../view_map/Functions1D.h" +# include "AdvancedFunctions1D.h" + +# include "../python/Director.h" + +// +// UnaryPredicate1D (base class for predicates in 1D) +// +/////////////////////////////////////////////////////////// +/*! Base class for Unary Predicates that work + * on Interface1D. + * A UnaryPredicate1D is a functor that evaluates + * a condition on a Interface1D and returns + * true or false depending on whether this condition is + * satisfied or not. + * The UnaryPredicate1D is used by calling its () operator. + * Any inherited class must overload the () operator. + */ +class UnaryPredicate1D +{ +public: + + bool result; + PyObject *py_up1D; + + /*! Default constructor. */ + UnaryPredicate1D() { py_up1D = 0; } + /*! Destructor. */ + virtual ~UnaryPredicate1D() {} + /*! Returns the string of the name + * of the UnaryPredicate1D. + */ + virtual string getName() const { + return "UnaryPredicate1D"; + } + /*! The () operator. Must be overload + * by inherited classes. + * \param inter + * The Interface1D on which we wish to evaluate + * the predicate. + * \return true if the condition is satisfied, + * false otherwise. + */ + virtual int operator()(Interface1D& inter) { + return Director_BPy_UnaryPredicate1D___call__(this, inter); + } + +}; + + +// +// BinaryPredicate1D (base class for predicates in 1D) +// +/////////////////////////////////////////////////////////// +/*! Base class for Binary Predicates working on Interface1D. + * A BinaryPredicate1D is typically an ordering relation + * between two Interface1D. + * It evaluates a relation between 2 Interface1D and + * returns true or false. + * It is used by calling the () operator. + */ +class BinaryPredicate1D +{ +public: + + bool result; + PyObject *py_bp1D; + + /*! Default constructor. */ + BinaryPredicate1D() { py_bp1D = 0; } + /*! Destructor. */ + virtual ~BinaryPredicate1D() {} + /*! Returns the string of the name of the + * binary predicate. + */ + virtual string getName() const { + return "BinaryPredicate1D"; + } + /*! The () operator. Must be overload by inherited classes. + * It evaluates a relation between 2 Interface1D. + * \param inter1 + * The first Interface1D. + * \param inter2 + * The second Interface1D. + * \return true or false. + */ + virtual int operator()(Interface1D& inter1, Interface1D& inter2) { + return Director_BPy_BinaryPredicate1D___call__(this, inter1, inter2); + } + +}; + + +// +// Predicates definitions +// +/////////////////////////////////////////////////////////// + +namespace Predicates1D { + + // TrueUP1D + /*! Returns true */ + class TrueUP1D : public UnaryPredicate1D + { + public: + /*! Constructor */ + TrueUP1D() {} + /*! Returns the string "TrueUP1D"*/ + string getName() const { + return "TrueUP1D"; + } + /*! the () operator */ + int operator()(Interface1D&) { + result = true; + return 0; + } + }; + + // FalseUP1D + /*! Returns false */ + class FalseUP1D : public UnaryPredicate1D + { + public: + /*! Constructor */ + FalseUP1D() {} + /*! Returns the string "FalseUP1D"*/ + string getName() const { + return "FalseUP1D"; + } + /*! the () operator */ + int operator()(Interface1D&) { + result = false; + return 0; + } + }; + + // QuantitativeInvisibilityUP1D + /*! Returns true if the Quantitative Invisibility evaluated + * at an Interface1D, using the QuantitativeInvisibilityF1D + * functor, equals a certain user-defined value. + */ + class QuantitativeInvisibilityUP1D : public UnaryPredicate1D + { + public: + /*! Builds the Predicate. + * \param qi + * The Quantitative Invisibility you want + * the Interface1D to have + */ + QuantitativeInvisibilityUP1D(unsigned qi = 0) : _qi(qi) {} + /*! Returns the string "QuantitativeInvisibilityUP1D"*/ + string getName() const { + return "QuantitativeInvisibilityUP1D"; + } + /*! the () operator */ + int operator()(Interface1D& inter) { + Functions1D::QuantitativeInvisibilityF1D func; + if (func(inter) < 0) + return -1; + result = (func.result == _qi); + return 0; + } + private: + unsigned _qi; + }; + + // ContourUP1D + /*! Returns true if the Interface1D is a contour. + * An Interface1D is a contour if it is borded + * by a different shape on each of its sides. + */ + class ContourUP1D : public UnaryPredicate1D + { + private: + Functions1D::CurveNatureF1D _getNature; + public: + /*! Returns the string "ContourUP1D"*/ + string getName() const { + return "ContourUP1D"; + } + /*! The () operator. */ + int operator()(Interface1D& inter) { + if (_getNature(inter) < 0) + return -1; + if((_getNature.result & Nature::SILHOUETTE) || (_getNature.result & Nature::BORDER)){ + Interface0DIterator it=inter.verticesBegin(); + for(; !it.isEnd(); ++it){ + if(Functions0D::getOccludeeF0D(it) != Functions0D::getShapeF0D(it)) { + result = true; + return 0; + } + } + } + result = false; + return 0; + } + }; + + // ExternalContourUP1D + /*! Returns true if the Interface1D is an external contour. + * An Interface1D is an external contour if it is borded + * by no shape on one of its sides. + */ + class ExternalContourUP1D : public UnaryPredicate1D + { + private: + Functions1D::CurveNatureF1D _getNature; + public: + /*! Returns the string "ExternalContourUP1D"*/ + string getName() const { + return "ExternalContourUP1D"; + } + /*! The () operator. */ + int operator()(Interface1D& inter) { + if (_getNature(inter) < 0) + return -1; + if((_getNature.result & Nature::SILHOUETTE) || (_getNature.result & Nature::BORDER)){ + set<ViewShape*> occluded; + Functions1D::getOccludeeF1D(inter, occluded); + for(set<ViewShape*>::iterator os=occluded.begin(), osend=occluded.end(); + os!=osend; + ++os){ + if((*os) == 0) { + result = true; + return 0; + } + } + } + result = false; + return 0; + } + }; + + // EqualToTimeStampUP1D + /*! Returns true if the Interface1D's time stamp + * is equal to a certain user-defined value. + */ + class EqualToTimeStampUP1D : public UnaryPredicate1D + { + protected: + unsigned _timeStamp; + public: + EqualToTimeStampUP1D(unsigned ts) : UnaryPredicate1D(){ + _timeStamp = ts; + } + /*! Returns the string "EqualToTimeStampUP1D"*/ + string getName() const { + return "EqualToTimeStampUP1D"; + } + /*! The () operator. */ + int operator()(Interface1D& inter) { + result = (inter.getTimeStamp() == _timeStamp); + return 0; + } + }; + + // EqualToChainingTimeStampUP1D + /*! Returns true if the Interface1D's time stamp + * is equal to a certain user-defined value. + */ + class EqualToChainingTimeStampUP1D : public UnaryPredicate1D + { + protected: + unsigned _timeStamp; + public: + EqualToChainingTimeStampUP1D(unsigned ts) : UnaryPredicate1D(){ + _timeStamp = ts; + } + /*! Returns the string "EqualToChainingTimeStampUP1D"*/ + string getName() const { + return "EqualToChainingTimeStampUP1D"; + } + /*! The () operator. */ + int operator()(Interface1D& inter) { + ViewEdge* edge = dynamic_cast<ViewEdge*>(&inter); + if (!edge) { + result = false; + return 0; + } + result = (edge->getChainingTimeStamp() >= _timeStamp); + return 0; + } + }; + + // ShapeUP1D + /*! Returns true if the shape to which the Interface1D + * belongs to has the same Id as the one specified by the + * user. + */ + class ShapeUP1D: public UnaryPredicate1D + { + private: + Id _id; + public: + /*! Builds the Predicate. + * \param idFirst + * The first Id component. + * \param idSecond + * The second Id component. + */ + ShapeUP1D(unsigned idFirst, unsigned idSecond=0) + : UnaryPredicate1D(){ + _id = Id(idFirst, idSecond); + } + /*! Returns the string "ShapeUP1D"*/ + string getName() const { + return "ShapeUP1D"; + } + /*! The () operator. */ + int operator()(Interface1D& inter) { + set<ViewShape*> shapes; + Functions1D::getShapeF1D(inter, shapes); + for(set<ViewShape*>::iterator s=shapes.begin(), send=shapes.end(); + s!=send; + ++s){ + if((*s)->getId() == _id) { + result = true; + return 0; + } + } + result = false; + return 0; + } + }; + + // + // Binary Predicates definitions + // + /////////////////////////////////////////////////////////// + + // TrueBP1D + /*! Returns true. */ + class TrueBP1D : public BinaryPredicate1D + { + public: + /*! Returns the string "TrueBP1D"*/ + string getName() const { + return "TrueBP1D"; + } + /*! The () operator. */ + int operator()(Interface1D& i1, Interface1D& i2) { + result = true; + return 0; + } + }; + + // FalseBP1D + /*! Returns false. */ + class FalseBP1D : public BinaryPredicate1D + { + public: + /*! Returns the string "FalseBP1D"*/ + string getName() const { + return "FalseBP1D"; + } + /*! The () operator. */ + int operator()(Interface1D& i1, Interface1D& i2) { + result = false; + return 0; + } + }; + + // Length2DBP1D + /*! Returns true if the 2D length of the Interface1D i1 + * is less than the 2D length of the Interface1D i2. + */ + class Length2DBP1D : public BinaryPredicate1D + { + public: + /*! Returns the string "Length2DBP1D"*/ + string getName() const { + return "Length2DBP1D"; + } + /*! The () operator. */ + int operator()(Interface1D& i1, Interface1D& i2) { + result = (i1.getLength2D() > i2.getLength2D()); + return 0; + } + }; + + // SameShapeIdBP1D + /*! Returns true if the Interface1D i1 and i2 belong + * to the same shape. + */ + class SameShapeIdBP1D : public BinaryPredicate1D + { + public: + /*! Returns the string "SameShapeIdBP1D"*/ + string getName() const { + return "SameShapeIdBP1D"; + } + /*! The () operator. */ + int operator()(Interface1D& i1, Interface1D& i2) { + set<ViewShape*> shapes1; + Functions1D::getShapeF1D(i1, shapes1); + set<ViewShape*> shapes2; + Functions1D::getShapeF1D(i2, shapes2); + // FIXME:// n2 algo, can do better... + for(set<ViewShape*>::iterator s=shapes1.begin(), send=shapes1.end(); + s!=send; + ++s){ + Id current = (*s)->getId(); + for(set<ViewShape*>::iterator s2=shapes2.begin(), s2end=shapes2.end(); + s2!=s2end; + ++s2){ + if((*s2)->getId() == current) { + result = true; + return 0; + } + } + } + result = false; + return 0; + } + }; + + // ViewMapGradientNormBP1D + /*! Returns true if the evaluation of the + * Gradient norm Function is higher for Interface1D i1 + * than for i2. + */ + class ViewMapGradientNormBP1D : public BinaryPredicate1D + { + private: + Functions1D::GetViewMapGradientNormF1D _func; + public: + ViewMapGradientNormBP1D(int level, IntegrationType iType=MEAN, float sampling=2.0) + : BinaryPredicate1D(), _func(level, iType, sampling) { + } + /*! Returns the string "ViewMapGradientNormBP1D"*/ + string getName() const { + return "ViewMapGradientNormBP1D"; + } + /*! The () operator. */ + int operator()(Interface1D& i1, Interface1D& i2) { + if (_func(i1) < 0) + return -1; + real n1 = _func.result; + if (_func(i2) < 0) + return -1; + real n2 = _func.result; + result = (n1 > n2); + return 0; + } + }; +} // end of namespace Predicates1D + +#endif // PREDICATES1D_H diff --git a/source/blender/freestyle/intern/stroke/QInformationMap.h b/source/blender/freestyle/intern/stroke/QInformationMap.h new file mode 100755 index 00000000000..ef068f15061 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/QInformationMap.h @@ -0,0 +1,58 @@ +// +// Filename : QInformationMap.h +// Author : Stephane Grabli +// Purpose : Class defining an information map using a QImage +// Date of creation : 04/01/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef QINFORMATIONMAP_H +# define QINFORMATIONMAP_H + +# include <qimage.h> +# include "InformationMap.h" + +class QInformationMap : public InformationMap +{ +private: + QImage _map; // the image or a piece of image + +public: + QInformationMap(); + QInformationMap(const QImage&); + QInformationMap(const QInformationMap&); + QInformationMap& operator=(const QInformationMap&); + + //float getSmoothedPixel(int x, int y, float sigma = 0.2f) + virtual float getMean(int x, int y) ; + virtual void retrieveMeanAndVariance(int x, int y, float &oMean, float &oVariance) ; + + inline const QImage& map() const {return _map;} + inline void setMap(const QImage& iMap, float iw, float ih) {_map = iMap.copy();_w=iw;_h=ih;} + +protected: + virtual float computeGaussian(int x, int y); +}; + +#endif // QINFORMATIONMAP_H diff --git a/source/blender/freestyle/intern/stroke/Stroke.cpp b/source/blender/freestyle/intern/stroke/Stroke.cpp new file mode 100755 index 00000000000..f6cefdfee34 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/Stroke.cpp @@ -0,0 +1,953 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "Stroke.h" +#include "StrokeRenderer.h" +#include "StrokeIterators.h" +#include "StrokeAdvancedIterators.h" + + /**********************************/ + /* */ + /* */ + /* StrokeAttribute */ + /* */ + /* */ + /**********************************/ + +StrokeAttribute::StrokeAttribute() +{ + int i; + _alpha = 1.f; + _thickness[0] = 1.f; + _thickness[1] = 1.f; + for(i=0; i<3; ++i) + _color[i] = 0.2f; + _color[0]=0.8; + _userAttributesReal = 0; + _userAttributesVec2f = 0; + _userAttributesVec3f = 0; + _visible = true; +} +StrokeAttribute::StrokeAttribute(const StrokeAttribute& iBrother) +{ + _alpha = iBrother._alpha; + _thickness[0] = iBrother._thickness[0]; + _thickness[1] = iBrother._thickness[1]; + for(int i=0; i<3; ++i) + _color[i] = iBrother._color[i]; + _visible = iBrother._visible; + if(iBrother._userAttributesReal) + _userAttributesReal = new realMap(*iBrother._userAttributesReal); + else + _userAttributesReal = 0; + if(iBrother._userAttributesVec2f) + _userAttributesVec2f = new Vec2fMap(*iBrother._userAttributesVec2f); + else + _userAttributesVec2f = 0; + if(iBrother._userAttributesVec3f) + _userAttributesVec3f = new Vec3fMap(*iBrother._userAttributesVec3f); + else + _userAttributesVec3f = 0; +} +StrokeAttribute::StrokeAttribute( float iRColor, float iGColor, float iBColor, + float iAlpha, + float iRThickness, float iLThickness) +{ + _color[0] = iRColor; + _color[1] = iGColor; + _color[2] = iBColor; + + _alpha = iAlpha; + + _thickness[0] = iRThickness; + _thickness[1] = iLThickness; + + _visible = true; + + _userAttributesReal = 0; + _userAttributesVec2f = 0; + _userAttributesVec3f = 0; +} +StrokeAttribute::StrokeAttribute(const StrokeAttribute& a1, const StrokeAttribute& a2, float t) + +{ + + _alpha = (1-t)*a1._alpha + t*a2._alpha; + _thickness[0] = (1-t)*a1._thickness[0] + t*a2._thickness[0]; + _thickness[1] = (1-t)*a1._thickness[1] + t*a2._thickness[1]; + for(int i=0; i<3; ++i) + _color[i] = (1-t)*a1._color[i] + t*a2._color[i]; + + _visible = true; + + // FIXME: a verifier (et a ameliorer) + if((a1._userAttributesReal) && (a2._userAttributesReal)){ + if(a1._userAttributesReal->size() == a2._userAttributesReal->size()){ + _userAttributesReal = new realMap; + realMap::iterator it1=a1._userAttributesReal->begin(), it1end=a1._userAttributesReal->end(); + realMap::iterator it2=a2._userAttributesReal->begin(), it2end=a2._userAttributesReal->end(); + for(; (it1!=it1end); ++it1){ + (*_userAttributesReal)[(*it1).first] = ((1-t)*(*it1).second+t*(*it2).second); + } + } + }else{ + _userAttributesReal = 0; + } + if((a1._userAttributesVec2f) && (a2._userAttributesVec2f)){ + if(a1._userAttributesVec2f->size() == a2._userAttributesVec2f->size()){ + _userAttributesVec2f = new Vec2fMap; + Vec2fMap::iterator it1=a1._userAttributesVec2f->begin(), it1end=a1._userAttributesVec2f->end(); + Vec2fMap::iterator it2=a2._userAttributesVec2f->begin(), it2end=a2._userAttributesVec2f->end(); + for(; (it1!=it1end); ++it1){ + (*_userAttributesVec2f)[(*it1).first] = ((1-t)*(*it1).second+t*(*it2).second); + } + } + }else{ + _userAttributesVec2f = 0; + } + if((a1._userAttributesVec3f) && (a2._userAttributesVec3f)){ + if(a1._userAttributesVec3f->size() == a2._userAttributesVec3f->size()){ + _userAttributesVec3f = new Vec3fMap; + Vec3fMap::iterator it1=a1._userAttributesVec3f->begin(), it1end=a1._userAttributesVec3f->end(); + Vec3fMap::iterator it2=a2._userAttributesVec3f->begin(), it2end=a2._userAttributesVec3f->end(); + for(; (it1!=it1end); ++it1){ + (*_userAttributesVec3f)[(*it1).first] = ((1-t)*(*it1).second+t*(*it2).second); + } + } + }else{ + _userAttributesVec3f = 0; + } +} + +StrokeAttribute::~StrokeAttribute() +{ + if(_userAttributesReal){ + _userAttributesReal->clear(); + delete _userAttributesReal; + } + if(_userAttributesVec2f){ + _userAttributesVec2f->clear(); + delete _userAttributesVec2f; + } + if(_userAttributesVec3f){ + _userAttributesVec3f->clear(); + delete _userAttributesVec3f; + } +} + +StrokeAttribute& StrokeAttribute::operator=(const StrokeAttribute& iBrother) +{ + int i; + _alpha = iBrother._alpha; + _thickness[0] = iBrother._thickness[0]; + _thickness[1] = iBrother._thickness[1]; + for(i=0; i<3; ++i) + _color[i] = iBrother._color[i]; + _visible = iBrother._visible; + if(iBrother._userAttributesReal){ + if(!_userAttributesReal) + _userAttributesReal = new realMap; + _userAttributesReal = new realMap(*(iBrother._userAttributesReal)); + }else{ + _userAttributesReal = 0; + } + if(iBrother._userAttributesVec2f){ + if(!_userAttributesVec2f) + _userAttributesVec2f = new Vec2fMap; + _userAttributesVec2f = new Vec2fMap(*(iBrother._userAttributesVec2f)); + }else{ + _userAttributesVec2f = 0; + } + if(iBrother._userAttributesVec3f){ + if(!_userAttributesVec3f) + _userAttributesVec3f = new Vec3fMap; + _userAttributesVec3f = new Vec3fMap(*(iBrother._userAttributesVec3f)); + }else{ + _userAttributesVec3f = 0; + } + return *this; +} + +float StrokeAttribute::getAttributeReal(const char *iName) const{ + if(!_userAttributesReal){ + cout << "StrokeAttribute warning: no real attribute was defined"<< endl; + return 0; + } + realMap::iterator a = _userAttributesReal->find(iName); + if(a ==_userAttributesReal->end()){ + cout << "StrokeAttribute warning: no real attribute was added with the name " << iName << endl; + return 0; + } + return (*a).second; +} +Vec2f StrokeAttribute::getAttributeVec2f(const char *iName) const{ + if(!_userAttributesVec2f){ + cout << "StrokeAttribute warning: no Vec2f attribute was defined "<< endl; + return 0; + } + Vec2fMap::iterator a = _userAttributesVec2f->find(iName); + if(a ==_userAttributesVec2f->end()){ + cout << "StrokeAttribute warning: no Vec2f attribute was added with the name " << iName << endl; + return 0; + } + return (*a).second; +} +Vec3f StrokeAttribute::getAttributeVec3f(const char *iName) const{ + if(!_userAttributesVec3f){ + cout << "StrokeAttribute warning: no Vec3f attribute was defined"<< endl; + return 0; + } + Vec3fMap::iterator a = _userAttributesVec3f->find(iName); + if(a ==_userAttributesVec3f->end()){ + cout << "StrokeAttribute warning: no Vec3f attribute was added with the name " << iName << endl; + return 0; + } + return (*a).second; +} +bool StrokeAttribute::isAttributeAvailableReal(const char *iName) const{ + if(!_userAttributesReal){ + return false; + } + realMap::iterator a = _userAttributesReal->find(iName); + if(a ==_userAttributesReal->end()){ + return false; + } + return true; +} +bool StrokeAttribute::isAttributeAvailableVec2f(const char *iName) const{ + if(!_userAttributesVec2f){ + return false; + } + Vec2fMap::iterator a = _userAttributesVec2f->find(iName); + if(a ==_userAttributesVec2f->end()){ + return false; + } + return true; +} +bool StrokeAttribute::isAttributeAvailableVec3f(const char *iName) const{ + if(!_userAttributesVec3f){ + return false; + } + Vec3fMap::iterator a = _userAttributesVec3f->find(iName); + if(a ==_userAttributesVec3f->end()){ + return false; + } + return true; +} +void StrokeAttribute::setAttributeReal(const char *iName, float att){ + if(!_userAttributesReal) + _userAttributesReal = new realMap; + (*_userAttributesReal)[iName] = att; +} +void StrokeAttribute::setAttributeVec2f(const char *iName, const Vec2f& att){ + if(!_userAttributesVec2f) + _userAttributesVec2f = new Vec2fMap; + (*_userAttributesVec2f)[iName] = att; +} +void StrokeAttribute::setAttributeVec3f(const char *iName, const Vec3f& att){ + if(!_userAttributesVec3f) + _userAttributesVec3f = new Vec3fMap; + (*_userAttributesVec3f)[iName] = att; +} + /**********************************/ + /* */ + /* */ + /* StrokeVertex */ + /* */ + /* */ + /**********************************/ + +StrokeVertex::StrokeVertex() + +:CurvePoint() +{ + + _CurvilignAbscissa = 0.f; + + _StrokeLength = 0.f; +} + + + +StrokeVertex::StrokeVertex(const StrokeVertex& iBrother) + +:CurvePoint(iBrother) +{ + _Attribute = iBrother._Attribute; + + _CurvilignAbscissa = 0.f; + + _StrokeLength = 0.f; +} +StrokeVertex::StrokeVertex(SVertex *iSVertex) + +:CurvePoint(iSVertex,0,0.f) + +{ + + _CurvilignAbscissa = 0.f; + + _StrokeLength = 0.f; + +} + + + +StrokeVertex::StrokeVertex(CurvePoint *iPoint) + +:CurvePoint(*iPoint) + +{ + + _CurvilignAbscissa = 0.f; + + _StrokeLength = 0.f; + +} + + + +StrokeVertex::StrokeVertex(StrokeVertex *iA, StrokeVertex *iB, float t3) + +:CurvePoint(iA,iB,t3) + +{ + + // interpolate attributes: + + _Attribute = StrokeAttribute(iA->attribute(), iB->attribute(), t3); + _CurvilignAbscissa = (1-t3)*iA->curvilinearAbscissa()+t3*iB->curvilinearAbscissa(); + _StrokeLength = iA->strokeLength(); + +} + + + +StrokeVertex::StrokeVertex(SVertex *iSVertex, const StrokeAttribute& iAttribute) + +:CurvePoint(iSVertex,0,0.f) + +{ + + _Attribute = iAttribute; + + _CurvilignAbscissa = 0.f; + + _StrokeLength = 0.f; + +} +StrokeVertex::~StrokeVertex() +{ +} + +StrokeVertex& StrokeVertex::operator=(const StrokeVertex& iBrother) +{ + ((CurvePoint*)this)->operator=(iBrother); + _Attribute = iBrother._Attribute; + + _CurvilignAbscissa = 0.f; + + _StrokeLength = 0.f; + return *this; +} + + /**********************************/ + /* */ + /* */ + /* Stroke */ + /* */ + /* */ + /**********************************/ + +Stroke::Stroke() +{ + _Length = 0; + _id = 0; + _sampling = FLT_MAX; + //_mediumType = DEFAULT_STROKE; + _mediumType = OPAQUE_MEDIUM; + _textureId = 0; + _tips = false; + _rep = 0; +} + +Stroke::Stroke(const Stroke& iBrother) +{ + for(vertex_container::const_iterator v=iBrother._Vertices.begin(), vend=iBrother._Vertices.end(); + v!=vend; + v++) + { + _Vertices.push_back(*v); + } + _Length = 0; + _id = iBrother._id; + _ViewEdges = iBrother._ViewEdges; + _sampling = iBrother._sampling; + _mediumType = iBrother._mediumType; + _textureId = iBrother._textureId; + _tips = iBrother._tips; + if(iBrother._rep) + _rep = new StrokeRep(*(iBrother._rep)); + else + _rep = 0; + +} + +Stroke::~Stroke() +{ + if(!_Vertices.empty()) + { + for(vertex_container::iterator v=_Vertices.begin(), vend=_Vertices.end(); + v!=vend; + v++) + { + delete (*v); + } + _Vertices.clear(); + } + + _ViewEdges.clear(); + if(_rep != 0) + { + delete _rep; + _rep = 0; + } +} + +Stroke& Stroke::operator=(const Stroke& iBrother) +{ + if(!_Vertices.empty()) + _Vertices.clear(); + + for(vertex_container::const_iterator v=iBrother._Vertices.begin(), vend=iBrother._Vertices.end(); + v!=vend; + v++) + { + _Vertices.push_back(*v); + } + _Length = iBrother._Length; + _id = iBrother._id; + _ViewEdges = iBrother._ViewEdges; + _sampling = iBrother._sampling; + if(_rep) delete _rep; + if(iBrother._rep) + _rep = new StrokeRep(*(iBrother._rep)); + return *this; +} + + +void Stroke::setLength(float iLength) +{ + _Length = iLength; + for(vertex_container::iterator v=_Vertices.begin(), vend=_Vertices.end(); + v!=vend; + ++v) + { + (*v)->setStrokeLength(iLength); + } +} + +float Stroke::ComputeSampling(int iNVertices) +{ + if(iNVertices <= (int)_Vertices.size()) //soc + return _sampling; + + float sampling = _Length/(float)(iNVertices-_Vertices.size()+1); + return sampling; +} + +class StrokeSegment +{ +public: + StrokeInternal::StrokeVertexIterator _begin; + StrokeInternal::StrokeVertexIterator _end; + float _length; + int _n; + float _sampling; + bool _resampled; + + StrokeSegment(StrokeInternal::StrokeVertexIterator ibegin, + StrokeInternal::StrokeVertexIterator iend, + float ilength, + int in, + float isampling) + { + _begin=ibegin; + _end=iend; + _length=ilength; + _n=in; + _sampling = isampling; + _resampled = false; + } +}; + +void Stroke::Resample(int iNPoints) +{ + int vertsize = strokeVerticesSize(); + if(iNPoints <= vertsize) + return; + + StrokeInternal::StrokeVertexIterator it = strokeVerticesBegin(); + StrokeInternal::StrokeVertexIterator next = it;++next; + StrokeInternal::StrokeVertexIterator itend = strokeVerticesEnd(); + + vertex_container newVertices; + real t=0.f; + StrokeVertex * newVertex = 0; + vector<StrokeSegment> strokeSegments; + int N=0; + float meanlength = 0; + int nsegments = 0; + while(((it!=itend)&&(next!=itend))) + { + Vec3r a((it)->point2d()); + Vec3r b((next)->point2d()); + Vec3r vec_tmp(b - a); + real norm_var = vec_tmp.norm(); + int numberOfPointsToAdd = (int)floor((iNPoints-strokeVerticesSize())*norm_var/_Length); + float csampling = norm_var/(float)(numberOfPointsToAdd+1); + strokeSegments.push_back(StrokeSegment(it,next,norm_var,numberOfPointsToAdd, csampling)); + N+=numberOfPointsToAdd; + meanlength += norm_var; + ++nsegments; + ++it; ++next; + } + meanlength /= (float)nsegments; + + // if we don't have enough points let's resample + // finer some segments + int NPointsToAdd = iNPoints-vertsize; + bool checkEveryone = false; + while(N < NPointsToAdd) + { + for(vector<StrokeSegment>::iterator s=strokeSegments.begin(), send=strokeSegments.end(); + s!=send; + ++s) + { + if(s->_sampling == 0.f) + continue; + + if(s->_resampled == false) + { + if((!checkEveryone) && (s->_length < meanlength)) + continue; + //resample + s->_n = s->_n+1; + s->_sampling = s->_length/(float)(s->_n+1); + s->_resampled = true; + N++; + if(N == NPointsToAdd) + break; + } + } + checkEveryone = true; + } + //actually resample: + for(vector<StrokeSegment>::iterator s=strokeSegments.begin(), send=strokeSegments.end(); + s!=send; + ++s) + { + newVertices.push_back(&(*(s->_begin))); + if(s->_sampling < _sampling) + _sampling = s->_sampling; + + t = s->_sampling/s->_length; + for(int i=0; i<s->_n; ++i) + { + newVertex = new StrokeVertex(&(*(s->_begin)),&(*(s->_end)),t); + newVertices.push_back(newVertex); + t += s->_sampling/s->_length; + } + it=s->_begin; + next=s->_end; + } + + // add last: + ++it;++next; + if((it != itend) && (next == itend))// && (t == 0.f)) + newVertices.push_back(&(*it)); + + int newsize = newVertices.size(); + if(newsize != iNPoints) + cerr << "Warning: incorrect points number" << endl; + + _Vertices.clear(); + _Vertices = newVertices; + newVertices.clear(); + + if(_rep) + { + delete _rep; + _rep = new StrokeRep(this); + } +} + + +void Stroke::Resample(float iSampling) +{ + // cerr<<"old size :"<<strokeVerticesSize()<<endl; + if(iSampling == 0) + + return; + if(iSampling >= _sampling) + return ; + + _sampling = iSampling; + // Resample... + //real curvilinearLength = 0.f; + vertex_container newVertices; + real t=0.f; + StrokeVertex * newVertex = 0; + StrokeInternal::StrokeVertexIterator it = strokeVerticesBegin(); + StrokeInternal::StrokeVertexIterator next = it;++next; + StrokeInternal::StrokeVertexIterator itend = strokeVerticesEnd(); + while(((it!=itend)&&(next!=itend))) + { + newVertices.push_back(&(*it)); + Vec3r a((it)->point2d()); + Vec3r b((next)->point2d()); + Vec3r vec_tmp(b - a); + real norm_var = vec_tmp.norm(); + if(norm_var <= _sampling) + { + //curvilinearLength += norm_var; + ++it; ++next; + continue; + } + + //curvilinearLength += _sampling; + t = _sampling/norm_var; + float limit = 0.99f; + while(t<limit) + { + newVertex = new StrokeVertex(&(*it),&(*next),t); + //newVertex->setCurvilinearAbscissa(curvilinearLength); + newVertices.push_back(newVertex); + t = t + _sampling/norm_var; + } + ++it; ++next; + } + // add last: + if((it != itend) && (next == itend))// && (t == 0.f)) + newVertices.push_back(&(*it)); + + _Vertices.clear(); + _Vertices = newVertices; + newVertices.clear(); + + if(_rep) + { + delete _rep; + _rep = new StrokeRep(this); + } +} + +void Stroke::RemoveVertex(StrokeVertex *iVertex) +{ + vertex_container::iterator it=_Vertices.begin(), itend=_Vertices.end(); + for(; + it!=itend; + ++it) + { + if((*it) == iVertex) + { + delete iVertex; + it = _Vertices.erase(it); // it is now the element just after the erased element + break; + } + } + // recompute various values (length, curvilign abscissa) + float curvabsc = 0.f; + it=_Vertices.begin(); + itend=_Vertices.end(); + vertex_container::iterator previous=it; + for(; + (it!=itend); + ++it) + { + if(it != previous) + curvabsc += ((*it)->point2d()-(*previous)->point2d()).norm(); + (*it)->setCurvilinearAbscissa(curvabsc); + previous = it; + } + _Length = curvabsc; + it=_Vertices.begin(); + for(; + (it!=itend); + ++it) + { + (*it)->setStrokeLength(_Length); + } +} + +void Stroke::InsertVertex(StrokeVertex *iVertex, StrokeInternal::StrokeVertexIterator next) +{ + vertex_container::iterator it=_Vertices.begin(), itend=_Vertices.end(); + + vertex_container::iterator itnext = next.getIt(); + _Vertices.insert(itnext, iVertex); + // recompute various values (length, curvilign abscissa) + float curvabsc = 0.f; + it=_Vertices.begin(); + itend=_Vertices.end(); + vertex_container::iterator previous=it; + for(; + (it!=itend); + ++it) + { + curvabsc += ((*it)->point2d()-(*previous)->point2d()).norm(); + (*it)->setCurvilinearAbscissa(curvabsc); + previous = it; + } + _Length = curvabsc; + for(; + (it!=itend); + ++it) + { + (*it)->setStrokeLength(_Length); + } +} + +//! embedding vertex iterator +Stroke::const_vertex_iterator Stroke::vertices_begin() const { return const_vertex_iterator(_Vertices.begin(),_Vertices.begin(), _Vertices.end()); } +Stroke::const_vertex_iterator Stroke::vertices_end() const { return const_vertex_iterator(_Vertices.end(),_Vertices.begin(), _Vertices.end()); } +Stroke::vertex_iterator Stroke::vertices_end() { return vertex_iterator(_Vertices.end(),_Vertices.begin(), _Vertices.end()); } + +StrokeInternal::StrokeVertexIterator Stroke::strokeVerticesBegin(float t) { + if((t!=0) && (t < _sampling)) + Resample(t); + return StrokeInternal::StrokeVertexIterator(this->_Vertices.begin(), this->_Vertices.begin(), this->_Vertices.end()); +} + +StrokeInternal::StrokeVertexIterator Stroke::strokeVerticesEnd() { + return StrokeInternal::StrokeVertexIterator(this->_Vertices.end(), this->_Vertices.begin(), this->_Vertices.end()); +} + +Interface0DIterator Stroke::verticesBegin() { + Interface0DIterator ret(new StrokeInternal::StrokeVertexIterator(this->_Vertices.begin(), + this->_Vertices.begin(), + this->_Vertices.end())); + return ret; +} + +Interface0DIterator Stroke::verticesEnd() { + Interface0DIterator ret(new StrokeInternal::StrokeVertexIterator(this->_Vertices.end(), + this->_Vertices.begin(), + this->_Vertices.end())); + return ret; +} + +Interface0DIterator Stroke::pointsBegin(float t) { + return verticesBegin(); // FIXME +} + +Interface0DIterator Stroke::pointsEnd(float t) { + return verticesEnd(); +} + +void Stroke::Render(const StrokeRenderer *iRenderer) +{ + if(!_rep) + _rep = new StrokeRep(this); + iRenderer->RenderStrokeRep(_rep); +} + +void Stroke::RenderBasic(const StrokeRenderer *iRenderer) +{ + if(!_rep) + _rep = new StrokeRep(this); + iRenderer->RenderStrokeRepBasic(_rep); +} + +Stroke::vertex_iterator Stroke::vertices_begin(float sampling) +{ + // Resample if necessary + if((sampling != 0) && (sampling < _sampling)) + Resample(sampling); + return vertex_iterator(_Vertices.begin(),_Vertices.begin(),_Vertices.end()); + //return _Vertices.begin(); +} +// +//Stroke::vertex_iterator Stroke::vertices_last() +//{ +// vertex_iterator res = vertices_begin(); +// vertex_iterator next = res;++next; +// while(!next.end()) +// { +// ++next; +// ++res; +// } +// return res; +//} +// +//Stroke::const_vertex_iterator Stroke::vertices_last() const +//{ +// const_vertex_iterator res = vertices_begin(); +// const_vertex_iterator next = res;++next; +// while(!next.end()) +// { +// ++next; +// ++res; +// } +// return res; +//} + +//Stroke::vertex_container::reverse_iterator Stroke::vertices_last(float sampling) +//{ +// // Resample if necessary +// if(sampling < _sampling) +// Resample(sampling); +// return _Vertices.rbegin(); +//} + + +//inline Vec3r shaded_color(int iCombination = 0) const ; +//inline Vec<3,real> Stroke::orientation2d(const_vertex_iterator it) const +//{ +// return iterator_edge_orientation2d_function<Stroke, const_vertex_iterator>(this, it); +//} +// Vec3r Stroke::orientation2d(int iCombination) const +// { +// return edge_orientation2d_function<Stroke>(*this, iCombination); +// } +//inline Vec3r Stroke::orientation3d(const_vertex_iterator it) const +//{ +// return iterator_edge_orientation3d_function<Stroke, const_vertex_iterator>(*this, it); +//} +// Vec3r Stroke::orientation3d(int iCombination) const +// { +// return edge_orientation3d_function<Stroke>(*this, iCombination); +// } + +//Material Stroke::material() const +//{ +// const_vertex_iterator v=vertices_begin(), vend=strokeVerticesEnd(); +// Material mat = (*v)->material(); +// for(;v!=vend;++v) +// { +// if(mat != (*v)->material()) +// Exception::raiseException(); +// } +// return mat; +//} + +//int Stroke::qi() const +//{ +// const_vertex_iterator v=vertices_begin(), vend=vertices_end(); +// int qi_= (*v)->qi(); +// for(;v!=vend;++v) +// { +// if((*v)->qi() != qi_) +// Exception::raiseException(); +// } +// return qi_; +//} +//inline occluder_container::const_iterator occluders_begin() const {return _FEdgeA->occluders().begin();} +//inline occluder_container::const_iterator occluders_end() const {return _FEdgeA->occluders().end();} + +//int Stroke::occluders_size() const +//{ +// return qi(); +//} +// +//bool Stroke::occluders_empty() const +//{ +// const_vertex_iterator v=vertices_begin(), vend=vertices_end(); +// bool empty = (*v)->occluders_empty(); +// for(;v!=vend;++v) +// { +// if((*v)->occluders_empty() != empty) +// Exception::raiseException(); +// } +// return empty; +//} +////inline const polygon3d& occludee() const {return *(_FEdgeA->aFace());} +//const SShape * Stroke::occluded_shape() const +//{ +// const_vertex_iterator v=vertices_begin(), vend=vertices_end(); +// const SShape *sshape = (*v)->occluded_shape(); +// for(;v!=vend;++v) +// { +// if((*v)->occluded_shape() != sshape) +// Exception::raiseException(); +// } +// return sshape; +//} +// +//const bool Stroke::occludee_empty() const +//{ +// const_vertex_iterator v=vertices_begin(), vend=vertices_end(); +// bool empty = (*v)->occludee_empty(); +// for(;v!=vend;++v) +// { +// if((*v)->occludee_empty() != empty) +// Exception::raiseException(); +// } +// return empty; +//} + +//const SShape * Stroke::shape() const +//{ +// const_vertex_iterator v=vertices_begin(), vend=vertices_end(); +// const SShape *sshape = (*v)->shape(); +// for(;v!=vend;++v) +// { +// if((*v)->shape() != sshape) +// Exception::raiseException(); +// } +// return sshape; +//} + +// real Stroke::z_discontinuity(int iCombination) const +// { +// return z_discontinuity_edge_function<Stroke>(*this, iCombination); +// } + +// Vec3r Stroke::curvature2d_as_vector(int iCombination) const +// { +// return curvature2d_as_vector_edge_function<Stroke>(*this, iCombination); +// } + +// real Stroke::curvature2d_as_angle(int iCombination) const +// { +// return curvature2d_as_angle_edge_function<Stroke>(*this, iCombination); +// } + +// float Stroke::shape_importance(int iCombination) const +// { +// return shape_importance_edge_function<Stroke>(*this, iCombination); +// } + + +// float Stroke::local_average_depth(int iCombination ) const +// { +// return local_average_depth_edge_function<Stroke >(*this, iCombination); +// } + +// float Stroke::local_depth_variance(int iCombination) const +// { +// return local_depth_variance_edge_function<Stroke>(*this, iCombination); +// } + +// real Stroke::local_average_density(float sigma , int iCombination ) const +// { +// return density_edge_function<Stroke>(*this, iCombination); +// } diff --git a/source/blender/freestyle/intern/stroke/Stroke.h b/source/blender/freestyle/intern/stroke/Stroke.h new file mode 100755 index 00000000000..5e0974edea7 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/Stroke.h @@ -0,0 +1,588 @@ +// +// Filename : Stroke.h +// Author(s) : Stephane Grabli +// Purpose : Classes to define a stroke +// Date of creation : 09/09/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef STROKE_H +# define STROKE_H + +# include "../view_map/Silhouette.h" +# include <vector> +# include <map> +# include "../system/FreestyleConfig.h" +# include "Curve.h" +# include "../view_map/Interface1D.h" +# include "../system/StringUtils.h" + + +// +// StrokeAttribute +// +//////////////////////////////////////////////////////// + +/*! Class to define an attribute associated to a Stroke Vertex. + * This attribute stores the color, alpha and thickness values + * for a Stroke Vertex. + */ +class LIB_STROKE_EXPORT StrokeAttribute +{ +public: + + /*! default constructor */ + StrokeAttribute(); + /*! Copy constructor */ + StrokeAttribute(const StrokeAttribute& iBrother); + /*! Builds a stroke vertex attribute from + * a set of parameters. + * \param iRColor + * The Red Component value. + * \param iGColor + * The Green Component value. + * \param iBColor + * The Blue Component value. + * \param iAlpha + * The transparency value + * \param iRThickness + * The thickness of the stroke on the right + * \param iLThickness + * The Thickness of the stroke on the left + */ + StrokeAttribute(float iRColor, float iGColor, float iBColor, + float iAlpha, + float iRThickness, float iLThickness); + + /*! Interpolation constructor. + * Builds a StrokeAttribute from two + * StrokeAttributes and an interpolation parameter. + * \param a1 + * The first Attribute. + * \param a2 + * The second parameter. + * \param t + * The interpolation parameter. + */ + StrokeAttribute(const StrokeAttribute& a1, const StrokeAttribute& a2, float t); + + /*! destructor */ + virtual ~StrokeAttribute(); + + /* operators */ + /*! operator = */ + StrokeAttribute& operator=(const StrokeAttribute& iBrother); + + /* accessors */ + /*! Returns the attribute's color. + * \return The array of 3 floats containing the R,G,B values + * of the attribute's color. + */ + inline const float* getColor() const { return _color; } + /*! Returns the R color component. */ + inline const float getColorR() const { return _color[0]; } + /*! Returns the G color component. */ + inline const float getColorG() const { return _color[1]; } + /*! Returns the B color component. */ + inline const float getColorB() const { return _color[2]; } + /*! Returns the RGB color components. */ + inline Vec3f getColorRGB() const { return Vec3f(_color[0], _color[1], _color[2]); } + /*! Returns the alpha color component. */ + inline float getAlpha() const { return _alpha; } + /*! Returns the attribute's thickness. + * \return an array of 2 floats. the first value is + * the thickness on the right of the vertex when following + * the stroke, the second one is the thickness on the left. + */ + inline const float* getThickness() const { return _thickness; } + /*! Returns the thickness on the right of the vertex when following the + * stroke. */ + inline const float getThicknessR() const { return _thickness[0]; } + /*! Returns the thickness on the left of the vertex when following the + * stroke. */ + inline const float getThicknessL() const { return _thickness[1]; } + /*! Returns the thickness on the right and on the left of the vertex when following the + * stroke. */ + inline Vec2f getThicknessRL() const { return Vec2f(_thickness[0], _thickness[1]); } + + /*! Returns true if the strokevertex is visible, false otherwise */ + inline bool isVisible() const {return _visible;} + + /*! Returns an attribute of type real + * \param iName + * The name of the attribute + */ + float getAttributeReal(const char *iName) const; + /*! Returns an attribute of type Vec2f + * \param iName + * The name of the attribute + */ + Vec2f getAttributeVec2f(const char *iName) const; + /*! Returns an attribute of type Vec3f + * \param iName + * The name of the attribute + */ + Vec3f getAttributeVec3f(const char *iName) const; + + /*! Checks whether the attribute iName is availbale */ + bool isAttributeAvailableReal(const char *iName) const ; + /*! Checks whether the attribute iName is availbale */ + bool isAttributeAvailableVec2f(const char *iName) const ; + /*! Checks whether the attribute iName is availbale */ + bool isAttributeAvailableVec3f(const char *iName) const ; + + /* modifiers */ + /*! sets the attribute's color. + * \param r + * The new R value. + * \param g + * The new G value. + * \param b + * The new B value. + */ + inline void setColor(float r, float g, float b) { _color[0]=r; _color[1]=g; _color[2]=b; } + /*! sets the attribute's color. + * \param iRGB + * The new RGB values. + */ + inline void setColor(const Vec3f& iRGB) { _color[0]=iRGB[0]; _color[1]=iRGB[1]; _color[2]=iRGB[2]; } + /*! sets the attribute's alpha value. + * \param alpha + * The new alpha value. + */ + inline void setAlpha(float alpha) { _alpha = alpha; } + /*! sets the attribute's thickness. + * \param tr + * The thickness on the right of the vertex when following the stroke. + * \param tl + * The thickness on the left of the vertex when following the stroke. + */ + inline void setThickness(float tr, float tl) { _thickness[0]=tr; _thickness[1]=tl; } + /*! sets the attribute's thickness. + * \param tRL + * The thickness on the right and on the left of the vertex when following the stroke. + */ + inline void setThickness(const Vec2f& tRL) { _thickness[0]=tRL[0]; _thickness[1]=tRL[1]; } + + /*! sets the visible flag. True means visible. */ + inline void setVisible(bool iVisible){ _visible = iVisible; } + + /*! Adds a user defined attribute of type real + * If there is no attribute of name iName, it is added. + * Otherwise, the new value replaces the old one. + * \param iName + * The name of the attribute + * \param att + * The attribute's value + */ + void setAttributeReal(const char *iName, float att); + /*! Adds a user defined attribute of type Vec2f + * If there is no attribute of name iName, it is added. + * Otherwise, the new value replaces the old one. + * \param iName + * The name of the attribute + * \param att + * The attribute's value + */ + void setAttributeVec2f(const char *iName, const Vec2f& att); + /*! Adds a user defined attribute of type Vec3f + * If there is no attribute of name iName, it is added. + * Otherwise, the new value replaces the old one. + * \param iName + * The name of the attribute + * \param att + * The attribute's value + */ + void setAttributeVec3f(const char *iName, const Vec3f& att); + +private: + + typedef std::map<const char*, float, StringUtils::ltstr> realMap ; + typedef std::map<const char*, Vec2f, StringUtils::ltstr> Vec2fMap ; + typedef std::map<const char*, Vec3f, StringUtils::ltstr> Vec3fMap ; + + float _color[3]; //! the color + float _alpha; //! alpha + float _thickness[2]; //! the thickness on the right and on the left of the backbone vertex (the stroke is oriented) + bool _visible; + realMap *_userAttributesReal; + Vec2fMap *_userAttributesVec2f; + Vec3fMap *_userAttributesVec3f; +}; + + +// +// StrokeVertex +// +//////////////////////////////////////////////////////// + +/*! Class to define a stroke vertex. + */ +class LIB_STROKE_EXPORT StrokeVertex : public CurvePoint +{ +public: // Implementation of Interface0D + + /*! Returns the string "StrokeVertex"*/ + virtual string getExactTypeName() const { + return "StrokeVertex"; + } + +private: + + StrokeAttribute _Attribute; //! The attribute associated to the vertex + float _CurvilignAbscissa; //! the curvilign abscissa + float _StrokeLength; // stroke length + +public: + + /*! default constructor */ + StrokeVertex(); + /*! Copy constructor */ + StrokeVertex(const StrokeVertex& iBrother); + /*! Builds a stroke vertex from a SVertex */ + StrokeVertex(SVertex *iSVertex); + /*! Builds a stroke vertex from a CurvePoint */ + StrokeVertex(CurvePoint *iPoint); + /*! Builds Stroke Vertex from 2 stroke vertices and an interpolation parameter*/ + StrokeVertex(StrokeVertex *iA, StrokeVertex *iB, float t3); + /*! Builds a stroke from a view vertex and an attribute */ + StrokeVertex(SVertex *iSVertex, const StrokeAttribute& iAttribute); + /*! destructor */ + virtual ~StrokeVertex(); + + /* operators */ + /*! operator = */ + StrokeVertex& operator=(const StrokeVertex& iBrother); + + /* accessors */ + /*! Returns the 2D point x coordinate */ + inline real x() const { return _Point2d[0]; } + /*! Returns the 2D point y coordinate */ + inline real y() const { return _Point2d[1]; } + /*! Returns the 2D point coordinates as a Vec2d */ + Vec2f getPoint () {return Vec2f((float)point2d()[0], (float)point2d()[1]);} + /*! Returns the ith 2D point coordinate (i=0 or 1)*/ + inline real operator[](const int i) const { return _Point2d[i]; } + /*! Returns the StrokeAttribute for this StrokeVertex */ + inline const StrokeAttribute& attribute() const { return _Attribute; } + /*! Returns a non-const reference to the StrokeAttribute of this StrokeVertex */ + inline StrokeAttribute& attribute() {return _Attribute;} + /*! Returns the curvilinear abscissa */ + inline float curvilinearAbscissa() const {return _CurvilignAbscissa;} + /*! Returns the length of the Stroke to which this StrokeVertex belongs */ + inline float strokeLength() const {return _StrokeLength;} + /*! Returns the curvilinear abscissa of this StrokeVertex in the Stroke */ + inline float u() const {return _CurvilignAbscissa/_StrokeLength;} + + /* modifiers */ + /*! sets the 2D x value */ + inline void setX(real x) { _Point2d[0]=x; } + /*! sets the 2D y value */ + inline void setY(real y) { _Point2d[1]=y; } + /*! sets the 2D x and y values */ + inline void setPoint(real x, real y) { _Point2d[0]=x; _Point2d[1]=y;} + /*! sets the 2D x and y values */ + inline void setPoint(const Vec2f& p) { _Point2d[0] = p[0];_Point2d[1] = p[1];} + /*! Returns a reference to the ith 2D point coordinate (i=0 or 1) */ + inline real& operator[](const int i) { return _Point2d[i]; } + /*! sets the attribute. */ + inline void setAttribute(const StrokeAttribute& iAttribute) { _Attribute = iAttribute; } + /*! sets the curvilinear abscissa of this StrokeVertex in the Stroke */ + inline void setCurvilinearAbscissa(float iAbscissa) {_CurvilignAbscissa = iAbscissa;} + /*! sets the Stroke's length (it's only a value stored by the Stroke Vertex, it won't + * change the real Stroke's length.) + */ + inline void setStrokeLength(float iLength) {_StrokeLength = iLength;} + + /* interface definition */ + /* inherited */ + +}; + + +// +// Stroke +// +//////////////////////////////////////////////////////// + +class StrokeRenderer; +class StrokeRep; + +namespace StrokeInternal { + class vertex_const_traits ; + class vertex_nonconst_traits ; + template<class Traits> class vertex_iterator_base; + class StrokeVertexIterator; +} // end of namespace StrokeInternal + +/*! Class to define a stroke. + * A stroke is made of a set of 2D vertices (StrokeVertex), regularly spaced out. + * This set of vertices defines the stroke's backbone geometry. + * Each of these stroke vertices defines the stroke's shape and appearance + * at this vertex position. + */ +class LIB_STROKE_EXPORT Stroke : public Interface1D +{ +public: // Implementation of Interface1D + + /*! Returns the string "Stroke" */ + virtual string getExactTypeName() const { + return "Stroke"; + } + + // Data access methods + + /*! Returns the Id of the Stroke */ + virtual Id getId() const { + return _id; + } + /*! The different blending modes + * available to similate the interaction + * media-medium. + */ + typedef enum{ + DRY_MEDIUM,/*!< To simulate a dry medium such as Pencil or Charcoal.*/ + HUMID_MEDIUM,/*!< To simulate ink painting (color substraction blending).*/ + OPAQUE_MEDIUM, /*!< To simulate an opaque medium (oil, spray...).*/ + } MediumType; + + +public: + typedef std::deque<StrokeVertex*> vertex_container; // the vertices container + typedef std::vector<ViewEdge*> viewedge_container; // the viewedges container + typedef StrokeInternal::vertex_iterator_base<StrokeInternal::vertex_nonconst_traits > vertex_iterator; + typedef StrokeInternal::vertex_iterator_base<StrokeInternal::vertex_const_traits> const_vertex_iterator; + +public: + //typedef StrokeVertex vertex_type; +private: + vertex_container _Vertices; //! The stroke's backbone vertices + Id _id; + float _Length; // The stroke length + viewedge_container _ViewEdges; + float _sampling; + StrokeRenderer *_renderer; // mark implementation OpenGL renderer + MediumType _mediumType; + unsigned int _textureId; + bool _tips; + Vec2r _extremityOrientations[2]; // the orientations of the first and last extermity + StrokeRep *_rep; + +public: + /*! default constructor */ + Stroke(); + /*! copy constructor */ + Stroke(const Stroke& iBrother); + /*! Builds a stroke from a set of StrokeVertex. + * This constructor is templated by an iterator type. + * This iterator type must allow the vertices parsing + * using the ++ operator. + * \param iBegin + * The iterator pointing to the first vertex. + * \param iEnd + * The iterator pointing to the end of the vertex list. + */ + template<class InputVertexIterator> + Stroke(InputVertexIterator iBegin, InputVertexIterator iEnd); + + /*! Destructor */ + virtual ~Stroke(); + + /* operators */ + /*! operator = */ + Stroke& operator=(const Stroke& iBrother); + + /*! Compute the sampling needed to get iNVertices + * vertices. + * If the specified number of vertices is less than the + * actual number of vertices, the actual sampling value is returned. + * (To remove Vertices, use the RemoveVertex() method of this class). + * \param iNVertices + * The number of StrokeVertices we eventually want + * in our Stroke. + * \return the sampling that must be used in the Resample(float) method. + * @see Resample(int) + * @see Resample(float) + */ + float ComputeSampling(int iNVertices); + + /*! Resampling method. + * Resamples the curve so that it eventually + * has iNPoints. That means it is going + * to add iNPoints-vertices_size, if vertices_size + * is the number of points we already have. + * Is vertices_size >= iNPoints, no resampling is done. + * \param iNPoints + * The number of vertices we eventually want in our stroke. + */ + void Resample(int iNPoints); + + /*! Resampling method. + * Resamples the curve with a given sampling. + * If this sampling is < to the actual sampling + * value, no resampling is done. + * \param iSampling + * The new sampling value. + */ + void Resample(float iSampling); + + /*! Removes the stroke vertex iVertex + * from the stroke. + * The length and curvilinear abscissa are updated + * consequently. + */ + void RemoveVertex(StrokeVertex *iVertex); + + /*! Inserts the stroke vertex iVertex + * in the stroke before next. + * The length, curvilinear abscissa are updated + * consequently. + * \param iVertex + * The StrokeVertex to insert in the Stroke. + * \param next + * A StrokeVertexIterator pointing to the StrokeVeretx before + * which iVertex must be inserted. + */ + void InsertVertex(StrokeVertex *iVertex, StrokeInternal::StrokeVertexIterator next); + + /* Render method */ + void Render(const StrokeRenderer *iRenderer ); + void RenderBasic(const StrokeRenderer *iRenderer ); + + /* Iterator definition */ + + /* accessors */ + /*! Returns the 2D length of the Stroke */ + inline real getLength2D() const {return _Length;} + /*! Returns a reference to the time stamp value of the stroke. */ + /*! Returns the MediumType used for this Stroke. */ + inline MediumType getMediumType() const {return _mediumType;} + /*! Returns the id of the texture used to simulate th marks system + * for this Stroke + */ + inline unsigned int getTextureId() {return _textureId;} + /*! Returns true if this Stroke uses a texture with tips, false + * otherwise. + */ + inline bool hasTips() const {return _tips;} + /* these advanced iterators are used only in C++ */ + inline int vertices_size() const {return _Vertices.size();} + inline viewedge_container::const_iterator viewedges_begin() const {return _ViewEdges.begin();} + inline viewedge_container::iterator viewedges_begin() {return _ViewEdges.begin();} + inline viewedge_container::const_iterator viewedges_end() const {return _ViewEdges.end();} + inline viewedge_container::iterator viewedges_end() {return _ViewEdges.end();} + inline int viewedges_size() const {return _ViewEdges.size();} + + inline Vec2r getBeginningOrientation() const {return _extremityOrientations[0];} + inline real getBeginningOrientationX() const {return _extremityOrientations[0].x();} + inline real getBeginningOrientationY() const {return _extremityOrientations[0].y();} + inline Vec2r getEndingOrientation() const {return _extremityOrientations[1];} + inline real getEndingOrientationX() const {return _extremityOrientations[1].x();} + inline real getEndingOrientationY() const {return _extremityOrientations[1].y();} + + + /* modifiers */ + /*! sets the Id of the Stroke. */ + inline void setId(const Id& id) {_id = id;} + /*! sets the 2D length of the Stroke. */ + void setLength(float iLength); + /*! sets the medium type that must be used for this Stroke. */ + inline void setMediumType(MediumType iType) {_mediumType = iType;} + /*! sets the texture id to be used to simulate the marks system for this Stroke. */ + inline void setTextureId(unsigned int id) {_textureId = id;} + /*! sets the flag telling whether this stroke is using a texture with + * tips or not. + */ + inline void setTips(bool iTips) {_tips = iTips;} + + inline void push_back(StrokeVertex* iVertex) { _Vertices.push_back(iVertex); } + inline void push_front(StrokeVertex* iVertex) { _Vertices.push_front(iVertex); } + inline void AddViewEdge(ViewEdge *iViewEdge) {_ViewEdges.push_back(iViewEdge);} + inline void setBeginningOrientation(const Vec2r& iOrientation) {_extremityOrientations[0] = iOrientation;} + inline void setBeginningOrientation(real x, real y) {_extremityOrientations[0] = Vec2r(x,y);} + inline void setEndingOrientation(const Vec2r& iOrientation) {_extremityOrientations[1] = iOrientation;} + inline void setEndingOrientation(real x, real y) {_extremityOrientations[1] = Vec2r(x,y);} + + /* Information access interface */ + + // embedding vertex iterator + const_vertex_iterator vertices_begin() const; + vertex_iterator vertices_begin(float t=0.f); + const_vertex_iterator vertices_end() const; + vertex_iterator vertices_end(); + + /*! Returns a StrokeVertexIterator pointing on the first StrokeVertex of the + * Stroke. One can specifly a sampling value to resample the Stroke + * on the fly if needed. + * \param t + * The resampling value with which we want our Stroke to be resampled. + * If 0 is specified, no resampling is done. + */ + StrokeInternal::StrokeVertexIterator strokeVerticesBegin(float t=0.f); + /*! Returns a StrokeVertexIterator pointing after the last StrokeVertex of the + * Stroke. + */ + StrokeInternal::StrokeVertexIterator strokeVerticesEnd(); + /*! Returns the number of StrokeVertex constituing the Stroke. */ + inline unsigned int strokeVerticesSize() const {return _Vertices.size();} + + /*! Returns the i-th StrokeVertex constituting the Stroke. */ + inline StrokeVertex& strokeVerticeAt(unsigned int i) {return *(_Vertices.at(i));} + + // Iterator access (Interface1D) + /*! Returns an Interface0DIterator pointing on the first StrokeVertex of the + * Stroke. + */ + virtual Interface0DIterator verticesBegin(); + /*! Returns an Interface0DIterator pointing after the last StrokeVertex of the + * Stroke. + */ + virtual Interface0DIterator verticesEnd(); + + virtual Interface0DIterator pointsBegin(float t=0.f); + virtual Interface0DIterator pointsEnd(float t=0.f); +}; + + + +// +// Implementation +// +//////////////////////////////////////////////////////// + + +template<class InputVertexIterator> +Stroke::Stroke(InputVertexIterator iBegin, InputVertexIterator iEnd) +{ + for(InputVertexIterator v=iBegin, vend=iEnd; + v!=vend; + v++) + { + _Vertices.push_back(*v); + } + _Length = 0; + _id = 0; +} + +#endif // STROKE_H diff --git a/source/blender/freestyle/intern/stroke/StrokeAdvancedIterators.h b/source/blender/freestyle/intern/stroke/StrokeAdvancedIterators.h new file mode 100755 index 00000000000..279a0b12089 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/StrokeAdvancedIterators.h @@ -0,0 +1,142 @@ +// +// Filename : StrokeAdvancedIterators.h +// Author(s) : Stephane Grabli +// Purpose : Iterators used to iterate over the elements of the Stroke +// Can't be used in python +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef STROKEADVANCEDITERATORS_H +# define STROKEADVANCEDITERATORS_H + +# include "Stroke.h" + +namespace StrokeInternal { + + class vertex_const_traits : public Const_traits<StrokeVertex*> { + public: + typedef std::deque<StrokeVertex*> vertex_container; + typedef vertex_container::const_iterator vertex_container_iterator ; + }; + class vertex_nonconst_traits : public Nonconst_traits<StrokeVertex*> { + public: + typedef std::deque<StrokeVertex*> vertex_container; //! the vertices container + typedef vertex_container::iterator vertex_container_iterator ; + }; + + + template<class Traits> + class vertex_iterator_base : public IteratorBase<Traits,BidirectionalIteratorTag_Traits> + { + public: + typedef vertex_iterator_base<Traits> Self; + protected: + typedef IteratorBase<Traits,BidirectionalIteratorTag_Traits> parent_class; + typedef typename Traits::vertex_container_iterator vertex_container_iterator; + typedef vertex_iterator_base<vertex_nonconst_traits> iterator; + typedef vertex_iterator_base<vertex_const_traits> const_iterator; + //protected: + public: + vertex_container_iterator _it; + vertex_container_iterator _begin; + vertex_container_iterator _end; + public: + friend class Stroke; + //friend class vertex_iterator; + inline vertex_iterator_base() + : parent_class() + {} + inline vertex_iterator_base(const iterator& iBrother) + : parent_class() + {_it = iBrother._it;_begin = iBrother._begin;_end = iBrother._end;} + inline vertex_iterator_base(const const_iterator& iBrother) + : parent_class() + {_it = iBrother._it;_begin = iBrother._begin;_end = iBrother._end;} + //protected://FIXME + public: + inline vertex_iterator_base(vertex_container_iterator it, vertex_container_iterator begin, vertex_container_iterator end) + : parent_class() + { + _it = it; + _begin = begin; + _end = end; + } + + public: + virtual ~vertex_iterator_base() {} + + virtual bool begin() const {return _it==_begin? true : false;} + virtual bool end() const {return _it==_end ? true : false;} + + // operators + inline Self& operator++() // operator corresponding to ++i + { + ++_it; + return *(this); + } + inline Self operator++(int) // opérateur correspondant à i++ + { + Self tmp = *this; // C'est pour cela qu'on stocke la valeur + ++_it; // dans un temporaire. + return tmp; + } + inline Self& operator--() // operator corresponding to ++i + { + --_it; + return *(this); + } + inline Self operator--(int) // opérateur correspondant à i++ + { // c.a.d qui renvoie la valeur *puis* incrémente. + Self tmp = *this; // C'est pour cela qu'on stocke la valeur + --_it; // dans un temporaire. + return tmp; + } + + // comparibility + virtual bool operator!=(const Self& b) const + { + return (_it != b._it); + } + virtual bool operator==(const Self& b) const + { + return !(*this != b); + } + + // dereferencing + virtual typename Traits::reference operator*() const {return *(_it);} + virtual typename Traits::pointer operator->() const { return &(operator*());} + + /*! accessors */ + inline vertex_container_iterator it() const {return _it;} + inline vertex_container_iterator getBegin() const {return _begin;} + inline vertex_container_iterator getEnd() const {return _end;} + }; + +} // end of namespace StrokeInternal + + +#endif // STROKEADVANCEDITERATORS_H + + diff --git a/source/blender/freestyle/intern/stroke/StrokeIO.cpp b/source/blender/freestyle/intern/stroke/StrokeIO.cpp new file mode 100755 index 00000000000..903a198adc2 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/StrokeIO.cpp @@ -0,0 +1,55 @@ +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "StrokeIO.h" +#include "StrokeAdvancedIterators.h" + + +ostream& operator<<(ostream& out, const StrokeAttribute& iStrokeAttribute){ + out << " StrokeAttribute" << endl; + out << " color : (" << iStrokeAttribute.getColorR() << "," << iStrokeAttribute.getColorG() << "," << iStrokeAttribute.getColorB() << ")" << endl; + out << " alpha : " << iStrokeAttribute.getAlpha() << endl; + out << " thickness : " << iStrokeAttribute.getThicknessR() << ", " << iStrokeAttribute.getThicknessL() << endl; + out << " visible : " << iStrokeAttribute.isVisible() << endl; + return out; +} + +ostream& operator<<(ostream& out, const StrokeVertex& iStrokeVertex){ + out << " StrokeVertex" << endl; + out << " id : " << iStrokeVertex.getId() << endl; + out << " curvilinear length : " << iStrokeVertex.curvilinearAbscissa() << endl; + out << " 2d coordinates : (" << iStrokeVertex.getProjectedX() << "," << iStrokeVertex.getProjectedY() << "," << iStrokeVertex.getProjectedZ() << ")" << endl; + out << " 3d coordinates : (" << iStrokeVertex.getX() << "," << iStrokeVertex.getY() << "," << iStrokeVertex.getZ() << ")"<< endl; + out << iStrokeVertex.attribute() << endl; + return out; +} + +ostream& operator<<(ostream& out, const Stroke& iStroke){ + out << "Stroke" << endl; + out << " id : " << iStroke.getId() << endl; + out << " length : " << iStroke.getLength2D() << endl; + out << " medium type : " << iStroke.getMediumType() << endl; + for(Stroke::const_vertex_iterator v=iStroke.vertices_begin(), vend=iStroke.vertices_end(); + v!=vend; + ++v){ + out << *(*v) << endl; + } + return out; +} diff --git a/source/blender/freestyle/intern/stroke/StrokeIO.h b/source/blender/freestyle/intern/stroke/StrokeIO.h new file mode 100755 index 00000000000..150c8340778 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/StrokeIO.h @@ -0,0 +1,47 @@ +// +// Filename : StrokeIO.h +// Author(s) : Stephane Grabli +// Purpose : Functions to manage I/O for the stroke +// Date of creation : 03/02/2004 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef STROKEIO_H +# define STROKEIO_H + +# include "Stroke.h" +# include <iostream> +# include "../system/FreestyleConfig.h" + +LIB_STROKE_EXPORT +ostream& operator<<(ostream& out, const StrokeAttribute& iStrokeAttribute); + +LIB_STROKE_EXPORT +ostream& operator<<(ostream& out, const StrokeVertex& iStrokeVertex); + +LIB_STROKE_EXPORT +ostream& operator<<(ostream& out, const Stroke& iStroke); + + +#endif // STROKEIO_H diff --git a/source/blender/freestyle/intern/stroke/StrokeIterators.h b/source/blender/freestyle/intern/stroke/StrokeIterators.h new file mode 100755 index 00000000000..b51189f3990 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/StrokeIterators.h @@ -0,0 +1,229 @@ +// +// Filename : StrokeIterators.h +// Author(s) : Stephane Grabli +// Purpose : Iterators used to iterate over the elements of the Stroke +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef STROKEITERATORS_H +# define STROKEITERATORS_H + +# include "Stroke.h" + +namespace StrokeInternal { + + // + // StrokeVertexIterator + // + ///////////////////////////////////////////////// + + /*! Class defining an iterator designed to iterate over + * the StrokeVertex of a Stroke. + * An instance of a StrokeVertexIterator can only be obtained + * from a Stroke by calling strokeVerticesBegin() or strokeVerticesEnd(). + * It is iterating over the same vertices as an Interface0DIterator. + * The difference resides in the object access. Indeed, an Interface0DIterator + * allows only an access to an Interface0D whereas we could need + * to access the specialized StrokeVertex type. In this case, one + * should use a StrokeVertexIterator. + * The castToInterface0DIterator() method is useful to get an Interface0DIterator + * from a StrokeVertexIterator in order to call any functions of the + * type UnaryFunction0D. + * \attention In the scripting language, you must call + * \code it2 = StrokeVertexIterator(it1) \endcode instead of + * \code it2 = it1 \endcode + * where \a it1 and \a it2 are 2 StrokeVertexIterator. + * Otherwise, incrementing \a it1 will also increment \a it2. + */ + class StrokeVertexIterator : public Interface0DIteratorNested + { + public: + + /*! Default constructor. */ + StrokeVertexIterator() {} + + /*! Copy constructor. */ + StrokeVertexIterator(const StrokeVertexIterator& vi) { + _it = vi._it; + _begin = vi._begin; + _end = vi._end; + } + + StrokeVertexIterator(const ::Stroke::vertex_container::iterator& it, + const ::Stroke::vertex_container::iterator& begin, + const ::Stroke::vertex_container::iterator& end) { + _it = it; + _begin = begin; + _end = end; + } + + virtual ~StrokeVertexIterator() {} + + /*! Casts this StrokeVertexIterator into an Interface0DIterator. + * Useful for any call to a function of the type UnaryFunction0D. + */ + inline Interface0DIterator castToInterface0DIterator() const { + Interface0DIterator ret(new StrokeVertexIterator(*this)); + return ret; + } + /*! operator= + * \attention In the scripting language, you must call + * \code it2 = StrokeVertexIterator(it1) \endcode instead of + * \code it2 = it1 \endcode + * where \a it1 and \a it2 are 2 StrokeVertexIterator. + * Otherwise, incrementing \a it1 will also increment \a it2. + * + */ + StrokeVertexIterator& operator=(const StrokeVertexIterator& vi) { + _it = vi._it; + _begin = vi._begin; + _end = vi._end; + return *this; + } + + /*! Returns the string "StrokeVertexIterator". */ + virtual string getExactTypeName() const { + return "StrokeVertexIterator"; + } + + /*! Returns a reference to the pointed StrokeVertex. + * In the scripting language, you must call + * "getObject()"instead. + */ + virtual StrokeVertex& operator*() { + return **_it; + } + + /*! Returns a pointer to the pointed StrokeVertex. + * Can't be called in the scripting language. + */ + virtual StrokeVertex* operator->() { + return &(operator*()); + } + + /*! Increments. In the scripting language, call + * "increment()". + */ + virtual StrokeVertexIterator& operator++() { + increment(); + return *this; + } + + /*! Increments. In the scripting language, call + * "increment()". + */ + virtual StrokeVertexIterator operator++(int) { + StrokeVertexIterator ret(*this); + increment(); + return ret; + } + + /*! Decrements. In the scripting language, call + * "decrement()". + */ + virtual StrokeVertexIterator& operator--() { + decrement(); + return *this; + } + + /*! Decrements. In the scripting language, call + * "decrement()". + */ + virtual StrokeVertexIterator operator--(int) { + StrokeVertexIterator ret(*this); + decrement(); + return ret; + } + + /*! Increments. */ + virtual int increment() { + ++_it; + return 0; + } + + /*! Decrements. */ + virtual int decrement() { + --_it; + return 0; + } + + /*! Returns true if the pointed StrokeVertex is the + * first of the Stroke. + */ + bool isBegin() const { + return _it == _begin; + } + + /*! Returns true if the pointed StrokeVertex is after the + * last StrokeVertex of the Stroke. + */ + bool isEnd() const { + return _it == _end; + } + + /*! operator == */ + virtual bool operator==(const Interface0DIteratorNested& it) const { + const StrokeVertexIterator* it_exact = dynamic_cast<const StrokeVertexIterator*>(&it); + if (!it_exact) + return false; + return (_it == it_exact->_it); + } + + /*! Returns the curvilinear abscissa of the current point */ + virtual float t() const{ + return (*_it)->curvilinearAbscissa(); + } + /*! Returns the point's parameter in the stroke */ + virtual float u() const{ + return (*_it)->u(); + } + + /*! Cloning method */ + virtual StrokeVertexIterator* copy() const { + return new StrokeVertexIterator(*this); + } + + // + // Not exported in Python + // + ////////////////////////////////////////////////// + + const ::Stroke::vertex_container::iterator& getIt() { + return _it; + } + + private: + + ::Stroke::vertex_container::iterator _it; + ::Stroke::vertex_container::iterator _begin; + ::Stroke::vertex_container::iterator _end; + }; + +} // end of namespace StrokeInternal + + +#endif // STROKEITERATORS_H + + diff --git a/source/blender/freestyle/intern/stroke/StrokeLayer.cpp b/source/blender/freestyle/intern/stroke/StrokeLayer.cpp new file mode 100755 index 00000000000..d5fc27d3d73 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/StrokeLayer.cpp @@ -0,0 +1,55 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "Stroke.h" +#include "StrokeLayer.h" +#include "Canvas.h" + +StrokeLayer::~StrokeLayer() +{ + clear(); +} + +void StrokeLayer::Render(const StrokeRenderer *iRenderer ) +{ + for(StrokeLayer::stroke_container::iterator s=_strokes.begin(), send=_strokes.end(); + s!=send; + ++s){ + (*s)->Render(iRenderer); + } +} + +void StrokeLayer::RenderBasic(const StrokeRenderer *iRenderer ) +{ + for(StrokeLayer::stroke_container::iterator s=_strokes.begin(), send=_strokes.end(); + s!=send; + ++s){ + (*s)->RenderBasic(iRenderer); + } +} +void StrokeLayer::clear() +{ + for(stroke_container::iterator s=_strokes.begin(), send=_strokes.end(); + s!=send; + ++s) + delete *s; + _strokes.clear(); +} diff --git a/source/blender/freestyle/intern/stroke/StrokeLayer.h b/source/blender/freestyle/intern/stroke/StrokeLayer.h new file mode 100755 index 00000000000..dbe9ea5a75c --- /dev/null +++ b/source/blender/freestyle/intern/stroke/StrokeLayer.h @@ -0,0 +1,75 @@ +// +// Filename : StrokeLayer.h +// Author : Stephane Grabli +// Purpose : Class to define a layer of strokes. +// Date of creation : 18/12/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef STROKELAYER_H +# define STROKELAYER_H + +# include <deque> + +class Stroke; +class StrokeRenderer; +class StrokeLayer +{ +public: + typedef std::deque<Stroke*> stroke_container; + +protected: + stroke_container _strokes; +public: + StrokeLayer() {} + StrokeLayer(const stroke_container& iStrokes) + { + _strokes = iStrokes; + } + StrokeLayer(const StrokeLayer& iBrother) + { + _strokes = iBrother._strokes; + } + virtual ~StrokeLayer() ; + + /*! Render method */ + void Render(const StrokeRenderer *iRenderer ); + void RenderBasic(const StrokeRenderer *iRenderer ); + + /*! clears the layer */ + void clear() ; + + /*! accessors */ + inline stroke_container::iterator strokes_begin() {return _strokes.begin();} + inline stroke_container::iterator strokes_end() {return _strokes.end();} + inline int strokes_size() const {return _strokes.size();} + inline bool empty() const {return _strokes.empty();} + + /*! modifiers */ + inline void setStrokes(stroke_container& iStrokes) {_strokes = iStrokes;} + inline void AddStroke(Stroke *iStroke) {_strokes.push_back(iStroke);} + +}; + +#endif // STROKELAYER_H diff --git a/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp b/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp new file mode 100755 index 00000000000..19e5ba35fed --- /dev/null +++ b/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp @@ -0,0 +1,121 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "StrokeRenderer.h" +#include "../geometry/GeomUtils.h" +using namespace std; + +/**********************************/ +/* */ +/* */ +/* StrokeRenderer */ +/* */ +/* */ +/**********************************/ + +LIB_STROKE_EXPORT +TextureManager *StrokeRenderer::_textureManager = 0; + +StrokeRenderer::StrokeRenderer () +{ +} + +StrokeRenderer::~StrokeRenderer () +{ +} + +bool StrokeRenderer::loadTextures() +{ + _textureManager->load(); + return true; +} + + +/**********************************/ +/* */ +/* */ +/* TextureManager */ +/* */ +/* */ +/**********************************/ + + +LIB_STROKE_EXPORT +TextureManager* TextureManager::_pInstance = 0; + +LIB_STROKE_EXPORT +string TextureManager::_patterns_path; + +LIB_STROKE_EXPORT +string TextureManager::_brushes_path; + +TextureManager::TextureManager () +{ + _hasLoadedTextures=false; + _pInstance = this; + _defaultTextureId = 0; +} + +TextureManager::~TextureManager () +{ + if(!_brushesMap.empty()) + _brushesMap.clear(); + _pInstance = 0; +} + +void TextureManager::load() +{ + if(_hasLoadedTextures) + return; + loadStandardBrushes(); + _hasLoadedTextures = true; +} + +unsigned TextureManager::getBrushTextureIndex(string name, Stroke::MediumType loadingMode) +{ + BrushTexture bt(name,loadingMode); + brushesMap::iterator b = _brushesMap.find(bt); + if(b == _brushesMap.end()){ + unsigned texId = loadBrush(name, loadingMode); + _brushesMap[bt] = texId; + return texId; + cout << "brush file " << name << " not found" << endl; + return 0; + }else{ + return _brushesMap[bt]; + } +} + +void TextureManager::Options::setPatternsPath(const string& path) { + _patterns_path = path; +} + +string TextureManager::Options::getPatternsPath() { + return _patterns_path; +} + +void TextureManager::Options::setBrushesPath(const string& path) { + _brushes_path = path; +} + +string TextureManager::Options::getBrushesPath() { + return _brushes_path; +} diff --git a/source/blender/freestyle/intern/stroke/StrokeRenderer.h b/source/blender/freestyle/intern/stroke/StrokeRenderer.h new file mode 100755 index 00000000000..c7c6df635d5 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/StrokeRenderer.h @@ -0,0 +1,132 @@ +// +// Filename : StrokeRenderer.h +// Author(s) : Fredo Durand +// Purpose : Classes to render a stroke with OpenGL +// Date of creation : 09/09/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef STROKE_RENDERER_H +# define STROKE_RENDERER_H + +# include "Stroke.h" +# include <vector> +# include <map> +# include <utility> +# include "../system/FreestyleConfig.h" +# include "StrokeRep.h" +# include <string.h> + + +/**********************************/ +/* */ +/* */ +/* TextureManager */ +/* */ +/* */ +/**********************************/ + + +/*! Class to load textures + */ +class LIB_STROKE_EXPORT TextureManager +{ +public: + + TextureManager (); + virtual ~TextureManager (); + static TextureManager * getInstance() {return _pInstance;} + void load () ; + unsigned getBrushTextureIndex(string name, Stroke::MediumType iType = Stroke::OPAQUE_MEDIUM) ; + + inline bool hasLoaded() const {return _hasLoadedTextures;} + inline unsigned int getDefaultTextureId() const {return _defaultTextureId;} + + struct LIB_STROKE_EXPORT Options + { + + static void setPatternsPath(const string& path); + static string getPatternsPath(); + + static void setBrushesPath(const string& path); + static string getBrushesPath(); + }; + + protected: + virtual void loadStandardBrushes() = 0; + virtual unsigned loadBrush(string fileName, Stroke::MediumType = Stroke::OPAQUE_MEDIUM) = 0; + + typedef std::pair<string,Stroke::MediumType> BrushTexture; + struct cmpBrushTexture{ + bool operator()(const BrushTexture& bt1, const BrushTexture& bt2) const{ + int r = strcmp(bt1.first.c_str(), bt2.first.c_str()); + if(r != 0) + return (r<0); + else + return (bt1.second < bt2.second); + } + }; + typedef std::map<BrushTexture, unsigned, cmpBrushTexture> brushesMap; + + static TextureManager * _pInstance; + bool _hasLoadedTextures; + brushesMap _brushesMap; + static string _patterns_path; + static string _brushes_path; + unsigned int _defaultTextureId; +}; + + +/**********************************/ +/* */ +/* */ +/* StrokeRenderer */ +/* */ +/* */ +/**********************************/ + +/*! Class to render a stroke. + Creates a triangle strip and stores it + strip is lazily created at the first rendering +*/ +class LIB_STROKE_EXPORT StrokeRenderer +{ + public: + StrokeRenderer(); + virtual ~StrokeRenderer (); + + /*! Renders a stroke rep */ + virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const = 0; + virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const = 0; + + // initializes the texture manager + // lazy, checks if it has already been done + static bool loadTextures() ; + + //static unsigned int getTextureIndex(unsigned int index) ; + static TextureManager *_textureManager; +}; + + +#endif // STROKE_RENDERER_H diff --git a/source/blender/freestyle/intern/stroke/StrokeRep.cpp b/source/blender/freestyle/intern/stroke/StrokeRep.cpp new file mode 100755 index 00000000000..6ae15c71833 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/StrokeRep.cpp @@ -0,0 +1,827 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "Stroke.h" +#include "StrokeRep.h" +#include "StrokeRenderer.h" +#include "StrokeAdvancedIterators.h" +#include "StrokeIterators.h" + +using namespace std; + +// +// STROKE VERTEX REP +///////////////////////////////////// +StrokeVertexRep::StrokeVertexRep(const StrokeVertexRep& iBrother){ + _point2d = iBrother._point2d; + _texCoord = iBrother._texCoord; + _color = iBrother._color; + _alpha = iBrother._alpha; +} + +// +// STRIP +///////////////////////////////////// + +Strip::Strip(const vector<StrokeVertex*>& iStrokeVertices, bool hasTips, bool beginTip, bool endTip){ + createStrip(iStrokeVertices); + if (!hasTips) + computeTexCoord (iStrokeVertices); + else + computeTexCoordWithTips (iStrokeVertices, beginTip, endTip); +} +Strip::Strip(const Strip& iBrother){ + if(!iBrother._vertices.empty()){ + for(vertex_container::const_iterator v=iBrother._vertices.begin(), vend=iBrother._vertices.end(); + v!=vend; + ++v){ + _vertices.push_back(new StrokeVertexRep(**v)); + } + } + _averageThickness = iBrother._averageThickness; +} + +Strip::~Strip(){ + if(!_vertices.empty()){ + for(vertex_container::iterator v=_vertices.begin(), vend=_vertices.end(); + v!=vend; + ++v){ + delete (*v); + } + _vertices.clear(); + } +} + +////////////////////////// +// Strip creation +////////////////////////// +#define EPS_SINGULARITY_RENDERER 0.05 +#define ZERO 0.00001 +#define MAX_RATIO_LENGTH_SINGU 2 +#define HUGE_COORD 1e4 + +bool notValid (Vec2r p) +{ + return (p[0]!=p[0]) || (p[1]!=p[1]) || (fabs(p[0])>HUGE_COORD) || (fabs(p[1])>HUGE_COORD) + || (p[0] <-HUGE_COORD) || (p[1]<-HUGE_COORD); +} + +real crossP(const Vec2r& A, const Vec2r& B){ + return A[0]*B[1] - A[1]*B[0]; +} + +void +Strip::createStrip (const vector<StrokeVertex*>& iStrokeVertices) +{ + //computeParameterization(); + if (iStrokeVertices.size() <2) + { + cerr << "Warning: strip has less than 2 vertices" << endl; + return; + } + _vertices.reserve(2*iStrokeVertices.size()); + if(!_vertices.empty()){ + for(vertex_container::iterator v=_vertices.begin(), vend=_vertices.end(); + v!=vend; + ++v){ + delete (*v); + } + _vertices.clear(); + } + _averageThickness=0.0; + + vector<StrokeVertex*>::const_iterator v ,vend, v2, vPrev; + StrokeVertex *sv, *sv2, *svPrev; + + //special case of first vertex + v=iStrokeVertices.begin(); + sv=*v; + vPrev=v; //in case the stroke has only 2 vertices; + ++v; sv2=*v; + Vec2r dir(sv2->getPoint()-sv->getPoint()); + Vec2r orthDir(-dir[1], dir[0]); + if (orthDir.norm() > ZERO) + orthDir.normalize(); + const float *thickness = sv->attribute().getThickness(); + _vertices.push_back(new StrokeVertexRep(sv->getPoint()+thickness[1]*orthDir)); + _vertices.push_back(new StrokeVertexRep(sv->getPoint()-thickness[0]*orthDir)); + + Vec2r stripDir(orthDir); + // check whether the orientation + // was user defined + if(sv->attribute().isAttributeAvailableVec2f("orientation")){ + Vec2r userDir = sv->attribute().getAttributeVec2f("orientation"); + userDir.normalize(); + Vec2r t(orthDir[1], -orthDir[0]); + real dp1 = userDir*orthDir; + real dp2 = userDir*t; + real h = (thickness[1]+thickness[0])/dp1; + real x = fabs(h*dp2/2.0); + if(dp1>0){ + //i'm in the upper part of the unit circle + if(dp2>0){ + //i'm in the upper-right part of the unit circle + // i must move vertex 1 + _vertices[1]->setPoint2d(_vertices[0]->point2d()-userDir*(h)); + //_vertices[0]->setPoint2d(_vertices[0]->point2d()+t*x); + //_vertices[1]->setPoint2d(_vertices[1]->point2d()-t*x); + }else{ + //i'm in the upper-left part of the unit circle + // i must move vertex 0 + _vertices[0]->setPoint2d(_vertices[1]->point2d()+userDir*(h)); + //_vertices[0]->setPoint2d(_vertices[0]->point2d()-t*x); + //_vertices[1]->setPoint2d(_vertices[1]->point2d()+t*x); + } + }else{ + //i'm in the lower part of the unit circle + if(dp2>0){ + //i'm in the lower-right part of the unit circle + // i must move vertex 0 + //_vertices[0]->setPoint2d(_vertices[1]->point2d()-userDir*(h)); + _vertices[0]->setPoint2d(_vertices[0]->point2d()-t*x); + //_vertices[1]->setPoint2d(_vertices[1]->point2d()+t*x); + }else{ + //i'm in the lower-left part of the unit circle + // i must move vertex 1 + _vertices[1]->setPoint2d(_vertices[0]->point2d()+userDir*(h)); + //_vertices[0]->setPoint2d(_vertices[0]->point2d()-t*x); + //_vertices[1]->setPoint2d(_vertices[1]->point2d()-t*x); + } + } + } + + + // Vec2r userDir = _stroke->getBeginningOrientation(); + // if(userDir != Vec2r(0,0)){ + // userDir.normalize(); + // real o1 = (orthDir*userDir); + // real o2 = crossP(orthDir,userDir); + // real orientation = o1 * o2; + // if(orientation > 0){ + // // then the vertex to move is v0 + // if(o1 > 0) + // _vertex[0]=_vertex[1]+userDir; + // else + // _vertex[0]=_vertex[1]-userDir; + // } + // if(orientation < 0){ + // // then we must move v1 + // if(o1 < 0) + // _vertex[1]=_vertex[0]+userDir; + // else + // _vertex[1]=_vertex[0]-userDir; + // } + // } + + int i=2; //2 because we have already processed the first vertex + + for(vend=iStrokeVertices.end(); + v!=vend; + v++){ + v2=v; ++v2; + if (v2==vend) break; + sv= (*v); sv2 = (*v2); svPrev=(*vPrev); + Vec2r p(sv->getPoint()), p2(sv2->getPoint()), pPrev(svPrev->getPoint()); + + //direction and orthogonal vector to the next segment + Vec2r dir(p2-p); + float dirNorm=dir.norm(); + dir.normalize(); + Vec2r orthDir(-dir[1], dir[0]); + Vec2r stripDir = orthDir; + if(sv->attribute().isAttributeAvailableVec2f("orientation")){ + Vec2r userDir = sv->attribute().getAttributeVec2f("orientation"); + userDir.normalize(); + real dp = userDir*orthDir; + if(dp<0) + userDir = userDir*(-1.f); + stripDir = userDir; + } + + //direction and orthogonal vector to the previous segment + Vec2r dirPrev(p-pPrev); + float dirPrevNorm=dirPrev.norm(); + dirPrev.normalize(); + Vec2r orthDirPrev(-dirPrev[1], dirPrev[0]); + Vec2r stripDirPrev = orthDirPrev; + if(svPrev->attribute().isAttributeAvailableVec2f("orientation")){ + Vec2r userDir = svPrev->attribute().getAttributeVec2f("orientation"); + userDir.normalize(); + real dp = userDir*orthDir; + if(dp<0) + userDir = userDir*(-1.f); + stripDirPrev = userDir; + } + + const float *thickness = sv->attribute().getThickness(); + _averageThickness+=thickness[0]+thickness[1]; + Vec2r pInter; + int interResult; + + interResult=GeomUtils::intersect2dLine2dLine(Vec2r(pPrev+thickness[1]*stripDirPrev), Vec2r(p+thickness[1]*stripDirPrev), + Vec2r(p+thickness[1]*stripDir), Vec2r(p2+thickness[1]*stripDir), + pInter); + + if (interResult==GeomUtils::DO_INTERSECT) + _vertices.push_back(new StrokeVertexRep(pInter)); + else + _vertices.push_back(new StrokeVertexRep(p+thickness[1]*stripDir)); + ++i; + + interResult=GeomUtils::intersect2dLine2dLine(Vec2r(pPrev-thickness[0]*stripDirPrev), Vec2r(p-thickness[0]*stripDirPrev), + Vec2r(p-thickness[0]*stripDir), Vec2r(p2-thickness[0]*stripDir), + pInter); + if (interResult==GeomUtils::DO_INTERSECT) + _vertices.push_back(new StrokeVertexRep(pInter)); + else + _vertices.push_back(new StrokeVertexRep(p-thickness[0]*stripDir)); + ++i; + + if((stripDir+stripDirPrev).norm() <= 1.e-06){ + // the strip is most likely doing a U-turn, we can't compute the average vector. + // We just continue and hope it's ok + vPrev = v; + continue; + } + + // if the angle is obtuse, we simply average the directions to avoid the singularity + stripDir=stripDir+stripDirPrev; + if ((dirNorm<ZERO) || (dirPrevNorm<ZERO) || (stripDir.norm() < ZERO)) { + stripDir[0] = 0; + stripDir[1] = 0; + }else + stripDir.normalize(); + + Vec2r vec_tmp(_vertices[i-2]->point2d()-p); + if ((vec_tmp.norm() > thickness[1]*MAX_RATIO_LENGTH_SINGU) || + (dirNorm<ZERO) || (dirPrevNorm<ZERO) || + notValid(_vertices[i-2]->point2d()) + || (fabs(stripDir * dir) < EPS_SINGULARITY_RENDERER)) + _vertices[i-2]->setPoint2d(p+thickness[1]*stripDir); + + vec_tmp = _vertices[i-1]->point2d()-p; + if ((vec_tmp.norm() > thickness[1]*MAX_RATIO_LENGTH_SINGU) || + (dirNorm<ZERO) || (dirPrevNorm<ZERO) || + notValid(_vertices[i-1]->point2d()) + || (fabs(stripDir * dir)<EPS_SINGULARITY_RENDERER)) + _vertices[i-1]->setPoint2d(p-thickness[0]*stripDir); + + vPrev=v; + } // end of for + + //special case of last vertex + sv=*v; + sv2=*vPrev; + dir=Vec2r (sv->getPoint()-sv2->getPoint()); + orthDir=Vec2r(-dir[1], dir[0]); + if (orthDir.norm() > ZERO) + orthDir.normalize(); + const float *thicknessLast = sv->attribute().getThickness(); + _vertices.push_back(new StrokeVertexRep(sv->getPoint()+thicknessLast[1]*orthDir)); + ++i; + _vertices.push_back(new StrokeVertexRep(sv->getPoint()-thicknessLast[0]*orthDir)); + int n = i; + ++i; + + // check whether the orientation + // was user defined + if(sv->attribute().isAttributeAvailableVec2f("orientation")){ + Vec2r userDir = sv->attribute().getAttributeVec2f("orientation"); + userDir.normalize(); + Vec2r t(orthDir[1], -orthDir[0]); + real dp1 = userDir*orthDir; + real dp2 = userDir*t; + real h = (thicknessLast[1]+thicknessLast[0])/dp1; + //soc unused - real x = fabs(h*dp2/2.0); + if(dp1>0){ + //i'm in the upper part of the unit circle + if(dp2>0){ + //i'm in the upper-right part of the unit circle + // i must move vertex n-1 + _vertices[n-1]->setPoint2d(_vertices[n]->point2d()-userDir*(h)); + //_vertices[n-1]->setPoint2d(_vertices[n-1]->point2d()+t*x); + //_vertices[n]->setPoint2d(_vertices[n]->point2d()-t*x); + }else{ + //i'm in the upper-left part of the unit circle + // i must move vertex n + _vertices[n]->setPoint2d(_vertices[n-1]->point2d()+userDir*(h)); + //_vertices[n-1]->setPoint2d(_vertices[n-1]->point2d()-t*x); + //_vertices[n]->setPoint2d(_vertices[n]->point2d()+t*x); + } + }else{ + //i'm in the lower part of the unit circle + if(dp2>0){ + //i'm in the lower-right part of the unit circle + // i must move vertex n + _vertices[n]->setPoint2d(_vertices[n-1]->point2d()-userDir*(h)); + //_vertices[n-1]->setPoint2d(_vertices[n-1]->point2d()-t*x); + //_vertices[n]->setPoint2d(_vertices[n]->point2d()+t*x); + }else{ + //i'm in the lower-left part of the unit circle + // i must move vertex n-1 + _vertices[n-1]->setPoint2d(_vertices[n]->point2d()+userDir*(h)); + //_vertices[n-1]->setPoint2d(_vertices[n-1]->point2d()+t*x); + //_vertices[n]->setPoint2d(_vertices[n]->point2d()-t*x); + } + } + } + + + // check whether the orientation of the extremity + // was user defined + // userDir = _stroke->getEndingOrientation(); + // if(userDir != Vec2r(0,0)){ + // userDir.normalize(); + // real o1 = (orthDir*userDir); + // real o2 = crossP(orthDir,userDir); + // real orientation = o1 * o2; + // if(orientation > 0){ + // // then the vertex to move is vn + // if(o1 < 0) + // _vertex[n]=_vertex[n-1]+userDir; + // else + // _vertex[n]=_vertex[n-1]-userDir; + // } + // if(orientation < 0){ + // // then we must move vn-1 + // if(o1 > 0) + // _vertex[n-1]=_vertex[n]+userDir; + // else + // _vertex[n-1]=_vertex[n]-userDir; + // } + // } + + _averageThickness/=float(iStrokeVertices.size()-2); + //I did not use the first and last vertex for the average + if (iStrokeVertices.size()<3) + _averageThickness=0.5*(thicknessLast[1]+thicknessLast[0]+thickness[0]+thickness[1]); + + if (i != 2*(int)iStrokeVertices.size()) + cerr << "Warning: problem with stripe size\n"; + + cleanUpSingularities (iStrokeVertices); +} + +// CLEAN UP +///////////////////////// + +void +Strip::cleanUpSingularities (const vector<StrokeVertex*>& iStrokeVertices) +{ + int k; + int sizeStrip = _vertices.size(); + + for (k=0; k<sizeStrip; k++) + if (notValid(_vertices[k]->point2d())) + { + cerr << "Warning: strip vertex " << k << " non valid" << endl; + return; + } + + //return; + if (iStrokeVertices.size()<2) return; + int i=0, j; + vector<StrokeVertex*>::const_iterator v ,vend, v2, vPrev; +StrokeVertex *sv, *sv2; //soc unused - *svPrev; + + bool singu1=false, singu2=false; + int timeSinceSingu1=0, timeSinceSingu2=0; + + //special case of first vertex + v=iStrokeVertices.begin(); + for(vend=iStrokeVertices.end(); + v!=vend; + v++) + { + v2=v; ++v2; + if (v2==vend) break; + sv= (*v); sv2 = (*v2); + Vec2r p(sv->getPoint()), p2(sv2->getPoint()); + + Vec2r dir(p2-p); + if (dir.norm() > ZERO) + dir.normalize(); + Vec2r dir1, dir2; + dir1=_vertices[2*i+2]->point2d()-_vertices[2*i]->point2d(); + dir2=_vertices[2*i+3]->point2d()-_vertices[2*i+1]->point2d(); + + if ((dir1 * dir) < -ZERO) + { + singu1=true; + timeSinceSingu1++; + } + else + { + if (singu1) + { + int toto=i-timeSinceSingu1; + if (toto<0) + cerr << "Stephane dit \"Toto\"" << endl; + //traverse all the vertices of the singularity and average them + Vec2r avP(0.0,0.0); + for (j=i-timeSinceSingu1; j<i+1; j++) + avP=Vec2r(avP+_vertices[2*j]->point2d()); + avP=Vec2r(1.0/float(timeSinceSingu1+1)*avP); + for (j=i-timeSinceSingu1; j<i+1; j++) + _vertices[2*j]->setPoint2d(avP); + //_vertex[2*j]=_vertex[2*i]; + singu1=false; timeSinceSingu1=0; + } + } + if ((dir2 * dir) < -ZERO) + { + singu2=true; + timeSinceSingu2++; + } + else + { + if (singu2) + { + int toto=i-timeSinceSingu2; + if (toto<0) + cerr << "Stephane dit \"Toto\"" << endl; + //traverse all the vertices of the singularity and average them + Vec2r avP(0.0,0.0); + for (j=i-timeSinceSingu2; j<i+1; j++) + avP=Vec2r(avP+_vertices[2*j+1]->point2d()); + avP=Vec2r(1.0/float(timeSinceSingu2+1)*avP); + for (j=i-timeSinceSingu2; j<i+1; j++) + _vertices[2*j+1]->setPoint2d(avP); + //_vertex[2*j+1]=_vertex[2*i+1]; + singu2=false; timeSinceSingu2=0; + } + } + i++; + } + + if (singu1) + { + //traverse all the vertices of the singularity and average them + Vec2r avP(0.0,0.0); + for (j=i-timeSinceSingu1; j<i; j++) + avP=Vec2r(avP+_vertices[2*j]->point2d()); + avP=Vec2r(1.0/float(timeSinceSingu1)*avP); + for (j=i-timeSinceSingu1; j<i; j++) + _vertices[2*j]->setPoint2d(avP); + } + if (singu2) + { + //traverse all the vertices of the singularity and average them + Vec2r avP(0.0,0.0); + for (j=i-timeSinceSingu2; j<i; j++) + avP=Vec2r(avP+_vertices[2*j+1]->point2d()); + avP=Vec2r(1.0/float(timeSinceSingu2)*avP); + for (j=i-timeSinceSingu2; j<i; j++) + _vertices[2*j+1]->setPoint2d(avP); + } + + + for (k=0; k<sizeStrip; k++) + if (notValid(_vertices[k]->point2d())) + { + cerr << "Warning: strip vertex " << k << " non valid after cleanup"<<endl; + return; + } +} + + +// Texture coordinates +//////////////////////////////// + +void +Strip::computeTexCoord (const vector<StrokeVertex*>& iStrokeVertices) +{ + vector<StrokeVertex*>::const_iterator v ,vend; + StrokeVertex *sv; + int i=0; + for(v=iStrokeVertices.begin(), vend=iStrokeVertices.end(); + v!=vend; v++) + { + sv= (*v); + _vertices[i]->setTexCoord(Vec2r((real)(sv->curvilinearAbscissa() / _averageThickness),0)); + _vertices[i]->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2])); + _vertices[i]->setAlpha(sv->attribute().getAlpha()); + i++; + _vertices[i]->setTexCoord(Vec2r((real)(sv->curvilinearAbscissa() / _averageThickness),1)); + _vertices[i]->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2])); + _vertices[i]->setAlpha(sv->attribute().getAlpha()); + i++; + // cerr<<"col=("<<sv->attribute().getColor()[0]<<", " + // <<sv->attribute().getColor()[1]<<", "<<sv->attribute().getColor()[2]<<")"<<endl; + } +} + +void +Strip::computeTexCoordWithTips (const vector<StrokeVertex*>& iStrokeVertices, bool tipBegin, bool tipEnd) +{ + //soc unused - unsigned int sizeStrip = _vertices.size()+8; //for the transition between the tip and the body + vector<StrokeVertex*>::const_iterator v ,vend; + StrokeVertex *sv = 0; + + v=iStrokeVertices.begin(); + vend=iStrokeVertices.end(); + float l=(*v)->strokeLength()/_averageThickness; + int tiles=int(l); + float fact=(float(tiles)+0.5)/l; + //soc unused - float uTip2=float(tiles)+0.25; + float u=0; + float uPrev=0; + int i=0; + float t; + StrokeVertexRep *tvRep1, *tvRep2; + + // cerr<<"l="<<l<<" tiles="<<tiles<<" _averageThicnkess=" + // <<_averageThickness<<" strokeLength="<<(*v)->strokeLength()<<endl; + // + vector<StrokeVertexRep*>::iterator currentSV = _vertices.begin(); + StrokeVertexRep *svRep; + if(tipBegin){ + for(;v!=vend; v++) + { + sv= (*v); + svRep = *currentSV; + u=sv->curvilinearAbscissa()/_averageThickness*fact; + if (u>0.25) break; + + + svRep->setTexCoord(Vec2r((real)u, 0.5)); + svRep->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2])); + svRep->setAlpha(sv->attribute().getAlpha()); + i++; + ++currentSV; + + svRep = *currentSV; + svRep->setTexCoord(Vec2r((real)u, 1)); + svRep->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2])); + svRep->setAlpha(sv->attribute().getAlpha()); + i++; + ++currentSV; + uPrev=u; + } + //first transition vertex + + if (fabs(u-uPrev)>ZERO) + t= (0.25-uPrev)/(u-uPrev); + else t=0; + //if (!tiles) t=0.5; + tvRep1 = new StrokeVertexRep(Vec2r((1-t)*_vertices[i-2]->point2d()+t*_vertices[i]->point2d())); + tvRep1->setTexCoord(Vec2r(0.25,0.5)); + tvRep1->setColor(Vec3r((1-t)*_vertices[i-2]->color()+ + t*Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2]))); + tvRep1->setAlpha((1-t)*_vertices[i-2]->alpha()+t*sv->attribute().getAlpha()); + i++; + + tvRep2 = new StrokeVertexRep(Vec2r((1-t)*_vertices[i-2]->point2d()+t*_vertices[i]->point2d())); + tvRep2->setTexCoord(Vec2r(0.25,1)); + tvRep2->setColor(Vec3r((1-t)*_vertices[i-2]->color()+ + t*Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2]))); + tvRep2->setAlpha((1-t)*_vertices[i-2]->alpha()+t*sv->attribute().getAlpha()); + i++; + + currentSV = _vertices.insert(currentSV, tvRep1); + ++currentSV; + currentSV = _vertices.insert(currentSV, tvRep2); + ++currentSV; + + //copy the vertices with different texture coordinates + tvRep1 = new StrokeVertexRep(_vertices[i-2]->point2d()); + tvRep1->setTexCoord(Vec2r(0.25,0)); + tvRep1->setColor(_vertices[i-2]->color()); + tvRep1->setAlpha(_vertices[i-2]->alpha()); + i++; + + tvRep2 = new StrokeVertexRep(_vertices[i-2]->point2d()); + tvRep2->setTexCoord(Vec2r(0.25,0.5)); + tvRep2->setColor(_vertices[i-2]->color()); + tvRep2->setAlpha(_vertices[i-2]->alpha()); + i++; + + currentSV = _vertices.insert(currentSV, tvRep1); + ++currentSV; + currentSV = _vertices.insert(currentSV, tvRep2); + ++currentSV; + } + uPrev=0; + + //body of the stroke + for(;v!=vend; v++) + { + sv= (*v); + svRep = *currentSV; + u=sv->curvilinearAbscissa()/_averageThickness*fact-0.25; + if (u>tiles) break; + + svRep->setTexCoord(Vec2r((real)u, 0)); + svRep->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2])); + svRep->setAlpha(sv->attribute().getAlpha()); + i++; + ++currentSV; + + svRep = *currentSV; + svRep->setTexCoord(Vec2r((real)u, 0.5)); + svRep->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2])); + svRep->setAlpha(sv->attribute().getAlpha()); + i++; + ++currentSV; + + uPrev=u; + } + if(tipEnd){ + //second transition vertex + if ((fabs(u-uPrev)>ZERO)) + t= (float(tiles)-uPrev)/(u-uPrev); + else t=0; + + tvRep1 = new StrokeVertexRep(Vec2r((1-t)*_vertices[i-2]->point2d()+t*_vertices[i]->point2d())); + tvRep1->setTexCoord(Vec2r((real)tiles,0)); + tvRep1->setColor(Vec3r((1-t)*_vertices[i-2]->color()+ + t*Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2]))); + tvRep1->setAlpha((1-t)*_vertices[i-2]->alpha()+t*sv->attribute().getAlpha()); + i++; + + tvRep2 = new StrokeVertexRep(Vec2r((1-t)*_vertices[i-2]->point2d()+t*_vertices[i]->point2d())); + tvRep2->setTexCoord(Vec2r((real)tiles,0.5)); + tvRep2->setColor(Vec3r((1-t)*_vertices[i-2]->color()+ + t*Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2]))); + tvRep2->setAlpha((1-t)*_vertices[i-2]->alpha()+t*sv->attribute().getAlpha()); + i++; + + currentSV = _vertices.insert(currentSV, tvRep1); + ++currentSV; + currentSV = _vertices.insert(currentSV, tvRep2); + ++currentSV; + + //copy the vertices with different texture coordinates + tvRep1 = new StrokeVertexRep(_vertices[i-2]->point2d()); + tvRep1->setTexCoord(Vec2r(0.75,0.5)); + tvRep1->setColor(_vertices[i-2]->color()); + tvRep1->setAlpha(_vertices[i-2]->alpha()); + i++; + + tvRep2 = new StrokeVertexRep(_vertices[i-2]->point2d()); + tvRep2->setTexCoord(Vec2r(0.75,1)); + tvRep2->setColor(_vertices[i-2]->color()); + tvRep2->setAlpha(_vertices[i-2]->alpha()); + i++; + + currentSV = _vertices.insert(currentSV, tvRep1); + ++currentSV; + currentSV = _vertices.insert(currentSV, tvRep2); + ++currentSV; + + //end tip + for(;v!=vend; v++) + { + sv= (*v); + svRep = *currentSV; + u=0.75+sv->curvilinearAbscissa()/_averageThickness*fact-float(tiles)-0.25; + + svRep->setTexCoord(Vec2r((real)u, 0.5)); + svRep->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2])); + svRep->setAlpha(sv->attribute().getAlpha()); + i++; + ++currentSV; + + svRep = *currentSV; + svRep->setTexCoord(Vec2r((real)u, 1)); + svRep->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2])); + svRep->setAlpha(sv->attribute().getAlpha()); + i++; + ++currentSV; + } + } + //cerr<<"u="<<u<<" i="<<i<<"/"<<_sizeStrip<<endl;; + + // for (i=0; i<_sizeStrip; i++) + // _alpha[i]=1.0; + + // for (i=0; i<_sizeStrip; i++) + // cerr<<"("<<_texCoord[i][0]<<", "<<_texCoord[i][1]<<") "; + // cerr<<endl; + + + // Vec2r vec_tmp; + // for (i=0; i<_sizeStrip/2; i++) + // vec_tmp = _vertex[2*i] - _vertex[2*i+1]; + // if (vec_tmp.norm() > 4*_averageThickness) + // cerr << "Warning (from Fredo): There is a pb in the texture coordinates computation" << endl; +} + +// +// StrokeRep +///////////////////////////////////// + +StrokeRep::StrokeRep() +{ + _stroke = 0; + _strokeType=Stroke::OPAQUE_MEDIUM; + TextureManager * ptm = TextureManager::getInstance(); + if(ptm) + _textureId = ptm->getDefaultTextureId(); + // _averageTextureAlpha=0.5; //default value + // if (_strokeType==OIL_STROKE) + // _averageTextureAlpha=0.75; + // if (_strokeType>=NO_BLEND_STROKE) + // _averageTextureAlpha=1.0 +} + +StrokeRep::StrokeRep(Stroke *iStroke) +{ + _stroke = iStroke; + _strokeType = iStroke->getMediumType(); + _textureId = iStroke->getTextureId(); + if(_textureId == 0){ + TextureManager * ptm = TextureManager::getInstance(); + if(ptm) + _textureId = ptm->getDefaultTextureId(); + } + + // _averageTextureAlpha=0.5; //default value + // if (_strokeType==OIL_STROKE) + // _averageTextureAlpha=0.75; + // if (_strokeType>=NO_BLEND_STROKE) + // _averageTextureAlpha=1.0; + create(); +} + +StrokeRep::StrokeRep(const StrokeRep& iBrother) +{ + //soc unused - int i=0; + _stroke = iBrother._stroke; + _strokeType=iBrother._strokeType; + _textureId = iBrother._textureId; + for(vector<Strip*>::const_iterator s=iBrother._strips.begin(), send=iBrother._strips.end(); + s!=send; + ++s){ + _strips.push_back(new Strip(**s)); + } +} + + +StrokeRep::~StrokeRep() +{ + if(!_strips.empty()){ + for(vector<Strip*>::iterator s=_strips.begin(), send=_strips.end(); + s!=send; + ++s){ + delete (*s); + } + _strips.clear(); + } +} + +void StrokeRep::create(){ + vector<StrokeVertex*> strip; + StrokeInternal::StrokeVertexIterator v = _stroke->strokeVerticesBegin(); + StrokeInternal::StrokeVertexIterator vend = _stroke->strokeVerticesEnd(); + + bool first=true; + bool end=false; + while(v!=vend){ + while((v!=vend) && (!(*v).attribute().isVisible())){ + ++v; + first = false; + } + while( (v!=vend) && ((*v).attribute().isVisible()) ) { + strip.push_back(&(*v)); + ++v; + } + if(v!=vend){ + // add the last vertex and create + strip.push_back(&(*v)); + }else{ + end=true; + } + if((!strip.empty()) && (strip.size()>1) ){ + _strips.push_back(new Strip(strip, _stroke->hasTips(), first, end)); + strip.clear(); + } + first = false; + } +} + +void StrokeRep::Render(const StrokeRenderer *iRenderer) +{ + iRenderer->RenderStrokeRep(this); +} + + + diff --git a/source/blender/freestyle/intern/stroke/StrokeRep.h b/source/blender/freestyle/intern/stroke/StrokeRep.h new file mode 100755 index 00000000000..d8a8dc2d609 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/StrokeRep.h @@ -0,0 +1,138 @@ +// +// Filename : StrokeRep.h +// Author(s) : Stephane Grabli +// Purpose : Class to define the representation of a stroke +// (for display purpose) +// Date of creation : 05/03/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef STROKEREP_H +# define STROKEREP_H + +# include "../geometry/Geom.h" +using namespace Geometry; + +//symbolic constant to call the appropriate renderers and textures +// # define NO_TEXTURE_WITH_BLEND_STROKE -2 +// # define NO_TEXTURE_STROKE -1 +// # define PSEUDO_CHARCOAL_STROKE 0 +// # define WASH_BRUSH_STROKE 1 +// # define OIL_STROKE 2 +// # define NO_BLEND_STROKE 3 +// # define CHARCOAL_MIN_STROKE 4 +// # define BRUSH_MIN_STROKE 5 +// # define OPAQUE_DRY_STROKE 6 +// # define OPAQUE_STROKE 7 +// +// # define DEFAULT_STROKE 0 +// +// # define NUMBER_STROKE_RENDERER 8 + +#include "Stroke.h" + +class StrokeVertexRep{ +public: + StrokeVertexRep(){} + StrokeVertexRep(const Vec2r& iPoint2d){_point2d=iPoint2d;} + StrokeVertexRep(const StrokeVertexRep& iBrother); + virtual ~StrokeVertexRep(){} + + inline Vec2r& point2d() {return _point2d;} + inline Vec2r& texCoord() {return _texCoord;} + inline Vec3r& color() {return _color;} + inline float alpha() {return _alpha;} + + inline void setPoint2d(const Vec2r& p){_point2d = p;} + inline void setTexCoord(const Vec2r& p){_texCoord = p;} + inline void setColor(const Vec3r& p){_color = p;} + inline void setAlpha(float a){_alpha = a;} +protected: + Vec2r _point2d; + Vec2r _texCoord; + Vec3r _color; + float _alpha; +}; + +class Strip{ +public: + typedef std::vector<StrokeVertexRep*> vertex_container; +protected: + vertex_container _vertices; + float _averageThickness; + + +public: + Strip(const std::vector<StrokeVertex*>& iStrokeVertices, bool hasTips=false, bool tipBegin=false, bool tipEnd=false) ; + Strip(const Strip& iBrother); + virtual ~Strip() ; + +protected: + void createStrip(const std::vector<StrokeVertex*>& iStrokeVertices); + void cleanUpSingularities(const std::vector<StrokeVertex*>& iStrokeVertices); + void computeTexCoord (const std::vector<StrokeVertex*>& iStrokeVertices); + void computeTexCoordWithTips (const std::vector<StrokeVertex*>& iStrokeVertices, bool tipBegin, bool tipEnd); +public: + inline int sizeStrip() const {return _vertices.size();} + inline vertex_container& vertices() {return _vertices;} +}; + +class StrokeRep +{ +protected: + Stroke *_stroke; + vector<Strip*> _strips; + Stroke::MediumType _strokeType; + unsigned int _textureId; + + // float _averageTextureAlpha; + + +public: + StrokeRep(); + StrokeRep(const StrokeRep&); + StrokeRep(Stroke *iStroke); + virtual ~StrokeRep(); + + /*! Creates the strips */ + virtual void create() ; + + /*! Renders the stroke using a Renderer */ + virtual void Render(const StrokeRenderer *iRenderer) ; + + /*! accessors */ + inline Stroke::MediumType getMediumType() const {return _strokeType;} + inline unsigned getTextureId() const {return _textureId;} + inline vector<Strip*>& getStrips() {return _strips;} + inline unsigned int getNumberOfStrips() const {return _strips.size();} + inline Stroke * getStroke() {return _stroke;} + + /*! modifiers */ + inline void setMediumType(Stroke::MediumType itype) {_strokeType=itype;} + inline void setTextureId(unsigned textureId) {_textureId = textureId;} + + +}; + +#endif // STROKEREP_H diff --git a/source/blender/freestyle/intern/stroke/StrokeShader.h b/source/blender/freestyle/intern/stroke/StrokeShader.h new file mode 100755 index 00000000000..63185438e91 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/StrokeShader.h @@ -0,0 +1,124 @@ +// +// Filename : StrokeShader.h +// Author(s) : Stephane Grabli, Emmanuel Turquin +// Purpose : Class defining StrokeShader +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef SHADERS_H +# define SHADERS_H + +# include <iostream> +# include <vector> + +# include "../python/Director.h" + +// +// StrokeShader base class +// +////////////////////////////////////////////////////// + +class Stroke; +/*! Base class for Stroke Shaders. + * Any Stroke Shader must inherit from + * this class and overload the shade() method. + * A StrokeShader is designed to modify any + * Stroke's attribute such as Thickness, Color, + * Geometry, Texture, Blending mode... + * The basic way to achieve this operation consists + * in iterating over the StrokeVertices of the Stroke + * and to modify each one's StrokeAttribute. + * Here is a python code example of such an iteration: + * \code + * it = ioStroke.strokeVerticesBegin() + * while it.isEnd() == 0: + * att = it.getObject().attribute() + * ## perform here any attribute modification + * it.increment() + * \endcode + * Here is a C++ code example of such an iteration: + * \code + * for(StrokeInternal::StrokeVertexIterator v=ioStroke.strokeVerticesBegin(), vend=ioStroke.strokeVerticesEnd(); + * v!=vend; + * ++v){ + * StrokeAttribute& att = v->attribute(); + * // perform any attribute modification here... + * } + * \endcode + */ +class LIB_STROKE_EXPORT StrokeShader +{ +public: + + PyObject *py_ss; + + /*! Default constructor. */ + StrokeShader() { py_ss = 0; } + /*! Destructor. */ + virtual ~StrokeShader() {} + /*! Returns the string corresponding to the + * shader's name. + */ + virtual string getName() const { + return "StrokeShader"; + } + /*! The shading method. This method must + * be overloaded by inherited classes. + * The shading method is designed to modify any + * Stroke's attribute such as Thickness, Color, + * Geometry, Texture, Blending mode... + * The basic way to achieve this operation consists + * in iterating over the StrokeVertices of the Stroke + * and to modify each one's StrokeAttribute. + * Here is a python code example of such an iteration: + * \code + * it = ioStroke.strokeVerticesBegin() + * while it.isEnd() == 0: + * att = it.getObject().attribute() + * ## perform here any attribute modification + * it.increment() + * \endcode + * Here is a C++ code example of such an iteration: + * \code + * for(StrokeInternal::StrokeVertexIterator v=ioStroke.strokeVerticesBegin(), vend=ioStroke.strokeVerticesEnd(); + * v!=vend; + * ++v){ + * StrokeAttribute& att = v->attribute(); + * // perform any attribute modification here... + * } + * \endcode + * \param ioStroke + * The stroke we wish to shade. this Stroke + * is modified by the Shader (which typically + * modifies the Stroke's attribute's values such + * as Color, Thickness, Geometry...) + */ + virtual int shade(Stroke& ioStroke) const { + return Director_BPy_StrokeShader_shade( const_cast<StrokeShader *>(this), ioStroke ); + } + +}; + +# endif // SHADERS_H diff --git a/source/blender/freestyle/intern/stroke/StrokeTesselator.cpp b/source/blender/freestyle/intern/stroke/StrokeTesselator.cpp new file mode 100755 index 00000000000..a8b71f9f3c3 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/StrokeTesselator.cpp @@ -0,0 +1,88 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "StrokeTesselator.h" +#include "../scene_graph/OrientedLineRep.h" +#include "../scene_graph/NodeGroup.h" +#include "../scene_graph/NodeShape.h" +#include "StrokeAdvancedIterators.h" + +LineRep* StrokeTesselator::Tesselate(Stroke *iStroke) +{ + if(0 == iStroke) + return 0; + + LineRep* line; + line = new OrientedLineRep(); + + Stroke::vertex_iterator v,vend; + if(2 == iStroke->vertices_size()) + { + line->setStyle(LineRep::LINES); + v = iStroke->vertices_begin(); + StrokeVertex *svA= (*v); + v++; + StrokeVertex *svB = (*v); + Vec3r A((*svA)[0], (*svA)[1], 0); + Vec3r B((*svB)[0], (*svB)[1], 0); + line->AddVertex(A); + line->AddVertex(B); + } + else + { + if(_overloadFrsMaterial) + line->setFrsMaterial(_FrsMaterial); + + line->setStyle(LineRep::LINE_STRIP); + + for(v=iStroke->vertices_begin(), vend=iStroke->vertices_end(); + v!=vend; + v++) + { + StrokeVertex *sv= (*v); + Vec3r V((*sv)[0], (*sv)[1], 0); + line->AddVertex(V); + } + } + line->setId(iStroke->getId()); + line->ComputeBBox(); + + return line; +} + +template<class StrokeVertexIterator> +NodeGroup* StrokeTesselator::Tesselate(StrokeVertexIterator begin, StrokeVertexIterator end) +{ + NodeGroup *group = new NodeGroup; + NodeShape *tshape = new NodeShape; + group->AddChild(tshape); + //tshape->material().setDiffuse(0.f, 0.f, 0.f, 1.f); + tshape->setFrsMaterial(_FrsMaterial); + + for(StrokeVertexIterator c=begin, cend=end; + c!=cend; + c++) + { + tshape->AddRep(Tesselate((*c))); + } + + return group; +} diff --git a/source/blender/freestyle/intern/stroke/StrokeTesselator.h b/source/blender/freestyle/intern/stroke/StrokeTesselator.h new file mode 100755 index 00000000000..671df00ef84 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/StrokeTesselator.h @@ -0,0 +1,67 @@ +// +// Filename : StrokeTesselator.h +// Author(s) : Stephane Grabli +// Purpose : Class to build a Node Tree designed to be displayed +// from a set of strokes structure. +// Date of creation : 26/03/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef STROKETESSELATOR_H +# define STROKETESSELATOR_H + +# include "Stroke.h" +# include "../scene_graph/LineRep.h" + +class StrokeTesselator +{ +public: + + inline StrokeTesselator() {_FrsMaterial.setDiffuse(0,0,0,1);_overloadFrsMaterial=false;} + virtual ~StrokeTesselator() {} + + /*! Builds a line rep contained from a Stroke + */ + LineRep* Tesselate(Stroke* iStroke) ; + + /*! Builds a set of lines rep contained under a + * a NodeShape, itself contained under a NodeGroup from a + * set of strokes + */ + template<class StrokeIterator> + NodeGroup* Tesselate(StrokeIterator begin, StrokeIterator end) ; + + + + inline void setFrsMaterial(const FrsMaterial& iMaterial) {_FrsMaterial=iMaterial;_overloadFrsMaterial=true;} + inline const FrsMaterial& frs_material() const {return _FrsMaterial;} + +private: + + FrsMaterial _FrsMaterial; + bool _overloadFrsMaterial; +}; + +#endif // STROKETESSELATOR_H + diff --git a/source/blender/freestyle/intern/stroke/StyleModule.h b/source/blender/freestyle/intern/stroke/StyleModule.h new file mode 100755 index 00000000000..c023ad7517b --- /dev/null +++ b/source/blender/freestyle/intern/stroke/StyleModule.h @@ -0,0 +1,157 @@ +// +// Filename : StyleModule.h +// Author(s) : Stephane Grabli, Emmanuel Turquin +// Purpose : Class representing a style module +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef STYLE_MODULE_H +# define STYLE_MODULE_H + +# include <iostream> +# include <string> +# include "../system/StringUtils.h" +# include "StrokeLayer.h" +# include "../system/Interpreter.h" +# include "Operators.h" +# include "StrokeShader.h" + +using namespace std; + +class StyleModule +{ +public: + + StyleModule(const string& file_name, + Interpreter* inter) : _file_name(file_name) { + _always_refresh = false; + _causal = false; + _drawable = true; + _modified = true; + _displayed = true; + _inter = inter; + } + + ~StyleModule() {} + + StrokeLayer* execute() { + if (!_inter) { + cerr << "Error: no interpreter was found to execute the script" << endl; + return NULL; + } + + if (!_drawable) { + cerr << "Error: not drawable" << endl; + return NULL; + } + + Operators::reset(); + + if( _inter->interpretFile(_file_name) ) { + cerr << "Error: interpretation failed" << endl; + return NULL; + } + + Operators::StrokesContainer* strokes_set = Operators::getStrokesSet(); + if( strokes_set->empty() ) { + cerr << "Error: strokes set empty" << endl; + return NULL; + } + + StrokeLayer* sl = new StrokeLayer; + for (Operators::StrokesContainer::iterator it = strokes_set->begin(); + it != strokes_set->end(); + ++it) + sl->AddStroke(*it); + + return sl; + } + + // accessors + + const string getFileName() const { + return _file_name; + } + + bool getAlwaysRefresh() const { + return _always_refresh; + } + + bool getCausal() const { + return _causal; + } + + bool getDrawable() const { + return _drawable; + } + + bool getModified() const { + return _modified; + } + + bool getDisplayed() const { + return _displayed; + } + + // modifiers + + void setFileName(const string& file_name) { + _file_name = file_name; + } + + void setAlwaysRefresh(bool b = true) { + _always_refresh = b; + } + + void setCausal(bool b = true) { + _causal = b; + } + + void setDrawable(bool b = true) { + _drawable = b; + } + + void setModified(bool b = true) { + if (_always_refresh) + return; + _modified = b; + } + + void setDisplayed(bool b = true) { + _displayed = b; + } + +private: + + string _file_name; + bool _always_refresh; + bool _causal; + bool _drawable; + bool _modified; + bool _displayed; + Interpreter* _inter; +}; + +#endif // STYLE_MODULE_H diff --git a/source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp new file mode 100755 index 00000000000..ea5af287bbe --- /dev/null +++ b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp @@ -0,0 +1,73 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +# include "TextStrokeRenderer.h" +# include "Canvas.h" +# include "StrokeIterators.h" + +TextStrokeRenderer::TextStrokeRenderer(const char* iFileName) +:StrokeRenderer(){ + if(!iFileName) + iFileName = "freestyle.txt"; + // open the stream: + _ofstream.open(iFileName, ios::out); + if(!_ofstream.is_open()){ + cerr << "couldn't open the output file " << iFileName << endl; + } + _ofstream << "%!FREESTYLE" << endl; + _ofstream << "%Creator: Freestyle (http://artis.imag.fr/Software/Freestyle)" << endl; + // Bounding box + _ofstream << 0 << " "<< 0 << " " << Canvas::getInstance()->width() << " " << Canvas::getInstance()->height() << endl; + _ofstream << "%u x y z tleft tright r g b ..." << endl; +} + +TextStrokeRenderer::~TextStrokeRenderer(){ + Close(); +} + +void TextStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const{ + RenderStrokeRepBasic(iStrokeRep); +} + +void TextStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const{ + Stroke *stroke = iStrokeRep->getStroke(); + if(!stroke){ + cerr << "no stroke associated with Rep" << endl; + return; + } + + StrokeInternal::StrokeVertexIterator v = stroke->strokeVerticesBegin(); + StrokeAttribute att; + while(!v.isEnd()){ + att = v->attribute(); + _ofstream << v->u() << " " << v->getProjectedX() << " " << v->getProjectedY() << " " << v->getProjectedZ() << " " \ + << att.getThicknessL() << " " << att.getThicknessR() << " " \ + << att.getColorR() << " " << att.getColorG() << " " << att.getColorB() << " "; + ++v; + } + _ofstream << endl; +} + +void TextStrokeRenderer::Close(){ + if(_ofstream.is_open()) + _ofstream.close(); +} + diff --git a/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h new file mode 100755 index 00000000000..8b4b6bc80d7 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h @@ -0,0 +1,68 @@ +// +// Filename : TextStrokeRenderer.h +// Author(s) : Stephane Grabli +// Purpose : Class to define the text rendering of a stroke +// Format: +// x y width height // bbox +// //list of vertices : +// t x y z t1 t2 r g b alpha ... +// ... +// Date of creation : 01/14/2005 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef TEXTSTROKERENDERER_H +# define TEXTSTROKERENDERER_H + +# include "StrokeRenderer.h" +# include "../system/FreestyleConfig.h" +# include <fstream> + +/**********************************/ +/* */ +/* */ +/* TextStrokeRenderer */ +/* */ +/* */ +/**********************************/ + +class LIB_STROKE_EXPORT TextStrokeRenderer : public StrokeRenderer +{ +public: + TextStrokeRenderer(const char * iFileName = 0); + virtual ~TextStrokeRenderer(); + + /*! Renders a stroke rep */ + virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const; + virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const; + + /*! Closes the output file */ + void Close(); + +protected: + mutable ofstream _ofstream; +}; + +#endif // TEXTSTROKERENDERER_H + diff --git a/source/blender/freestyle/intern/system/BaseIterator.h b/source/blender/freestyle/intern/system/BaseIterator.h new file mode 100755 index 00000000000..45cc19df4fe --- /dev/null +++ b/source/blender/freestyle/intern/system/BaseIterator.h @@ -0,0 +1,90 @@ +// +// Filename : BaseIterator.h +// Author(s) : Stephane Grabli +// Purpose : Classes defining the basic "Iterator" design pattern +// Date of creation : 18/03/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef BASEITERATOR_H +# define BASEITERATOR_H + +# include <iterator> + +// use for iterators defintions +template <class Element> +class Nonconst_traits; + +template <class Element> +class Const_traits { +public: + typedef Element value_type; + typedef const Element& reference; + typedef const Element* pointer; + typedef ptrdiff_t difference_type; + typedef Nonconst_traits<Element> Non_const_traits; +}; + +template <class Element> +class Nonconst_traits { +public: + typedef Element value_type; + typedef Element& reference; + typedef Element* pointer; + typedef ptrdiff_t difference_type; + typedef Nonconst_traits<Element> Non_const_traits; +}; + +class InputIteratorTag_Traits { +public: + typedef std::input_iterator_tag iterator_category; +}; + +class BidirectionalIteratorTag_Traits { +public: + typedef std::bidirectional_iterator_tag iterator_category; +}; + +template<class Traits, class IteratorTagTraits> +class IteratorBase +{ +public: + + virtual ~IteratorBase() {} + + virtual bool begin() const = 0; + virtual bool end() const = 0; + + typedef typename IteratorTagTraits::iterator_category iterator_category; + typedef typename Traits::value_type value_type; + typedef typename Traits::difference_type difference_type; + typedef typename Traits::pointer pointer; + typedef typename Traits::reference reference; + +protected: + + IteratorBase() {} +}; + +#endif // BASEITERATOR_H diff --git a/source/blender/freestyle/intern/system/BaseObject.cpp b/source/blender/freestyle/intern/system/BaseObject.cpp new file mode 100755 index 00000000000..0cf1c917195 --- /dev/null +++ b/source/blender/freestyle/intern/system/BaseObject.cpp @@ -0,0 +1 @@ +#include "BaseObject.h" diff --git a/source/blender/freestyle/intern/system/BaseObject.h b/source/blender/freestyle/intern/system/BaseObject.h new file mode 100755 index 00000000000..a8515f98385 --- /dev/null +++ b/source/blender/freestyle/intern/system/BaseObject.h @@ -0,0 +1,73 @@ +// +// Filename : BaseObject.h +// Author(s) : Stephane Grabli +// Purpose : Base Class for most shared objects (Node, Rep). +// Defines the addRef, release system. +// Inspired by COM IUnknown system. +// Date of creation : 06/02/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef BASEOBJECT_H +# define BASEOBJECT_H + +#include "FreestyleConfig.h" + +class LIB_SYSTEM_EXPORT BaseObject +{ +public: + + inline BaseObject() { + _ref_counter = 0; + } + + virtual ~BaseObject() {} + + /*! At least makes a release on this. + * The BaseObject::destroy method must be + * explicitely called at the end of any + * overloaded destroy + */ + virtual int destroy() { + return release(); + } + + /*! Increments the reference counter */ + inline int addRef() { + return ++_ref_counter; + } + + /*! Decrements the reference counter */ + inline int release() { + if (_ref_counter) + _ref_counter--; + return _ref_counter; + } + +private: + + unsigned _ref_counter; +}; + +#endif // BASEOBJECT_H diff --git a/source/blender/freestyle/intern/system/Cast.h b/source/blender/freestyle/intern/system/Cast.h new file mode 100755 index 00000000000..15af767443e --- /dev/null +++ b/source/blender/freestyle/intern/system/Cast.h @@ -0,0 +1,44 @@ +// +// Filename : Cast.h +// Author(s) : Emmanuel Turquin +// Purpose : Cast function +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef CAST_HPP +# define CAST_HPP + +namespace Cast { + + template <class T, class U> + U* cast(T* in) { + if (!in) + return NULL; + return dynamic_cast<U*>(in); + } + +} // end of namespace Cast + +#endif // CAST_HPP diff --git a/source/blender/freestyle/intern/system/Exception.cpp b/source/blender/freestyle/intern/system/Exception.cpp new file mode 100755 index 00000000000..d1d12d18297 --- /dev/null +++ b/source/blender/freestyle/intern/system/Exception.cpp @@ -0,0 +1,24 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "Exception.h" + +Exception::exception_type Exception::_exception = Exception::NO_EXCEPTION; diff --git a/source/blender/freestyle/intern/system/Exception.h b/source/blender/freestyle/intern/system/Exception.h new file mode 100755 index 00000000000..378de6b558f --- /dev/null +++ b/source/blender/freestyle/intern/system/Exception.h @@ -0,0 +1,64 @@ +// +// Filename : Exception.h +// Author(s) : Stephane Grabli +// Purpose : Singleton to manage exceptions +// Date of creation : 10/01/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef EXCEPTION_H +# define EXCEPTION_H + +# include "FreestyleConfig.h" + +class LIB_SYSTEM_EXPORT Exception +{ +public: + + typedef enum { + NO_EXCEPTION, + UNDEFINED + } exception_type; + + static int getException() { + exception_type e = _exception; + _exception = NO_EXCEPTION; + return e; + } + + static int raiseException(exception_type exception = UNDEFINED) { + _exception = exception; + return _exception; + } + + static void reset() { + _exception = NO_EXCEPTION; + } + +private: + + static exception_type _exception; +}; + +#endif // EXCEPTION_H diff --git a/source/blender/freestyle/intern/system/FreestyleConfig.h b/source/blender/freestyle/intern/system/FreestyleConfig.h new file mode 100755 index 00000000000..f06b9928d1d --- /dev/null +++ b/source/blender/freestyle/intern/system/FreestyleConfig.h @@ -0,0 +1,90 @@ +// +// Filename : Config.h +// Author(s) : Emmanuel Turquin +// Purpose : Configuration definitions +// Date of creation : 25/02/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + + +#ifndef CONFIG_H +# define CONFIG_H + +# include <string> +# include "BLI_math.h" + +using namespace std; + +namespace Config { + + // Directory separators +# ifdef WIN32 + static const string DIR_SEP("\\"); + static const string PATH_SEP(";"); +# else + static const string DIR_SEP("/"); + static const string PATH_SEP(":"); +# endif // WIN32 + + // DLL import/export macros for Win32 + +# ifndef LIB_SYSTEM_EXPORT +# define LIB_SYSTEM_EXPORT +# endif // LIB_SYSTEM_EXPORT + +# ifndef LIB_IMAGE_EXPORT +# define LIB_IMAGE_EXPORT +# endif // LIB_IMAGE_EXPORT + +# ifndef LIB_GEOMETRY_EXPORT +# define LIB_GEOMETRY_EXPORT +# endif // LIB_GEOMETRY_EXPORT + +# ifndef LIB_SCENE_GRAPH_EXPORT +# define LIB_SCENE_GRAPH_EXPORT +# endif // LIB_SCENE_GRAPH_EXPORT + +# ifndef LIB_WINGED_EDGE_EXPORT +# define LIB_WINGED_EDGE_EXPORT +# endif // LIB_WINGED_EDGE_EXPORT + +# ifndef LIB_VIEW_MAP_EXPORT +# define LIB_VIEW_MAP_EXPORT +# endif // LIB_VIEW_MAP_EXPORT + +# ifndef LIB_STROKE_EXPORT +# define LIB_STROKE_EXPORT +# endif // LIB_STROKE_EXPORT + +# ifndef LIB_RENDERING_EXPORT +# define LIB_RENDERING_EXPORT +# endif // LIB_RENDERING_EXPORT + +# ifndef LIB_WRAPPER_EXPORT +# define LIB_WRAPPER_EXPORT +# endif // LIB_WRAPPER_EXPORT + +} // end of namespace Config + +#endif // CONFIG_H diff --git a/source/blender/freestyle/intern/system/Id.h b/source/blender/freestyle/intern/system/Id.h new file mode 100755 index 00000000000..1f2206ed337 --- /dev/null +++ b/source/blender/freestyle/intern/system/Id.h @@ -0,0 +1,126 @@ +// +// Filename : Id.h +// Author(s) : Emmanuel Turquin +// Purpose : Identification system +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef ID_H +# define ID_H + +/*! Class used to tag any object by an id . + * It is made of two unsigned integers. + */ +class Id +{ +public: + + typedef unsigned id_type; + + /*! Default constructor */ + Id() { + _first = 0; + _second = 0; + } + + /*! Builds an Id from an integer. + * The second number is set to 0. + */ + Id(id_type id) { + _first = id; + _second = 0; + } + + /*! Builds the Id from the two numbers */ + Id(id_type ifirst, id_type isecond) { + _first = ifirst; + _second = isecond; + } + + /*! Copy constructor */ + Id(const Id& iBrother) { + _first = iBrother._first; + _second = iBrother._second; + } + + /*! Operator= */ + Id& operator=(const Id& iBrother) { + _first = iBrother._first; + _second = iBrother._second; + return *this; + } + + /*! Returns the first Id number */ + id_type getFirst() const { + return _first; + } + + /*! Returns the second Id number */ + id_type getSecond() const { + return _second; + } + + /*! Sets the first number constituing the Id */ + void setFirst(id_type first) { + _first = first; + } + + /*! Sets the second number constituing the Id */ + void setSecond(id_type second) { + _second = second; + } + + /*! Operator== */ + bool operator==(const Id& id) const { + return ((_first == id._first) && (_second == id._second)); + } + + /*! Operator!= */ + bool operator!=(const Id& id) const { + return !((*this)==id); + } + + /*! Operator< */ + bool operator<(const Id& id) const { + if (_first < id._first) + return true; + if (_first == id._first && _second < id._second) + return true; + return false; +} + +private: + + id_type _first; + id_type _second; +}; + +// stream operator +inline std::ostream& operator<<(std::ostream& s, const Id& id) { + s << "[" << id.getFirst() << ", " << id.getSecond() << "]"; + return s; +} + +# endif // ID_H diff --git a/source/blender/freestyle/intern/system/Interpreter.h b/source/blender/freestyle/intern/system/Interpreter.h new file mode 100755 index 00000000000..75aaa2ccd18 --- /dev/null +++ b/source/blender/freestyle/intern/system/Interpreter.h @@ -0,0 +1,56 @@ +// +// Filename : Interpreter.h +// Author(s) : Emmanuel Turquin +// Purpose : Base Class of all script interpreters +// Date of creation : 17/04/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef INTERPRETER_H +# define INTERPRETER_H + +# include <string> + +using namespace std; + +class LIB_SYSTEM_EXPORT Interpreter +{ + public: + + Interpreter() { _language = "Unknown"; } + + virtual ~Interpreter() {}; //soc + + virtual int interpretFile(const string& filename) = 0; + + virtual string getLanguage() const { return _language; } + + virtual void reset() = 0; + + protected: + + string _language; +}; + +#endif // INTERPRETER_H diff --git a/source/blender/freestyle/intern/system/Iterator.cpp b/source/blender/freestyle/intern/system/Iterator.cpp new file mode 100644 index 00000000000..67acc893589 --- /dev/null +++ b/source/blender/freestyle/intern/system/Iterator.cpp @@ -0,0 +1 @@ +#include "Iterator.h" diff --git a/source/blender/freestyle/intern/system/Iterator.h b/source/blender/freestyle/intern/system/Iterator.h new file mode 100644 index 00000000000..1801c1e3b2f --- /dev/null +++ b/source/blender/freestyle/intern/system/Iterator.h @@ -0,0 +1,41 @@ +#ifndef ITERATOR_H +#define ITERATOR_H + +#include <iostream> +#include <string> +using namespace std; + + +class Iterator +{ +public: + + virtual ~Iterator() {} + + virtual string getExactTypeName() const { + return "Iterator"; + } + + virtual int increment() { + cerr << "Warning: increment() not implemented" << endl; + return 0; + } + + virtual int decrement() { + cerr << "Warning: decrement() not implemented" << endl; + return 0; + } + + virtual bool isBegin() const { + cerr << "Warning: isBegin() not implemented" << endl; + return false; + } + + virtual bool isEnd() const { + cerr << "Warning: isEnd() not implemented" << endl; + return false; + } + +}; + +#endif // ITERATOR_H diff --git a/source/blender/freestyle/intern/system/Precision.h b/source/blender/freestyle/intern/system/Precision.h new file mode 100755 index 00000000000..24327a280df --- /dev/null +++ b/source/blender/freestyle/intern/system/Precision.h @@ -0,0 +1,39 @@ +// +// Filename : Precision.h +// Author(s) : Stephane Grabli +// Purpose : Define the float precision used in the program +// Date of creation : 30/07/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef PRECISION_H +# define PRECISION_H + +typedef double real; + +# ifndef SWIG +static const real M_EPSILON = 0.00000001; +# endif // SWIG + +#endif // PRECISION_H diff --git a/source/blender/freestyle/intern/system/ProgressBar.h b/source/blender/freestyle/intern/system/ProgressBar.h new file mode 100755 index 00000000000..5b61f936c90 --- /dev/null +++ b/source/blender/freestyle/intern/system/ProgressBar.h @@ -0,0 +1,85 @@ +// +// Filename : ProgressBar.h +// Author(s) : Stephane Grabli +// Purpose : Class to encapsulate a progress bar +// Date of creation : 27/08/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef PROGRESSBAR_H +# define PROGRESSBAR_H + +# include <string> + +using namespace std; + +class ProgressBar +{ +public: + + inline ProgressBar() { + _numtotalsteps = 0; + _progress = 0; + } + + virtual ~ProgressBar() {} + + virtual void reset() { + _numtotalsteps = 0; + _progress = 0; + } + + virtual void setTotalSteps(unsigned n) { + _numtotalsteps = n; + } + + virtual void setProgress(unsigned i) { + _progress = i; + } + + virtual void setLabelText(const string& s) { + _label = s; + } + + /*! accessors */ + inline unsigned int getTotalSteps() const { + return _numtotalsteps; + } + + inline unsigned int getProgress() const { + return _progress; + } + + inline string getLabelText() const { + return _label; + } + +protected: + + unsigned _numtotalsteps; + unsigned _progress; + string _label; +}; + +#endif // PROGRESSBAR_H diff --git a/source/blender/freestyle/intern/system/PseudoNoise.cpp b/source/blender/freestyle/intern/system/PseudoNoise.cpp new file mode 100755 index 00000000000..87ee45e69b2 --- /dev/null +++ b/source/blender/freestyle/intern/system/PseudoNoise.cpp @@ -0,0 +1,108 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include <math.h> +#include "RandGen.h" +#include "PseudoNoise.h" + +static const unsigned NB_VALUE_NOISE = 512; + +real *PseudoNoise::_values; + +PseudoNoise::PseudoNoise () +{ +} + +void +PseudoNoise::init (long seed) +{ + _values = new real[NB_VALUE_NOISE]; + RandGen::srand48(seed); + for (unsigned int i=0; i<NB_VALUE_NOISE; i++) + _values[i] = -1.0 + 2.0 * RandGen::drand48(); +} + +real +PseudoNoise::linearNoise (real x) +{ + int i = x*NB_VALUE_NOISE; + real x1=_values[i%NB_VALUE_NOISE], x2=_values[(i+1)%NB_VALUE_NOISE]; + real t=x*real(NB_VALUE_NOISE)-real(i); + return x1*(1-t)+x2*t; +} + +real +LanczosWindowed(real t) +{ + if (fabs(t)>2) return 0; + if (fabs(t)<M_EPSILON) return 1.0; + return sin(M_PI*t)/(M_PI*t) * sin(M_PI*t/2.0)/(M_PI*t/2.0); +} + +real +PseudoNoise::smoothNoise (real x) +{ + int i = x*NB_VALUE_NOISE; + real t=x*real(NB_VALUE_NOISE)-real(i); + if (i - 1 < 0) + { + int plus=-i/NB_VALUE_NOISE; + i=i+NB_VALUE_NOISE*(plus+2); + t=(x+plus+2)*real(NB_VALUE_NOISE)-real(i); + } + + real x1=_values[i%NB_VALUE_NOISE], x2=_values[(i+1)%NB_VALUE_NOISE]; + real x0=_values[(i-1)%NB_VALUE_NOISE], x3=_values[(i+2)%NB_VALUE_NOISE]; + + real y0=LanczosWindowed(-1-t); + real y1=LanczosWindowed(-t); + real y2=LanczosWindowed(1-t); + real y3=LanczosWindowed(2-t); + // cerr<<"x0="<<x0<<" x1="<<x1<<" x2="<<x2<<" x3="<<x3<<endl; + // cerr<<"y0="<<y0<<" y1="<<y1<<" y2="<<y2<<" y3="<<y3<<" :"; + return (x0*y0+x1*y1+x2*y2+x3*y3)/(y0+y1+y2+y3); +} + +real +PseudoNoise::turbulenceSmooth (real x, unsigned nbOctave) +{ + real y=0; + real k=1.0; + for (unsigned i=0; i<nbOctave; i++) + { + y=y+k*smoothNoise(x*k); + k=k/2.0; + } + return y; +} + +real +PseudoNoise::turbulenceLinear (real x, unsigned nbOctave) +{ + real y=0; + real k=1.0; + for (unsigned i=0; i<nbOctave; i++) + { + y=y+k*linearNoise(x*k); + k=k/2.0; + } + return y; +} diff --git a/source/blender/freestyle/intern/system/PseudoNoise.h b/source/blender/freestyle/intern/system/PseudoNoise.h new file mode 100755 index 00000000000..43143865600 --- /dev/null +++ b/source/blender/freestyle/intern/system/PseudoNoise.h @@ -0,0 +1,58 @@ +// +// Filename : PseudoNoise.h +// Author(s) : Fredo Durand +// Purpose : Class to define a pseudo Perlin noise +// Date of creation : 16/06/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef PSEUDONOISE_H +# define PSEUDONOISE_H + +# include "FreestyleConfig.h" +# include "Precision.h" + +class LIB_SYSTEM_EXPORT PseudoNoise +{ +public: + + PseudoNoise (); + + virtual ~PseudoNoise () {} + + real smoothNoise (real x); + real linearNoise (real x); + + real turbulenceSmooth (real x, unsigned nbOctave = 8); + real turbulenceLinear (real x, unsigned nbOctave = 8); + + static void init (long seed); + +protected: + + static real *_values; +}; + +#endif // PSEUDONOISE_H + diff --git a/source/blender/freestyle/intern/system/PythonInterpreter.cpp b/source/blender/freestyle/intern/system/PythonInterpreter.cpp new file mode 100755 index 00000000000..821bd32b40b --- /dev/null +++ b/source/blender/freestyle/intern/system/PythonInterpreter.cpp @@ -0,0 +1,25 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "PythonInterpreter.h" + +string PythonInterpreter::_path = ""; +bool PythonInterpreter::_initialized = false; diff --git a/source/blender/freestyle/intern/system/PythonInterpreter.h b/source/blender/freestyle/intern/system/PythonInterpreter.h new file mode 100755 index 00000000000..1178e18cdea --- /dev/null +++ b/source/blender/freestyle/intern/system/PythonInterpreter.h @@ -0,0 +1,158 @@ +// +// Filename : PythonInterpreter.h +// Author(s) : Emmanuel Turquin +// Purpose : Python Interpreter +// Date of creation : 17/04/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef PYTHON_INTERPRETER_H +# define PYTHON_INTERPRETER_H + +# include <Python.h> +# include <iostream> +# include "StringUtils.h" +# include "Interpreter.h" + +//soc +extern "C" { +#include "MEM_guardedalloc.h" +#include "BKE_main.h" +#include "BKE_context.h" +#include "BKE_global.h" +#include "BKE_report.h" +#include "BKE_text.h" +#include "BKE_library.h" +#include "BPY_extern.h" +} + +class LIB_SYSTEM_EXPORT PythonInterpreter : public Interpreter +{ + public: + + PythonInterpreter() { + _language = "Python"; + _context = 0; + //Py_Initialize(); + } + + virtual ~PythonInterpreter() { + //Py_Finalize(); + } + + void setContext(bContext *C) { + _context = C; + } + + int interpretFile(const string& filename) { + + initPath(); + + ReportList* reports = CTX_wm_reports(_context); + BKE_reports_clear(reports); + char *fn = const_cast<char*>(filename.c_str()); +#if 0 + int status = BPY_run_python_script(_context, fn, NULL, reports); +#else + int status; + Text *text = add_text(fn, G.sce); + if (text) { + status = BPY_run_python_script(_context, NULL, text, reports); + unlink_text(G.main, text); + free_libblock(&G.main->text, text); + } else { + BKE_reportf(reports, RPT_ERROR, "Cannot open file: %s", fn); + status = 0; + } +#endif + + if (status != 1) { + cout << "\nError executing Python script from PythonInterpreter::interpretFile" << endl; + cout << "File: " << fn << endl; + cout << "Errors: " << endl; + BKE_reports_print(reports, RPT_ERROR); + return 1; + } + + // cleaning up + BKE_reports_clear(reports); + + return 0; + } + + struct Options + { + static void setPythonPath(const string& path) { + _path = path; + } + + static string getPythonPath() { + return _path; + } + }; + + void reset() { + Py_Finalize(); + Py_Initialize(); + _initialized = false; + } + +private: + + bContext* _context; + + void initPath() { + if (_initialized) + return; + + vector<string> pathnames; + StringUtils::getPathName(_path, "", pathnames); + + struct Text *text = add_empty_text("tmp_freestyle_initpath.txt"); + string cmd = "import sys\n"; + txt_insert_buf(text, const_cast<char*>(cmd.c_str())); + + for (vector<string>::const_iterator it = pathnames.begin(); it != pathnames.end();++it) { + if ( !it->empty() ) { + cout << "Adding Python path: " << *it << endl; + cmd = "sys.path.append(r\"" + *it + "\")\n"; + txt_insert_buf(text, const_cast<char*>(cmd.c_str())); + } + } + + BPY_run_python_script(_context, NULL, text, NULL); + + // cleaning up + unlink_text(G.main, text); + free_libblock(&G.main->text, text); + + //PyRun_SimpleString("from Freestyle import *"); + _initialized = true; + } + + static bool _initialized; + static string _path; +}; + +#endif // PYTHON_INTERPRETER_H diff --git a/source/blender/freestyle/intern/system/RandGen.cpp b/source/blender/freestyle/intern/system/RandGen.cpp new file mode 100755 index 00000000000..a328cb7f583 --- /dev/null +++ b/source/blender/freestyle/intern/system/RandGen.cpp @@ -0,0 +1,86 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "RandGen.h" + +// +// Macro definitions +// +/////////////////////////////////////////////////////////////////////////////// + +#define N 16 +#define MASK ((unsigned)(1 << (N - 1)) + (1 << (N - 1)) - 1) +#define X0 0x330E +#define X1 0xABCD +#define X2 0x1234 +#define A0 0xE66D +#define A1 0xDEEC +#define A2 0x5 +#define C 0xB +#define HI_BIT (1L << (2 * N - 1)) + +#define LOW(x) ((unsigned)(x) & MASK) +#define HIGH(x) LOW((x) >> N) +#define MUL(x, y, z) { long l = (long)(x) * (long)(y); \ + (z)[0] = LOW(l); (z)[1] = HIGH(l); } +#define CARRY(x, y) ((unsigned long)((long)(x) + (long)(y)) > MASK) +#define ADDEQU(x, y, z) (z = CARRY(x, (y)), x = LOW(x + (y))) +#define SET3(x, x0, x1, x2) ((x)[0] = (x0), (x)[1] = (x1), (x)[2] = (x2)) +#define SETLOW(x, y, n) SET3(x, LOW((y)[n]), LOW((y)[(n)+1]), LOW((y)[(n)+2])) +#define SEED(x0, x1, x2) (SET3(x, x0, x1, x2), SET3(a, A0, A1, A2), c = C) +#define REST(v) for (i = 0; i < 3; i++) { xsubi[i] = x[i]; x[i] = temp[i]; } \ + return (v); +#define NEST(TYPE, f, F) TYPE f(register unsigned short *xsubi) { \ + register int i; register TYPE v; unsigned temp[3]; \ + for (i = 0; i < 3; i++) { temp[i] = x[i]; x[i] = LOW(xsubi[i]); } \ + v = F(); REST(v); } + +static unsigned x[3] = { X0, X1, X2 }, a[3] = { A0, A1, A2 }, c = C; + +// +// Methods implementation +// +/////////////////////////////////////////////////////////////////////////////// + +real RandGen::drand48() { + static real two16m = 1.0 / (1L << N); + next(); + return (two16m * (two16m * (two16m * x[0] + x[1]) + x[2])); +} + +void RandGen::srand48(long seedval) { + SEED(X0, LOW(seedval), HIGH(seedval)); +} + +void RandGen::next() { + unsigned p[2], q[2], r[2], carry0, carry1; + + MUL(a[0], x[0], p); + ADDEQU(p[0], c, carry0); + ADDEQU(p[1], carry0, carry1); + MUL(a[0], x[1], q); + ADDEQU(p[1], q[0], carry0); + MUL(a[1], x[0], r); + x[2] = LOW(carry0 + carry1 + CARRY(p[1], r[0]) + q[1] + r[1] + + a[0] * x[2] + a[1] * x[1] + a[2] * x[0]); + x[1] = LOW(p[1] + r[0]); + x[0] = LOW(p[0]); +} diff --git a/source/blender/freestyle/intern/system/RandGen.h b/source/blender/freestyle/intern/system/RandGen.h new file mode 100755 index 00000000000..409d3b79609 --- /dev/null +++ b/source/blender/freestyle/intern/system/RandGen.h @@ -0,0 +1,48 @@ +// +// Filename : RandGen.h +// Author(s) : Fredo Durand +// Purpose : Pseudo-random number generator +// Date of creation : 20/05/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef RAND_GEN_H +# define RAND_GEN_H + +# include "FreestyleConfig.h" +# include "../system/Precision.h" + +class LIB_SYSTEM_EXPORT RandGen +{ +public: + + static real drand48(); + static void srand48(long value); + +private: + + static void next(); +}; + +#endif // RAND_GEN_H diff --git a/source/blender/freestyle/intern/system/StringUtils.cpp b/source/blender/freestyle/intern/system/StringUtils.cpp new file mode 100755 index 00000000000..58798daf42a --- /dev/null +++ b/source/blender/freestyle/intern/system/StringUtils.cpp @@ -0,0 +1,74 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +//soc #include <qfileinfo.h> +#include "FreestyleConfig.h" +#include "StringUtils.h" + +namespace StringUtils { + + void getPathName(const string& path, const string& base, vector<string>& pathnames) { + string dir; + string res; + char cleaned[FILE_MAX]; + unsigned size = path.size(); + + pathnames.push_back(base); + + for ( unsigned pos = 0, sep = path.find(Config::PATH_SEP, pos); + pos < size; + pos = sep + 1, sep = path.find(Config::PATH_SEP, pos)) { + + if (sep == (unsigned)string::npos) + sep = size; + + dir = path.substr(pos, sep - pos); + + BLI_strncpy(cleaned, dir.c_str(), FILE_MAX); + BLI_cleanup_file(NULL, cleaned); + res = toAscii( string(cleaned) ); + + if (!base.empty()) + res += Config::DIR_SEP + base; + + pathnames.push_back(res); + } + } + + string toAscii( const string &str ){ + stringstream out(""); + char s; + + for(unsigned int i=0; i < str.size() ; i++){ + s = ((char)(str.at(i) & 0x7F)); + out << s; + } + + return out.str(); + } + + const char* toAscii( const char *str ){ + return toAscii(string(str)).c_str(); + } + + + +} // end of namespace StringUtils diff --git a/source/blender/freestyle/intern/system/StringUtils.h b/source/blender/freestyle/intern/system/StringUtils.h new file mode 100755 index 00000000000..d44d3f62732 --- /dev/null +++ b/source/blender/freestyle/intern/system/StringUtils.h @@ -0,0 +1,62 @@ +// +// Filename : StringUtils.h +// Author(s) : Emmanuel Turquin +// Purpose : String utilities +// Date of creation : 20/05/2003 +// +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef STRING_UTILS_H +# define STRING_UTILS_H + +# include <cstring> +# include <vector> +# include <string> +# include <sstream> +# include <iostream> +# include "FreestyleConfig.h" + +//soc +extern "C" { +#include "BKE_utildefines.h" +#include "BLI_blenlib.h" +} + +using namespace std; + +namespace StringUtils { + + LIB_SYSTEM_EXPORT + void getPathName(const string& path, const string& base, vector<string>& pathnames); + string toAscii( const string &str ); + const char* toAscii( const char *str ); + + // STL related + struct ltstr{ + bool operator()(const char* s1, const char* s2) const{ + return strcmp(s1, s2) < 0; + } +}; + +} // end of namespace StringUtils + +#endif // STRING_UTILS_H diff --git a/source/blender/freestyle/intern/system/TimeStamp.cpp b/source/blender/freestyle/intern/system/TimeStamp.cpp new file mode 100755 index 00000000000..c66e1131611 --- /dev/null +++ b/source/blender/freestyle/intern/system/TimeStamp.cpp @@ -0,0 +1,25 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "TimeStamp.h" + +LIB_SYSTEM_EXPORT +TimeStamp* TimeStamp::_instance = 0; diff --git a/source/blender/freestyle/intern/system/TimeStamp.h b/source/blender/freestyle/intern/system/TimeStamp.h new file mode 100755 index 00000000000..568a7851e30 --- /dev/null +++ b/source/blender/freestyle/intern/system/TimeStamp.h @@ -0,0 +1,71 @@ +// +// Filename : TimeStamp.h +// Author(s) : Stephane Grabli +// Purpose : Class defining a singleton used as timestamp +// Date of creation : 12/12/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef TIMESTAMP_H +# define TIMESTAMP_H + +# include "FreestyleConfig.h" + +class LIB_SYSTEM_EXPORT TimeStamp +{ + public: + + static inline TimeStamp* instance() { + if (_instance == 0) + _instance = new TimeStamp; + return _instance; + } + + inline unsigned getTimeStamp() const { + return _time_stamp; + } + + inline void increment() { + ++_time_stamp; + } + + inline void reset() { + _time_stamp = 1; + } + + protected: + + TimeStamp() { + _time_stamp = 1; + } + + TimeStamp(const TimeStamp&) {} + + private: + + static TimeStamp* _instance; + unsigned _time_stamp; +}; + +#endif // TIMESTAMP_H diff --git a/source/blender/freestyle/intern/system/TimeUtils.h b/source/blender/freestyle/intern/system/TimeUtils.h new file mode 100755 index 00000000000..99dd5b0a669 --- /dev/null +++ b/source/blender/freestyle/intern/system/TimeUtils.h @@ -0,0 +1,58 @@ +// +// Filename : TimeUtils.h +// Author(s) : Stephane Grabli +// Purpose : Class to measure ellapsed time +// Date of creation : 10/04/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef TIMEUTILS_H +# define TIMEUTILS_H + +#include <time.h> +#include "FreestyleConfig.h" + +class Chronometer +{ + public: + + inline Chronometer() {} + inline ~Chronometer() {} + + inline clock_t start() { + _start = clock(); + return _start; + } + + inline double stop() { + clock_t stop = clock(); + return (double)(stop - _start) / CLOCKS_PER_SEC ; + } + + private: + + clock_t _start; +}; + +#endif // TIMEUTILS_H diff --git a/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp new file mode 100755 index 00000000000..16c38c63813 --- /dev/null +++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp @@ -0,0 +1,727 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "FEdgeXDetector.h" +#include "float.h" +#include "../geometry/GeomUtils.h" +#include <math.h> +#include "../geometry/normal_cycle.h" + +void FEdgeXDetector::processShapes(WingedEdge& we) { + bool progressBarDisplay = false; + Vec3r Min, Max; + vector<WShape*> wshapes = we.getWShapes(); + WXShape * wxs; + + if(_pProgressBar != NULL) { + _pProgressBar->reset(); + _pProgressBar->setLabelText("Detecting feature lines"); + _pProgressBar->setTotalSteps(wshapes.size() * 3); + _pProgressBar->setProgress(0); + progressBarDisplay = true; + } + + for(vector<WShape*>::const_iterator it = wshapes.begin(); + it != wshapes.end(); + it++){ + wxs = dynamic_cast<WXShape*>(*it); + wxs->bbox(Min, Max); + _bbox_diagonal = (Max-Min).norm(); + if(_changes){ + vector<WFace*>& wfaces = wxs->GetFaceList(); + for(vector<WFace*>::iterator wf=wfaces.begin(), wfend=wfaces.end(); + wf!=wfend; + ++wf){ + WXFace* wxf = dynamic_cast<WXFace*>(*wf); + wxf->Clear(); + } + _computeViewIndependant = true; + } else if (!(wxs)->getComputeViewIndependantFlag()) { + wxs->Reset(); + _computeViewIndependant = false; + } else { + _computeViewIndependant = true; + } + preProcessShape(wxs); + if (progressBarDisplay) + _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); + processBorderShape(wxs); + if(_computeMaterialBoundaries) + processMaterialBoundaryShape(wxs); + processCreaseShape(wxs); + if(_computeRidgesAndValleys) + processRidgesAndValleysShape(wxs); + if(_computeSuggestiveContours) + processSuggestiveContourShape(wxs); + processSilhouetteShape(wxs); + if (progressBarDisplay) + _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); + + // build smooth edges: + buildSmoothEdges(wxs); + + // Post processing for suggestive contours + if(_computeSuggestiveContours) + postProcessSuggestiveContourShape(wxs); + if (progressBarDisplay) + _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); + + wxs->setComputeViewIndependantFlag(false); + _computeViewIndependant = false; + _changes = false; + + // reset user data + (*it)->ResetUserData(); + } +} + +// GENERAL STUFF +//////////////// +void FEdgeXDetector::preProcessShape(WXShape* iWShape) { + _meanK1 = 0; + _meanKr = 0; + _minK1 = FLT_MAX; + _maxK1 = -FLT_MAX; + _minKr = FLT_MAX; + _maxKr = -FLT_MAX; + _nPoints = 0; + _meanEdgeSize = iWShape->getMeanEdgeSize(); + + vector<WFace*>& wfaces = iWShape->GetFaceList(); + vector<WFace*>::iterator f,fend; + // view dependant stuff + for(f=wfaces.begin(), fend=wfaces.end(); + f!=fend; + ++f){ + preProcessFace((WXFace*)(*f)); + } + + vector<WVertex*>& wvertices = iWShape->getVertexList(); + for(vector<WVertex*>::iterator wv=wvertices.begin(), wvend=wvertices.end(); + wv!=wvend; + ++wv){ + // Compute curvatures + WXVertex * wxv = dynamic_cast<WXVertex*>(*wv); + computeCurvatures(wxv); + } + _meanK1 /= (real)(_nPoints); + _meanKr /= (real)(_nPoints); +} + +void FEdgeXDetector::preProcessFace(WXFace *iFace){ + Vec3r firstPoint = iFace->GetVertex(0)->GetVertex(); + Vec3r N = iFace->GetNormal(); + + // Compute the dot product between V (=_Viewpoint - firstPoint) and N: + Vec3r V; + if (_orthographicProjection) { + V = Vec3r(0.0, 0.0, _Viewpoint.z() - firstPoint.z()); + } else { + V = Vec3r(_Viewpoint - firstPoint); + } + N.normalize(); + V.normalize(); + iFace->setDotP(N * V); + + // compute the distance between the face center and the viewpoint: + if (_orthographicProjection) { + iFace->setZ(iFace->center().z() - _Viewpoint.z()); + } else { + Vec3r dist_vec(iFace->center() - _Viewpoint); + iFace->setZ(dist_vec.norm()); + } +} + +void FEdgeXDetector::computeCurvatures(WXVertex *vertex){ + // CURVATURE LAYER + // store all the curvature datas for each vertex + + //soc unused - real K1, K2 + real cos2theta, sin2theta; + Vec3r e1, n, v; + // one vertex curvature info : + CurvatureInfo *C; + float radius = _sphereRadius*_meanEdgeSize; + + // view independant stuff + if(_computeViewIndependant){ + C = new CurvatureInfo(); + vertex->setCurvatures(C); + OGF::NormalCycle ncycle ; + ncycle.begin() ; + if(radius > 0) { + OGF::compute_curvature_tensor(vertex, radius, ncycle) ; + } else { + OGF::compute_curvature_tensor_one_ring(vertex, ncycle) ; + } + ncycle.end() ; + C->K1 = ncycle.kmin(); + C->K2 = ncycle.kmax(); + C->e1 = ncycle.Kmax(); //ncycle.kmin() * ncycle.Kmax(); + C->e2 = ncycle.Kmin(); //ncycle.kmax() * ncycle.Kmin() ; + + real absK1 = fabs(C->K1); + _meanK1 += absK1; + if(absK1 > _maxK1) + _maxK1 = absK1; + if(absK1 < _minK1) + _minK1 = absK1; + } + // view dependant + C = vertex->curvatures(); + if(C == 0) + return; + + // compute radial curvature : + n = C->e1 ^ C->e2; + if (_orthographicProjection) { + v = Vec3r(0.0, 0.0, _Viewpoint.z() - vertex->GetVertex().z()); + } else { + v = Vec3r(_Viewpoint - vertex->GetVertex()); + } + C->er = v - (v * n) * n; + C->er.normalize(); + e1 = C->e1; + e1.normalize(); + cos2theta = C->er * e1; + cos2theta *= cos2theta; + sin2theta = 1 - cos2theta; + C->Kr = C->K1 * cos2theta + C->K2 * sin2theta; + real absKr = fabs(C->Kr); + _meanKr += absKr; + if(absKr > _maxKr) + _maxKr = absKr; + if(absKr < _minKr) + _minKr = absKr; + + ++_nPoints; +} + +// SILHOUETTE +///////////// +void FEdgeXDetector::processSilhouetteShape(WXShape* iWShape) { + // Make a first pass on every polygons in order + // to compute all their silhouette relative values: + //------------------------------------------------ + vector<WFace*>& wfaces = iWShape->GetFaceList(); + vector<WFace*>::iterator f,fend; + for(f=wfaces.begin(), fend=wfaces.end(); + f!=fend; + ++f) + { + ProcessSilhouetteFace((WXFace*)(*f)); + } + + // Make a pass on the edges to detect + // the silhouette edges that are not smooth + // -------------------- + vector<WEdge*>::iterator we, weend; + vector<WEdge*> &wedges = iWShape->getEdgeList(); + for(we=wedges.begin(), weend=wedges.end(); + we!=weend; + ++we) + { + ProcessSilhouetteEdge((WXEdge*)(*we)); + } +} + +void FEdgeXDetector::ProcessSilhouetteFace(WXFace *iFace) +{ + + // SILHOUETTE LAYER + Vec3r normal; + // Compute the dot products between View direction and N at each vertex + // of the face: + Vec3r point; + int closestPointId = 0; + real dist, minDist = FLT_MAX; + int numVertices = iFace->numberOfVertices(); + WXFaceLayer * faceLayer = new WXFaceLayer(iFace, Nature::SILHOUETTE, true); + for(int i=0; i<numVertices; i++){ + point = iFace->GetVertex(i)->GetVertex(); + normal = iFace->GetVertexNormal(i); + normal.normalize(); + Vec3r V; + if (_orthographicProjection) { + V = Vec3r(0.0, 0.0, _Viewpoint.z() - point.z()); + } else { + V = Vec3r(_Viewpoint - point); + } + V.normalize(); + real d = normal * V; + faceLayer->PushDotP(d); + // Find the point the closest to the viewpoint + if (_orthographicProjection) { + dist = point.z() - _Viewpoint.z(); + } else { + Vec3r dist_vec(point - _Viewpoint); + dist = dist_vec.norm(); + } + if(dist < minDist) { + minDist = dist; + closestPointId = i; + } + } + // Set the closest point id: + faceLayer->setClosestPointIndex(closestPointId); + // Add this layer to the face: + iFace->AddSmoothLayer(faceLayer); +} + +void FEdgeXDetector::ProcessSilhouetteEdge(WXEdge *iEdge) +{ + if(iEdge->nature() & Nature::BORDER) + return; + // SILHOUETTE ? + //------------- + WXFace * fA = (WXFace *)iEdge->GetaOEdge()->GetaFace(); + WXFace * fB = (WXFace *)iEdge->GetaOEdge()->GetbFace(); + + if((fA->front())^(fB->front())){ // fA->visible XOR fB->visible (true if one is 0 and the other is 1) + // The only edges we want to set as silhouette edges in this + // way are the ones with 2 different normals for 1 vertex + // for these two faces + //-------------------- + // In reality we only test the normals for 1 of the 2 vertices. + if(fA->GetVertexNormal(iEdge->GetaVertex()) == fB->GetVertexNormal(iEdge->GetaVertex())) + return; + iEdge->AddNature(Nature::SILHOUETTE); + if(fB->front()) + iEdge->setOrder(1); + else + iEdge->setOrder(-1); + } +} + + +// BORDER +///////// +void FEdgeXDetector::processBorderShape(WXShape* iWShape) { + + if(!_computeViewIndependant) + return; + // Make a pass on the edges to detect + // the BORDER + // -------------------- + vector<WEdge*>::iterator we, weend; + vector<WEdge*> &wedges = iWShape->getEdgeList(); + for(we=wedges.begin(), weend=wedges.end(); + we!=weend; + ++we){ + ProcessBorderEdge((WXEdge*)(*we)); + } +} + +void FEdgeXDetector::ProcessBorderEdge(WXEdge *iEdge) +{ + // first check whether it is a border edge: + // BORDER ? + //--------- + if(iEdge->GetaFace() == 0){ + // it is a border edge + iEdge->AddNature(Nature::BORDER); + } +} + + +// CREASE +///////// +void FEdgeXDetector::processCreaseShape(WXShape* iWShape) { + if(!_computeViewIndependant) + return; + + // Make a pass on the edges to detect + // the CREASE + // -------------------- + vector<WEdge*>::iterator we, weend; + vector<WEdge*> &wedges = iWShape->getEdgeList(); + for(we=wedges.begin(), weend=wedges.end(); + we!=weend; + ++we){ + ProcessCreaseEdge((WXEdge*)(*we)); + } +} + +void FEdgeXDetector::ProcessCreaseEdge(WXEdge *iEdge) +{ + // CREASE ? + //--------- + if(iEdge->nature() & Nature::BORDER) + return; + WXFace * fA = (WXFace *)iEdge->GetaOEdge()->GetaFace(); + WXFace * fB = (WXFace *)iEdge->GetaOEdge()->GetbFace(); + + WVertex * aVertex = iEdge->GetaVertex(); + if((fA->GetVertexNormal(aVertex) * fB->GetVertexNormal(aVertex)) <= _creaseAngle) + iEdge->AddNature(Nature::CREASE); +} + +// RIDGES AND VALLEYS +///////////////////// + +void FEdgeXDetector::processRidgesAndValleysShape(WXShape* iWShape) { + // Don't forget to add the built layer to the face at the end + // of the ProcessFace: + //iFace->AddSmoothLayer(faceLayer); + + if((!_computeViewIndependant)) + return; + + // Here the curvatures must already have been computed + vector<WFace*>& wfaces = iWShape->GetFaceList(); + vector<WFace*>::iterator f, fend; + for(f=wfaces.begin(), fend=wfaces.end(); + f!=fend; + ++f) + { + ProcessRidgeFace((WXFace*)(*f)); + } +} + + +// RIDGES +///////// + +void FEdgeXDetector::ProcessRidgeFace(WXFace *iFace) +{ + WXFaceLayer * flayer = new WXFaceLayer(iFace, Nature::RIDGE|Nature::VALLEY, false); + iFace->AddSmoothLayer(flayer); + + unsigned int numVertices = iFace->numberOfVertices(); + for(unsigned int i=0; i<numVertices; ++i){ + WVertex *wv = iFace->GetVertex(i); + WXVertex * wxv = dynamic_cast<WXVertex*>(wv); + flayer->PushDotP(wxv->curvatures()->K1); + } + + real threshold = 0; + //real threshold = _maxK1 - (_maxK1-_meanK1)/20.0; + + if(flayer->nPosDotP()!=numVertices){ + if((fabs(flayer->dotP(0)) < threshold) && (fabs(flayer->dotP(1)) < threshold) && (fabs(flayer->dotP(2)) < threshold)){ + flayer->ReplaceDotP(0, 0); + flayer->ReplaceDotP(1, 0); + flayer->ReplaceDotP(2, 0); + } + } +} + +// void FEdgeXDetector::ProcessRidgeFace(WXFace *iFace) +// { + +// // RIDGE LAYER +// // compute the RidgeFunction, that is the derivative of the ppal curvature +// // along e1 at each vertex of the face + +// WVertex *v; +// Vec3r v1v2; +// real t; +// vector<WXFaceLayer*> SmoothLayers; +// WXFaceLayer *faceLayer; +// Face_Curvature_Info *layer_info; +// real K1_a(0), K1_b(0); +// Vec3r Inter_a, Inter_b; + +// // find the ridge layer of the face +// iFace->retrieveSmoothLayers(Nature::RIDGE, SmoothLayers); +// if(SmoothLayers.size()!=1) +// return; +// faceLayer = SmoothLayers[0]; +// // retrieve the curvature info of this layer +// layer_info = (Face_Curvature_Info *)faceLayer->userdata; + +// int numVertices = iFace->numberOfVertices(); +// for(int i=0; i<numVertices; i++){ +// v = iFace->GetVertex(i); +// // vec_curvature_info[i] contains the curvature info of this vertex +// Vec3r e2 = layer_info->vec_curvature_info[i]->K2*layer_info->vec_curvature_info[i]->e2; +// Vec3r e1 = layer_info->vec_curvature_info[i]->K1*layer_info->vec_curvature_info[i]->e1; +// e2.normalize(); + +// WVertex::face_iterator fit = v->faces_begin(); +// WVertex::face_iterator fitend = v->faces_end(); +// for(; fit!=fitend; ++fit){ +// WXFace * wxf = dynamic_cast<WXFace*>(*fit); +// WOEdge * oppositeEdge; +// if(!(wxf->getOppositeEdge(v, oppositeEdge))) +// continue; +// v1v2 = oppositeEdge->GetbVertex()->GetVertex() - oppositeEdge->GetaVertex()->GetVertex(); +// GeomUtils::intersection_test res; +// res = GeomUtils::intersectRayPlane(oppositeEdge->GetaVertex()->GetVertex(), v1v2, +// e2, -(v->GetVertex()*e2), +// t,1.e-06); +// if((res == GeomUtils::DO_INTERSECT) && (t>=0.0) && (t<=1.0)){ +// vector<WXFaceLayer*> second_ridge_layer; +// wxf->retrieveSmoothLayers(Nature::RIDGE, second_ridge_layer); +// if(second_ridge_layer.size()!=1) +// continue; +// Face_Curvature_Info *second_layer_info = (Face_Curvature_Info*)second_ridge_layer[0]->userdata; + +// unsigned index1 = wxf->GetIndex(oppositeEdge->GetaVertex()); +// unsigned index2 = wxf->GetIndex(oppositeEdge->GetbVertex()); +// real K1_1 = second_layer_info->vec_curvature_info[index1]->K1; +// real K1_2 = second_layer_info->vec_curvature_info[index2]->K1; +// real K1 = (1.0-t)*K1_1 + t*K1_2; +// Vec3r inter((1.0-t)*oppositeEdge->GetaVertex()->GetVertex() + t*oppositeEdge->GetbVertex()->GetVertex()); +// Vec3r vtmp(inter - v->GetVertex()); +// // is it K1_a or K1_b ? +// if(vtmp*e1 > 0){ +// K1_b = K1; +// Inter_b = inter; +// }else{ +// K1_a = K1; +// Inter_a = inter; +// } +// } +// } +// // Once we have K1 along the the ppal direction +// // compute the derivative : K1b - K1a +// // put it in DotP +// //real d = fabs(K1_b)-fabs(K1_a); +// real d = 0; +// real threshold = _meanK1 + (_maxK1-_meanK1)/7.0; +// //real threshold = _meanK1; +// //if((fabs(K1_b) > threshold) || ((fabs(K1_a) > threshold))) +// d = (K1_b)-(K1_a)/(Inter_b-Inter_a).norm(); +// faceLayer->PushDotP(d); +// //faceLayer->PushDotP(layer_info->vec_curvature_info[i]->K1); +// } + +// // Make the values relevant by checking whether all principal +// // directions have the "same" direction: +// Vec3r e0((layer_info->vec_curvature_info[0]->K1*layer_info->vec_curvature_info[0]->e1)); +// e0.normalize(); +// Vec3r e1((layer_info->vec_curvature_info[1]->K1*layer_info->vec_curvature_info[1]->e1)); +// e1.normalize(); +// Vec3r e2((layer_info->vec_curvature_info[2]->K1*layer_info->vec_curvature_info[2]->e1)); +// e2.normalize(); +// if (e0 * e1 < 0) +// // invert dotP[1] +// faceLayer->ReplaceDotP(1, -faceLayer->dotP(1)); +// if (e0 * e2 < 0) +// // invert dotP[2] +// faceLayer->ReplaceDotP(2, -faceLayer->dotP(2)); + +// // remove the weakest values; +// //real minDiff = (_maxK1 - _minK1)/10.0; +// // real minDiff = _meanK1; +// // if((faceLayer->dotP(0) < minDiff) && (faceLayer->dotP(1) < minDiff) && (faceLayer->dotP(2) < minDiff)){ +// // faceLayer->ReplaceDotP(0, 0); +// // faceLayer->ReplaceDotP(1, 0); +// // faceLayer->ReplaceDotP(2, 0); +// // } +// } + +// SUGGESTIVE CONTOURS +////////////////////// + +void FEdgeXDetector::processSuggestiveContourShape(WXShape* iWShape) { + + // Here the curvatures must already have been computed + vector<WFace*>& wfaces = iWShape->GetFaceList(); + vector<WFace*>::iterator f, fend; + for(f=wfaces.begin(), fend=wfaces.end(); + f!=fend; + ++f) + { + ProcessSuggestiveContourFace((WXFace*)(*f)); + } +} + +void FEdgeXDetector::ProcessSuggestiveContourFace(WXFace *iFace) +{ + WXFaceLayer *faceLayer = new WXFaceLayer(iFace, Nature::SUGGESTIVE_CONTOUR, true); + iFace->AddSmoothLayer(faceLayer); + + unsigned int numVertices = iFace->numberOfVertices(); + for(unsigned int i=0; i<numVertices; ++i){ + WVertex *wv = iFace->GetVertex(i); + WXVertex * wxv = dynamic_cast<WXVertex*>(wv); + faceLayer->PushDotP(wxv->curvatures()->Kr); + } + + // FIXME: find a more clever way to compute the threshold +// real threshold = _meanKr; +// if(faceLayer->nPosDotP()!=numVertices){ +// if((fabs(faceLayer->dotP(0)) < threshold) && (fabs(faceLayer->dotP(1)) < threshold) && (fabs(faceLayer->dotP(2)) < threshold)){ +// faceLayer->ReplaceDotP(0, 0); +// faceLayer->ReplaceDotP(1, 0); +// faceLayer->ReplaceDotP(2, 0); +// } +// } +} + +void FEdgeXDetector::postProcessSuggestiveContourShape(WXShape* iShape) { + vector<WFace*>& wfaces = iShape->GetFaceList(); + vector<WFace*>::iterator f, fend; + for(f=wfaces.begin(), fend=wfaces.end(); + f!=fend; + ++f) + { + postProcessSuggestiveContourFace((WXFace*)(*f)); + } +} + +void FEdgeXDetector::postProcessSuggestiveContourFace(WXFace *iFace) { + + // Compute the derivative of the radial curvature in the radial direction, + // at the two extremities of the smooth edge. + // If the derivative is smaller than a given threshold _kr_derivative_epsilon, + // discard the edge. + + // Find the suggestive contour layer of the face (zero or one edge). + vector<WXFaceLayer*> sc_layers; + iFace->retrieveSmoothEdgesLayers(Nature::SUGGESTIVE_CONTOUR, sc_layers); + if(sc_layers.empty()) + return; + + WXFaceLayer *sc_layer; + sc_layer = sc_layers[0]; + + // Compute the derivative value at each vertex of the face, and add it in a vector. + vector<real> kr_derivatives; + + unsigned vertices_nb = iFace->numberOfVertices(); + WXVertex *v, *opposite_vertex_a, *opposite_vertex_b; + WXFace *wxf; + WOEdge *opposite_edge; + Vec3r opposite_edge_vec, normal_vec, radial_normal_vec, er_vec, v_vec, inter, inter1, inter2, tmp_vec; + GeomUtils::intersection_test res; + real kr(0), kr1(0), kr2(0), t; + + for (unsigned i = 0; i < vertices_nb; ++i) { + v = (WXVertex*)(iFace->GetVertex(i)); + + // v is a singular vertex, skip it. + if (v->isBoundary()) { + kr_derivatives.push_back(0); + continue; + } + + v_vec = v->GetVertex(); + er_vec = v->curvatures()->er; + + // For each vertex, iterate on its adjacent faces. + for (WVertex::face_iterator fit = v->faces_begin(), fitend = v->faces_end(); + fit != fitend; + ++fit) { + wxf = dynamic_cast<WXFace*>(*fit); + if(!(wxf->getOppositeEdge(v, opposite_edge))) + continue; + + opposite_vertex_a = (WXVertex*)opposite_edge->GetaVertex(); + opposite_vertex_b = (WXVertex*)opposite_edge->GetbVertex(); + opposite_edge_vec = opposite_vertex_b->GetVertex() - opposite_vertex_a->GetVertex(); + normal_vec = wxf->GetVertexNormal(v); // FIXME: what about e1 ^ e2 ? + radial_normal_vec = er_vec ^ normal_vec; + + // Test wether the radial plan intersects with the edge at the opposite of v. + res = GeomUtils::intersectRayPlane(opposite_vertex_a->GetVertex(), opposite_edge_vec, + radial_normal_vec, -(v_vec * radial_normal_vec), + t, + 1.e-06); + + // If there is an intersection, compute the value of the derivative ath that point. + if ((res == GeomUtils::DO_INTERSECT) && (t >= 0) && (t <= 1)) { + kr = t * opposite_vertex_a->curvatures()->Kr + (1 - t) * opposite_vertex_b->curvatures()->Kr; + inter = opposite_vertex_a->GetVertex() + t * opposite_edge_vec; + tmp_vec = inter - v->GetVertex(); + // Is it kr1 or kr2? + if (tmp_vec * er_vec > 0) { + kr2 = kr; + inter2 = inter; + } else { + kr1 = kr; + inter1 = inter; + } + } + } + + // Now we have kr1 and kr2 along the radial direction, for one vertex of iFace. + // We have to compute the derivative of kr for that vertex, equal to: + // (kr2 - kr1) / dist(inter1, inter2). + // Then we add it to the vector of derivatives. + v->curvatures()->dKr = (kr2 - kr1) / (inter2 - inter1).norm(); + kr_derivatives.push_back(v->curvatures()->dKr); + } + + // At that point, we have the derivatives for each vertex of iFace. + // All we have to do now is to use linear interpolation to compute the values at + // the extremities of the smooth edge. + WXSmoothEdge *sc_edge = sc_layer->getSmoothEdge(); + WOEdge *sc_oedge = sc_edge->woea(); + t = sc_edge->ta(); + if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] + + (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] < _kr_derivative_epsilon) { + sc_layer->removeSmoothEdge(); + return; + } + sc_oedge = sc_edge->woeb(); + t = sc_edge->tb(); + if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] + + (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] < _kr_derivative_epsilon) + sc_layer->removeSmoothEdge(); +} + +// MATERIAL_BOUNDARY +//////////////////// +void FEdgeXDetector::processMaterialBoundaryShape(WXShape* iWShape) { + + if(!_computeViewIndependant) + return; + // Make a pass on the edges to detect material boundaries + vector<WEdge*>::iterator we, weend; + vector<WEdge*> &wedges = iWShape->getEdgeList(); + for(we=wedges.begin(), weend=wedges.end(); + we!=weend; + ++we){ + ProcessMaterialBoundaryEdge((WXEdge*)(*we)); + } +} + +void FEdgeXDetector::ProcessMaterialBoundaryEdge(WXEdge *iEdge) +{ + // check whether the edge is a material boundary? + WFace *aFace = iEdge->GetaFace(); + WFace *bFace = iEdge->GetbFace(); + if(aFace && bFace && aFace->frs_materialIndex() != bFace->frs_materialIndex()){ + iEdge->AddNature(Nature::MATERIAL_BOUNDARY); + } +} + +// Build Smooth edges +///////////////////// +void FEdgeXDetector::buildSmoothEdges(WXShape* iShape){ + // Make a last pass to build smooth edges from the previous stored values: + //-------------------------------------------------------------------------- + vector<WFace*>& wfaces = iShape->GetFaceList(); + for(vector<WFace*>::iterator f=wfaces.begin(), fend=wfaces.end(); + f!=fend; + ++f) + { + vector<WXFaceLayer*>& faceLayers = ((WXFace*)(*f))->getSmoothLayers(); + for(vector<WXFaceLayer*>::iterator wxfl = faceLayers.begin(), wxflend=faceLayers.end(); + wxfl!=wxflend; + ++wxfl){ + (*wxfl)->BuildSmoothEdge(); + } + } +} diff --git a/source/blender/freestyle/intern/view_map/FEdgeXDetector.h b/source/blender/freestyle/intern/view_map/FEdgeXDetector.h new file mode 100755 index 00000000000..4cbaa4a7b5a --- /dev/null +++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.h @@ -0,0 +1,179 @@ +// +// Filename : FEdgeXDetector.h +// Author(s) : Stephane Grabli +// Purpose : Detects/flags/builds extended features edges on the +// WXEdge structure +// Date of creation : 26/10/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + + +#ifndef FEDGEXDETECTOR_H +# define FEDGEXDETECTOR_H + +# include <vector> +# include "../system/FreestyleConfig.h" +# include "../geometry/Geom.h" +# include "../winged_edge/WXEdge.h" +# include "../winged_edge/Curvature.h" +# include "../system/ProgressBar.h" + +using namespace Geometry; + +/*! This class takes as input a WXEdge structure and fills it + */ + +class LIB_VIEW_MAP_EXPORT FEdgeXDetector +{ +public: + + FEdgeXDetector() { + _pProgressBar = 0; + _computeViewIndependant = true; + _bbox_diagonal = 1.0; + _meanEdgeSize = 0; + _computeRidgesAndValleys = true; + _computeSuggestiveContours = true; + _computeMaterialBoundaries = true; + _sphereRadius = 1.0; + _orthographicProjection = false; + _changes = false; + _kr_derivative_epsilon = 0.0; + _creaseAngle = 0.7; // angle of 134.43 degrees + } + virtual ~FEdgeXDetector() {} + + /*! Process shapes from a WingedEdge containing a list of WShapes */ + virtual void processShapes(WingedEdge&); + + // GENERAL STUFF + virtual void preProcessShape(WXShape* iShape); + virtual void preProcessFace(WXFace* iFace); + virtual void computeCurvatures(WXVertex *iVertex); + + // SILHOUETTE + virtual void processSilhouetteShape(WXShape* iShape); + virtual void ProcessSilhouetteFace(WXFace *iFace); + virtual void ProcessSilhouetteEdge(WXEdge *iEdge); + + // CREASE + virtual void processCreaseShape(WXShape* iShape); + virtual void ProcessCreaseEdge(WXEdge *iEdge); + /*! Sets the minimum angle for detecting crease edges + * \param angle + * The angular threshold in degrees (between 0 and 180) for detecting crease + * edges. An edge is considered a crease edge if the angle between two faces + * sharing the edge is smaller than the given threshold. + */ + inline void setCreaseAngle(real angle) { + if (angle < 0.0) + angle = 0.0; + else if (angle > 180.0) + angle = 180.0; + angle = cos(M_PI * (180.0 - angle) / 180.0); + if (angle != _creaseAngle){ + _creaseAngle = angle; + _changes = true; + } + } + + // BORDER + virtual void processBorderShape(WXShape* iShape); + virtual void ProcessBorderEdge(WXEdge *iEdge); + + // RIDGES AND VALLEYS + virtual void processRidgesAndValleysShape(WXShape* iShape); + virtual void ProcessRidgeFace(WXFace *iFace); + + // SUGGESTIVE CONTOURS + virtual void processSuggestiveContourShape(WXShape* iShape); + virtual void ProcessSuggestiveContourFace(WXFace *iFace); + virtual void postProcessSuggestiveContourShape(WXShape* iShape); + virtual void postProcessSuggestiveContourFace(WXFace *iFace); + /*! Sets the minimal derivative of the radial curvature for suggestive contours + * \param dkr + * The minimal derivative of the radial curvature + */ + inline void setSuggestiveContourKrDerivativeEpsilon(real dkr) { + if (dkr != _kr_derivative_epsilon){ + _kr_derivative_epsilon = dkr; + _changes = true; + } + } + + // MATERIAL BOUNDARY + virtual void processMaterialBoundaryShape(WXShape* iWShape); + virtual void ProcessMaterialBoundaryEdge(WXEdge *iEdge); + + // EVERYBODY + virtual void buildSmoothEdges(WXShape* iShape); + + /*! Sets the current viewpoint */ + inline void setViewpoint(const Vec3r& ivp) {_Viewpoint = ivp;} + inline void enableOrthographicProjection(bool b) {_orthographicProjection = b;} + inline void enableRidgesAndValleysFlag(bool b) {_computeRidgesAndValleys = b;} + inline void enableSuggestiveContours(bool b) {_computeSuggestiveContours = b;} + inline void enableMaterialBoundaries(bool b) {_computeMaterialBoundaries = b;} + /*! Sets the radius of the geodesic sphere around each vertex (for the curvature computation) + * \param r + * The radius of the sphere expressed as a ratio of the mean edge size + */ + inline void setSphereRadius(real r) { + if(r!=_sphereRadius){ + _sphereRadius = r; + _changes=true; + } + } + + inline void setProgressBar(ProgressBar *iProgressBar) {_pProgressBar = iProgressBar;} + +protected: + + Vec3r _Viewpoint; + real _bbox_diagonal; // diagonal of the current processed shape bbox + //oldtmp values + bool _computeViewIndependant; + real _meanK1; + real _meanKr; + real _minK1; + real _minKr; + real _maxK1; + real _maxKr; + unsigned _nPoints; + real _meanEdgeSize; + bool _orthographicProjection; + + bool _computeRidgesAndValleys; + bool _computeSuggestiveContours; + bool _computeMaterialBoundaries; + real _sphereRadius; // expressed as a ratio of the mean edge size + real _creaseAngle; // [-1, 1] compared with the inner product of face normals + bool _changes; + + real _kr_derivative_epsilon; + + ProgressBar *_pProgressBar; +}; + +#endif // FEDGEDXETECTOR_H diff --git a/source/blender/freestyle/intern/view_map/Functions0D.cpp b/source/blender/freestyle/intern/view_map/Functions0D.cpp new file mode 100755 index 00000000000..dc38ca34184 --- /dev/null +++ b/source/blender/freestyle/intern/view_map/Functions0D.cpp @@ -0,0 +1,362 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +# include "Functions0D.h" +# include "ViewMap.h" + +using namespace std; + +namespace Functions0D { + + // Internal function + FEdge* getFEdge(Interface0D& it1, Interface0D& it2){ + return it1.getFEdge(it2); + } + + void getFEdges(Interface0DIterator& it, + FEdge*& fe1, + FEdge*& fe2) { + // count number of vertices + Interface0DIterator prev = it, next = it; + ++next; + int count = 1; + if (!it.isBegin() && !next.isEnd()) { + count = 3; + } + if(count < 3) + { + // if we only have 2 vertices + FEdge * fe = 0; + Interface0DIterator tmp = it; + if(it.isBegin()) + { + ++tmp; + fe = it->getFEdge(*tmp); + } + else + { + --tmp; + fe = it->getFEdge(*tmp); + } + fe1 = fe; + fe2 = 0; + } + else + { + // we have more than 2 vertices + bool begin=false,last=false; + Interface0DIterator previous = it; + if(!previous.isBegin()) + --previous; + else + begin=true; + Interface0DIterator next = it; + ++next; + if(next.isEnd()) + last = true; + if(begin) + { + fe1 = it->getFEdge(*next); + fe2 = 0; + } + else if(last) + { + fe1 = previous->getFEdge(*it); + fe2 = 0; + } + else + { + fe1 = previous->getFEdge(*it); + fe2 = it->getFEdge(*next); + } + } + } + + void getViewEdges(Interface0DIterator &it, + ViewEdge *&ve1, + ViewEdge *&ve2) + { + FEdge * fe1, *fe2; + getFEdges(it, fe1, fe2); + ve1 = fe1->viewedge(); + if(fe2 != 0) + { + ve2 = fe2->viewedge(); + if(ve2 == ve1) + ve2 = 0; + } + else + ve2 = 0; + } + + ViewShape* getShapeF0D(Interface0DIterator& it) + { + ViewEdge *ve1, *ve2; + getViewEdges(it, ve1, ve2); + return ve1->viewShape(); + } + + void getOccludersF0D(Interface0DIterator& it, set<ViewShape*>& oOccluders){ + ViewEdge * ve1, *ve2; + getViewEdges(it, ve1, ve2); + occluder_container::const_iterator oit = ve1->occluders_begin(); + occluder_container::const_iterator oitend = ve1->occluders_end(); + + for(;oit!=oitend; ++oit) + oOccluders.insert((*oit)); + + if(ve2!=0){ + oit = ve2->occluders_begin(); + oitend = ve2->occluders_end(); + for(;oit!=oitend; ++oit) + oOccluders.insert((*oit)); + } + } + + ViewShape * getOccludeeF0D(Interface0DIterator& it){ + ViewEdge * ve1, *ve2; + getViewEdges(it, ve1, ve2); + ViewShape *aShape = ve1->aShape(); + return aShape; + } + + // + int VertexOrientation2DF0D::operator()(Interface0DIterator& iter) { + Vec2f A,C; + Vec2f B(iter->getProjectedX(), iter->getProjectedY()); + if(iter.isBegin()) + A = Vec2f(iter->getProjectedX(), iter->getProjectedY()); + else + { + Interface0DIterator previous = iter; + --previous ; + A = Vec2f(previous->getProjectedX(), previous->getProjectedY()); + } + Interface0DIterator next = iter; + ++next ; + if(next.isEnd()) + C = Vec2f(iter->getProjectedX(), iter->getProjectedY()); + else + C = Vec2f(next->getProjectedX(), next->getProjectedY()); + + Vec2f AB(B-A); + if(AB.norm() != 0) + AB.normalize(); + Vec2f BC(C-B); + if(BC.norm() != 0) + BC.normalize(); + result = AB + BC; + if(result.norm() != 0) + result.normalize(); + return 0; + } + + int VertexOrientation3DF0D::operator()(Interface0DIterator& iter) { + Vec3r A,C; + Vec3r B(iter->getX(), iter->getY(), iter->getZ()); + if(iter.isBegin()) + A = Vec3r(iter->getX(), iter->getY(), iter->getZ()); + else + { + Interface0DIterator previous = iter; + --previous ; + A = Vec3r(previous->getX(), previous->getY(), previous->getZ()); + } + Interface0DIterator next = iter; + ++next ; + if(next.isEnd()) + C = Vec3r(iter->getX(), iter->getY(), iter->getZ()); + else + C = Vec3r(next->getX(), next->getY(), next->getZ()); + + Vec3r AB(B-A); + if(AB.norm() != 0) + AB.normalize(); + Vec3r BC(C-B); + if(BC.norm() != 0) + BC.normalize(); + result = AB + BC; + if(result.norm() != 0) + result.normalize(); + return 0; + } + + int Curvature2DAngleF0D::operator()(Interface0DIterator& iter) { + Interface0DIterator tmp1 = iter, tmp2 = iter; + ++tmp2; + unsigned count = 1; + while((!tmp1.isBegin()) && (count < 3)) + { + --tmp1; + ++count; + } + while((!tmp2.isEnd()) && (count < 3)) + { + ++tmp2; + ++count; + } + if(count < 3) { + // if we only have 2 vertices + result = 0; + return 0; + } + + Interface0DIterator v = iter; + if(iter.isBegin()) + ++v; + Interface0DIterator next=v; + ++next; + if(next.isEnd()) + { + next = v; + --v; + } + Interface0DIterator prev=v; + --prev; + + Vec2r A(prev->getProjectedX(), prev->getProjectedY()); + Vec2r B(v->getProjectedX(), v->getProjectedY()); + Vec2r C(next->getProjectedX(), next->getProjectedY()); + Vec2r AB(B-A); + Vec2r BC(C-B); + Vec2r N1(-AB[1], AB[0]); + if(N1.norm() != 0) + N1.normalize(); + Vec2r N2(-BC[1], BC[0]); + if(N2.norm() != 0) + N2.normalize(); + if((N1.norm() == 0) && (N2.norm() == 0)) + { + Exception::raiseException(); + result = 0; + return -1; + } + double cosin = N1*N2; + if(cosin > 1) + cosin = 1; + if(cosin < -1) + cosin = -1; + result = acos(cosin); + return 0; + } + + int ZDiscontinuityF0D::operator()(Interface0DIterator& iter) { + FEdge *fe1, *fe2; + getFEdges(iter, fe1, fe2); + result = fe1->z_discontinuity(); + if(fe2!=0){ + result += fe2->z_discontinuity(); + result /= 2.f; + } + return 0; + } + + int Normal2DF0D::operator()(Interface0DIterator& iter) { + FEdge *fe1, *fe2; + getFEdges(iter,fe1,fe2); + Vec3f e1(fe1->orientation2d()); + Vec2f n1(e1[1], -e1[0]); + Vec2f n(n1); + if(fe2 != 0) + { + Vec3f e2(fe2->orientation2d()); + Vec2f n2(e2[1], -e2[0]); + n += n2; + } + n.normalize(); + result = n; + return 0; + } + + int MaterialF0D::operator()(Interface0DIterator& iter) { + FEdge *fe1, *fe2; + getFEdges(iter,fe1,fe2); + + if(fe1 == 0) { + // DEBUG + getFEdges(iter, fe1, fe2); + return 1; + } + + if(fe1->isSmooth()) + result = ((FEdgeSmooth*)fe1)->frs_material(); + else + result = ((FEdgeSharp*)fe1)->bFrsMaterial(); + // const SShape * sshape = getShapeF0D(iter); + // return sshape->material(); + return 0; + } + + int ShapeIdF0D::operator()(Interface0DIterator& iter) { + ViewShape * vshape = getShapeF0D(iter); + result = vshape->getId(); + return 0; + } + + int QuantitativeInvisibilityF0D::operator()(Interface0DIterator& iter) { + ViewEdge * ve1, *ve2; + getViewEdges(iter,ve1,ve2); + unsigned int qi1, qi2; + qi1 = ve1->qi(); + if(ve2 != 0){ + qi2 = ve2->qi(); + if(qi2!=qi1) + cout << "QuantitativeInvisibilityF0D: ambiguous evaluation for point " << iter->getId() << endl; + } + result = qi1; + return 0; + } + + int CurveNatureF0D::operator()(Interface0DIterator& iter) { + Nature::EdgeNature nat = 0; + ViewEdge * ve1, *ve2; + getViewEdges(iter, ve1, ve2); + nat |= ve1->getNature(); + if(ve2!=0) + nat |= ve2->getNature(); + result = nat; + return 0; + } + + int GetOccludersF0D::operator()(Interface0DIterator& iter) { + set<ViewShape*> occluders; + getOccludersF0D(iter,occluders); + result.clear(); + // vsOccluders.insert(vsOccluders.begin(), occluders.begin(), occluders.end()); + for(set<ViewShape*>::iterator it=occluders.begin(), itend=occluders.end(); + it!=itend; + ++it){ + result.push_back((*it)); + } + return 0; + } + + int GetShapeF0D::operator()(Interface0DIterator& iter) { + result = getShapeF0D(iter); + return 0; + } + + int GetOccludeeF0D::operator()(Interface0DIterator& iter) { + result = getOccludeeF0D(iter); + return 0; + } + +} // end of namespace Functions0D diff --git a/source/blender/freestyle/intern/view_map/Functions0D.h b/source/blender/freestyle/intern/view_map/Functions0D.h new file mode 100755 index 00000000000..4adbc8a1bf5 --- /dev/null +++ b/source/blender/freestyle/intern/view_map/Functions0D.h @@ -0,0 +1,500 @@ +// +// Filename : Functions0D.h +// Author(s) : Stephane Grabli, Emmanuel Turquin +// Purpose : Functions taking 0D input +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef FUNCTIONS0D_H +# define FUNCTIONS0D_H + +# include "../system/Precision.h" +# include "Interface0D.h" +# include "../geometry/Geom.h" +# include "../system/Exception.h" +# include "../scene_graph/FrsMaterial.h" +# include <set> +# include <vector> +class FEdge; +class ViewEdge; +class SShape; + +using namespace Geometry; + +#include "../python/Director.h" + +// +// UnaryFunction0D (base class for functions in 0D) +// +/////////////////////////////////////////////////////////// + +template <class T> +/*! Base class for Unary Functions (functors) working + * on Interface0DIterator. + * A unary function will be used by calling + * its operator() on an Interface0DIterator. + * \attention In the scripting language, there exists + * several prototypes depending on the returned value type. + * For example, you would inherit from a UnaryFunction0DDouble + * if you wish to define a function that returns a double. + * The different existing prototypes are: + * - UnaryFunction0DVoid + * - UnaryFunction0DUnsigned + * - UnaryFunction0DReal + * - UnaryFunction0DFloat + * - UnaryFunction0DDouble + * - UnaryFunction0DVec2f + * - UnaryFunction0DVec3f + */ +class /*LIB_VIEW_MAP_EXPORT*/ UnaryFunction0D +{ +public: + + T result; + PyObject *py_uf0D; + + /*! The type of the value + * returned by the functor. + */ + typedef T ReturnedValueType; + /*! Default constructor. */ +UnaryFunction0D() { py_uf0D = 0;} + /*! Destructor; */ + virtual ~UnaryFunction0D() {} + /*! Returns the string "UnaryFunction0D" */ + virtual string getName() const { + return "UnaryFunction0D"; + } + /*! The operator (). + * \param iter + * An Interface0DIterator pointing onto + * the point at which we wish to evaluate + * the function. + * \return the result of the function of type T. + */ + virtual int operator()(Interface0DIterator& iter) { + return Director_BPy_UnaryFunction0D___call__( this, py_uf0D, iter ); + } + +}; + +# ifdef SWIG +%feature("director") UnaryFunction0D<void>; +%feature("director") UnaryFunction0D<unsigned>; +%feature("director") UnaryFunction0D<float>; +%feature("director") UnaryFunction0D<double>; +%feature("director") UnaryFunction0D<Vec2f>; +%feature("director") UnaryFunction0D<Vec3f>; +%feature("director") UnaryFunction0D<Id>; + +%template(UnaryFunction0DVoid) UnaryFunction0D<void>; +%template(UnaryFunction0DUnsigned) UnaryFunction0D<unsigned>; +%template(UnaryFunction0DFloat) UnaryFunction0D<float>; +%template(UnaryFunction0DDouble) UnaryFunction0D<double>; +%template(UnaryFunction0DVec2f) UnaryFunction0D<Vec2f>; +%template(UnaryFunction0DVec3f) UnaryFunction0D<Vec3f>; +%template(UnaryFunction0DId) UnaryFunction0D<Id>; +%template(UnaryFunction0DViewShape) UnaryFunction0D<ViewShape*>; +%template(UnaryFunction0DVectorViewShape) UnaryFunction0D<std::vector<ViewShape*> >; +# endif // SWIG + + +// +// Functions definitions +// +/////////////////////////////////////////////////////////// +class ViewShape; +namespace Functions0D { + + // GetXF0D + /*! Returns the X 3D coordinate of an Interface0D. */ + class LIB_VIEW_MAP_EXPORT GetXF0D : public UnaryFunction0D<real> + { + public: + /*! Returns the string "GetXF0D"*/ + string getName() const { + return "GetXF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter) { + result = iter->getX(); + return 0; + } + }; + + // GetYF0D + /*! Returns the Y 3D coordinate of an Interface0D. */ + class LIB_VIEW_MAP_EXPORT GetYF0D : public UnaryFunction0D<real> + { + public: + /*! Returns the string "GetYF0D"*/ + string getName() const { + return "GetYF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter) { + result = iter->getY(); + return 0; + } + }; + + // GetZF0D + /*! Returns the Z 3D coordinate of an Interface0D. */ + class LIB_VIEW_MAP_EXPORT GetZF0D : public UnaryFunction0D<real> + { + public: + /*! Returns the string "GetZF0D"*/ + string getName() const { + return "GetZF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter) { + result = iter->getZ(); + return 0; + } + }; + + // GetProjectedXF0D + /*! Returns the X 3D projected coordinate of an Interface0D. */ + class LIB_VIEW_MAP_EXPORT GetProjectedXF0D : public UnaryFunction0D<real> + { + public: + /*! Returns the string "GetProjectedXF0D"*/ + string getName() const { + return "GetProjectedXF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter) { + result = iter->getProjectedX(); + return 0; + } + }; + + // GetProjectedYF0D + /*! Returns the Y projected 3D coordinate of an Interface0D. */ + class LIB_VIEW_MAP_EXPORT GetProjectedYF0D : public UnaryFunction0D<real> + { + public: + /*! Returns the string "GetProjectedYF0D"*/ + string getName() const { + return "GetProjectedYF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter) { + result = iter->getProjectedY(); + return 0; + } + }; + + // GetProjectedZF0D + /*! Returns the Z projected 3D coordinate of an Interface0D. */ + class LIB_VIEW_MAP_EXPORT GetProjectedZF0D : public UnaryFunction0D<real> + { + public: + /*! Returns the string "GetProjectedZF0D"*/ + string getName() const { + return "GetProjectedZF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter) { + result = iter->getProjectedZ(); + return 0; + } + }; + + // GetCurvilinearAbscissaF0D + /*! Returns the curvilinear abscissa of an Interface0D in the context of its 1D element. */ + class LIB_VIEW_MAP_EXPORT GetCurvilinearAbscissaF0D : public UnaryFunction0D<float> + { + public: + /*! Returns the string "GetCurvilinearAbscissaF0D"*/ + string getName() const { + return "GetCurvilinearAbscissaF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter) { + result = iter.t(); + return 0; + } + }; + + // GetParameterF0D + /*! Returns the parameter of an Interface0D in the context of its 1D element. */ + class LIB_VIEW_MAP_EXPORT GetParameterF0D : public UnaryFunction0D<float> + { + public: + /*! Returns the string "GetCurvilinearAbscissaF0D"*/ + string getName() const { + return "GetParameterF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter) { + result = iter.u(); + return 0; + } + }; + + // VertexOrientation2DF0D + /*! Returns a Vec2r giving the 2D oriented tangent to the 1D element + * to which the Interface0DIterator& belongs to and + * evaluated at the Interface0D pointed by this Interface0DIterator&. + */ + class LIB_VIEW_MAP_EXPORT VertexOrientation2DF0D : public UnaryFunction0D<Vec2f> + { + public: + /*! Returns the string "VertexOrientation2DF0D"*/ + string getName() const { + return "VertexOrientation2DF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter); + }; + + // VertexOrientation3DF0D + /*! Returns a Vec3r giving the 3D oriented tangent to the 1D element + * to which the Interface0DIterator& belongs to and + * evaluated at the Interface0D pointed by this Interface0DIterator&. + */ + class LIB_VIEW_MAP_EXPORT VertexOrientation3DF0D : public UnaryFunction0D<Vec3f> + { + public: + /*! Returns the string "VertexOrientation3DF0D"*/ + string getName() const { + return "VertexOrientation3DF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter); + }; + + // Curvature2DAngleF0D + /*! Returns a real giving the 2D curvature (as an angle) of the 1D element + * to which the Interface0DIterator& belongs to and + * evaluated at the Interface0D pointed by this Interface0DIterator&. + */ + class LIB_VIEW_MAP_EXPORT Curvature2DAngleF0D : public UnaryFunction0D<real> + { + public: + /*! Returns the string "Curvature2DAngleF0D"*/ + string getName() const { + return "Curvature2DAngleF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter); + }; + + // ZDiscontinuity + /*! Returns a real giving the distance between + * and Interface0D and the shape that lies behind (occludee). + * This distance is evaluated in the camera space and normalized + * between 0 and 1. Therefore, if no oject is occluded by the + * shape to which the Interface0D belongs to, 1 is returned. + */ + class LIB_VIEW_MAP_EXPORT ZDiscontinuityF0D : public UnaryFunction0D<real> + { + public: + /*! Returns the string "ZDiscontinuityF0D"*/ + string getName() const { + return "ZDiscontinuityF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter); + }; + + // Normal2DF0D + /*! Returns a Vec2f giving the normalized 2D normal to the 1D element + * to which the Interface0DIterator& belongs to and + * evaluated at the Interface0D pointed by this Interface0DIterator&. + */ + class LIB_VIEW_MAP_EXPORT Normal2DF0D : public UnaryFunction0D<Vec2f> + { + public: + /*! Returns the string "Normal2DF0D"*/ + string getName() const { + return "Normal2DF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter); + }; + + // MaterialF0D + /*! Returns the material of the object evaluated at the Interface0D. + * This evaluation can be ambiguous (in the case of a TVertex for example. + * This functor tries to remove this ambiguity using the context + * offered by the 1D element to which the Interface0DIterator& belongs + * to and by arbitrary chosing the material of the face + * that lies on its left when following the 1D element if there + * are two different materials on each side of the point. + * However, there still can be problematic cases, and the user willing + * to deal with this cases in a specific way should implement + * its own getMaterial functor. + */ + class LIB_VIEW_MAP_EXPORT MaterialF0D : public UnaryFunction0D<FrsMaterial> + { + public: + /*! Returns the string "MaterialF0D"*/ + string getName() const { + return "MaterialF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter); + }; + + // ShapeIdF0D + /*! Returns the Id of the Shape the Interface0D belongs to. + * This evaluation can be ambiguous (in the case of a TVertex for example). + * This functor tries to remove this ambiguity using the context + * offered by the 1D element to which the Interface0DIterator& belongs + * to. + * However, there still can be problematic cases, and the user willing + * to deal with this cases in a specific way should implement + * its own getShapeIdF0D functor. + */ + class LIB_VIEW_MAP_EXPORT ShapeIdF0D : public UnaryFunction0D<Id> + { + public: + /*! Returns the string "ShapeIdF0D"*/ + string getName() const { + return "ShapeIdF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter); + }; + + // QiF0D + /*! Returns the quantitative invisibility of this Interface0D. + * This evaluation can be ambiguous (in the case of a TVertex for example). + * This functor tries to remove this ambiguity using the context + * offered by the 1D element to which the Interface0DIterator& belongs + * to. + * However, there still can be problematic cases, and the user willing + * to deal with this cases in a specific way should implement + * its own getQIF0D functor. + */ + class LIB_VIEW_MAP_EXPORT QuantitativeInvisibilityF0D : public UnaryFunction0D<unsigned int> + { + public: + /*! Returns the string "QuantitativeInvisibilityF0D"*/ + string getName() const { + return "QuantitativeInvisibilityF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter); + }; + + // CurveNatureF0D + /*! Returns the Nature::EdgeNature of the 1D element the + * Interface0DIterator& belongs to. + */ + class LIB_VIEW_MAP_EXPORT CurveNatureF0D : public UnaryFunction0D<Nature::EdgeNature> + { + public: + /*! Returns the string "QuantitativeInvisibilityF0D"*/ + string getName() const { + return "CurveNatureF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter); + }; + + // GetShapeF0D + /*! Returns the ViewShape* + * containing the Interface0D + */ + class LIB_VIEW_MAP_EXPORT GetShapeF0D : public UnaryFunction0D< ViewShape*> + { + public: + /*! Returns the string "GetShapeF0D"*/ + string getName() const { + return "GetShapeF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter); + }; + + // GetOccludersF0D + /*! Returns a vector containing the ViewShape* + * occluding the Interface0D + */ + class LIB_VIEW_MAP_EXPORT GetOccludersF0D : public UnaryFunction0D< std::vector<ViewShape*> > + { + public: + /*! Returns the string "GetOccludersF0D"*/ + string getName() const { + return "GetOccludersF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter); + }; + + // GetOccludeeF0D + /*! Returns the ViewShape* + * "occluded" by the Interface0D + */ + class LIB_VIEW_MAP_EXPORT GetOccludeeF0D: public UnaryFunction0D< ViewShape*> + { + public: + /*! Returns the string "GetOccludeeF0D"*/ + string getName() const { + return "GetOccludeeF0D"; + } + /*! the () operator.*/ + int operator()(Interface0DIterator& iter); + }; + + + + /////////////////////////// Internal //////////////////////////// + + // getFEdge + LIB_VIEW_MAP_EXPORT + FEdge* getFEdge(Interface0D& it1, Interface0D& it2); + + // getFEdges + LIB_VIEW_MAP_EXPORT + void getFEdges(Interface0DIterator& it, + FEdge*& fe1, + FEdge*& fe2); + + // getViewEdges + LIB_VIEW_MAP_EXPORT + void getViewEdges(Interface0DIterator& it, + ViewEdge *&ve1, + ViewEdge *&ve2); + + // getShapeF0D + LIB_VIEW_MAP_EXPORT + ViewShape* getShapeF0D(Interface0DIterator& it); + + // getOccludersF0D + LIB_VIEW_MAP_EXPORT + void getOccludersF0D(Interface0DIterator& it, std::set<ViewShape*>& oOccluders); + + // getOccludeeF0D + LIB_VIEW_MAP_EXPORT + ViewShape* getOccludeeF0D(Interface0DIterator& it); + +} // end of namespace Functions0D + +#endif // FUNCTIONS0D_H diff --git a/source/blender/freestyle/intern/view_map/Functions1D.cpp b/source/blender/freestyle/intern/view_map/Functions1D.cpp new file mode 100755 index 00000000000..8545c660084 --- /dev/null +++ b/source/blender/freestyle/intern/view_map/Functions1D.cpp @@ -0,0 +1,231 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +# include "Functions1D.h" +using namespace std; + +namespace Functions1D { + + int GetXF1D::operator()(Interface1D& inter) { + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; + } + + int GetYF1D::operator()(Interface1D& inter) { + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; + } + + int GetZF1D::operator()(Interface1D& inter) { + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; + } + + int GetProjectedXF1D::operator()(Interface1D& inter) { + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; + } + + int GetProjectedYF1D::operator()(Interface1D& inter) { + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; + } + + int GetProjectedZF1D::operator()(Interface1D& inter) { + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; + } + + int Orientation2DF1D::operator()(Interface1D& inter) { + FEdge * fe = dynamic_cast<FEdge*>(&inter); + if(fe){ + Vec3r res = fe->orientation2d(); + result = Vec2f(res[0], res[1]); + } else { + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); + } + return 0; + } + + int Orientation3DF1D::operator()(Interface1D& inter) { + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; + } + + int ZDiscontinuityF1D::operator()(Interface1D& inter) { + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; + } + + int QuantitativeInvisibilityF1D::operator()(Interface1D& inter) { + ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter); + if (ve) { + result = ve->qi(); + return 0; + } + FEdge *fe = dynamic_cast<FEdge*>(&inter); + if (fe) { + result = ve->qi(); + return 0; + } + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; + } + + int CurveNatureF1D::operator()(Interface1D& inter) { + ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter); + if (ve) + result = ve->getNature(); + else{ + // we return a nature that contains every + // natures of the viewedges spanned by the chain. + Nature::EdgeNature nat = Nature::NO_FEATURE; + Interface0DIterator it = inter.verticesBegin(); + while(!it.isEnd()){ + nat |= _func(it); + ++it; + } + result = nat; + } + return 0; + } + + int TimeStampF1D::operator()(Interface1D& inter) { + TimeStamp *timestamp = TimeStamp::instance(); + inter.setTimeStamp(timestamp->getTimeStamp()); + return 0; + } + + int ChainingTimeStampF1D::operator()(Interface1D& inter) { + TimeStamp *timestamp = TimeStamp::instance(); + ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter); + if(ve) + ve->setChainingTimeStamp(timestamp->getTimeStamp()); + return 0; + } + + int IncrementChainingTimeStampF1D::operator()(Interface1D& inter) { + ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter); + if(ve) + ve->setChainingTimeStamp(ve->getChainingTimeStamp()+1); + return 0; + } + + int GetShapeF1D::operator()(Interface1D& inter) { + vector<ViewShape*> shapesVector; + set<ViewShape*> shapesSet; + ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter); + if (ve){ + shapesVector.push_back(ve->viewShape()); + }else{ + Interface0DIterator it=inter.verticesBegin(), itend=inter.verticesEnd(); + for(;it!=itend;++it) + shapesSet.insert(Functions0D::getShapeF0D(it)); + shapesVector.insert<set<ViewShape*>::iterator>(shapesVector.begin(), shapesSet.begin(), shapesSet.end()); + } + result = shapesVector; + return 0; + } + + int GetOccludersF1D::operator()(Interface1D& inter) { + vector<ViewShape*> shapesVector; + set<ViewShape*> shapesSet; + ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter); + if (ve){ + result = ve->occluders(); + }else{ + Interface0DIterator it=inter.verticesBegin(), itend=inter.verticesEnd(); + for(;it!=itend;++it){ + Functions0D::getOccludersF0D(it, shapesSet); + } + shapesVector.insert(shapesVector.begin(), shapesSet.begin(), shapesSet.end()); + result = shapesVector; + } + return 0; + } + + int GetOccludeeF1D::operator()(Interface1D& inter) { + vector<ViewShape*> shapesVector; + set<ViewShape*> shapesSet; + ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter); + if (ve){ + ViewShape * aShape = ve->aShape(); + shapesVector.push_back(aShape); + }else{ + Interface0DIterator it=inter.verticesBegin(), itend=inter.verticesEnd(); + for(;it!=itend;++it){ + shapesSet.insert(Functions0D::getOccludeeF0D(it)); + } + shapesVector.insert<set<ViewShape*>::iterator>(shapesVector.begin(), shapesSet.begin(), shapesSet.end()); + } + result = shapesVector; + return 0; + } + // Internal + //////////// + + void getOccludeeF1D(Interface1D& inter, set<ViewShape*>& oShapes){ + ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter); + if (ve){ + ViewShape * aShape = ve->aShape(); + if(aShape == 0){ + oShapes.insert(0); + return; + } + oShapes.insert(aShape); + } + else{ + Interface0DIterator it=inter.verticesBegin(), itend=inter.verticesEnd(); + for(;it!=itend;++it) + oShapes.insert(Functions0D::getOccludeeF0D(it)); + } + } + + void getOccludersF1D(Interface1D& inter, set<ViewShape*>& oShapes){ + ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter); + if (ve){ + vector<ViewShape*>& occluders = ve->occluders(); + oShapes.insert<vector<ViewShape*>::iterator>(occluders.begin(), occluders.end()); + } + else{ + Interface0DIterator it=inter.verticesBegin(), itend=inter.verticesEnd(); + for(;it!=itend;++it){ + set<ViewShape*> shapes; + Functions0D::getOccludersF0D(it, shapes); + for(set<ViewShape*>::iterator s=shapes.begin(), send=shapes.end(); + s!=send; + ++s) + oShapes.insert(*s); + } + } + } + + void getShapeF1D(Interface1D& inter, set<ViewShape*>& oShapes){ + ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter); + if (ve){ + oShapes.insert(ve->viewShape()); + }else{ + Interface0DIterator it=inter.verticesBegin(), itend=inter.verticesEnd(); + for(;it!=itend;++it) + oShapes.insert(Functions0D::getShapeF0D(it)); + } + } +} // end of namespace Functions1D diff --git a/source/blender/freestyle/intern/view_map/Functions1D.h b/source/blender/freestyle/intern/view_map/Functions1D.h new file mode 100755 index 00000000000..ba42b25b47e --- /dev/null +++ b/source/blender/freestyle/intern/view_map/Functions1D.h @@ -0,0 +1,555 @@ +// +// Filename : Functions1D.h +// Author(s) : Stephane Grabli, Emmanuel Turquin +// Purpose : Functions taking 1D input +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef FUNCTIONS1D_HPP +# define FUNCTIONS1D_HPP + +# include "ViewMap.h" +# include "Functions0D.h" +# include "Interface1D.h" +# include "../system/Precision.h" +# include "../system/TimeStamp.h" +# include "../system/FreestyleConfig.h" + +#include "../python/Director.h" + +// +// UnaryFunction1D (base class for functions in 1D) +// +/////////////////////////////////////////////////////////// + +/*! Base class for Unary Functions (functors) working + * on Interface1D. + * A unary function will be used by calling + * its operator() on an Interface1D. + * \attention In the scripting language, there exists + * several prototypes depending on the returned value type. + * For example, you would inherit from a UnaryFunction1DDouble + * if you wish to define a function that returns a double. + * The different existing prototypes are: + * - UnaryFunction1DVoid + * - UnaryFunction1DUnsigned + * - UnaryFunction1DReal + * - UnaryFunction1DFloat + * - UnaryFunction1DDouble + * - UnaryFunction1DVec2f + * - UnaryFunction1DVec3f + */ +template <class T> +class /*LIB_VIEW_MAP_EXPORT*/ UnaryFunction1D +{ +public: + + T result; + PyObject *py_uf1D; + + /*! The type of the value + * returned by the functor. + */ + typedef T ReturnedValueType; + + /*! Default constructor */ + UnaryFunction1D(){_integration = MEAN;} + /*! Builds a UnaryFunction1D from an integration type. + * \param iType + * In case the result for the Interface1D would be + * obtained by evaluating a 0D function over the different + * Interface0D of the Interface1D, \a iType tells which + * integration method to use. + * The default integration method is the MEAN. + */ + UnaryFunction1D(IntegrationType iType){_integration = iType;} + /*! destructor. */ + virtual ~UnaryFunction1D() {} + + /*! returns the string "UnaryFunction1D". */ + virtual string getName() const { + return "UnaryFunction1D"; + } + /*! The operator (). + * \param inter + * The Interface1D on which we wish to evaluate + * the function. + * \return the result of the function of type T. + */ + virtual int operator()(Interface1D& inter) { + return Director_BPy_UnaryFunction1D___call__( this, py_uf1D, inter ); + } + + /*! Sets the integration method */ + void setIntegrationType(IntegrationType integration) { + _integration = integration; + } + /*! Returns the integration method. */ + IntegrationType getIntegrationType() const { + return _integration; + } + +protected: + + IntegrationType _integration; +}; + + +class UnaryFunction1D_void +{ +public: + + PyObject *py_uf1D; + + UnaryFunction1D_void(){_integration = MEAN;} + UnaryFunction1D_void(IntegrationType iType){_integration = iType;} + virtual ~UnaryFunction1D_void() {} + + virtual string getName() const { + return "UnaryFunction1D_void"; + } + + int operator()(Interface1D& inter) { + return Director_BPy_UnaryFunction1D___call__( this, py_uf1D, inter ); + } + + void setIntegrationType(IntegrationType integration) { _integration = integration; } + IntegrationType getIntegrationType() const { return _integration; } + + protected: + IntegrationType _integration; +}; + + +// +// Functions definitions +// +/////////////////////////////////////////////////////////// + +namespace Functions1D { + + // GetXF1D + /*! Returns the X 3D coordinate of an Interface1D. */ + class LIB_VIEW_MAP_EXPORT GetXF1D : public UnaryFunction1D<real> + { + private: + Functions0D::GetXF0D _func; + public: + /*! Builds the functor. + * \param iType + * The integration method used to compute + * a single value from a set of values. + */ + GetXF1D(IntegrationType iType) : UnaryFunction1D<real>(iType){} + /*! Returns the string "GetXF1D"*/ + string getName() const { + return "GetXF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter) ; + }; + + // GetYF1D + /*! Returns the Y 3D coordinate of an Interface1D. */ + class LIB_VIEW_MAP_EXPORT GetYF1D : public UnaryFunction1D<real> + { + private: + Functions0D::GetYF0D _func; + public: + /*! Builds the functor. + * \param iType + * The integration method used to compute + * a single value from a set of values. + */ + GetYF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType){} + /*! Returns the string "GetYF1D"*/ + string getName() const { + return "GetYF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter) ; + }; + + // GetZF1D + /*! Returns the Z 3D coordinate of an Interface1D. */ + class LIB_VIEW_MAP_EXPORT GetZF1D : public UnaryFunction1D<real> + { + private: + Functions0D::GetZF0D _func; + public: + /*! Builds the functor. + * \param iType + * The integration method used to compute + * a single value from a set of values. + */ + GetZF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType){} + /*! Returns the string "GetZF1D"*/ + string getName() const { + return "GetZF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter) ; + }; + + // GetProjectedXF1D + /*! Returns the projected X 3D coordinate of an Interface1D. */ + class LIB_VIEW_MAP_EXPORT GetProjectedXF1D : public UnaryFunction1D<real> + { + private: + Functions0D::GetProjectedXF0D _func; + public: + /*! Builds the functor. + * \param iType + * The integration method used to compute + * a single value from a set of values. + */ + GetProjectedXF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType){} + public: + /*! Returns the string "GetProjectedXF1D"*/ + string getName() const { + return "GetProjectedXF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter); + }; + + // GetProjectedYF1D + /*! Returns the projected Y 3D coordinate of an Interface1D. */ + class LIB_VIEW_MAP_EXPORT GetProjectedYF1D : public UnaryFunction1D<real> + { + private: + Functions0D::GetProjectedYF0D _func; + public: + /*! Builds the functor. + * \param iType + * The integration method used to compute + * a single value from a set of values. + */ + GetProjectedYF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType){} + public: + /*! Returns the string "GetProjectedYF1D"*/ + string getName() const { + return "GetProjectedYF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter); + }; + + // GetProjectedZF1D + /*! Returns the projected Z 3D coordinate of an Interface1D. */ + class LIB_VIEW_MAP_EXPORT GetProjectedZF1D : public UnaryFunction1D<real> + { + private: + Functions0D::GetProjectedZF0D _func; + public: + /*! Builds the functor. + * \param iType + * The integration method used to compute + * a single value from a set of values. + */ + GetProjectedZF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType){} + public: + /*! Returns the string "GetProjectedZF1D"*/ + string getName() const { + return "GetProjectedZF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter); + }; + + // Orientation2DF1D + /*! Returns the 2D orientation as a Vec2f*/ + class LIB_VIEW_MAP_EXPORT Orientation2DF1D : public UnaryFunction1D<Vec2f> + { + private: + Functions0D::VertexOrientation2DF0D _func; + public: + /*! Builds the functor. + * \param iType + * The integration method used to compute + * a single value from a set of values. + */ + Orientation2DF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Vec2f>(iType){} + /*! Returns the string "Orientation2DF1D"*/ + string getName() const { + return "Orientation2DF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter); + }; + + // Orientation3DF1D + /*! Returns the 3D orientation as a Vec3f. */ + class LIB_VIEW_MAP_EXPORT Orientation3DF1D : public UnaryFunction1D<Vec3f> + { + private: + Functions0D::VertexOrientation3DF0D _func; + public: + /*! Builds the functor. + * \param iType + * The integration method used to compute + * a single value from a set of values. + */ + Orientation3DF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Vec3f>(iType){} + /*! Returns the string "Orientation3DF1D"*/ + string getName() const { + return "Orientation3DF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter); + }; + + // ZDiscontinuityF1D + /*! Returns a real giving the distance between + * and Interface1D and the shape that lies behind (occludee). + * This distance is evaluated in the camera space and normalized + * between 0 and 1. Therefore, if no oject is occluded by the + * shape to which the Interface1D belongs to, 1 is returned. + */ + class LIB_VIEW_MAP_EXPORT ZDiscontinuityF1D : public UnaryFunction1D<real> + { + private: + Functions0D::ZDiscontinuityF0D _func; + public: + /*! Builds the functor. + * \param iType + * The integration method used to compute + * a single value from a set of values. + */ + ZDiscontinuityF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType){} + /*! Returns the string "ZDiscontinuityF1D"*/ + string getName() const { + return "ZDiscontinuityF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter); + }; + + // QuantitativeInvisibilityF1D + /*! Returns the Quantitative Invisibility of an Interface1D element. + * If the Interface1D is a ViewEdge, then there is no ambiguity + * concerning the result. But, if the Interface1D results of a chaining + * (chain, stroke), then it might be made of several 1D elements + * of different Quantitative Invisibilities. + */ + class LIB_VIEW_MAP_EXPORT QuantitativeInvisibilityF1D : public UnaryFunction1D<unsigned> + { + private: + Functions0D::QuantitativeInvisibilityF0D _func; + public: + /*! Builds the functor. + * \param iType + * The integration method used to compute + * a single value from a set of values. + */ + QuantitativeInvisibilityF1D(IntegrationType iType = MEAN) : UnaryFunction1D<unsigned int>(iType) {} + /*! Returns the string "QuantitativeInvisibilityF1D"*/ + string getName() const { + return "QuantitativeInvisibilityF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter); + }; + + // CurveNatureF1D +/*! Returns the nature of the Interface1D (silhouette, ridge, crease...). + * Except if the Interface1D is a ViewEdge, this result might be ambiguous. + * Indeed, the Interface1D might result from the gathering of several 1D elements, + * each one being of a different nature. An integration method, such as + * the MEAN, might give, in this case, irrelevant results. + */ + class LIB_VIEW_MAP_EXPORT CurveNatureF1D : public UnaryFunction1D<Nature::EdgeNature> + { + private: + Functions0D::CurveNatureF0D _func; + public: + /*! Builds the functor. + * \param iType + * The integration method used to compute + * a single value from a set of values. + */ + CurveNatureF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Nature::EdgeNature>(iType) {} + /*! Returns the string "CurveNatureF1D"*/ + string getName() const { + return "CurveNatureF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter); + }; + + // TimeStampF1D +/*! Returns the time stamp of the Interface1D. */ + class LIB_VIEW_MAP_EXPORT TimeStampF1D : public UnaryFunction1D_void + { + public: + /*! Returns the string "TimeStampF1D"*/ + string getName() const { + return "TimeStampF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter); + }; + + // IncrementChainingTimeStampF1D +/*! Increments the chaining time stamp of the Interface1D. */ + class LIB_VIEW_MAP_EXPORT IncrementChainingTimeStampF1D : public UnaryFunction1D_void + { + public: + /*! Returns the string "IncrementChainingTimeStampF1D"*/ + string getName() const { + return "IncrementChainingTimeStampF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter); + }; + + // ChainingTimeStampF1D +/*! Sets the chaining time stamp of the Interface1D. */ + class LIB_VIEW_MAP_EXPORT ChainingTimeStampF1D : public UnaryFunction1D_void + { + public: + /*! Returns the string "ChainingTimeStampF1D"*/ + string getName() const { + return "ChainingTimeStampF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter); + }; + + + // Curvature2DAngleF1D +/*! Returns the 2D curvature as an angle for an Interface1D. */ + class LIB_VIEW_MAP_EXPORT Curvature2DAngleF1D : public UnaryFunction1D<real> + { + public: + /*! Builds the functor. + * \param iType + * The integration method used to compute + * a single value from a set of values. + */ + Curvature2DAngleF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType) {} + /*! Returns the string "Curvature2DAngleF1D"*/ + string getName() const { + return "Curvature2DAngleF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter) { + result = integrate(_fun, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; + } + private: + Functions0D::Curvature2DAngleF0D _fun; + }; + + // Normal2DF1D + /*! Returns the 2D normal for an interface 1D. */ + class LIB_VIEW_MAP_EXPORT Normal2DF1D : public UnaryFunction1D<Vec2f> + { + public: + /*! Builds the functor. + * \param iType + * The integration method used to compute + * a single value from a set of values. + */ + Normal2DF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Vec2f>(iType) {} + /*! Returns the string "Normal2DF1D"*/ + string getName() const { + return "Normal2DF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter) { + result = integrate(_fun, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; + } + private: + Functions0D::Normal2DF0D _fun; + }; + + // GetShapeF1D + /*! Returns list of shapes covered by this Interface1D. */ + class LIB_VIEW_MAP_EXPORT GetShapeF1D : public UnaryFunction1D<std::vector<ViewShape*> > + { + public: + /*! Builds the functor. + */ + GetShapeF1D() : UnaryFunction1D<std::vector<ViewShape*> >() {} + /*! Returns the string "GetShapeF1D"*/ + string getName() const { + return "GetShapeF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter); + }; + + // GetOccludersF1D + /*! Returns list of occluding shapes covered by this Interface1D. */ + class LIB_VIEW_MAP_EXPORT GetOccludersF1D : public UnaryFunction1D<std::vector<ViewShape*> > + { + public: + /*! Builds the functor. + */ + GetOccludersF1D() : UnaryFunction1D<std::vector<ViewShape*> >() {} + /*! Returns the string "GetOccludersF1D"*/ + string getName() const { + return "GetOccludersF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter); + }; + + // GetOccludeeF1D + /*! Returns list of occluded shapes covered by this Interface1D. */ + class LIB_VIEW_MAP_EXPORT GetOccludeeF1D : public UnaryFunction1D<std::vector<ViewShape*> > + { + public: + /*! Builds the functor. + */ + GetOccludeeF1D() : UnaryFunction1D<std::vector<ViewShape*> >() {} + /*! Returns the string "GetOccludeeF1D"*/ + string getName() const { + return "GetOccludeeF1D"; + } + /*! the () operator.*/ + int operator()(Interface1D& inter); + }; + + // internal + //////////// + + // getOccludeeF1D + LIB_VIEW_MAP_EXPORT + void getOccludeeF1D(Interface1D& inter, set<ViewShape*>& oShapes); + + // getOccludersF1D + LIB_VIEW_MAP_EXPORT + void getOccludersF1D(Interface1D& inter, set<ViewShape*>& oShapes); + + // getShapeF1D + LIB_VIEW_MAP_EXPORT + void getShapeF1D(Interface1D& inter, set<ViewShape*>& oShapes); + +} // end of namespace Functions1D + +#endif // FUNCTIONS1D_HPP diff --git a/source/blender/freestyle/intern/view_map/Interface0D.h b/source/blender/freestyle/intern/view_map/Interface0D.h new file mode 100755 index 00000000000..48d956eec19 --- /dev/null +++ b/source/blender/freestyle/intern/view_map/Interface0D.h @@ -0,0 +1,360 @@ +// +// Filename : Interface0D.h +// Author(s) : Emmanuel Turquin +// Purpose : Interface to 0D elts +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef INTERFACE0D_H +# define INTERFACE0D_H + +# include <Python.h> +# include <string> +# include <iostream> +# include "../system/Id.h" +# include "../system/Precision.h" +# include "../winged_edge/Nature.h" +# include "../geometry/Geom.h" +using namespace std; + +#include "../system/Iterator.h" //soc + +// +// Interface0D +// +////////////////////////////////////////////////// + +class FEdge; +class SVertex; +class ViewVertex; +class NonTVertex; +class TVertex; +/*! Base class for any 0D element. */ +class Interface0D +{ +public: + + /*! Default constructor */ + Interface0D() {} + virtual ~Interface0D() {}; //soc + + /*! Returns the string "Interface0D".*/ + virtual string getExactTypeName() const { + return "Interface0D"; + } + + // Data access methods + + /*! Returns the 3D x coordinate of the point. */ + virtual real getX() const { + PyErr_SetString(PyExc_TypeError, "method getX() not properly overridden"); + return 0; + } + + /*! Returns the 3D y coordinate of the point. */ + virtual real getY() const { + PyErr_SetString(PyExc_TypeError, "method getY() not properly overridden"); + return 0; + } + + /*! Returns the 3D z coordinate of the point. */ + virtual real getZ() const { + PyErr_SetString(PyExc_TypeError, "method getZ() not properly overridden"); + return 0; + } + + /*! Returns the 3D point. */ + virtual Geometry::Vec3f getPoint3D() const { + PyErr_SetString(PyExc_TypeError, "method getPoint3D() not properly overridden"); + return 0; + } + + /*! Returns the 2D x coordinate of the point. */ + virtual real getProjectedX() const { + PyErr_SetString(PyExc_TypeError, "method getProjectedX() not properly overridden"); + return 0; + } + + /*! Returns the 2D y coordinate of the point. */ + virtual real getProjectedY() const { + PyErr_SetString(PyExc_TypeError, "method getProjectedY() not properly overridden"); + return 0; + } + + /*! Returns the 2D z coordinate of the point. */ + virtual real getProjectedZ() const { + PyErr_SetString(PyExc_TypeError, "method getProjectedZ() not properly overridden"); + return 0; + } + + /*! Returns the 2D point. */ + virtual Geometry::Vec2f getPoint2D() const { + PyErr_SetString(PyExc_TypeError, "method getPoint2D() not properly overridden"); + return 0; + } + + /*! Returns the FEdge that lies between this Interface0D and the + * Interface0D given as argument. */ + virtual FEdge* getFEdge(Interface0D&) { + PyErr_SetString(PyExc_TypeError, "method getFEdge() not properly overridden"); + return 0; + } + + /*! Returns the Id of the point. */ + virtual Id getId() const { + PyErr_SetString(PyExc_TypeError, "method getId() not properly overridden"); + return 0; + } + + /*! Returns the nature of the point. */ + virtual Nature::VertexNature getNature() const { + PyErr_SetString(PyExc_TypeError, "method getNature() not properly overridden"); + return Nature::POINT; + } + + + /*! Cast the Interface0D in SVertex if it can be. */ + virtual SVertex * castToSVertex(){ + PyErr_SetString(PyExc_TypeError, "method castToSVertex() not properly overridden"); + return 0; + } + + /*! Cast the Interface0D in ViewVertex if it can be. */ + virtual ViewVertex * castToViewVertex(){ + PyErr_SetString(PyExc_TypeError, "method castToViewVertex() not properly overridden"); + return 0; + } + + /*! Cast the Interface0D in NonTVertex if it can be. */ + virtual NonTVertex * castToNonTVertex(){ + PyErr_SetString(PyExc_TypeError, "method castToNonTVertex() not properly overridden"); + return 0; + } + + /*! Cast the Interface0D in TVertex if it can be. */ + virtual TVertex * castToTVertex(){ + PyErr_SetString(PyExc_TypeError, "method castToTVertex() not properly overridden"); + return 0; + } + +}; + + +// +// Interface0DIteratorNested +// +////////////////////////////////////////////////// + +class Interface0DIteratorNested : public Iterator +{ +public: + + virtual ~Interface0DIteratorNested() {} + + virtual string getExactTypeName() const { + return "Interface0DIteratorNested"; + } + + virtual Interface0D& operator*() = 0; + + virtual Interface0D* operator->() { + return &(operator*()); + } + + virtual int increment() = 0; + + virtual int decrement() = 0; + + virtual bool isBegin() const = 0; + + virtual bool isEnd() const = 0; + + virtual bool operator==(const Interface0DIteratorNested& it) const = 0; + + virtual bool operator!=(const Interface0DIteratorNested& it) const { + return !(*this == it); + } + + /*! Returns the curvilinear abscissa */ + virtual float t() const = 0; + /*! Returns the point parameter 0<u<1 */ + virtual float u() const = 0; + + virtual Interface0DIteratorNested* copy() const = 0; +}; + + +// +// Interface0DIterator +// +////////////////////////////////////////////////// + +/*! Class defining an iterator over Interface0D elements. + * An instance of this iterator is always obtained + * from a 1D element. + * \attention In the scripting language, you must call + * \code it2 = Interface0DIterator(it1) \endcode instead of \code it2 = it1 \endcode + * where \a it1 and \a it2 are 2 Interface0DIterator. + * Otherwise, incrementing \a it1 will also increment \a it2. + */ +class Interface0DIterator : public Iterator +{ +public: + + Interface0DIterator(Interface0DIteratorNested* it = NULL) { + _iterator = it; + } + + /*! Copy constructor */ + Interface0DIterator(const Interface0DIterator& it) { + _iterator = it._iterator->copy(); + } + + /*! Destructor */ + virtual ~Interface0DIterator() { + if (_iterator) + delete _iterator; + } + + /*! Operator = + * \attention In the scripting language, you must call + * \code it2 = Interface0DIterator(it1) \endcode instead of \code it2 = it1 \endcode + * where \a it1 and \a it2 are 2 Interface0DIterator. + * Otherwise, incrementing \a it1 will also increment \a it2. + */ + Interface0DIterator& operator=(const Interface0DIterator& it) { + if(_iterator) + delete _iterator; + _iterator = it._iterator->copy(); + return *this; + } + + /*! Returns the string "Interface0DIterator". */ + virtual string getExactTypeName() const { + if (!_iterator) + return "Interface0DIterator"; + return _iterator->getExactTypeName() + "Proxy"; + } + + // FIXME test it != 0 (exceptions ?) + + /*! Returns a reference to the pointed Interface0D. + * In the scripting language, you must call + * "getObject()" instead using this operator. + */ + Interface0D& operator*() { + return _iterator->operator*(); + } + + /*! Returns a pointer to the pointed Interface0D. + * Can't be called in the scripting language. + */ + Interface0D* operator->() { + return &(operator*()); + } + + /*! Increments. In the scripting language, call + * "increment()". + */ + Interface0DIterator& operator++() { + _iterator->increment(); + return *this; + } + + /*! Increments. In the scripting language, call + * "increment()". + */ + Interface0DIterator operator++(int) { + Interface0DIterator ret(*this); + _iterator->increment(); + return ret; + } + + /*! Decrements. In the scripting language, call + * "decrement()". + */ + Interface0DIterator& operator--() { + _iterator->decrement(); + return *this; + } + + /*! Decrements. In the scripting language, call + * "decrement()". + */ + Interface0DIterator operator--(int) { + Interface0DIterator ret(*this); + _iterator->decrement(); + return ret; + } + + /*! Increments. */ + virtual int increment() { + return _iterator->increment(); + } + + /*! Decrements. */ + virtual int decrement() { + return _iterator->decrement(); + } + + /*! Returns true if the pointed Interface0D is the + * first of the 1D element containing the points over + * which we're iterating. + */ + virtual bool isBegin() const { + return _iterator->isBegin(); + } + + /*! Returns true if the pointed Interface0D is after the + * after the last point of the 1D element we're iterating from. + */ + virtual bool isEnd() const { + return _iterator->isEnd(); + } + + /*! operator == . */ + bool operator==(const Interface0DIterator& it) const { + return _iterator->operator==(*(it._iterator)); + } + + /*! operator != . */ + bool operator!=(const Interface0DIterator& it) const { + return !(*this == it); + } + + /*! Returns the curvilinear abscissa. */ + inline float t() const { + return _iterator->t(); + } + /*! Returns the point parameter in the curve 0<=u<=1. */ + inline float u() const { + return _iterator->u(); + } +protected: + + Interface0DIteratorNested* _iterator; +}; + +#endif // INTERFACE0D_H diff --git a/source/blender/freestyle/intern/view_map/Interface1D.h b/source/blender/freestyle/intern/view_map/Interface1D.h new file mode 100755 index 00000000000..60cc0ebcb7e --- /dev/null +++ b/source/blender/freestyle/intern/view_map/Interface1D.h @@ -0,0 +1,226 @@ +// +// Filename : Interface1D.h +// Author(s) : Emmanuel Turquin +// Purpose : Interface to 1D elts +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef INTERFACE1D_H +# define INTERFACE1D_H + +# include <Python.h> +# include <string> +# include <iostream> +# include <float.h> +# include "../system/Id.h" +# include "../system/Precision.h" +# include "../winged_edge/Nature.h" +# include "Functions0D.h" + +using namespace std; +/*! \file Interface1D.h + * Interface1D and related tools definitions + */ +// Integration method +/*! The different integration + * methods that can be invoked + * to integrate into a single value the set of values obtained + * from each 0D element of a 1D element. + */ +typedef enum { + MEAN,/*!< The value computed for the 1D element is the mean of the values obtained for the 0D elements.*/ + MIN,/*!< The value computed for the 1D element is the minimum of the values obtained for the 0D elements.*/ + MAX,/*!< The value computed for the 1D element is the maximum of the values obtained for the 0D elements.*/ + FIRST,/*!< The value computed for the 1D element is the first of the values obtained for the 0D elements.*/ + LAST/*!< The value computed for the 1D element is the last of the values obtained for the 0D elements.*/ +} IntegrationType; + +/*! Returns a single + * value from a set of values evaluated at each 0D element + * of this 1D element. + * \param fun + * The UnaryFunction0D used to compute a value at each Interface0D. + * \param it + * The Interface0DIterator used to iterate over the 0D elements of + * this 1D element. The integration will occur over the 0D elements + * starting from the one pointed by it. + * \param it_end + * The Interface0DIterator pointing the end of the 0D elements of the + * 1D element. + * \param integration_type + * The integration method used to compute a single value from + * a set of values. + * \return the single value obtained for the 1D element. + */ +template <class T> +T integrate(UnaryFunction0D<T>& fun, + Interface0DIterator it, + Interface0DIterator it_end, + IntegrationType integration_type = MEAN) { + T res; + unsigned size; + switch (integration_type) { + case MIN: + fun(it); + res = fun.result;++it; + for (; !it.isEnd(); ++it) { + fun(it); + if (fun.result < res) + res = fun.result; + } + break; + case MAX: + fun(it); + res = fun.result;++it; + for (; !it.isEnd(); ++it) { + fun(it); + if (fun.result > res) + res = fun.result; + } + break; + case FIRST: + fun(it); + res = fun.result; + break; + case LAST: + fun(--it_end); + res = fun.result; + break; + case MEAN: + default: + fun(it); + res = fun.result;++it; + for (size = 1; !it.isEnd(); ++it, ++size) { + fun(it); + res += fun.result; + } + res /= (size ? size : 1); + break; + } + return res; +} + +// +// Interface1D +// +////////////////////////////////////////////////// + +/*! Base class for any 1D element. */ +class Interface1D +{ +public: + + /*! Default constructor */ + Interface1D() {_timeStamp=0;} + virtual ~Interface1D() {}; //soc + + /*! Returns the string "Interface1D" .*/ + virtual string getExactTypeName() const { + return "Interface1D"; + } + + // Iterator access + + /*! Returns an iterator over the Interface1D vertices, + * pointing to the first vertex. + */ + virtual Interface0DIterator verticesBegin() { + PyErr_SetString(PyExc_TypeError, "method verticesBegin() not properly overridden"); + return Interface0DIterator(); + } + + /*! Returns an iterator over the Interface1D vertices, + * pointing after the last vertex. + */ + virtual Interface0DIterator verticesEnd(){ + PyErr_SetString(PyExc_TypeError, "method verticesEnd() not properly overridden"); + return Interface0DIterator(); + } + + /*! Returns an iterator over the Interface1D points, + * pointing to the first point. The difference with + * verticesBegin() is that here we can iterate over + * points of the 1D element at a any given sampling. + * Indeed, for each iteration, a virtual point is created. + * \param t + * The sampling with which we want to iterate over points of + * this 1D element. + */ + virtual Interface0DIterator pointsBegin(float t=0.f) { + PyErr_SetString(PyExc_TypeError, "method pointsBegin() not properly overridden"); + return Interface0DIterator(); + } + + /*! Returns an iterator over the Interface1D points, + * pointing after the last point. The difference with + * verticesEnd() is that here we can iterate over + * points of the 1D element at a any given sampling. + * Indeed, for each iteration, a virtual point is created. + * \param t + * The sampling with which we want to iterate over points of + * this 1D element. + */ + virtual Interface0DIterator pointsEnd(float t=0.f) { + PyErr_SetString(PyExc_TypeError, "method pointsEnd() not properly overridden"); + return Interface0DIterator(); + } + + // Data access methods + + /*! Returns the 2D length of the 1D element. */ + virtual real getLength2D() const { + PyErr_SetString(PyExc_TypeError, "method getLength2D() not properly overridden"); + return 0; + } + + /*! Returns the Id of the 1D element .*/ + virtual Id getId() const { + PyErr_SetString(PyExc_TypeError, "method getId() not properly overridden"); + return Id(0, 0); + } + + + // FIXME: ce truc n'a rien a faire la...(c une requete complexe qui doit etre ds les Function1D) + /*! Returns the nature of the 1D element. */ + virtual Nature::EdgeNature getNature() const { + PyErr_SetString(PyExc_TypeError, "method getNature() not properly overridden"); + return Nature::NO_FEATURE; + } + + /*! Returns the time stamp of the 1D element. Mainly used for selection. */ + virtual unsigned getTimeStamp() const { + return _timeStamp; + } + + /*! Sets the time stamp for the 1D element. */ + inline void setTimeStamp(unsigned iTimeStamp){ + _timeStamp = iTimeStamp; + } + +protected: + unsigned _timeStamp; +}; + +#endif // INTERFACE1D_H diff --git a/source/blender/freestyle/intern/view_map/Silhouette.cpp b/source/blender/freestyle/intern/view_map/Silhouette.cpp new file mode 100755 index 00000000000..7a7d0a51d4b --- /dev/null +++ b/source/blender/freestyle/intern/view_map/Silhouette.cpp @@ -0,0 +1,370 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "Silhouette.h" +#include "ViewMap.h" + + /**********************************/ + /* */ + /* */ + /* SVertex */ + /* */ + /* */ + /**********************************/ + +Nature::VertexNature SVertex::getNature() const { + Nature::VertexNature nature = Nature::S_VERTEX; + if (_pViewVertex) + nature |= _pViewVertex->getNature(); + return nature; +} + +SVertex * SVertex::castToSVertex(){ + return this; +} + +ViewVertex * SVertex::castToViewVertex(){ + return _pViewVertex; +} + +NonTVertex * SVertex::castToNonTVertex(){ + return dynamic_cast<NonTVertex*>(_pViewVertex); +} + +TVertex * SVertex::castToTVertex(){ + return dynamic_cast<TVertex*>(_pViewVertex); +} + +float SVertex::shape_importance() const +{ + return shape()->importance(); +} + +//Material SVertex::material() const {return _Shape->material();} +Id SVertex::shape_id() const {return _Shape->getId();} +const SShape * SVertex::shape() const {return _Shape;} + +const int SVertex::qi() const +{ + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->qi(); +} + +occluder_container::const_iterator SVertex::occluders_begin() const +{ + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->occluders_begin(); +} + +occluder_container::const_iterator SVertex::occluders_end() const +{ + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->occluders_end(); +} + +bool SVertex::occluders_empty() const +{ + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->occluders_empty(); +} + +int SVertex::occluders_size() const +{ + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->occluders_size(); +} + +const Polygon3r& SVertex::occludee() const +{ + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->occludee(); +} + +const SShape* SVertex::occluded_shape() const +{ + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->occluded_shape(); +} + +const bool SVertex::occludee_empty() const +{ + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->occludee_empty(); +} + +real SVertex::z_discontinuity() const +{ + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->z_discontinuity(); +} + +FEdge* SVertex::fedge() +{ + if (getNature() & Nature::T_VERTEX) + return 0; + return _FEdges[0]; +} + +FEdge* SVertex::getFEdge(Interface0D& inter) +{ + FEdge * result = 0; + SVertex* iVertexB = dynamic_cast<SVertex*>(&inter); + if (!iVertexB) + return result; + vector<FEdge*>::const_iterator fe=_FEdges.begin(), feend=_FEdges.end(); + for(; + fe!=feend; + ++fe) + { + if( (((*fe)->vertexA() == this) && ((*fe)->vertexB() == iVertexB)) + || (((*fe)->vertexB() == this) && ((*fe)->vertexA() == iVertexB))) + result = (*fe); + } + if((result == 0) && (getNature() & Nature::T_VERTEX)) + { + SVertex *brother; + ViewVertex *vvertex = viewvertex(); + TVertex * tvertex = dynamic_cast<TVertex*>(vvertex); + if(tvertex) + { + brother = tvertex->frontSVertex(); + if(this == brother) + brother = tvertex->backSVertex(); + const vector<FEdge*>& fedges = brother->fedges(); + for(fe=fedges.begin(),feend=fedges.end(); + fe!=feend; + ++fe) + { + if( (((*fe)->vertexA() == brother) && ((*fe)->vertexB() == iVertexB)) + || (((*fe)->vertexB() == brother) && ((*fe)->vertexA() == iVertexB))) + result = (*fe); + } + } + } + if((result == 0) && (iVertexB->getNature() & Nature::T_VERTEX)) + { + SVertex *brother; + ViewVertex *vvertex = iVertexB->viewvertex(); + TVertex * tvertex = dynamic_cast<TVertex*>(vvertex); + if(tvertex) + { + brother = tvertex->frontSVertex(); + if(iVertexB == brother) + brother = tvertex->backSVertex(); + for(fe=_FEdges.begin(),feend=_FEdges.end(); + fe!=feend; + ++fe) + { + if( (((*fe)->vertexA() == this) && ((*fe)->vertexB() == brother)) + || (((*fe)->vertexB() == this) && ((*fe)->vertexA() == brother))) + result = (*fe); + } + } + } + + return result; +} + + + /**********************************/ + /* */ + /* */ + /* FEdge */ + /* */ + /* */ + /**********************************/ + + +int FEdge::viewedge_nature() const {return _ViewEdge->getNature();} +//float FEdge::viewedge_length() const {return _ViewEdge->viewedge_length();} +const SShape* FEdge::occluded_shape() const +{ + ViewShape * aShape = _ViewEdge->aShape(); + if(aShape == 0) + return 0; + return aShape->sshape(); +} + +float FEdge::shape_importance() const +{ + return _VertexA->shape()->importance(); +} + +int FEdge::invisibility() const +{ + return _ViewEdge->qi(); +} + +occluder_container::const_iterator FEdge::occluders_begin() const {return _ViewEdge->occluders_begin();} +occluder_container::const_iterator FEdge::occluders_end() const {return _ViewEdge->occluders_end();} +bool FEdge::occluders_empty() const {return _ViewEdge->occluders_empty();} +int FEdge::occluders_size() const {return _ViewEdge->occluders_size();} +const bool FEdge::occludee_empty() const +{ + return _ViewEdge->occludee_empty(); +} + + + +Id FEdge::shape_id() const +{ + return _VertexA->shape()->getId(); +} +const SShape* FEdge::shape() const +{ + return _VertexA->shape(); +} + +real FEdge::z_discontinuity() const +{ + if(!(getNature() & Nature::SILHOUETTE) && !(getNature() & Nature::BORDER)) + { + return 0; + } + + BBox<Vec3r> box = ViewMap::getInstance()->getScene3dBBox(); + + Vec3r bbox_size_vec(box.getMax() - box.getMin()); + real bboxsize = bbox_size_vec.norm(); + if(occludee_empty()) + + { + //return FLT_MAX; + + return 1.0; + + //return bboxsize; + + } + // real result; + // z_discontinuity_functor<SVertex> _functor; + + // Evaluate<SVertex,z_discontinuity_functor<SVertex> >(&_functor, iCombination, result ) + Vec3r middle((_VertexB->point3d()-_VertexA->point3d())); + + middle /= 2; + Vec3r disc_vec(middle - _occludeeIntersection); + real res = disc_vec.norm() / bboxsize; + return res; + + //return fabs((middle.z()-_occludeeIntersection.z())); +} + + +//float FEdge::local_average_depth(int iCombination ) const +//{ +// +// float result; +// local_average_depth_functor<SVertex> functor; +// Evaluate(&functor, iCombination, result); +// +// return result; +//} +//float FEdge::local_depth_variance(int iCombination ) const +//{ +// float result; +// +// local_depth_variance_functor<SVertex> functor; +// +// Evaluate(&functor, iCombination, result); +// +// return result; +//} +// +// +//real FEdge::local_average_density( float sigma, int iCombination) const +//{ +// float result; +// +// density_functor<SVertex> functor(sigma); +// +// Evaluate(&functor, iCombination, result); +// +// return result; +//} +// +////Vec3r FEdge::normal(int& oException /* = Exception::NO_EXCEPTION */) +////{ +//// Vec3r Na = _VertexA->normal(oException); +//// if(oException != Exception::NO_EXCEPTION) +//// return Na; +//// Vec3r Nb = _VertexB->normal(oException); +//// if(oException != Exception::NO_EXCEPTION) +//// return Nb; +//// return (Na+Nb)/2.0; +////} +// +//Vec3r FEdge::curvature2d_as_vector(int iCombination) const +//{ +// Vec3r result; +// curvature2d_as_vector_functor<SVertex> _functor; +// Evaluate<Vec3r,curvature2d_as_vector_functor<SVertex> >(&_functor, iCombination, result ); +// return result; +//} +// +//real FEdge::curvature2d_as_angle(int iCombination) const +//{ +// real result; +// curvature2d_as_angle_functor<SVertex> _functor; +// Evaluate<real,curvature2d_as_angle_functor<SVertex> >(&_functor, iCombination, result ); +// return result; +//} + + /**********************************/ + /* */ + /* */ + /* FEdgeSharp */ + /* */ + /* */ + /**********************************/ + +//Material FEdge::material() const +//{ +// return _VertexA->shape()->material(); +//} +const FrsMaterial& FEdgeSharp::aFrsMaterial() const { + return _VertexA->shape()->frs_material(_aFrsMaterialIndex); +} + +const FrsMaterial& FEdgeSharp::bFrsMaterial() const { + return _VertexA->shape()->frs_material(_bFrsMaterialIndex); +} + + /**********************************/ + /* */ + /* */ + /* FEdgeSmooth */ + /* */ + /* */ + /**********************************/ + +const FrsMaterial& FEdgeSmooth::frs_material() const { + return _VertexA->shape()->frs_material(_FrsMaterialIndex); +} diff --git a/source/blender/freestyle/intern/view_map/Silhouette.h b/source/blender/freestyle/intern/view_map/Silhouette.h new file mode 100755 index 00000000000..86a4efcdc48 --- /dev/null +++ b/source/blender/freestyle/intern/view_map/Silhouette.h @@ -0,0 +1,1435 @@ +// +// Filename : Silhouette.h +// Author(s) : Stephane Grabli +// Purpose : Classes to define a silhouette structure +// Date of creation : 25/03/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef SILHOUETTE_H +# define SILHOUETTE_H + +# include "Interface0D.h" +# include "Interface1D.h" +# include <iostream> +# include <string> +# include <vector> +# include <set> +# include <float.h> +# include "../system/FreestyleConfig.h" +# include "../geometry/Geom.h" +# include "../geometry/BBox.h" +# include "../scene_graph/FrsMaterial.h" +# include "../geometry/Polygon.h" +# include "../system/Exception.h" +# include "../winged_edge/Curvature.h" + +using namespace std; +using namespace Geometry; + +class ViewShape; +typedef vector<ViewShape*> occluder_container; + + /**********************************/ + /* */ + /* */ + /* SVertex */ + /* */ + /* */ + /**********************************/ + +class FEdge; +class ViewVertex; +class SShape; + +/*! Class to define a vertex of the embedding. */ +class LIB_VIEW_MAP_EXPORT SVertex : public Interface0D +{ +public: // Implementation of Interface0D + + /*! Returns the string "SVertex" .*/ + virtual string getExactTypeName() const { + return "SVertex"; + } + + // Data access methods + + /*! Returns the 3D x coordinate of the vertex .*/ + virtual real getX() const { + return _Point3D.x(); + } + + /*! Returns the 3D y coordinate of the vertex .*/ + virtual real getY() const { + return _Point3D.y(); + } + + /*! Returns the 3D z coordinate of the vertex .*/ + virtual real getZ() const { + return _Point3D.z(); + } + + /*! Returns the 3D point. */ + virtual Vec3f getPoint3D() const { + return _Point3D; + } + + /*! Returns the projected 3D x coordinate of the vertex .*/ + virtual real getProjectedX() const { + return _Point2D.x(); + } + + /*! Returns the projected 3D y coordinate of the vertex .*/ + virtual real getProjectedY() const { + return _Point2D.y(); + } + + /*! Returns the projected 3D z coordinate of the vertex .*/ + virtual real getProjectedZ() const { + return _Point2D.z(); + } + + /*! Returns the 2D point. */ + virtual Vec2f getPoint2D() const { + return Vec2f((float)_Point2D.x(),(float)_Point2D.y()); + } + + /*! Returns the FEdge that lies between this Svertex and the + * Interface0D given as argument. */ + virtual FEdge* getFEdge(Interface0D&); + + /*! Returns the Id of the vertex .*/ + virtual Id getId() const { + return _Id; + } + + /*! Returns the nature of the vertex .*/ + virtual Nature::VertexNature getNature() const; + + /*! Cast the Interface0D in SVertex if it can be. */ + virtual SVertex * castToSVertex(); + + /*! Cast the Interface0D in ViewVertex if it can be. */ + virtual ViewVertex * castToViewVertex(); + + /*! Cast the Interface0D in NonTVertex if it can be. */ + virtual NonTVertex * castToNonTVertex(); + + /*! Cast the Interface0D in TVertex if it can be. */ + virtual TVertex * castToTVertex(); + +public: + + typedef vector<FEdge*> fedges_container; + +private: + + Id _Id; + Vec3r _Point3D; + Vec3r _Point2D; + set<Vec3r> _Normals; + vector<FEdge*> _FEdges; // the edges containing this vertex + SShape *_Shape; // the shape to which belongs the vertex + ViewVertex *_pViewVertex; // The associated viewvertex, in case there is one. + real _curvatureFredo; + Vec2r _directionFredo; + CurvatureInfo* _curvature_info; + +public: + + /*! A field that can be used by the user to store any data. + * This field must be reseted afterwards using ResetUserData(). + */ + void *userdata; + + /*! Default constructor.*/ + inline SVertex() { + _Id = 0; + userdata = NULL; + _Shape = NULL; + _pViewVertex = 0; + _curvature_info = 0; + } + + /*! Builds a SVertex from 3D coordinates and an Id. */ + inline SVertex(const Vec3r &iPoint3D, const Id& id) { + _Point3D = iPoint3D; + _Id=id; + userdata = NULL; + _Shape = NULL; + _pViewVertex=0; + _curvature_info = 0; + } + + /*! Copy constructor. */ + inline SVertex(SVertex& iBrother) { + _Id = iBrother._Id; + _Point3D = iBrother.point3D(); + _Point2D = iBrother.point2D(); + _Normals = iBrother._Normals; + _FEdges = iBrother.fedges(); + _Shape = iBrother.shape(); + _pViewVertex = iBrother._pViewVertex; + if (!(iBrother._curvature_info)) + _curvature_info = 0; + else + _curvature_info = new CurvatureInfo(*(iBrother._curvature_info)); + iBrother.userdata = this; + userdata = 0; + } + + /*! Destructor. */ + virtual ~SVertex() { + if (_curvature_info) + delete _curvature_info; + } + + /*! Cloning method. */ + virtual SVertex * duplicate() { + SVertex *clone = new SVertex(*this); + return clone; + } + + /*! operator == */ + virtual bool operator==(const SVertex& iBrother) { + return ((_Point2D == iBrother._Point2D) && + (_Point3D == iBrother._Point3D)); + } + + /* accessors */ + inline const Vec3r& point3D() const {return _Point3D;} + inline const Vec3r& point2D() const {return _Point2D;} + /*! Returns the set of normals for this Vertex. + * In a smooth surface, a vertex has exactly one normal. + * In a sharp surface, a vertex can have any number of normals. + */ + inline set<Vec3r> normals() {return _Normals;} + /*! Returns the number of different normals for this vertex. */ + inline unsigned normalsSize() const {return _Normals.size();} + inline const vector<FEdge*>& fedges() {return _FEdges;} + inline fedges_container::iterator fedges_begin() {return _FEdges.begin();} + inline fedges_container::iterator fedges_end() {return _FEdges.end();} + inline SShape * shape() {return _Shape;} + inline real z() const {return _Point2D[2];} + /*! If this SVertex is also a ViewVertex, this method + * returns a pointer onto this ViewVertex. 0 is returned + * otherwise. + */ + inline ViewVertex * viewvertex() {return _pViewVertex;} + + /*! modifiers */ + /*! Sets the 3D coordinates of the SVertex. */ + inline void setPoint3D(const Vec3r &iPoint3D) {_Point3D = iPoint3D;} + /*! Sets the 3D projected coordinates of the SVertex. */ + inline void setPoint2D(const Vec3r &iPoint2D) {_Point2D = iPoint2D;} + /*! Adds a normal to the Svertex's set of normals. If the same + * normal is already in the set, nothing changes. + */ + inline void AddNormal(const Vec3r& iNormal) + { + _Normals.insert(iNormal); // if iNormal in the set already exists, nothing is done + } + + void setCurvatureInfo(CurvatureInfo* ci) { + _curvature_info = ci; + } + + const CurvatureInfo* getCurvatureInfo() const { + return _curvature_info; + } + + /* Fredo's normal and curvature*/ + void setCurvatureFredo(real c) {_curvatureFredo=c;} + void setDirectionFredo(Vec2r d) {_directionFredo=d;} + real curvatureFredo () {return _curvatureFredo;} + const Vec2r directionFredo () {return _directionFredo;} + + /*! Sets the Id */ + inline void setId(const Id& id) {_Id = id;} + inline void setFEdges(const vector<FEdge*>& iFEdges) {_FEdges = iFEdges;} + inline void setShape(SShape *iShape) {_Shape = iShape;} + inline void setViewVertex(ViewVertex *iViewVertex) {_pViewVertex = iViewVertex;} + /*! Add an FEdge to the list of edges emanating from this SVertex. */ + inline void AddFEdge(FEdge* iFEdge) {_FEdges.push_back(iFEdge);} + /* replaces edge 1 by edge 2 in the list of edges */ + inline void Replace(FEdge *e1, FEdge *e2) + { + vector<FEdge*>::iterator insertedfe; + for(vector<FEdge*>::iterator fe=_FEdges.begin(),fend=_FEdges.end(); + fe!=fend; + fe++) + { + if((*fe) == e1) + { + insertedfe = _FEdges.insert(fe, e2);// inserts e2 before fe. + // returns an iterator pointing toward e2. fe is invalidated. + // we want to remove e1, but we can't use fe anymore: + insertedfe++; // insertedfe points now to e1 + _FEdges.erase(insertedfe); + return; + } + } + } + +public: + + /* Information access interface */ + + FEdge *fedge() ; // for non T vertex + inline const Vec3r& point2d() const {return point2D();} + inline const Vec3r& point3d() const {return point3D();} + inline Vec3r normal() const {if(_Normals.size() == 1) return (*(_Normals.begin())); Exception::raiseException(); return *(_Normals.begin());} + //Material material() const ; + Id shape_id() const ; + const SShape* shape() const ; + float shape_importance() const ; + + const int qi() const ; + occluder_container::const_iterator occluders_begin() const ; + occluder_container::const_iterator occluders_end() const ; + bool occluders_empty() const ; + int occluders_size() const ; + const Polygon3r& occludee() const ; + const SShape * occluded_shape() const ; + const bool occludee_empty() const ; + real z_discontinuity() const ; + //inline float local_average_depth() const ; + // inline float local_depth_variance() const ; + // inline real local_average_density(float sigma = 2.3f) const ; + //inline Vec3r shaded_color() const ; + // inline Vec3r orientation2d() const ; + // inline Vec3r orientation3d() const ; + // inline Vec3r curvature2d_as_vector() const ; + /*! angle in radians */ + // inline real curvature2d_as_angle() const ; + +}; + + /**********************************/ + /* */ + /* */ + /* FEdge */ + /* */ + /* */ + /**********************************/ + + +class ViewEdge; +/*! Base Class for feature edges. + * This FEdge can represent a silhouette, a crease, + * a ridge/valley, a border or a suggestive contour. + * For silhouettes, the FEdge is oriented + * such as, the visible face lies on the left of the edge. + * For borders, the FEdge is oriented + * such as, the face lies on the left of the edge. + * An FEdge can represent an initial edge of the mesh + * or runs accross a face of the initial mesh depending + * on the smoothness or sharpness of the mesh. + * This class is specialized into a smooth and a sharp + * version since their properties slightly vary from + * one to the other. + */ +class LIB_VIEW_MAP_EXPORT FEdge : public Interface1D +{ +public: // Implementation of Interface0D + + /*! Returns the string "FEdge" . */ + virtual string getExactTypeName() const { + return "FEdge"; + } + + // Data access methods + + /*! Returns the 2D length of the FEdge. */ + virtual real getLength2D() const { + if (!_VertexA || !_VertexB) + return 0; + return (_VertexB->getPoint2D() - _VertexA->getPoint2D()).norm(); + } + + /*! Returns the Id of the FEdge. */ + virtual Id getId() const { + return _Id; + } + +public: + + // An edge can only be of one kind (SILHOUETTE or BORDER, etc...) + // For an multi-nature edge there must be several different FEdge. + // DEBUG: + // Vec3r A; + // Vec3r u; + // vector<Polygon3r> _Occludees; + // Vec3r intersection; + // vector<Vec3i> _Cells; + +protected: + SVertex *_VertexA; + SVertex *_VertexB; + Id _Id; + Nature::EdgeNature _Nature; + //vector<Polygon3r> _Occluders; // visibility // NON GERE PAR LE COPY CONSTRUCTOR!! + + FEdge *_NextEdge; // next edge on the chain + FEdge *_PreviousEdge; + ViewEdge *_ViewEdge; + // Sometimes we need to deport the visibility computation onto another + // edge. For example the exact edges use edges of the mesh to + // compute their visibility + + Polygon3r _aFace; // The occluded face which lies on the right of a silhouette edge + Vec3r _occludeeIntersection; + bool _occludeeEmpty; + + bool _isSmooth; + +public: + /*! A field that can be used by the user to store any data. + * This field must be reseted afterwards using ResetUserData(). + */ + void *userdata; + /*! Default constructor */ + inline FEdge() { + userdata = NULL; + _VertexA = NULL; + _VertexB = NULL; + _Nature = Nature::NO_FEATURE; + _NextEdge = NULL; + _PreviousEdge = NULL; + _ViewEdge = NULL; + //_hasVisibilityPoint=false; + _occludeeEmpty = true; + _isSmooth = false; + } + /*! Builds an FEdge going from vA to vB. */ + inline FEdge(SVertex *vA, SVertex *vB) { + userdata = NULL; + _VertexA = vA; + _VertexB = vB; + _Nature = Nature::NO_FEATURE; + _NextEdge=NULL; + _PreviousEdge=NULL; + _ViewEdge = NULL; + //_hasVisibilityPoint=false; + _occludeeEmpty = true; + _isSmooth = false; + } + /*! Copy constructor */ + inline FEdge(FEdge& iBrother) + { + _VertexA = iBrother.vertexA(); + _VertexB = iBrother.vertexB(); + _NextEdge = iBrother.nextEdge(); + _PreviousEdge = iBrother._PreviousEdge; + _Nature = iBrother.getNature(); + _Id = iBrother._Id; + _ViewEdge = iBrother._ViewEdge; + //_hasVisibilityPoint = iBrother._hasVisibilityPoint; + //_VisibilityPointA = iBrother._VisibilityPointA; + //_VisibilityPointB = iBrother._VisibilityPointB; + _aFace = iBrother._aFace; + _occludeeEmpty = iBrother._occludeeEmpty; + _isSmooth = iBrother._isSmooth; + iBrother.userdata = this; + userdata = 0; + } + /*! Destructor */ + virtual ~FEdge() {} + /*! Cloning method. */ + virtual FEdge* duplicate() + { + FEdge *clone = new FEdge(*this); + return clone; + } + /* accessors */ + /*! Returns the first SVertex. */ + inline SVertex* vertexA() {return _VertexA;} + /*! Returns the second SVertex. */ + inline SVertex* vertexB() {return _VertexB;} + /*! Returns the first SVertex if i=0, the seccond SVertex + * if i=1. */ + inline SVertex* operator[](const unsigned short int& i) const{ + return i%2==0 ? _VertexA : _VertexB; + } + /*! Returns the nature of the FEdge. */ + inline Nature::EdgeNature getNature() const {return _Nature;} + /*! Returns the FEdge following this one in the ViewEdge. + * If this FEdge is the last of the ViewEdge, 0 is returned. + */ + inline FEdge * nextEdge() {return _NextEdge;} + /*! Returns the Edge preceding this one in the ViewEdge. + * If this FEdge is the first one of the ViewEdge, 0 is returned. + */ + inline FEdge * previousEdge() {return _PreviousEdge;} + inline SShape * shape() {return _VertexA->shape();} + //inline int invisibility() const {return _Occluders.size();} + int invisibility() const ; + //inline const vector<Polygon3r>& occluders() const {return _Occluders;} + /*! Returns a pointer to the ViewEdge to which this FEdge belongs to. */ + inline ViewEdge * viewedge() const {return _ViewEdge;} + inline Vec3r center3d() {return Vec3r((_VertexA->point3D()+_VertexB->point3D())/2.0);} + inline Vec3r center2d() {return Vec3r((_VertexA->point2D()+_VertexB->point2D())/2.0);} + // inline bool hasVisibilityPoint() const {return _hasVisibilityPoint;} + // inline Vec3r visibilityPointA() const {return _VisibilityPointA;} + // inline Vec3r visibilityPointB() const {return _VisibilityPointB;} + inline const Polygon3r& aFace() const {return _aFace;} + inline const Vec3r& getOccludeeIntersection() { return _occludeeIntersection; } + inline bool getOccludeeEmpty() { return _occludeeEmpty; } + /*! Returns true if this FEdge is a smooth FEdge. */ + inline bool isSmooth() const {return _isSmooth;} + + /* modifiers */ + /*! Sets the first SVertex. */ + inline void setVertexA(SVertex *vA) {_VertexA = vA;} + /*! Sets the second SVertex. */ + inline void setVertexB(SVertex *vB) {_VertexB = vB;} + /*! Sets the FEdge Id . */ + inline void setId(const Id& id) {_Id = id;} + /*! Sets the pointer to the next FEdge. */ + inline void setNextEdge(FEdge* iEdge) {_NextEdge = iEdge;} + /*! Sets the pointer to the previous FEdge. */ + inline void setPreviousEdge(FEdge *iEdge) {_PreviousEdge = iEdge;} + /*! Sets the nature of this FEdge. */ + inline void setNature(Nature::EdgeNature iNature) {_Nature = iNature;} + //inline void AddOccluder(Polygon3r& iPolygon) {_Occluders.push_back(iPolygon);} + /*! Sets the ViewEdge to which this FEdge belongs to. */ + inline void setViewEdge(ViewEdge *iViewEdge) {_ViewEdge = iViewEdge;} + // inline void setHasVisibilityPoint(bool iBool) {_hasVisibilityPoint = iBool;} + // inline void setVisibilityPointA(const Vec3r& iPoint) {_VisibilityPointA = iPoint;} + // inline void setVisibilityPointB(const Vec3r& iPoint) {_VisibilityPointB = iPoint;} + inline void setaFace(Polygon3r& iFace) {_aFace = iFace;} + inline void setOccludeeIntersection(const Vec3r& iPoint) {_occludeeIntersection = iPoint;} + inline void setOccludeeEmpty(bool iempty) {_occludeeEmpty = iempty;} + /*! Sets the flag telling whether this FEdge is smooth or sharp. + * true for Smooth, false for Sharp. + */ + inline void setSmooth(bool iFlag) {_isSmooth = iFlag;} + + /* checks whether two FEdge have a common vertex. + * Returns a pointer on the common vertex if it exists, + * NULL otherwise. + */ + static inline SVertex* CommonVertex(FEdge *iEdge1, FEdge* iEdge2) + { + if((NULL == iEdge1) || (NULL == iEdge2)) + return NULL; + + SVertex *sv1 = iEdge1->vertexA(); + SVertex *sv2 = iEdge1->vertexB(); + SVertex *sv3 = iEdge2->vertexA(); + SVertex *sv4 = iEdge2->vertexB(); + + if((sv1 == sv3) || (sv1 == sv4)) + { + return sv1; + } + else if((sv2 == sv3) || (sv2 == sv4)) + { + return sv2; + } + + return NULL; + } + + inline const SVertex* min2d() const + { + if(_VertexA->point2D() < _VertexB->point2D()) + return _VertexA; + else + return _VertexB; + } + inline const SVertex* max2d() const + { + if(_VertexA->point2D() < _VertexB->point2D()) + return _VertexB; + else + return _VertexA; + } + + /* Information access interface */ + /* Information access interface */ + + //Material material() const ; + Id shape_id() const ; + const SShape * shape() const ; + float shape_importance() const ; + inline const int qi() const {return invisibility();} + occluder_container::const_iterator occluders_begin() const ; + occluder_container::const_iterator occluders_end() const ; + bool occluders_empty() const ; + int occluders_size() const ; + inline const Polygon3r& occludee() const {return aFace();} + const SShape * occluded_shape() const ; + //inline const bool occludee_empty() const {return _occludeeEmpty;} + const bool occludee_empty() const ; + real z_discontinuity() const ; + // inline float local_average_depth(int iCombination = 0) const ; + // inline float local_depth_variance(int iCombination = 0) const ; + // inline real local_average_density(float sigma = 2.3f, int iCombination = 0) const ; + //inline Vec3r shaded_color(int iCombination = 0) const {} + int viewedge_nature() const ; + //float viewedge_length() const ; + inline Vec3r orientation2d() const {return Vec3r(_VertexB->point2d()-_VertexA->point2d());} + inline Vec3r orientation3d() const {return Vec3r(_VertexB->point3d()-_VertexA->point3d());} + // //inline real curvature2d() const {return viewedge()->curvature2d((_VertexA->point2d()+_VertexB->point2d())/2.0);} + // inline Vec3r curvature2d_as_vector(int iCombination = 0) const ; + // /* angle in degrees*/ + // inline real curvature2d_as_angle(int iCombination = 0) const ; + + + // Iterator access (Interface1D) + /*! Returns an iterator over the 2 (!) SVertex + * pointing to the first SVertex. */ + virtual inline Interface0DIterator verticesBegin(); + /*! Returns an iterator over the 2 (!) SVertex + * pointing after the last SVertex. */ + virtual inline Interface0DIterator verticesEnd(); + + /*! Returns an iterator over the FEdge points, + * pointing to the first point. The difference with + * verticesBegin() is that here we can iterate over + * points of the FEdge at a any given sampling. + * Indeed, for each iteration, a virtual point is created. + * \param t + * The sampling with which we want to iterate over points of + * this FEdge. + */ + virtual inline Interface0DIterator pointsBegin(float t=0.f); + /*! Returns an iterator over the FEdge points, + * pointing after the last point. The difference with + * verticesEnd() is that here we can iterate over + * points of the FEdge at a any given sampling. + * Indeed, for each iteration, a virtual point is created. + * \param t + * The sampling with which we want to iterate over points of + * this FEdge. + */ + virtual inline Interface0DIterator pointsEnd(float t=0.f); +}; + +// +// SVertexIterator +// +///////////////////////////////////////////////// + +namespace FEdgeInternal { + + class SVertexIterator : public Interface0DIteratorNested + { + public: + + SVertexIterator() { + _vertex = NULL; + _edge = NULL; + } + + SVertexIterator(const SVertexIterator& vi) { + _vertex = vi._vertex; + _edge = vi._edge; + } + + SVertexIterator(SVertex* v, FEdge* edge) { + _vertex = v; + _edge = edge; + } + + SVertexIterator& operator=(const SVertexIterator& vi) { + _vertex = vi._vertex; + _edge = vi._edge; + return *this; + } + + virtual string getExactTypeName() const { + return "SVertexIterator"; + } + + virtual SVertex& operator*() { + return *_vertex; + } + + virtual SVertex* operator->() { + return &(operator*()); + } + + virtual SVertexIterator& operator++() { + increment(); + return *this; + } + + virtual SVertexIterator operator++(int) { + SVertexIterator ret(*this); + increment(); + return ret; + } + + virtual SVertexIterator& operator--() { + decrement(); + return *this; + } + + virtual SVertexIterator operator--(int) { + SVertexIterator ret(*this); + decrement(); + return ret; + } + + virtual int increment() { + if (_vertex == _edge->vertexB()) { + _vertex = 0; + return 0; + } + + _vertex = _edge->vertexB(); + return 0; + } + + virtual int decrement() { + if (_vertex == _edge->vertexA()) { + _vertex = 0; + return 0; + } + _vertex = _edge->vertexA(); + return 0; + } + + virtual bool isBegin() const { + return _vertex == _edge->vertexA(); + } + + virtual bool isEnd() const { + return _vertex == _edge->vertexB(); + } + + virtual bool operator==(const Interface0DIteratorNested& it) const { + const SVertexIterator* it_exact = dynamic_cast<const SVertexIterator*>(&it); + if (!it_exact) + return false; + return ((_vertex == it_exact->_vertex) && + (_edge == it_exact->_edge)); + } + + virtual float t() const{ + if(_vertex == _edge->vertexA()){ + return 0; + } + return ((float)_edge->getLength2D()); + } + virtual float u() const{ + if(_vertex == _edge->vertexA()){ + return 0; + } + return 1.0; + } + virtual SVertexIterator* copy() const { + return new SVertexIterator(*this); + } + + private: + + SVertex* _vertex; + FEdge* _edge; + }; + +} // end of namespace FEdgeInternal + +// Iterator access (implementation) + +Interface0DIterator FEdge::verticesBegin() { + Interface0DIterator ret(new FEdgeInternal::SVertexIterator(_VertexA, this)); + return ret; +} + +Interface0DIterator FEdge::verticesEnd() { + Interface0DIterator ret(new FEdgeInternal::SVertexIterator(0, this)); + return ret; +} + +Interface0DIterator FEdge::pointsBegin(float t) { + return verticesBegin(); +} + +Interface0DIterator FEdge::pointsEnd(float t) { + return verticesEnd(); +} + +/*! Class defining a sharp FEdge. A Sharp FEdge + * corresponds to an initial edge of the input mesh. + * It can be a silhouette, a crease or a border. + * If it is a crease edge, then it is borded + * by two faces of the mesh. Face a lies on its right + * whereas Face b lies on its left. + * If it is a border edge, then it doesn't have any + * face on its right, and thus Face a = 0. + */ +class LIB_VIEW_MAP_EXPORT FEdgeSharp : public FEdge +{ +protected: + Vec3r _aNormal; // When following the edge, normal of the right face + Vec3r _bNormal; // When following the edge, normal of the left face + unsigned _aFrsMaterialIndex; + unsigned _bFrsMaterialIndex; + +public: + /*! Returns the string "FEdgeSharp" . */ + virtual string getExactTypeName() const { + return "FEdgeSharp"; + } + /*! Default constructor. */ + inline FEdgeSharp() : FEdge(){ + _aFrsMaterialIndex = _bFrsMaterialIndex = 0; + } + /*! Builds an FEdgeSharp going from vA to vB. */ + inline FEdgeSharp(SVertex *vA, SVertex *vB) : FEdge(vA, vB){ + _aFrsMaterialIndex = _bFrsMaterialIndex = 0; + } + /*! Copy constructor. */ + inline FEdgeSharp(FEdgeSharp& iBrother) : FEdge(iBrother){ + _aNormal = iBrother._aNormal; + _bNormal = iBrother._bNormal; + _aFrsMaterialIndex = iBrother._aFrsMaterialIndex; + _bFrsMaterialIndex = iBrother._bFrsMaterialIndex; + } + /*! Destructor. */ + virtual ~FEdgeSharp() {} + /*! Cloning method. */ + virtual FEdge* duplicate(){ + FEdge *clone = new FEdgeSharp(*this); + return clone; + } + /*! Returns the normal to the face lying on the + * right of the FEdge. If this FEdge is a border, + * it has no Face on its right and therefore, no normal. + */ + inline const Vec3r& normalA() {return _aNormal;} + /*! Returns the normal to the face lying on the + * left of the FEdge. + */ + inline const Vec3r& normalB() {return _bNormal;} + /*! Returns the index of the material of the face lying on the + * right of the FEdge. If this FEdge is a border, + * it has no Face on its right and therefore, no material. + */ + inline unsigned aFrsMaterialIndex() const {return _aFrsMaterialIndex;} + /*! Returns the material of the face lying on the + * right of the FEdge. If this FEdge is a border, + * it has no Face on its right and therefore, no material. + */ + const FrsMaterial& aFrsMaterial() const ; + /*! Returns the index of the material of the face lying on the + * left of the FEdge. + */ + inline unsigned bFrsMaterialIndex() const {return _bFrsMaterialIndex;} + /*! Returns the material of the face lying on the + * left of the FEdge. + */ + const FrsMaterial& bFrsMaterial() const ; + + /*! Sets the normal to the face lying on the right of the FEdge. */ + inline void setNormalA(const Vec3r& iNormal) {_aNormal = iNormal;} + /*! Sets the normal to the face lying on the left of the FEdge. */ + inline void setNormalB(const Vec3r& iNormal) {_bNormal = iNormal;} + /*! Sets the index of the material lying on the right of the FEdge.*/ + inline void setaFrsMaterialIndex(unsigned i) {_aFrsMaterialIndex = i;} + /*! Sets the index of the material lying on the left of the FEdge.*/ + inline void setbFrsMaterialIndex(unsigned i) {_bFrsMaterialIndex = i;} + +}; + +/*! Class defining a smooth edge. This kind of edge typically + * runs across a face of the input mesh. It can be + * a silhouette, a ridge or valley, a suggestive contour. + */ +class LIB_VIEW_MAP_EXPORT FEdgeSmooth : public FEdge +{ +protected: + Vec3r _Normal; + unsigned _FrsMaterialIndex; + // bool _hasVisibilityPoint; + // Vec3r _VisibilityPointA; // The edge on which the visibility will be computed represented + // Vec3r _VisibilityPointB; // using its 2 extremity points A and B + void * _Face; // In case of exact silhouette, Face is the WFace crossed by Fedge + // NON GERE PAR LE COPY CONSTRUCTEUR +public: + /*! Returns the string "FEdgeSmooth" . */ + virtual string getExactTypeName() const { + return "FEdgeSmooth"; + } + /*! Default constructor. */ + inline FEdgeSmooth() : FEdge(){ + _Face=0; + _FrsMaterialIndex = 0; + _isSmooth = true; + } + /*! Builds an FEdgeSmooth going from vA to vB. */ + inline FEdgeSmooth(SVertex *vA, SVertex *vB) : FEdge(vA, vB){ + _Face=0; + _FrsMaterialIndex = 0; + _isSmooth = true; + + } + /*! Copy constructor. */ + inline FEdgeSmooth(FEdgeSmooth& iBrother) : FEdge(iBrother){ + _Normal = iBrother._Normal; + _Face = iBrother._Face; + _FrsMaterialIndex = iBrother._FrsMaterialIndex; + _isSmooth = true; + } + /*! Destructor. */ + virtual ~FEdgeSmooth() {} + /*! Cloning method. */ + virtual FEdge* duplicate(){ + FEdge *clone = new FEdgeSmooth(*this); + return clone; + } + + inline void * face() const {return _Face;} + /*! Returns the normal to the Face it is running accross. */ + inline const Vec3r& normal() {return _Normal;} + /*! Returns the index of the material of the face it is running accross. */ + inline unsigned frs_materialIndex() const {return _FrsMaterialIndex;} + /*! Returns the material of the face it is running accross. */ + const FrsMaterial& frs_material() const ; + + inline void setFace(void * iFace) {_Face = iFace;} + /*! Sets the normal to the Face it is running accross. */ + inline void setNormal(const Vec3r& iNormal) {_Normal = iNormal;} + /*! Sets the index of the material of the face it is running accross. */ + inline void setFrsMaterialIndex(unsigned i) {_FrsMaterialIndex = i;} +}; + /**********************************/ + /* */ + /* */ + /* SShape */ + /* */ + /* */ + /**********************************/ + + +/*! Class to define a feature shape. It is the gathering + * of feature elements from an identified input shape + */ +class LIB_VIEW_MAP_EXPORT SShape +{ +private: + vector<FEdge*> _chains; // list of fedges that are chains starting points. + vector<SVertex*> _verticesList; // list of all vertices + vector<FEdge*> _edgesList; // list of all edges + Id _Id; + string _Name; + BBox<Vec3r> _BBox; + vector<FrsMaterial> _FrsMaterials; + + float _importance; + + ViewShape *_ViewShape; + +public: + /*! A field that can be used by the user to store any data. + * This field must be reseted afterwards using ResetUserData(). + */ + void* userdata; // added by E.T. + /*! Default constructor */ + inline SShape() + { + userdata = 0; + + _importance = 0.f; + _ViewShape = 0; + } + /*! Copy constructor */ + inline SShape(SShape& iBrother) + { + userdata = 0; + _Id = iBrother._Id; + _Name = iBrother._Name; + _BBox = iBrother.bbox(); + _FrsMaterials = iBrother._FrsMaterials; + + _importance = iBrother._importance; + + _ViewShape = iBrother._ViewShape; + + + //--------- + // vertices + //--------- + vector<SVertex*>::iterator sv,svend; + vector<SVertex*>& verticesList = iBrother.getVertexList(); + for(sv=verticesList.begin(), svend=verticesList.end(); + sv!=svend; + sv++) + { + SVertex *newv = new SVertex(*(*sv)); + newv->setShape(this); + _verticesList.push_back(newv); + } + + //------ + // edges + //------ + vector<FEdge*>::iterator e,eend; + vector<FEdge*>& edgesList = iBrother.getEdgeList(); + for(e=edgesList.begin(),eend=edgesList.end(); + e!=eend; + e++) + { + FEdge *newe = (*e)->duplicate(); + _edgesList.push_back(newe); + } + + //------------------------- + // starting chain edges + //------------------------- + vector<FEdge*>::iterator fe,fend; + vector<FEdge*>& fedges = iBrother.getChains(); + for(fe=fedges.begin(),fend=fedges.end(); + fe!=fend; + fe++) + { + _chains.push_back((FEdge*)((*fe)->userdata)); + } + + + //------------------------- + // remap edges in vertices: + //------------------------- + for(sv=_verticesList.begin(),svend=_verticesList.end(); + sv!=svend; + sv++) + { + const vector<FEdge*>& fedgeList = (*sv)->fedges(); + vector<FEdge*> newfedgelist; + for(vector<FEdge*>::const_iterator fed=fedgeList.begin(),fedend=fedgeList.end(); + fed!=fedend; + fed++) + { + FEdge *current = *fed; + newfedgelist.push_back((FEdge*)current->userdata); + } + (*sv)->setFEdges(newfedgelist); + } + + //------------------------------------- + // remap vertices and nextedge in edges: + //------------------------------------- + for(e=_edgesList.begin(),eend=_edgesList.end(); + e!=eend; + e++) + { + (*e)->setVertexA((SVertex*)((*e)->vertexA()->userdata)); + (*e)->setVertexB((SVertex*)((*e)->vertexB()->userdata)); + (*e)->setNextEdge((FEdge*)((*e)->nextEdge()->userdata)); + (*e)->setPreviousEdge((FEdge*)((*e)->previousEdge()->userdata)); + } + + + // reset all brothers userdata to NULL: + //------------------------------------- + //--------- + // vertices + //--------- + for(sv=_verticesList.begin(),svend=_verticesList.end(); + sv!=svend; + sv++) + { + (*sv)->userdata = NULL; + } + + //------ + // edges + //------ + for(e=_edgesList.begin(),eend=_edgesList.end(); + e!=eend; + e++) + { + (*e)->userdata = NULL; + } + } + /*! Cloning method. */ + virtual SShape * duplicate() + { + SShape *clone = new SShape(*this); + return clone; + } + /*! Destructor. */ + virtual inline ~SShape() + { + vector<SVertex*>::iterator sv,svend; + vector<FEdge*>::iterator e,eend; + if(0 != _verticesList.size()) + { + for(sv=_verticesList.begin(),svend=_verticesList.end(); + sv!=svend; + sv++) + { + delete (*sv); + } + _verticesList.clear(); + } + + if(0 != _edgesList.size()) + { + for(e=_edgesList.begin(),eend=_edgesList.end(); + e!=eend; + e++) + { + delete (*e); + } + _edgesList.clear(); + } + + //! Clear the chains list + //----------------------- + if(0 != _chains.size()) + { + _chains.clear(); + } + } + + /*! Adds a FEdge to the list of FEdges. */ + inline void AddEdge(FEdge *iEdge) + { + _edgesList.push_back(iEdge); + } + + /*! Adds a SVertex to the list of SVertex of this Shape. + * The SShape attribute of the SVertex is also set to 'this'. + */ + inline void AddNewVertex(SVertex* iv) {iv->setShape(this);_verticesList.push_back(iv);} + inline void AddChain(FEdge *iEdge){ + _chains.push_back(iEdge); + } + + inline SVertex * CreateSVertex(const Vec3r& P3D, const Vec3r& P2D, const Id& id) + { + SVertex *Ia = new SVertex(P3D, id); + Ia->setPoint2D(P2D); + AddNewVertex(Ia); + return Ia; + } + /* splits an edge into several edges. + * The edge's vertices are passed rather than + * the edge itself. This way, all feature edges (SILHOUETTE, + * CREASE, BORDER) are splitted in the same time. + * The processed edges are flagged as done (using the userdata + * flag).One single new vertex is created whereas + * several splitted edges might created for the different + * kinds of edges. These new elements are added to the lists + * maintained by the shape. + * new chains are also created. + * ioA + * The first vertex for the edge that gets splitted + * ioB + * The second vertex for the edge that gets splitted + * iParameters + * A vector containing 2D real vectors indicating the parameters + * giving the intersections coordinates in 3D and in 2D. + * These intersections points must be sorted from B to A. + * Each parameter defines the intersection point I as I=A+T*AB. + * T<0 and T>1 are then incorrect insofar as they give intersections + * points that lie outside the segment. + * ioNewEdges + * The edges that are newly created (the initial edges are not + * included) are added to this list. + */ + inline void SplitEdge(FEdge *fe, const vector<Vec2r>& iParameters, vector<FEdge*>& ioNewEdges) + { + + SVertex *ioA = fe->vertexA(); + SVertex *ioB = fe->vertexB(); + Vec3r A = ioA->point3D(); + Vec3r B = ioB->point3D(); + Vec3r a = ioA->point2D(); + Vec3r b = ioB->point2D(); + SVertex *svA, *svB; + + Vec3r newpoint3d,newpoint2d; + vector<SVertex*> intersections; + real t,T; + for(vector<Vec2r>::const_iterator p=iParameters.begin(),pend=iParameters.end(); + p!=pend; + p++) + { + T=(*p)[0]; + t=(*p)[1]; + + if((t < 0) || (t > 1)) + cerr << "Warning: Intersection out of range for edge " << ioA->getId() << " - " << ioB->getId() << endl; + + // compute the 3D and 2D coordinates for the intersections points: + newpoint3d = Vec3r(A + T*(B-A)); + newpoint2d = Vec3r(a + t*(b-a)); + + // create new SVertex: + // (we keep B's id) + SVertex* newVertex = new SVertex(newpoint3d, ioB->getId()); + newVertex->setPoint2D(newpoint2d); + + // Add this vertex to the intersections list: + intersections.push_back(newVertex); + + // Add this vertex to this sshape: + AddNewVertex(newVertex); + } + + for(vector<SVertex*>::iterator sv=intersections.begin(),svend=intersections.end(); + sv!=svend; + sv++) + { + svA = fe->vertexA(); + svB = fe->vertexB(); + + // We split edge AB into AA' and A'B. A' and A'B are created. + // AB becomes (address speaking) AA'. B is updated. + //-------------------------------------------------- + // The edge AB becomes edge AA'. + (fe)->setVertexB((*sv)); + // a new edge, A'B is created. + FEdge *newEdge; + if(fe->isSmooth()){ + newEdge = new FEdgeSmooth((*sv), svB); + FEdgeSmooth * se = dynamic_cast<FEdgeSmooth*>(newEdge); + FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(fe); + se->setFrsMaterialIndex(fes->frs_materialIndex()); + }else{ + newEdge = new FEdgeSharp((*sv), svB); + FEdgeSharp * se = dynamic_cast<FEdgeSharp*>(newEdge); + FEdgeSharp * fes = dynamic_cast<FEdgeSharp*>(fe); + se->setaFrsMaterialIndex(fes->aFrsMaterialIndex()); + se->setbFrsMaterialIndex(fes->bFrsMaterialIndex()); + } + + newEdge->setNature((fe)->getNature()); + + + // to build a new chain: + AddChain(newEdge); + // add the new edge to the sshape edges list. + AddEdge(newEdge); + // add new edge to the list of new edges passed as argument: + ioNewEdges.push_back(newEdge); + + // update edge A'B for the next pointing edge + newEdge->setNextEdge((fe)->nextEdge()); + fe->nextEdge()->setPreviousEdge(newEdge); + Id id(fe->getId().getFirst(), fe->getId().getSecond()+1); + newEdge->setId(fe->getId()); + fe->setId(id); + + // update edge AA' for the next pointing edge + //ioEdge->setNextEdge(newEdge); + (fe)->setNextEdge(NULL); + + // update vertex pointing edges list: + // -- vertex B -- + svB->Replace((fe), newEdge); + // -- vertex A' -- + (*sv)->AddFEdge((fe)); + (*sv)->AddFEdge(newEdge); + } + + } + + /* splits an edge into 2 edges. The new vertex and edge are added + * to the sshape list of vertices and edges + * a new chain is also created. + * returns the new edge. + * ioEdge + * The edge that gets splitted + * newpoint + * x,y,z coordinates of the new point. + */ + inline FEdge* SplitEdgeIn2(FEdge* ioEdge, SVertex * ioNewVertex) + { + //soc unused - SVertex *A = ioEdge->vertexA(); + SVertex *B = ioEdge->vertexB(); + + + // We split edge AB into AA' and A'B. A' and A'B are created. + // AB becomes (address speaking) AA'. B is updated. + //-------------------------------------------------- + + // a new edge, A'B is created. + FEdge *newEdge; + if(ioEdge->isSmooth()){ + newEdge = new FEdgeSmooth(ioNewVertex, B); + FEdgeSmooth * se = dynamic_cast<FEdgeSmooth*>(newEdge); + FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(ioEdge); + se->setFrsMaterialIndex(fes->frs_materialIndex()); + }else{ + newEdge = new FEdgeSharp(ioNewVertex, B); + FEdgeSharp * se = dynamic_cast<FEdgeSharp*>(newEdge); + FEdgeSharp * fes = dynamic_cast<FEdgeSharp*>(ioEdge); + se->setaFrsMaterialIndex(fes->aFrsMaterialIndex()); + se->setbFrsMaterialIndex(fes->bFrsMaterialIndex()); + } + newEdge->setNature(ioEdge->getNature()); + + + if(ioEdge->nextEdge() != 0) + ioEdge->nextEdge()->setPreviousEdge(newEdge); + + // update edge A'B for the next pointing edge + newEdge->setNextEdge(ioEdge->nextEdge()); + // update edge A'B for the previous pointing edge + newEdge->setPreviousEdge(0); // because it is now a TVertex + Id id(ioEdge->getId().getFirst(), ioEdge->getId().getSecond()+1); + newEdge->setId(ioEdge->getId()); + ioEdge->setId(id); + + // update edge AA' for the next pointing edge + ioEdge->setNextEdge(0); // because it is now a TVertex + + // update vertex pointing edges list: + // -- vertex B -- + B->Replace(ioEdge, newEdge); + // -- vertex A' -- + ioNewVertex->AddFEdge(ioEdge); + ioNewVertex->AddFEdge(newEdge); + + // to build a new chain: + AddChain(newEdge); + AddEdge(newEdge); // FIXME ?? + + // The edge AB becomes edge AA'. + ioEdge->setVertexB(ioNewVertex); + + if(ioEdge->isSmooth()){ + ((FEdgeSmooth*)newEdge)->setFace(((FEdgeSmooth*)ioEdge)->face()); + } + + return newEdge; + } + + /*! Sets the Bounding Box of the Shape */ + inline void setBBox(const BBox<Vec3r>& iBBox) {_BBox = iBBox;} + + /*! Compute the bbox of the sshape */ + inline void ComputeBBox() + { + if(0 == _verticesList.size()) + return; + + Vec3r firstVertex = _verticesList[0]->point3D(); + real XMax = firstVertex[0]; + real YMax = firstVertex[1]; + real ZMax = firstVertex[2]; + + real XMin = firstVertex[0]; + real YMin = firstVertex[1]; + real ZMin = firstVertex[2]; + + vector<SVertex*>::iterator v,vend; + // parse all the coordinates to find + // the Xmax, YMax, ZMax + for(v=_verticesList.begin(),vend=_verticesList.end(); + v!=vend; + v++) + { + Vec3r vertex = (*v)->point3D(); + // X + real x = vertex[0]; + if(x > XMax) + XMax = x; + if(x < XMin) + XMin = x; + + // Y + real y = vertex[1]; + if(y > YMax) + YMax = y; + if(y < YMin) + YMin = y; + + // Z + real z = vertex[2]; + if(z > ZMax) + ZMax = z; + if(z < ZMin) + ZMin = z; + } + + + setBBox(BBox<Vec3r>(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax))); + } + + inline void RemoveEdgeFromChain(FEdge *iEdge) + { + for(vector<FEdge*>::iterator fe=_chains.begin(), feend=_chains.end(); + fe!=feend; + fe++) + { + if(iEdge == (*fe)) + { + _chains.erase(fe); + break; + } + } + } + + inline void RemoveEdge(FEdge *iEdge) + { + for(vector<FEdge*>::iterator fe=_edgesList.begin(), feend=_edgesList.end(); + fe!=feend; + fe++) + { + if(iEdge == (*fe)) + { + _edgesList.erase(fe); + break; + } + } + } + + /* accessors */ + /*! Returns the list of SVertex of the Shape. */ + inline vector<SVertex*>& getVertexList() {return _verticesList;} // Get vertices list + /*! Returns the list of FEdges of the Shape. */ + inline vector<FEdge*>& getEdgeList() {return _edgesList;} // Get edges list + inline vector<FEdge*>& getChains() {return _chains;} + /*! Returns the bounding box of the shape. */ + inline const BBox<Vec3r>& bbox() {return _BBox;} + /*! Returns the ith material of the shape. */ + inline const FrsMaterial& frs_material(unsigned i) const {return _FrsMaterials[i];} + /*! Returns the list of materials of the Shape. */ + inline const vector<FrsMaterial>& frs_materials() const {return _FrsMaterials;} + inline ViewShape * viewShape() {return _ViewShape;} + inline float importance() const {return _importance;} + /*! Returns the Id of the Shape. */ + inline Id getId() const { return _Id; } + /*! Returns the name of the Shape. */ + inline const string& getName() const { return _Name; } + + /* Modififers */ + /*! Sets the Id of the shape.*/ + inline void setId(Id id) {_Id = id;} + /*! Sets the name of the shape.*/ + inline void setName(const string& name) {_Name = name;} + /*! Sets the list of materials for the shape */ + inline void setFrsMaterials(const vector<FrsMaterial>& iMaterials) {_FrsMaterials = iMaterials;} + inline void setViewShape(ViewShape *iShape) {_ViewShape = iShape;} + inline void setImportance(float importance){_importance = importance;} +}; + +#endif // SILHOUETTE_H diff --git a/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp new file mode 100755 index 00000000000..c0817189bc2 --- /dev/null +++ b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp @@ -0,0 +1,266 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "Silhouette.h" +#include "SilhouetteGeomEngine.h" +#include "../geometry/GeomUtils.h" + +using namespace std; + +Vec3r SilhouetteGeomEngine::_Viewpoint = Vec3r(0,0,0); +real SilhouetteGeomEngine::_translation[3] = {0,0,0}; +real SilhouetteGeomEngine::_modelViewMatrix[4][4] = {{1,0,0,0}, + {0,1,0,0}, + {0,0,1,0}, + {0,0,0,1}}; +real SilhouetteGeomEngine::_projectionMatrix[4][4] = {{1,0,0,0}, + {0,1,0,0}, + {0,0,1,0}, + {0,0,0,1}}; +real SilhouetteGeomEngine::_transform[4][4] = {{1,0,0,0}, + {0,1,0,0}, + {0,0,1,0}, + {0,0,0,1}}; +int SilhouetteGeomEngine::_viewport[4] = {1,1,1,1}; // the viewport +real SilhouetteGeomEngine::_Focal = 0.0; + +real SilhouetteGeomEngine::_glProjectionMatrix[4][4] = {{1,0,0,0}, + {0,1,0,0}, + {0,0,1,0}, + {0,0,0,1}}; +real SilhouetteGeomEngine::_glModelViewMatrix[4][4] = {{1,0,0,0}, + {0,1,0,0}, + {0,0,1,0}, + {0,0,0,1}}; +real SilhouetteGeomEngine::_znear = 0.0; +real SilhouetteGeomEngine::_zfar = 100.0; +bool SilhouetteGeomEngine::_isOrthographicProjection = false; + +SilhouetteGeomEngine * SilhouetteGeomEngine::_pInstance = 0; + +void SilhouetteGeomEngine::setTransform(const real iModelViewMatrix[4][4], const real iProjectionMatrix[4][4], const int iViewport[4], real iFocal) +{ + unsigned int i,j; + _translation[0] = iModelViewMatrix[3][0]; + _translation[1] = iModelViewMatrix[3][1]; + _translation[2] = iModelViewMatrix[3][2]; + + for(i=0; i<4; i++){ + for(j=0; j<4; j++) + { + _modelViewMatrix[i][j] = iModelViewMatrix[j][i]; + _glModelViewMatrix[i][j] = iModelViewMatrix[i][j]; + } + } + + for(i=0; i<4; i++){ + for(j=0; j<4; j++) + { + _projectionMatrix[i][j] = iProjectionMatrix[j][i]; + _glProjectionMatrix[i][j] = iProjectionMatrix[i][j]; + } + } + + for(i=0; i<4; i++){ + for(j=0; j<4; j++) + { + _transform[i][j] = 0; + for(unsigned int k=0; k<4; k++) + _transform[i][j] += _projectionMatrix[i][k] * _modelViewMatrix[k][j]; + } + } + + for(i=0; i<4; i++){ + _viewport[i] = iViewport[i]; + } + _Focal = iFocal; + + _isOrthographicProjection = (iProjectionMatrix[3][3] != 0.0); +} + +void SilhouetteGeomEngine::setFrustum(real iZNear, real iZFar) +{ + _znear = iZNear; + _zfar = iZFar; +} + +void SilhouetteGeomEngine::retrieveViewport(int viewport[4]){ + memcpy(viewport, _viewport, 4*sizeof(int)); +} +//#define HUGE 1e9 + +void SilhouetteGeomEngine::ProjectSilhouette(vector<SVertex*>& ioVertices) +{ + Vec3r newPoint; + // real min=HUGE; + // real max=-HUGE; + vector<SVertex*>::iterator sv, svend; + + for(sv=ioVertices.begin(), svend=ioVertices.end(); + sv!=svend; + sv++) + { + GeomUtils::fromWorldToImage((*sv)->point3D(), newPoint, _modelViewMatrix, _projectionMatrix, _viewport); + newPoint[2] = (-newPoint[2]-_znear)/(_zfar-_znear); // normalize Z between 0 and 1 + (*sv)->setPoint2D(newPoint); + //cerr << (*sv)->point2d().z() << " "; + // real d=(*sv)->point2d()[2]; + // if (d>max) max =d; + // if (d<min) min =d; + } + // for(sv=ioVertices.begin(), svend=ioVertices.end(); + // sv!=svend; + // sv++) + // { + // Vec3r P((*sv)->point2d()); + // (*sv)->setPoint2D(Vec3r(P[0], P[1], 1.0-(P[2]-min)/(max-min))); + // //cerr<<(*sv)->point2d()[2]<<" "; + // } +} + +void SilhouetteGeomEngine::ProjectSilhouette(SVertex* ioVertex) +{ + Vec3r newPoint; + // real min=HUGE; + // real max=-HUGE; + vector<SVertex*>::iterator sv, svend; + GeomUtils::fromWorldToImage(ioVertex->point3D(), newPoint, _modelViewMatrix, _projectionMatrix, _viewport); + newPoint[2] = (-newPoint[2]-_znear)/(_zfar-_znear); // normalize Z between 0 and 1 + ioVertex->setPoint2D(newPoint); +} + +real SilhouetteGeomEngine::ImageToWorldParameter(FEdge *fe, real t) +{ + if( _isOrthographicProjection ) + return t; + + // we need to compute for each parameter t the corresponding + // parameter T which gives the intersection in 3D. + real T; + + // suffix w for world, c for camera, r for retina, i for image + Vec3r Aw = (fe)->vertexA()->point3D(); + Vec3r Bw = (fe)->vertexB()->point3D(); + Vec3r Ac, Bc; + GeomUtils::fromWorldToCamera(Aw, Ac, _modelViewMatrix); + GeomUtils::fromWorldToCamera(Bw, Bc, _modelViewMatrix); + Vec3r ABc = Bc - Ac; +#if 0 + cout << "Ac " << Ac << endl; + cout << "Bc " << Bc << endl; + cout << "ABc " << ABc << endl; +#endif + Vec3r Ai = (fe)->vertexA()->point2D(); + Vec3r Bi = (fe)->vertexB()->point2D(); + Vec3r Ii = Ai + t * (Bi - Ai); // the intersection point in the 2D image space + Vec3r Ir, Ic; + GeomUtils::fromImageToRetina(Ii, Ir, _viewport); + + real alpha, beta, denom; + real m11 = _projectionMatrix[0][0]; + real m13 = _projectionMatrix[0][2]; + real m22 = _projectionMatrix[1][1]; + real m23 = _projectionMatrix[1][2]; + + if (fabs(ABc[0]) > 1e-6) { + + alpha = ABc[2] / ABc[0]; + beta = Ac[2] - alpha * Ac[0]; + denom = alpha * (Ir[0] + m13) + m11; + if (fabs(denom) < 1e-6) + goto iter; + Ic[0] = -beta * (Ir[0] + m13) / denom; +// Ic[1] = -(Ir[1] + m23) * (alpha * Ic[0] + beta) / m22; +// Ic[2] = alpha * (Ic[0] - Ac[0]) + Ac[2]; + T = (Ic[0] - Ac[0]) / ABc[0]; + + } else if (fabs(ABc[1]) > 1e-6) { + + alpha = ABc[2] / ABc[1]; + beta = Ac[2] - alpha * Ac[1]; + denom = alpha * (Ir[1] + m23) + m22; + if (fabs(denom) < 1e-6) + goto iter; + Ic[1] = -beta * (Ir[1] + m23) / denom; +// Ic[0] = -(Ir[0] + m13) * (alpha * Ic[1] + beta) / m11; +// Ic[2] = alpha * (Ic[1] - Ac[1]) + Ac[2]; + T = (Ic[1] - Ac[1]) / ABc[1]; + + } else { + +iter: bool x_coords, less_than; + if (fabs(Bi[0] - Ai[0]) > 1e-6) { + x_coords = true; + less_than = Ai[0] < Bi[0]; + } else { + x_coords = false; + less_than = Ai[1] < Bi[1]; + } + Vec3r Pc, Pr, Pi; + real T_sta = 0.0; + real T_end = 1.0; + real delta_x, delta_y, dist, dist_threshold = 1e-6; + int i, max_iters = 100; + for (i = 0; i < max_iters; i++) { + T = T_sta + 0.5 * (T_end - T_sta); + Pc = Ac + T * ABc; + GeomUtils::fromCameraToRetina(Pc, Pr, _projectionMatrix); + GeomUtils::fromRetinaToImage(Pr, Pi, _viewport); + delta_x = Ii[0] - Pi[0]; + delta_y = Ii[1] - Pi[1]; + dist = sqrt(delta_x * delta_x + delta_y * delta_y); + if (dist < dist_threshold) + break; + if (x_coords) { + if (less_than) { + if (Pi[0] < Ii[0]) { T_sta = T; } else { T_end = T; } + } else { + if (Pi[0] > Ii[0]) { T_sta = T; } else { T_end = T; } + } + } else { + if (less_than) { + if (Pi[1] < Ii[1]) { T_sta = T; } else { T_end = T; } + } else { + if (Pi[1] > Ii[1]) { T_sta = T; } else { T_end = T; } + } + } + } +#if 0 + printf("SilhouetteGeomEngine::ImageToWorldParameter(): #iters = %d, dist = %e\n", i, dist); +#endif + if (i == max_iters) + printf("SilhouetteGeomEngine::ImageToWorldParameter(): reached to max_iters (dist = %e)\n", dist); + } + + return T; +} + +Vec3r SilhouetteGeomEngine::WorldToImage(const Vec3r& M) + +{ + + Vec3r newPoint; + GeomUtils::fromWorldToImage(M, newPoint, _transform, _viewport); + newPoint[2] = (-newPoint[2]-_znear)/(_zfar-_znear); // normalize Z between 0 and 1 + return newPoint; + +} + diff --git a/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h new file mode 100755 index 00000000000..5bd89f8a162 --- /dev/null +++ b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h @@ -0,0 +1,123 @@ +// +// Filename : SilhouetteGeomEngine.h +// Author(s) : Stephane Grabli +// Purpose : Class to perform all geometric operations dedicated +// to silhouette. That, for example, implies that +// this geom engine has as member data the viewpoint, +// transformations, projections... +// Date of creation : 03/09/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef SILHOUETTEGEOMENGINE_H +# define SILHOUETTEGEOMENGINE_H + +# include <vector> +# include "../system/FreestyleConfig.h" +# include "../geometry/Geom.h" + +using namespace Geometry; + +class SVertex; +class FEdge; + +class LIB_VIEW_MAP_EXPORT SilhouetteGeomEngine +{ +private: + static Vec3r _Viewpoint; // The viewpoint under which the silhouette has to be computed + static real _translation[3]; + static real _modelViewMatrix[4][4]; // the model view matrix (_modelViewMatrix[i][j] means element of line i and column j) + static real _projectionMatrix[4][4]; // the projection matrix (_projectionMatrix[i][j] means element of line i and column j) + static real _transform[4][4]; // the global transformation from world to screen (projection included) (_transform[i][j] means element of line i and column j) + static int _viewport[4]; // the viewport + static real _Focal; + + static real _znear; + static real _zfar; + + static real _glProjectionMatrix[4][4]; // GL style (column major) projection matrix + static real _glModelViewMatrix[4][4]; // GL style (column major) model view matrix + +static bool _isOrthographicProjection; + + + static SilhouetteGeomEngine *_pInstance; +public: + + /*! retrieves an instance on the singleton */ + static SilhouetteGeomEngine * getInstance() + { + if(0 == _pInstance) + { + _pInstance = new SilhouetteGeomEngine; + } + return _pInstance; + } + + /*! Sets the current viewpoint */ + static inline void setViewpoint(const Vec3r& ivp) {_Viewpoint = ivp;} + + /*! Sets the current transformation + * iModelViewMatrix + * The 4x4 model view matrix, in column major order (openGL like). + * iProjection matrix + * The 4x4 projection matrix, in column major order (openGL like). + * iViewport + * The viewport. 4 real array: origin.x, origin.y, width, length + * iFocal + * The focal length + */ + static void setTransform(const real iModelViewMatrix[4][4], const real iProjectionMatrix[4][4], const int iViewport[4], real iFocal) ; + + /*! Sets the current znear and zfar + */ + static void setFrustum(real iZNear, real iZFar) ; + + /* accessors */ + static void retrieveViewport(int viewport[4]); + + /*! Projects the silhouette in camera coordinates + * This method modifies the ioEdges passed as argument. + * ioVertices + * The vertices to project. It is modified during the + * operation. + */ + static void ProjectSilhouette(std::vector<SVertex*>& ioVertices); + static void ProjectSilhouette(SVertex* ioVertex); + + /*! transforms the parameter t defining a 2D intersection for edge fe in order to obtain + * the parameter giving the corresponding 3D intersection. + * Returns the 3D parameter + * fe + * The edge + * t + * The parameter for the 2D intersection. + */ + static real ImageToWorldParameter(FEdge *fe, real t); + + /*! From world to image */ + static Vec3r WorldToImage(const Vec3r& M); +}; + +#endif // SILHOUETTEGEOMENGINE_H diff --git a/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp new file mode 100755 index 00000000000..d1d9eb71e77 --- /dev/null +++ b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp @@ -0,0 +1,267 @@ +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "Silhouette.h" +#include "SteerableViewMap.h" +#include "../image/ImagePyramid.h" +#include "../image/Image.h" +#include <math.h> +#include "../geometry/Geom.h" +using namespace Geometry; + +//soc #include <qstring.h> +//soc #include <qimage.h> +#include <sstream> + +extern "C" { +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" +} + +SteerableViewMap::SteerableViewMap(unsigned int nbOrientations){ + _nbOrientations = nbOrientations; + _bound = cos(M_PI/(float)_nbOrientations); + for(unsigned i=0; i<_nbOrientations; ++i){ + _directions.push_back(Vec2d(cos((float)i*M_PI/(float)_nbOrientations), sin((float)i*M_PI/(float)_nbOrientations))); + } + Build(); +} + +void SteerableViewMap::Build(){ + _imagesPyramids = new ImagePyramid*[_nbOrientations+1]; // one more map to store the complete visible VM + memset((_imagesPyramids),0,(_nbOrientations+1)*sizeof(ImagePyramid*)); +} + +SteerableViewMap::SteerableViewMap(const SteerableViewMap& iBrother){ + _nbOrientations = iBrother._nbOrientations; + unsigned i; + _bound = iBrother._bound; + _directions = iBrother._directions; + _mapping = iBrother._mapping; + _imagesPyramids = new ImagePyramid*[_nbOrientations+1]; // one more map to store the complete visible VM + for(i=0;i<_nbOrientations+1;++i) + _imagesPyramids[i] = new GaussianPyramid(*(dynamic_cast<GaussianPyramid*>(iBrother._imagesPyramids[i]))); +} + +SteerableViewMap::~SteerableViewMap(){ + Clear(); +} + +void SteerableViewMap::Clear(){ + unsigned i; + if(_imagesPyramids){ + for(i=0; i<=_nbOrientations; ++i){ + if(_imagesPyramids[i]) + delete (_imagesPyramids)[i]; + } + delete [] _imagesPyramids; + _imagesPyramids = 0; + } + if(!_mapping.empty()){ + for(map<unsigned int, double*>::iterator m=_mapping.begin(), mend=_mapping.end(); + m!=mend; + ++m){ + delete [] (*m).second; + } + _mapping.clear(); + } +} + +void SteerableViewMap::Reset(){ + Clear(); + Build(); +} + +double SteerableViewMap::ComputeWeight(const Vec2d& dir, unsigned i){ + double dotp = fabs(dir*_directions[i]); + if(dotp < _bound) + return 0; + if(dotp>1) + dotp = 1; + + return cos((float)_nbOrientations/2.0*acos(dotp)); +} + +double * SteerableViewMap::AddFEdge(FEdge *iFEdge){ + unsigned i; + unsigned id = iFEdge->getId().getFirst(); + map<unsigned int, double* >::iterator o = _mapping.find(id); + if(o!=_mapping.end()){ + return (*o).second; + } + double * res = new double[_nbOrientations]; + for(i=0; i<_nbOrientations; ++i){ + res[i] = 0; + } + Vec3r o2d3 = iFEdge->orientation2d(); + Vec2r o2d2(o2d3.x(), o2d3.y()); + real norm = o2d2.norm(); + if(norm < 1e-6){ + return res; + } + o2d2/=norm; + + for(i=0; i<_nbOrientations; ++i){ + res[i] = ComputeWeight(o2d2, i); + } + _mapping[id] = res; + return res; +} + +unsigned SteerableViewMap::getSVMNumber(const Vec2f& orient){ + Vec2f dir(orient); + //soc unsigned res = 0; + real norm = dir.norm(); + if(norm < 1e-6){ + return _nbOrientations+1; + } + dir/=norm; + double maxw = 0.f; + unsigned winner = _nbOrientations+1; + for(unsigned i=0; i<_nbOrientations; ++i){ + double w = ComputeWeight(dir, i); + if(w>maxw){ + maxw = w; + winner = i; + } + } + return winner; +} + + +unsigned SteerableViewMap::getSVMNumber(unsigned id){ + map<unsigned int, double* >::iterator o = _mapping.find(id); + if(o!=_mapping.end()){ + double* wvalues= (*o).second; + double maxw = 0.f; + unsigned winner = _nbOrientations+1; + for(unsigned i=0; i<_nbOrientations; ++i){ + double w = wvalues[i]; + if(w>maxw){ + maxw = w; + winner = i; + } + } + return winner; + } + return _nbOrientations+1; +} + +void SteerableViewMap::buildImagesPyramids(GrayImage **steerableBases, bool copy, unsigned iNbLevels, float iSigma){ + for(unsigned i=0; i<=_nbOrientations; ++i){ + ImagePyramid * svm = (_imagesPyramids)[i]; + if(svm) + delete svm; + if(copy) + svm = new GaussianPyramid(*(steerableBases[i]), iNbLevels, iSigma); + else + svm = new GaussianPyramid(steerableBases[i], iNbLevels, iSigma); + _imagesPyramids[i] = svm; + } +} + +float SteerableViewMap::readSteerableViewMapPixel(unsigned iOrientation, int iLevel, int x, int y){ + ImagePyramid *pyramid = _imagesPyramids[iOrientation]; + if(pyramid==0){ + cout << "Warning: this steerable ViewMap level doesn't exist" << endl; + return 0; + } + if((x<0) || (x>=pyramid->width()) || (y<0) || (y>=pyramid->height())) + return 0; + //float v = pyramid->pixel(x,pyramid->height()-1-y,iLevel)*255.f; + float v = pyramid->pixel(x,pyramid->height()-1-y,iLevel)/32.f; // we encode both the directionality and the lines counting on 8 bits + // (because of frame buffer). Thus, we allow until 8 lines to pass through + // the same pixel, so that we can discretize the Pi/_nbOrientations angle into + // 32 slices. Therefore, for example, in the vertical direction, a vertical line + // will have the value 32 on each pixel it passes through. + return v; +} + +float SteerableViewMap::readCompleteViewMapPixel(int iLevel, int x, int y){ + return readSteerableViewMapPixel(_nbOrientations,iLevel,x,y); +} + +unsigned int SteerableViewMap::getNumberOfPyramidLevels() const{ + if(_imagesPyramids[0]) + return _imagesPyramids[0]->getNumberOfLevels(); + return 0; +} + +void SteerableViewMap::saveSteerableViewMap() const { + for(unsigned i=0; i<=_nbOrientations; ++i){ + if(_imagesPyramids[i] == 0){ + cerr << "SteerableViewMap warning: orientation " << i <<" of steerable View Map whas not been computed yet" << endl; + continue; + } + int ow = _imagesPyramids[i]->width(0); + int oh = _imagesPyramids[i]->height(0); + + //soc QString base("SteerableViewMap"); + string base("SteerableViewMap"); + stringstream filename; + + for(int j=0; j<_imagesPyramids[i]->getNumberOfLevels(); ++j){ //soc + float coeff = 1;//1/255.f; //100*255;//*pow(2,j); + //soc QImage qtmp(ow, oh, QImage::Format_RGB32); + ImBuf *ibuf = IMB_allocImBuf(ow, oh, 32, IB_rect, 0); + int rowbytes = ow*4; + char *pix; + + for(int y=0;y<oh;++y){ //soc + for(int x=0;x<ow;++x){ //soc + int c = (int)(coeff*_imagesPyramids[i]->pixel(x,y,j)); + if(c>255) + c=255; + //int c = (int)(_imagesPyramids[i]->pixel(x,y,j)); + + //soc qtmp.setPixel(x,y,qRgb(c,c,c)); + pix = (char*)ibuf->rect + y*rowbytes + x*4; + pix[0] = pix [1] = pix[2] = c; + } + } + + //soc qtmp.save(base+QString::number(i)+"-"+QString::number(j)+".png", "PNG"); + filename << base; + filename << i << "-" << j << ".png"; + ibuf->ftype= PNG; + IMB_saveiff(ibuf, const_cast<char *>(filename.str().c_str()), 0); + + } + // QString base("SteerableViewMap"); + // for(unsigned j=0; j<_imagesPyramids[i]->getNumberOfLevels(); ++j){ + // GrayImage * img = _imagesPyramids[i]->getLevel(j); + // int ow = img->width(); + // int oh = img->height(); + // float coeff = 1; //100*255;//*pow(2,j); + // QImage qtmp(ow, oh, 32); + // for(unsigned y=0;y<oh;++y){ + // for(unsigned x=0;x<ow;++x){ + // int c = (int)(coeff*img->pixel(x,y)); + // if(c>255) + // c=255; + // //int c = (int)(_imagesPyramids[i]->pixel(x,y,j)); + // qtmp.setPixel(x,y,qRgb(c,c,c)); + // } + // } + // qtmp.save(base+QString::number(i)+"-"+QString::number(j)+".png", "PNG"); + // } + // + } +} diff --git a/source/blender/freestyle/intern/view_map/SteerableViewMap.h b/source/blender/freestyle/intern/view_map/SteerableViewMap.h new file mode 100755 index 00000000000..fe7c2493752 --- /dev/null +++ b/source/blender/freestyle/intern/view_map/SteerableViewMap.h @@ -0,0 +1,153 @@ +// +// Filename : SteerbaleViewMap.h +// Author(s) : Stephane Grabli +// Purpose : Convenient access to the steerable ViewMap +// to which any element of the ViewMap belongs to. +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// +#ifndef STEERABLEVIEWMAP_H +# define STEERABLEVIEWMAP_H + +#include <map> +#include "../system/FreestyleConfig.h" +#include "../geometry/Geom.h" +using namespace Geometry; + +using namespace std; + +class FEdge; +class ImagePyramid; +class GrayImage; +/*! This class checks for every FEdge in which steerable + * it belongs and stores the mapping allowing to retrieve + * this information from the FEdge Id + */ +class LIB_VIEW_MAP_EXPORT SteerableViewMap{ +protected: + map<unsigned int, double* > _mapping; // for each vector the list of nbOrientations weigths corresponding to its contributions to the nbOrientations directional maps + unsigned _nbOrientations; + ImagePyramid **_imagesPyramids; // the pyramids of images storing the different SVM + + // internal + double _bound; // cos(Pi/N) + vector<Vec2d> _directions; + +public: + SteerableViewMap(unsigned int nbOrientations = 4); + SteerableViewMap(const SteerableViewMap& iBrother); + virtual ~SteerableViewMap(); + + /*! Resets everything */ + virtual void Reset(); + + /*! Adds a FEdge to steerable VM. + * Returns the nbOrientations weigths corresponding to + * the FEdge contributions to the nbOrientations directional maps. + */ + double* AddFEdge(FEdge *iFEdge); + + /*! Compute the weight of direction dir for orientation iNOrientation */ + double ComputeWeight(const Vec2d& dir, unsigned iNOrientation); + + /*! Returns the number of the SVM to which a direction belongs + * to. + * \param dir + * The direction + */ + unsigned getSVMNumber(const Vec2f& dir); + + /*! Returns the number of the SVM to which a FEdge belongs + * most. + * \param id + * The First element of the Id struct of the FEdge + * we're intersted in. + */ + unsigned getSVMNumber(unsigned id); + + /*! Builds _nbOrientations+1 pyramids of images from the _nbOrientations+1 base images + * of the steerable viewmap. + * \param steerableBases + * The _nbOrientations+1 images constituing the basis for the steerable + * pyramid. + * \param copy + * If false, the data is not duplicated, and Canvas deals + * with the memory management of these _nbOrientations+1 images. If true, data + * is copied, and it's up to the caller to delete the images. + * \params iNbLevels + * The number of levels desired for each pyramid. + * If iNbLevels == 0, the complete pyramid is built. + * \param iSigma + * The sigma that will be used for the gaussian blur + */ + void buildImagesPyramids(GrayImage **steerableBases, bool copy = false, unsigned iNbLevels=4, float iSigma = 1.f); + + /*! Reads a pixel value in one of the VewMap density steerable pyramids. + * Returns a value between 0 and 1. + * \param iOrientation + * the number telling which orientation we need to check. + * There are _nbOrientations+1 oriented ViewMaps: + * 0 -> the ViewMap containing every horizontal lines + * 1 -> the ViewMap containing every lines whose orientation is around PI/4 + * 2 -> the ViewMap containing every vertical lines + * 3 -> the ViewMap containing every lines whose orientation is around 3PI/4 + * 4 -> the complete ViewMap + * \param iLevel + * The level of the pyramid we want to read + * \param x + * The abscissa of the desired pixel specified in level0 coordinate + * system. The origin is the lower left corner. + * \param y + * The ordinate of the desired pixel specified in level0 coordinate + * system. The origin is the lower left corner. + */ + float readSteerableViewMapPixel(unsigned iOrientation, int iLevel, int x, int y); + + /*! Reads a pixel in the one of the level of the + * pyramid containing the images of the complete + * ViewMap. + * Returns a value between 0 and 1. + * Equivalent to : readSteerableViewMapPixel(nbOrientations, x,y) + */ + float readCompleteViewMapPixel(int iLevel, int x, int y); + + /*! Returns the number of levels in the pyramids */ + unsigned int getNumberOfPyramidLevels() const; + + /*! Returns the number of orientations */ + unsigned int getNumberOfOrientations() const{ + return _nbOrientations; + } + + /*! for debug purposes */ + void saveSteerableViewMap() const ; + +protected: + void Clear(); + void Build(); + + +}; + +#endif // STEERABLEVIEWMAP_H diff --git a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp new file mode 100755 index 00000000000..3e0979f684f --- /dev/null +++ b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp @@ -0,0 +1,666 @@ +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "ViewMap.h" +#include "ViewEdgeXBuilder.h" +#include "../winged_edge/WXEdge.h" +#include "SilhouetteGeomEngine.h" +#include <list> + +using namespace std; + +void ViewEdgeXBuilder::Init(ViewShape *oVShape){ + if(0 == oVShape) + return; + + // for design conveniance, we store the current SShape. + _pCurrentSShape = oVShape->sshape(); + if(0 == _pCurrentSShape) + return; + + _pCurrentVShape = oVShape; + + // Reset previous data + //-------------------- + if(!_SVertexMap.empty()) + _SVertexMap.clear(); +} + +void ViewEdgeXBuilder::BuildViewEdges( WXShape *iWShape, ViewShape *oVShape, + vector<ViewEdge*>& ioVEdges, + vector<ViewVertex*>& ioVVertices, + vector<FEdge*>& ioFEdges, + vector<SVertex*>& ioSVertices){ + // Reinit structures + Init(oVShape); + + ViewEdge *vedge ; + // Let us build the smooth stuff + //---------------------------------------- + // We parse all faces to find the ones + // that contain smooth edges + vector<WFace*>& wfaces = iWShape->GetFaceList(); + vector<WFace*>::iterator wf, wfend; + WXFace *wxf; + for(wf=wfaces.begin(), wfend=wfaces.end(); + wf!=wfend; + wf++){ + wxf = dynamic_cast<WXFace*>(*wf); + if(false == ((wxf))->hasSmoothEdges()) // does it contain at least one smooth edge ? + continue; + // parse all smooth layers: + vector<WXFaceLayer*>& smoothLayers = wxf->getSmoothLayers(); + for(vector<WXFaceLayer*>::iterator sl = smoothLayers.begin(), slend=smoothLayers.end(); + sl!=slend; + ++sl){ + if(!(*sl)->hasSmoothEdge()) + continue; + if(stopSmoothViewEdge((*sl))) // has it been parsed already ? + continue; + // here we know that we're dealing with a face layer that has not been + // processed yet and that contains a smooth edge. + vedge = BuildSmoothViewEdge(OWXFaceLayer(*sl, true)); + } + } + + // Now let's build sharp view edges: + //---------------------------------- + // Reset all userdata for WXEdge structure + //---------------------------------------- + //iWShape->ResetUserData(); + + WXEdge * wxe; + vector<WEdge*>& wedges = iWShape->getEdgeList(); + // + //------------------------------ + for(vector<WEdge*>::iterator we=wedges.begin(),weend=wedges.end(); + we!=weend; + we++){ + wxe = dynamic_cast<WXEdge*>(*we); + if(Nature::NO_FEATURE == wxe->nature()) + continue; + + if(!stopSharpViewEdge(wxe)){ + bool b=true; + if(wxe->order() == -1) + b = false; + BuildSharpViewEdge(OWXEdge(wxe,b)); + } + } + + // Reset all userdata for WXEdge structure + //---------------------------------------- + iWShape->ResetUserData(); + + // Add all these new edges to the scene's feature edges list: + //----------------------------------------------------------- + vector<FEdge*>& newedges = _pCurrentSShape->getEdgeList(); + vector<SVertex*>& newVertices = _pCurrentSShape->getVertexList(); + vector<ViewVertex*>& newVVertices = _pCurrentVShape->vertices(); + vector<ViewEdge*>& newVEdges = _pCurrentVShape->edges(); + + // inserts in ioFEdges, at its end, all the edges of newedges + ioFEdges.insert(ioFEdges.end(), newedges.begin(), newedges.end()); + ioSVertices.insert(ioSVertices.end(), newVertices.begin(), newVertices.end()); + ioVVertices.insert(ioVVertices.end(), newVVertices.begin(), newVVertices.end()); + ioVEdges.insert(ioVEdges.end(), newVEdges.begin(), newVEdges.end()); + +} + +ViewEdge * ViewEdgeXBuilder::BuildSmoothViewEdge(const OWXFaceLayer& iFaceLayer){ + // Find first edge: + OWXFaceLayer first = iFaceLayer; + OWXFaceLayer currentFace = first; + + // bidirectional chaining. + // first direction + list<OWXFaceLayer> facesChain; + unsigned size = 0; + while(!stopSmoothViewEdge(currentFace.fl)){ + facesChain.push_back(currentFace); + ++size; + currentFace.fl->userdata = (void*)1; // processed + // Find the next edge! + currentFace = FindNextFaceLayer(currentFace); + } + OWXFaceLayer end = facesChain.back(); + // second direction + currentFace = FindPreviousFaceLayer(first); + while(!stopSmoothViewEdge(currentFace.fl)){ + facesChain.push_front(currentFace); + ++size; + currentFace.fl->userdata = (void*)1; // processed + // Find the previous edge! + currentFace = FindPreviousFaceLayer(currentFace); + } + first = facesChain.front(); + + if(iFaceLayer.fl->nature() & Nature::RIDGE){ + if(size<4){ + return 0; + } + } + + // Start a new chain edges + ViewEdge * newVEdge = new ViewEdge; + newVEdge->setId(_currentViewId); + ++_currentViewId; + + _pCurrentVShape->AddEdge(newVEdge); + + + // build FEdges + FEdge * feprevious = 0; + FEdge * fefirst = 0; + FEdge * fe = 0; + for(list<OWXFaceLayer>::iterator fl = facesChain.begin(), flend=facesChain.end(); + fl!=flend; + ++fl){ + fe = BuildSmoothFEdge(feprevious, (*fl)); + fe->setViewEdge(newVEdge); + if(!fefirst) + fefirst = fe; + feprevious = fe; + } + // Store the chain starting edge: + _pCurrentSShape->AddChain(fefirst); + newVEdge->setNature(iFaceLayer.fl->nature()); + newVEdge->setFEdgeA(fefirst); + newVEdge->setFEdgeB(fe); + + // is it a closed loop ? + if((first == end) && (size != 1)){ + fefirst->setPreviousEdge(fe); + fe->setNextEdge(fefirst); + newVEdge->setA(0); + newVEdge->setB(0); + }else{ + ViewVertex *vva = MakeViewVertex(fefirst->vertexA()); + ViewVertex *vvb = MakeViewVertex(fe->vertexB()); + + ((NonTVertex*)vva)->AddOutgoingViewEdge(newVEdge); + ((NonTVertex*)vvb)->AddIncomingViewEdge(newVEdge); + + newVEdge->setA(vva); + newVEdge->setB(vvb); + } + + return newVEdge; +} + +ViewEdge * ViewEdgeXBuilder::BuildSharpViewEdge(const OWXEdge& iWEdge) { + // Start a new sharp chain edges + ViewEdge * newVEdge = new ViewEdge; + newVEdge->setId(_currentViewId); + ++_currentViewId; + unsigned size=0; + + _pCurrentVShape->AddEdge(newVEdge); + + // Find first edge: + OWXEdge firstWEdge = iWEdge; + OWXEdge previousWEdge = firstWEdge; + OWXEdge currentWEdge = firstWEdge; + list<OWXEdge> edgesChain; + // bidirectional chaining + // first direction: + while(!stopSharpViewEdge(currentWEdge.e)){ + edgesChain.push_back(currentWEdge); + ++size; + currentWEdge.e->userdata = (void*)1; // processed + // Find the next edge! + currentWEdge = FindNextWEdge(currentWEdge); + } + OWXEdge endWEdge = edgesChain.back(); + // second direction + currentWEdge = FindPreviousWEdge(firstWEdge); + while(!stopSharpViewEdge(currentWEdge.e)){ + edgesChain.push_front(currentWEdge); + ++size; + currentWEdge.e->userdata = (void*)1; // processed + // Find the previous edge! + currentWEdge = FindPreviousWEdge(currentWEdge); + } + firstWEdge = edgesChain.front(); + + // build FEdges + FEdge * feprevious = 0; + FEdge * fefirst = 0; + FEdge * fe = 0; + for(list<OWXEdge>::iterator we = edgesChain.begin(), weend=edgesChain.end(); + we!=weend; + ++we){ + fe = BuildSharpFEdge(feprevious, (*we)); + fe->setViewEdge(newVEdge); + if(!fefirst) + fefirst = fe; + feprevious = fe; + } + // Store the chain starting edge: + _pCurrentSShape->AddChain(fefirst); + newVEdge->setNature(iWEdge.e->nature()); + newVEdge->setFEdgeA(fefirst); + newVEdge->setFEdgeB(fe); + + // is it a closed loop ? + if((firstWEdge == endWEdge) && (size!=1)){ + fefirst->setPreviousEdge(fe); + fe->setNextEdge(fefirst); + newVEdge->setA(0); + newVEdge->setB(0); + }else{ + ViewVertex *vva = MakeViewVertex(fefirst->vertexA()); + ViewVertex *vvb = MakeViewVertex(fe->vertexB()); + + ((NonTVertex*)vva)->AddOutgoingViewEdge(newVEdge); + ((NonTVertex*)vvb)->AddIncomingViewEdge(newVEdge); + + newVEdge->setA(vva); + newVEdge->setB(vvb); + } + + return newVEdge; +} + +OWXFaceLayer ViewEdgeXBuilder::FindNextFaceLayer(const OWXFaceLayer& iFaceLayer){ + WXFace *nextFace = 0; + WOEdge * woeend; + real tend; + if(iFaceLayer.order){ + woeend = iFaceLayer.fl->getSmoothEdge()->woeb(); + tend = iFaceLayer.fl->getSmoothEdge()->tb(); + }else{ + woeend = iFaceLayer.fl->getSmoothEdge()->woea(); + tend = iFaceLayer.fl->getSmoothEdge()->ta(); + } + // special case of EDGE_VERTEX config: + if((tend == 0.0) || (tend == 1.0)){ + WVertex *nextVertex; + if(tend == 0.0) + nextVertex = woeend->GetaVertex(); + else + nextVertex = woeend->GetbVertex(); + if(nextVertex->isBoundary()) // if it's a non-manifold vertex -> ignore + return OWXFaceLayer(0,true); + bool found = false; + WVertex::face_iterator f=nextVertex->faces_begin(); + WVertex::face_iterator fend=nextVertex->faces_end(); + while((!found) && (f!=fend)){ + nextFace = dynamic_cast<WXFace*>(*f); + if((0 != nextFace) && (nextFace!=iFaceLayer.fl->getFace())){ + vector<WXFaceLayer*> sameNatureLayers; + nextFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers); + if(sameNatureLayers.size() == 1) {// don't know + // maybe should test whether this face has + // also a vertex_edge configuration + WXFaceLayer * winner = sameNatureLayers[0]; + if(woeend == winner->getSmoothEdge()->woea()->twin()) + return OWXFaceLayer(winner,true); + else + return OWXFaceLayer(winner,false); + } + } + ++f; + } + }else{ + nextFace = dynamic_cast<WXFace*>(iFaceLayer.fl->getFace()->GetBordingFace(woeend)); + if(0 == nextFace) + return OWXFaceLayer(0,true); + // if the next face layer has either no smooth edge or + // no smooth edge of same nature, no next face + if(!nextFace->hasSmoothEdges()) + return OWXFaceLayer(0,true); + vector<WXFaceLayer*> sameNatureLayers; + nextFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers); + if((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) // don't know how to deal with several edges of same nature on a single face + return OWXFaceLayer(0,true); + else{ + WXFaceLayer * winner = sameNatureLayers[0]; + if(woeend == winner->getSmoothEdge()->woea()->twin()) + return OWXFaceLayer(winner,true); + else + return OWXFaceLayer(winner,false); + } + } + return OWXFaceLayer(0,true); +} + +OWXFaceLayer ViewEdgeXBuilder::FindPreviousFaceLayer(const OWXFaceLayer& iFaceLayer) { + WXFace *previousFace = 0; + WOEdge * woebegin; + real tend; + if(iFaceLayer.order){ + woebegin = iFaceLayer.fl->getSmoothEdge()->woea(); + tend = iFaceLayer.fl->getSmoothEdge()->ta(); + }else{ + woebegin = iFaceLayer.fl->getSmoothEdge()->woeb(); + tend = iFaceLayer.fl->getSmoothEdge()->tb(); + } + + // special case of EDGE_VERTEX config: + if((tend == 0.0) || (tend == 1.0)){ + WVertex *previousVertex; + if(tend == 0.0) + previousVertex = woebegin->GetaVertex(); + else + previousVertex = woebegin->GetbVertex(); + if(previousVertex->isBoundary()) // if it's a non-manifold vertex -> ignore + return OWXFaceLayer(0,true); + bool found = false; + WVertex::face_iterator f=previousVertex->faces_begin(); + WVertex::face_iterator fend=previousVertex->faces_end(); + while((!found) && (f!=fend)){ + previousFace = dynamic_cast<WXFace*>(*f); + if((0 != previousFace) && (previousFace!=iFaceLayer.fl->getFace())){ + vector<WXFaceLayer*> sameNatureLayers; + previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers); + if(sameNatureLayers.size() == 1) {// don't know + // maybe should test whether this face has + // also a vertex_edge configuration + WXFaceLayer * winner = sameNatureLayers[0]; + if(woebegin == winner->getSmoothEdge()->woeb()->twin()) + return OWXFaceLayer(winner,true); + else + return OWXFaceLayer(winner,false); + } + } + ++f; + } + }else{ + previousFace = dynamic_cast<WXFace*>(iFaceLayer.fl->getFace()->GetBordingFace(woebegin)); + if(0 == previousFace) + return OWXFaceLayer(0,true); + + // if the next face layer has either no smooth edge or + // no smooth edge of same nature, no next face + if(!previousFace->hasSmoothEdges()) + return OWXFaceLayer(0,true); + vector<WXFaceLayer*> sameNatureLayers; + previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers); + if((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) // don't know how to deal with several edges of same nature on a single face + return OWXFaceLayer(0,true); + else{ + WXFaceLayer * winner = sameNatureLayers[0]; + if(woebegin == winner->getSmoothEdge()->woeb()->twin()) + return OWXFaceLayer(winner,true); + else + return OWXFaceLayer(winner,false); + } + } + return OWXFaceLayer(0,true); +} + +FEdge * ViewEdgeXBuilder::BuildSmoothFEdge(FEdge *feprevious, const OWXFaceLayer& ifl){ + SVertex *va, *vb; + FEdgeSmooth *fe; + // retrieve exact silhouette data + WXSmoothEdge *se = ifl.fl->getSmoothEdge(); + + Vec3r normal; + // Make the 2 Svertices + if(feprevious == 0){ // that means that we don't have any vertex already built for that face + real ta = se->ta(); + Vec3r A1(se->woea()->GetaVertex()->GetVertex()); + Vec3r A2(se->woea()->GetbVertex()->GetVertex()); + Vec3r A(A1+ta*(A2-A1)); + + va = MakeSVertex(A); + // Set normal: + Vec3r NA1(ifl.fl->getFace()->GetVertexNormal(se->woea()->GetaVertex())); + Vec3r NA2(ifl.fl->getFace()->GetVertexNormal(se->woea()->GetbVertex())); + Vec3r na((1 - ta) * NA1 + ta * NA2); + na.normalize(); + va->AddNormal(na); + normal = na; + + // Set CurvatureInfo + CurvatureInfo* curvature_info_a = new CurvatureInfo(*(dynamic_cast<WXVertex*>(se->woea()->GetaVertex())->curvatures()), + *(dynamic_cast<WXVertex*>(se->woea()->GetbVertex())->curvatures()), + ta); + va->setCurvatureInfo(curvature_info_a); + } + else + va = feprevious->vertexB(); + + real tb = se->tb(); + Vec3r B1(se->woeb()->GetaVertex()->GetVertex()); + Vec3r B2(se->woeb()->GetbVertex()->GetVertex()); + Vec3r B(B1+tb*(B2-B1)); + + vb = MakeSVertex(B); + // Set normal: + Vec3r NB1(ifl.fl->getFace()->GetVertexNormal(se->woeb()->GetaVertex())); + Vec3r NB2(ifl.fl->getFace()->GetVertexNormal(se->woeb()->GetbVertex())); + Vec3r nb((1 - tb) * NB1 + tb * NB2); + nb.normalize(); + normal += nb; + vb->AddNormal(nb); + + // Set CurvatureInfo + CurvatureInfo* curvature_info_b = new CurvatureInfo(*(dynamic_cast<WXVertex*>(se->woeb()->GetaVertex())->curvatures()), + *(dynamic_cast<WXVertex*>(se->woeb()->GetbVertex())->curvatures()), + tb); + vb->setCurvatureInfo(curvature_info_b); + + // if the order is false we must swap va and vb + if(!ifl.order){ + SVertex *tmp = va; + va = vb; + vb = tmp; + } + + // Creates the corresponding feature edge + fe = new FEdgeSmooth(va, vb); + fe->setNature(ifl.fl->nature()); + fe->setId(_currentFId); + fe->setFrsMaterialIndex(ifl.fl->getFace()->frs_materialIndex()); + fe->setFace(ifl.fl->getFace()); + fe->setNormal(normal); + fe->setPreviousEdge(feprevious); + if(feprevious) + feprevious->setNextEdge(fe); + _pCurrentSShape->AddEdge(fe); + va->AddFEdge(fe); + vb->AddFEdge(fe); + + ++_currentFId; + ifl.fl->userdata = fe; + return fe; +} + +bool ViewEdgeXBuilder::stopSmoothViewEdge(WXFaceLayer *iFaceLayer){ + if(0 == iFaceLayer) + return true; + if(iFaceLayer->userdata == 0) + return false; + return true; +} + +OWXEdge ViewEdgeXBuilder::FindNextWEdge(const OWXEdge& iEdge){ + if(Nature::NO_FEATURE == iEdge.e->nature()) + return OWXEdge(0, true); + + WVertex *v; + if(true == iEdge.order) + v = iEdge.e->GetbVertex(); + else + v = iEdge.e->GetaVertex(); + + if(((WXVertex*)v)->isFeature()) + return 0; + + + vector<WEdge*>& vEdges = (v)->GetEdges(); + for(vector<WEdge*>::iterator ve=vEdges.begin(),veend=vEdges.end(); + ve!=veend; + ve++){ + WXEdge *wxe = dynamic_cast<WXEdge*>(*ve); + if(wxe == iEdge.e) + continue; // same edge as the one processed + + if(wxe->nature() != iEdge.e->nature()) + continue; + + if(wxe->GetaVertex() == v){ + // That means that the face necesarily lies on the edge left. + // So the vertex order is OK. + return OWXEdge(wxe, true); + }else{ + // That means that the face necesarily lies on the edge left. + // So the vertex order is OK. + return OWXEdge(wxe, false); + } + } + // we did not find: + return OWXEdge(0, true); +} + +OWXEdge ViewEdgeXBuilder::FindPreviousWEdge(const OWXEdge& iEdge){ + if(Nature::NO_FEATURE == iEdge.e->nature()) + return OWXEdge(0, true); + + WVertex *v; + if(true == iEdge.order) + v = iEdge.e->GetaVertex(); + else + v = iEdge.e->GetbVertex(); + + if(((WXVertex*)v)->isFeature()) + return 0; + + + vector<WEdge*>& vEdges = (v)->GetEdges(); + for(vector<WEdge*>::iterator ve=vEdges.begin(),veend=vEdges.end(); + ve!=veend; + ve++){ + WXEdge *wxe = dynamic_cast<WXEdge*>(*ve); + if(wxe == iEdge.e) + continue; // same edge as the one processed + + if(wxe->nature() != iEdge.e->nature()) + continue; + + if(wxe->GetbVertex() == v){ + return OWXEdge(wxe, true); + }else{ + return OWXEdge(wxe, false); + } + } + // we did not find: + return OWXEdge(0, true); +} + +FEdge * ViewEdgeXBuilder::BuildSharpFEdge(FEdge *feprevious, const OWXEdge& iwe){ + SVertex *va, *vb; + FEdgeSharp *fe; + WXVertex *wxVA, *wxVB; + if(iwe.order){ + wxVA = (WXVertex*)iwe.e->GetaVertex(); + wxVB = (WXVertex*)iwe.e->GetbVertex(); + }else{ + wxVA = (WXVertex*)iwe.e->GetbVertex(); + wxVB = (WXVertex*)iwe.e->GetaVertex(); + } + // Make the 2 SVertex + va = MakeSVertex(wxVA->GetVertex()); + vb = MakeSVertex(wxVB->GetVertex()); + + // get the faces normals and the material indices + Vec3r normalA, normalB; + unsigned matA(0), matB(0); + if(iwe.order){ + normalB = (iwe.e->GetbFace()->GetNormal()); + matB = (iwe.e->GetbFace()->frs_materialIndex()); + if(!(iwe.e->nature() & Nature::BORDER)) { + normalA = (iwe.e->GetaFace()->GetNormal()); + matA = (iwe.e->GetaFace()->frs_materialIndex()); + } + }else{ + normalA = (iwe.e->GetbFace()->GetNormal()); + matA = (iwe.e->GetbFace()->frs_materialIndex()); + if(!(iwe.e->nature() & Nature::BORDER)) { + normalB = (iwe.e->GetaFace()->GetNormal()); + matB = (iwe.e->GetaFace()->frs_materialIndex()); + } + } + // Creates the corresponding feature edge + // Creates the corresponding feature edge + fe = new FEdgeSharp(va, vb); + fe->setNature(iwe.e->nature()); + fe->setId(_currentFId); + fe->setaFrsMaterialIndex(matA); + fe->setbFrsMaterialIndex(matB); + fe->setNormalA(normalA); + fe->setNormalB(normalB); + fe->setPreviousEdge(feprevious); + if(feprevious) + feprevious->setNextEdge(fe); + _pCurrentSShape->AddEdge(fe); + va->AddFEdge(fe); + vb->AddFEdge(fe); + //Add normals: + va->AddNormal(normalA); + va->AddNormal(normalB); + vb->AddNormal(normalA); + vb->AddNormal(normalB); + + ++_currentFId; + iwe.e->userdata = fe; + return fe; +} + +bool ViewEdgeXBuilder::stopSharpViewEdge(WXEdge *iEdge){ + if(0 == iEdge) + return true; + if(iEdge->userdata == 0) + return false; + return true; +} + +SVertex * ViewEdgeXBuilder::MakeSVertex(Vec3r& iPoint){ + SVertex *va; + // Check whether the vertices are already in the table: + // fisrt vertex + // ------------- + SVertexMap::const_iterator found = _SVertexMap.find(iPoint); + if (found != _SVertexMap.end()) { + va = (*found).second; + }else{ + va = new SVertex(iPoint, _currentSVertexId); + SilhouetteGeomEngine::ProjectSilhouette(va); + ++_currentSVertexId; + // Add the svertex to the SShape svertex list: + _pCurrentSShape->AddNewVertex(va); + // Add the svertex in the table using its id: + _SVertexMap[iPoint] = va; + } + return va; +} + +ViewVertex * ViewEdgeXBuilder::MakeViewVertex(SVertex *iSVertex){ + ViewVertex *vva = iSVertex->viewvertex(); + if(vva != 0) + return vva; + vva = new NonTVertex(iSVertex); + // Add the view vertex to the ViewShape svertex list: + _pCurrentVShape->AddVertex(vva); + return vva; +} + diff --git a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h new file mode 100755 index 00000000000..28a5d7d9dd4 --- /dev/null +++ b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h @@ -0,0 +1,215 @@ +// +// Filename : ViewEdgeXBuilder.h +// Author(s) : Stephane Grabli +// Purpose : Class to build view edges and the underlying chains +// of feature edges... +// Date of creation : 27/10/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef VIEWEDGEXBUILDER_H +# define VIEWEDGEXBUILDER_H + +# include <map> +# include <utility> +# include <vector> + +// soc +// # if defined(__GNUC__) && (__GNUC__ >= 3) +// //hash_map is not part of the C++ standard anymore; hash_map.h has been kept though for backward compatibility +// # include <hash_map.h> +// # else +// # include <hash_map> +// # endif + +# include "../system/FreestyleConfig.h" +# include "../geometry/Geom.h" +# include "Interface1D.h" + +using namespace Geometry; +using namespace std; + +class SVertex; +/*! Defines a hash table used for searching the SVertex */ +struct SVertexHasher { +#define _MUL 950706376UL +#define _MOD 2147483647UL + inline size_t operator() (const Vec3r& p) const { + size_t res = ((unsigned long) (p[0] * _MUL)) % _MOD; + res = ((res + (unsigned long) (p[1]) * _MUL)) % _MOD; + return ((res +(unsigned long) (p[2]) * _MUL)) % _MOD; + } +}; + +// Key_compare predicate for hash_map. In particular, return false if equal. +struct epsilonEquals{ + bool operator()(const Vec3r& v1, const Vec3r& v2) const{ + real norm = (v1-v2).norm(); + return (norm<1e-06); + } +}; + + +// typedef hash_map<Vec3r, SVertex*, SVertexHasher, epsilonEquals> SVertexMap; +typedef map<Vec3r , SVertex*> SVertexMap; + +class WXFaceLayer; +/*! class to describe an oriented smooth edge */ +class OWXFaceLayer{ +public: + WXFaceLayer * fl; + bool order; + + OWXFaceLayer() {fl=0;order=true;} + OWXFaceLayer(WXFaceLayer *ifl, bool iOrder=true){fl = ifl;order=iOrder;} + OWXFaceLayer& operator=(const OWXFaceLayer& iBrother){ + fl = iBrother.fl; + order = iBrother.order; + return *this; + } + bool operator==(const OWXFaceLayer& b){ + return ((fl == b.fl) && (order == b.order)); + } + bool operator!=(const OWXFaceLayer& b){ + return !(*this==b); + } +}; + +class WXEdge; +/*! class to describe an oriented sharp edge */ +class OWXEdge{ +public: + WXEdge * e; + bool order; + + OWXEdge() {e=0;order=true;} + OWXEdge(WXEdge *ie, bool iOrder=true){e = ie;order=iOrder;} + OWXEdge& operator=(const OWXEdge& iBrother){ + e = iBrother.e; + order = iBrother.order; + return *this; + } + bool operator==(const OWXEdge& b){ + return ((e == b.e) && (order == b.order)); + } + bool operator!=(const OWXEdge& b){ + return !(*this==b); + } +}; + +class WOEdge; +class WXEdge; +class WXShape; +class SVertex; +class FEdge; +class ViewVertex; +class ViewEdge; +class ViewShape; +class LIB_VIEW_MAP_EXPORT ViewEdgeXBuilder +{ +protected: + int _currentViewId; // Id for view edges + int _currentFId; // Id for FEdges + int _currentSVertexId; // Id for SVertex +public: + + inline ViewEdgeXBuilder() + {_currentViewId = 1;_currentFId=0;_currentSVertexId=0;} + virtual ~ViewEdgeXBuilder(){} + + /*! Builds a view shape from a WXShape in which the feature edges + * are flagged + * Builds chains of feature edges (so ViewEdges) from a WXShape + * iWShape + * The Winged Edge structure in which all silhouette edges + * and vertices are flagged. + * oViewShape + * The Silhouette Shape in which the chains must be added. + * ioVEdges + * The list of new ViewEdges. + * ioVVertices + * THe new ViewVertices + * ioFEdges + * A list in which all new FEdges are added + * ioSVertices + * A list of SVertex where all created SVertex are added. + */ + virtual void BuildViewEdges(WXShape *iWShape, ViewShape *oVShape, + std::vector<ViewEdge*>& ioVEdges, + std::vector<ViewVertex*>& ioVVertices, + std::vector<FEdge*>& ioFEdges, + std::vector<SVertex*>& ioSVertices) ; + + /*! Builds a smooth view edge, starting the face iFace.*/ + ViewEdge * BuildSmoothViewEdge(const OWXFaceLayer& iFaceLayer); + + /*! Makes a sharp viewedge + */ + ViewEdge * BuildSharpViewEdge(const OWXEdge& iWEdge) ; + + +public: + /*! accessors */ + inline int currentViewId() const { return _currentViewId; } + inline int currentFId() const { return _currentFId; } + inline int currentSVertexId() const { return _currentSVertexId; } + /*! modifiers */ + inline void setCurrentViewId(int id) { _currentViewId = id; } + inline void setCurrentFId(int id) { _currentFId = id; } + inline void setCurrentSVertexId(int id) { _currentSVertexId = id; } + +protected: + /*! Init the view edges building */ + virtual void Init(ViewShape *oVShape) ; + + // SMOOTH // + /*! checks whether a face has already been processed or not */ + bool stopSmoothViewEdge(WXFaceLayer *iFaceLayer); + OWXFaceLayer FindNextFaceLayer(const OWXFaceLayer& iFaceLayer); + OWXFaceLayer FindPreviousFaceLayer(const OWXFaceLayer& iFaceLayer); + FEdge * BuildSmoothFEdge(FEdge *feprevious, const OWXFaceLayer& ifl); + + // SHARP // + /*! checks whether a WEdge has already been processed or not */ + bool stopSharpViewEdge(WXEdge *iFace); + OWXEdge FindNextWEdge(const OWXEdge& iEdge); + OWXEdge FindPreviousWEdge(const OWXEdge& iEdge); + FEdge * BuildSharpFEdge(FEdge *feprevious, const OWXEdge& iwe); + + // GENERAL // + /*! Instanciate a SVertex if it hasn't been already created */ + SVertex * MakeSVertex(Vec3r& iPoint); + /*! instanciate a ViewVertex from a SVertex, if it doesn't exist yet */ + ViewVertex * MakeViewVertex(SVertex *iSVertex); + + //oldtmp values + // IdHashTable _hashtable; + // VVIdHashTable _multivertexHashTable; + SVertexMap _SVertexMap; + SShape *_pCurrentSShape; + ViewShape * _pCurrentVShape; +}; + +#endif + diff --git a/source/blender/freestyle/intern/view_map/ViewMap.cpp b/source/blender/freestyle/intern/view_map/ViewMap.cpp new file mode 100755 index 00000000000..87624669204 --- /dev/null +++ b/source/blender/freestyle/intern/view_map/ViewMap.cpp @@ -0,0 +1,703 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "ViewMap.h" +#include "../geometry/GeomUtils.h" +#include <float.h> +#include "ViewMapIterators.h" +#include "ViewMapAdvancedIterators.h" + + /**********************************/ + /* */ + /* */ + /* ViewMap */ + /* */ + /* */ + /**********************************/ + +ViewMap * ViewMap::_pInstance = 0; + +ViewMap::~ViewMap() +{ + // The view vertices must be deleted here as some of them + // are shared between two shapes: + for(vector<ViewVertex*>::iterator vv=_VVertices.begin(), vvend=_VVertices.end(); + vv!=vvend; + vv++) + { + delete (*vv); + } + _VVertices.clear(); + + for(vector<ViewShape*>::iterator vs=_VShapes.begin(),vsend=_VShapes.end(); + vs!=vsend; + vs++) + { + delete (*vs); + } + _VShapes.clear(); + + _FEdges.clear(); + _SVertices.clear(); + _VEdges.clear(); +} + +ViewShape * ViewMap::viewShape(unsigned id) +{ + int index = _shapeIdToIndex[id]; + return _VShapes[ index ]; +} +void ViewMap::AddViewShape(ViewShape *iVShape) { + _shapeIdToIndex[iVShape->getId().getFirst()] = _VShapes.size(); + _VShapes.push_back(iVShape); +} +const FEdge * ViewMap::getClosestFEdge(real x, real y) const +{ + // find the closest of this candidates: + real minDist = DBL_MAX; + FEdge * winner = 0; + for(fedges_container::const_iterator fe=_FEdges.begin(),feend=_FEdges.end(); + fe!=feend; + fe++) + { + Vec2d A((*fe)->vertexA()->point2D()[0], (*fe)->vertexA()->point2D()[1]); + Vec2d B((*fe)->vertexB()->point2D()[0], (*fe)->vertexB()->point2D()[1]); + real dist = GeomUtils::distPointSegment<Vec2r>(Vec2r(x,y),A, B); + if(dist < minDist) + { + minDist = dist; + winner = (*fe); + } + + } + if(winner==0) + return 0; + + return winner; +} + +const ViewEdge * ViewMap::getClosestViewEdge(real x, real y) const +{ + // find the closest of this candidates: + real minDist = DBL_MAX; + FEdge * winner = 0; + for(fedges_container::const_iterator fe=_FEdges.begin(),feend=_FEdges.end(); + fe!=feend; + fe++) + { + Vec2d A((*fe)->vertexA()->point2D()[0], (*fe)->vertexA()->point2D()[1]); + Vec2d B((*fe)->vertexB()->point2D()[0], (*fe)->vertexB()->point2D()[1]); + real dist = GeomUtils::distPointSegment<Vec2r>(Vec2r(x,y),A, B); + if(dist < minDist) + { + minDist = dist; + winner = (*fe); + } + + } + if(winner==0) + return 0; + + return winner->viewedge(); +} + + +TVertex* ViewMap::CreateTVertex(const Vec3r& iA3D, const Vec3r& iA2D, FEdge *iFEdgeA, + const Vec3r& iB3D, const Vec3r& iB2D, FEdge *iFEdgeB, + const Id& id) +{ + ViewShape *vshapeA = iFEdgeA->viewedge()->viewShape(); + SShape *shapeA = iFEdgeA->shape(); + ViewShape *vshapeB = iFEdgeB->viewedge()->viewShape(); + SShape *shapeB = iFEdgeB->shape(); + + SVertex * Ia = shapeA->CreateSVertex(iA3D, iA2D, iFEdgeA->vertexA()->getId()); + SVertex * Ib = shapeB->CreateSVertex(iB3D, iB2D, iFEdgeB->vertexA()->getId()); + + // depending on which of these 2 svertices is the nearest from the + // viewpoint, we're going to build the TVertex by giving them in + // an order or another (the first one must be the nearest) + real dista = Ia->point2D()[2]; + real distb = Ib->point2D()[2]; + + TVertex * tvertex; + if(dista < distb) + tvertex = new TVertex(Ia, Ib); + else + tvertex = new TVertex(Ib,Ia); + + tvertex->setId(id); + + // add these vertices to the view map + AddViewVertex(tvertex); + AddSVertex(Ia); + AddSVertex(Ib); + + // and this T Vertex to the view shapes: + vshapeA->AddVertex(tvertex); + vshapeB->AddVertex(tvertex); + + return tvertex; +} + +ViewVertex * ViewMap::InsertViewVertex(SVertex *iVertex, + vector<ViewEdge*>& newViewEdges){ + NonTVertex *vva = dynamic_cast<NonTVertex*>(iVertex->viewvertex()); + if(vva != 0) + return vva; + // beacuse it is not already a ViewVertex, this SVertex must have only + // 2 FEdges. The incoming one still belongs to ioEdge, the outgoing one + // now belongs to newVEdge + const vector<FEdge*>& fedges = iVertex->fedges(); + if(fedges.size()!=2){ + cerr << "ViewMap warning: Can't split the ViewEdge" << endl; + return 0; + } + FEdge * fend(0), * fbegin(0); + for(vector<FEdge*>::const_iterator fe=fedges.begin(), feend=fedges.end(); + fe!=feend; + ++fe){ + if((*fe)->vertexB() == iVertex){ + fend = (*fe); + } + if((*fe)->vertexA() == iVertex){ + fbegin = (*fe); + } + if((fbegin!=0) && (fend!=0)) + break; + } + ViewEdge *ioEdge = fbegin->viewedge(); + ViewShape * vshape = ioEdge->viewShape(); + vva = new NonTVertex(iVertex); + // if the ViewEdge is a closed loop, we don't create + // a new VEdge + if(ioEdge->A() == 0){ + // closed loop + ioEdge->setA(vva); + ioEdge->setB(vva); + // update sshape + vshape->sshape()->RemoveEdgeFromChain(ioEdge->fedgeA()); + vshape->sshape()->RemoveEdgeFromChain(ioEdge->fedgeB()); + + ioEdge->setFEdgeA(fbegin); + ioEdge->setFEdgeB(fend); + + // Update FEdges + fend->setNextEdge(0); + fbegin->setPreviousEdge(0); + + // update new View Vertex: + vva->AddOutgoingViewEdge(ioEdge); + vva->AddIncomingViewEdge(ioEdge); + + vshape->sshape()->AddChain(ioEdge->fedgeA()); + vshape->sshape()->AddChain(ioEdge->fedgeB()); + }else{ + // Create new ViewEdge + ViewEdge * newVEdge = new ViewEdge(vva, ioEdge->B(), fbegin, ioEdge->fedgeB(), vshape); + newVEdge->setId(Id(ioEdge->getId().getFirst(), ioEdge->getId().getSecond()+1)); + newVEdge->setNature(ioEdge->getNature()); + //newVEdge->UpdateFEdges(); // done in the ViewEdge constructor + // Update old ViewEdge + ioEdge->setB(vva); + ioEdge->setFEdgeB(fend); + + // Update FEdges + fend->setNextEdge(0); + fbegin->setPreviousEdge(0); + + // update new View Vertex: + vva->AddOutgoingViewEdge(newVEdge); + vva->AddIncomingViewEdge(ioEdge); + // update ViewShape + //vshape->AddEdge(newVEdge); + // update SShape + vshape->sshape()->AddChain(fbegin); + // update ViewMap + //_VEdges.push_back(newVEdge); + newViewEdges.push_back(newVEdge); + } + + // update ViewShape + vshape->AddVertex(vva); + + // update ViewMap + _VVertices.push_back(vva); + + return vva; +} + +//FEdge * ViewMap::Connect(FEdge *ioEdge, SVertex *ioVertex, vector<ViewEdge*>& oNewVEdges){ +// SShape * sshape = ioEdge->shape(); +// FEdge *newFEdge = sshape->SplitEdgeIn2(ioEdge, ioVertex); +// AddFEdge(newFEdge); +// InsertViewVertex(ioVertex, oNewVEdges); +// return newFEdge; +//} + + /**********************************/ + /* */ + /* */ + /* TVertex */ + /* */ + /* */ + /**********************************/ + +// is dve1 before dve2 ? (does it have a smaller angle ?) +bool ViewEdgeComp(ViewVertex::directedViewEdge& dve1, ViewVertex::directedViewEdge& dve2){ + FEdge *fe1; + if(dve1.second) + fe1 = dve1.first->fedgeB(); + else + fe1 = dve1.first->fedgeA(); + FEdge *fe2; + if(dve2.second) + fe2 = dve2.first->fedgeB(); + else + fe2 = dve2.first->fedgeA(); + + Vec3r V1 = fe1->orientation2d(); + Vec2r v1(V1.x(), V1.y());v1.normalize(); + Vec3r V2 = fe2->orientation2d(); + Vec2r v2(V2.x(), V2.y());v2.normalize(); + if(v1.y() > 0){ + if(v2.y() < 0) + return true; + else + return (v1.x() > v2.x()); + }else{ + if(v2.y() > 0) + return false; + else + return (v1.x() < v2.x()); + } + return false; +} +void TVertex::setFrontEdgeA(ViewEdge *iFrontEdgeA, bool incoming) { + if (!iFrontEdgeA) { + cerr << "Warning: null pointer passed as argument of TVertex::setFrontEdgeA()" << endl; + return; + } + _FrontEdgeA = directedViewEdge(iFrontEdgeA, incoming); + if(!_sortedEdges.empty()){ + edge_pointers_container::iterator dve = _sortedEdges.begin(), dveend = _sortedEdges.end(); + while((dve!=dveend) && ViewEdgeComp(**dve, _FrontEdgeA)){ + ++dve; + } + _sortedEdges.insert( dve, &_FrontEdgeA); + } + else + _sortedEdges.push_back(&_FrontEdgeA); +} +void TVertex::setFrontEdgeB(ViewEdge *iFrontEdgeB, bool incoming) { + if (!iFrontEdgeB) { + cerr << "Warning: null pointer passed as argument of TVertex::setFrontEdgeB()" << endl; + return; + } + _FrontEdgeB = directedViewEdge(iFrontEdgeB, incoming); + if(!_sortedEdges.empty()){ + edge_pointers_container::iterator dve = _sortedEdges.begin(), dveend = _sortedEdges.end(); + while((dve!=dveend) && ViewEdgeComp(**dve, _FrontEdgeB)){ + ++dve; + } + _sortedEdges.insert(dve, &_FrontEdgeB); + } + else + _sortedEdges.push_back(&_FrontEdgeB); +} +void TVertex::setBackEdgeA(ViewEdge *iBackEdgeA, bool incoming) { + if (!iBackEdgeA) { + cerr << "Warning: null pointer passed as argument of TVertex::setBackEdgeA()" << endl; + return; + } + _BackEdgeA = directedViewEdge(iBackEdgeA, incoming); + if(!_sortedEdges.empty()){ + edge_pointers_container::iterator dve = _sortedEdges.begin(), dveend = _sortedEdges.end(); + while((dve!=dveend) && ViewEdgeComp(**dve, _BackEdgeA)){ + ++dve; + } + _sortedEdges.insert(dve, &_BackEdgeA); + } + else + _sortedEdges.push_back(&_BackEdgeA); +} +void TVertex::setBackEdgeB(ViewEdge *iBackEdgeB, bool incoming) { + if (!iBackEdgeB) { + cerr << "Warning: null pointer passed as argument of TVertex::setBackEdgeB()" << endl; + return; + } + _BackEdgeB = directedViewEdge(iBackEdgeB, incoming); + if(!_sortedEdges.empty()){ + edge_pointers_container::iterator dve = _sortedEdges.begin(), dveend = _sortedEdges.end(); + while((dve!=dveend) && ViewEdgeComp(**dve, _BackEdgeB)){ + ++dve; + } + _sortedEdges.insert(dve, &_BackEdgeB); + } + else + _sortedEdges.push_back(&_BackEdgeB); +} +void TVertex::Replace(ViewEdge *iOld, ViewEdge *iNew) +{ + // theoritically, we only replace edges for which this + // view vertex is the B vertex + if((iOld == _FrontEdgeA.first) && (_FrontEdgeA.first->B() == this)) + { + _FrontEdgeA.first = iNew; + return; + } + if((iOld == _FrontEdgeB.first) && (_FrontEdgeB.first->B() == this)) + { + _FrontEdgeB.first = iNew; + return; + } + if((iOld == _BackEdgeA.first) && (_BackEdgeA.first->B() == this)) + { + _BackEdgeA.first = iNew; + return; + } + if((iOld == _BackEdgeB.first) && (_BackEdgeB.first->B() == this)) + { + _BackEdgeB.first = iNew; + return; + } +} + +/*! iterators access */ +ViewVertex::edge_iterator TVertex::edges_begin() +{ + //return edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, _FrontEdgeA); + return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin()); +} +ViewVertex::const_edge_iterator TVertex::edges_begin() const +{ + //return const_edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, _FrontEdgeA); + return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin()); +} +ViewVertex::edge_iterator TVertex::edges_end() +{ + //return edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, directedViewEdge(0,true)); + return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.end()); +} +ViewVertex::const_edge_iterator TVertex::edges_end() const +{ + //return const_edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, directedViewEdge(0, true)); + return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.end()); +} +ViewVertex::edge_iterator TVertex::edges_iterator(ViewEdge *iEdge) +{ + for(edge_pointers_container::iterator it=_sortedEdges.begin(), itend=_sortedEdges.end(); + it!=itend; + it++) + { + if((*it)->first == iEdge) + return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), it); + } + return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin()); + + // directedViewEdge dEdge; + // if(_FrontEdgeA.first == iEdge) + // dEdge = _FrontEdgeA; + // else if(_FrontEdgeB.first == iEdge) + // dEdge = _FrontEdgeB; + // else if(_BackEdgeA.first == iEdge) + // dEdge = _BackEdgeA; + // else if(_BackEdgeB.first == iEdge) + // dEdge = _BackEdgeB; + // return edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, dEdge); +} +ViewVertex::const_edge_iterator TVertex::edges_iterator(ViewEdge *iEdge) const +{ + for(edge_pointers_container::const_iterator it=_sortedEdges.begin(), itend=_sortedEdges.end(); + it!=itend; + it++) + { + if((*it)->first == iEdge) + return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), it); + } + return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin()); + + // directedViewEdge dEdge; + // if(_FrontEdgeA.first == iEdge) + // dEdge = _FrontEdgeA; + // else if(_FrontEdgeB.first == iEdge) + // dEdge = _FrontEdgeB; + // else if(_BackEdgeA.first == iEdge) + // dEdge = _BackEdgeA; + // else if(_BackEdgeB.first == iEdge) + // dEdge = _BackEdgeB; + // return const_edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, dEdge); +} + +ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesBegin() { + return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin()); +} +ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesEnd() { + return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.end()); +} +ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesIterator(ViewEdge *iEdge) { + for(edge_pointers_container::iterator it=_sortedEdges.begin(), itend=_sortedEdges.end(); + it!=itend; + it++) + { + if((*it)->first == iEdge) + return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), it); + } + return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin()); +} + /**********************************/ + /* */ + /* */ + /* NonTVertex */ + /* */ + /* */ + /**********************************/ + +void NonTVertex::AddOutgoingViewEdge(ViewEdge * iVEdge){ + // let's keep the viewedges ordered in CCW order + // in the 2D image plan + directedViewEdge idve(iVEdge, false); + if(!_ViewEdges.empty()){ + edges_container::iterator dve = _ViewEdges.begin(), dveend = _ViewEdges.end(); + while((dve!=dveend) && ViewEdgeComp(*dve, idve)){ + ++dve; + } + _ViewEdges.insert(dve, idve); + } + else + _ViewEdges.push_back(idve); +} + +void NonTVertex::AddIncomingViewEdge(ViewEdge * iVEdge){ + // let's keep the viewedges ordered in CCW order + // in the 2D image plan + directedViewEdge idve(iVEdge, true); + if(!_ViewEdges.empty()){ + edges_container::iterator dve = _ViewEdges.begin(), dveend = _ViewEdges.end(); + while((dve!=dveend) && ViewEdgeComp(*dve, idve)){ + ++dve; + } + _ViewEdges.insert(dve, idve); + } + else + _ViewEdges.push_back(idve); +} + +/*! iterators access */ +ViewVertex::edge_iterator NonTVertex::edges_begin() +{ + return edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin()); +} +ViewVertex::const_edge_iterator NonTVertex::edges_begin() const +{ + return const_edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin()); +} +ViewVertex::edge_iterator NonTVertex::edges_end() +{ + return edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.end()); +} +ViewVertex::const_edge_iterator NonTVertex::edges_end() const +{ + return const_edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.end()); +} +ViewVertex::edge_iterator NonTVertex::edges_iterator(ViewEdge *iEdge) +{ + for(edges_container::iterator it=_ViewEdges.begin(), itend=_ViewEdges.end(); + it!=itend; + it++) + { + if((it)->first == iEdge) + return edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), it); + } + return edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin()); +} +ViewVertex::const_edge_iterator NonTVertex::edges_iterator(ViewEdge *iEdge) const +{ + for(edges_container::const_iterator it=_ViewEdges.begin(), itend=_ViewEdges.end(); + it!=itend; + it++) + { + if((it)->first == iEdge) + return const_edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), it); + } + return const_edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin()); +} + +ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesBegin() { + return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin()); +} +ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesEnd() { + return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.end()); +} +ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesIterator(ViewEdge *iEdge) { + for(edges_container::iterator it=_ViewEdges.begin(), itend=_ViewEdges.end(); + it!=itend; + it++) + { + if((it)->first == iEdge) + return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), it); + } + return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin()); +} + /**********************************/ + /* */ + /* */ + /* ViewEdge */ + /* */ + /* */ + /**********************************/ + +real ViewEdge::getLength2D() const +{ + float length = 0.f; + ViewEdge::const_fedge_iterator itlast = fedge_iterator_last(); + ViewEdge::const_fedge_iterator it = fedge_iterator_begin(), itend=fedge_iterator_end(); + Vec2r seg; + do{ + seg = Vec2r((*it)->orientation2d()[0], (*it)->orientation2d()[1]); + length += seg.norm(); + ++it; + }while((it!=itend) && (it!=itlast)); + return length; +} + + +//! view edge iterator +ViewEdge::edge_iterator ViewEdge::ViewEdge_iterator() {return edge_iterator(this);} +ViewEdge::const_edge_iterator ViewEdge::ViewEdge_iterator() const {return const_edge_iterator((ViewEdge*)this);} +//! feature edge iterator +ViewEdge::fedge_iterator ViewEdge::fedge_iterator_begin() {return fedge_iterator(this->_FEdgeA, this->_FEdgeB);} +ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_begin() const {return const_fedge_iterator(this->_FEdgeA, this->_FEdgeB);} +ViewEdge::fedge_iterator ViewEdge::fedge_iterator_last() {return fedge_iterator(this->_FEdgeB, this->_FEdgeB);} +ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_last() const {return const_fedge_iterator(this->_FEdgeB, this->_FEdgeB);} +ViewEdge::fedge_iterator ViewEdge::fedge_iterator_end() {return fedge_iterator(0, this->_FEdgeB);} +ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_end() const {return const_fedge_iterator(0, this->_FEdgeB);} +//! embedding vertex iterator +ViewEdge::const_vertex_iterator ViewEdge::vertices_begin() const {return const_vertex_iterator(this->_FEdgeA->vertexA(), 0, _FEdgeA);} +ViewEdge::vertex_iterator ViewEdge::vertices_begin() {return vertex_iterator(this->_FEdgeA->vertexA(), 0, _FEdgeA);} +ViewEdge::const_vertex_iterator ViewEdge::vertices_last() const {return const_vertex_iterator(this->_FEdgeB->vertexB(), _FEdgeB, 0);} +ViewEdge::vertex_iterator ViewEdge::vertices_last() {return vertex_iterator(this->_FEdgeB->vertexB(), _FEdgeB, 0);} +ViewEdge::const_vertex_iterator ViewEdge::vertices_end() const {return const_vertex_iterator(0, _FEdgeB, 0);} +ViewEdge::vertex_iterator ViewEdge::vertices_end() {return vertex_iterator(0, _FEdgeB, 0);} + + +Interface0DIterator ViewEdge::verticesBegin() { + Interface0DIterator ret(new ViewEdgeInternal::SVertexIterator(this->_FEdgeA->vertexA(), this->_FEdgeA->vertexA(), 0, _FEdgeA, 0.f)); + return ret; +} + +Interface0DIterator ViewEdge::verticesEnd() { + Interface0DIterator ret(new ViewEdgeInternal::SVertexIterator(0, this->_FEdgeA->vertexA(), _FEdgeB, 0, getLength2D())); + return ret; +} + +Interface0DIterator ViewEdge::pointsBegin(float t) { + return verticesBegin(); +} + +Interface0DIterator ViewEdge::pointsEnd(float t) { + return verticesEnd(); +} + + + + /**********************************/ + /* */ + /* */ + /* ViewShape */ + /* */ + /* */ + /**********************************/ + + +ViewShape::~ViewShape() +{ + _Vertices.clear(); + + if(!(_Edges.empty())) + { + for(vector<ViewEdge*>::iterator e=_Edges.begin(), eend=_Edges.end(); + e!=eend; + e++) + { + delete (*e); + } + _Edges.clear(); + } + + if(0 != _SShape) + { + delete _SShape; + _SShape = 0; + } +} + +void ViewShape::RemoveEdge(ViewEdge * iViewEdge) +{ + FEdge * fedge = iViewEdge->fedgeA(); + for(vector<ViewEdge*>::iterator ve=_Edges.begin(),veend=_Edges.end(); + ve!=veend; + ve++) + { + if(iViewEdge == (*ve)) + { + _Edges.erase(ve); + _SShape->RemoveEdge(fedge); + break; + } + } +} + +void ViewShape::RemoveVertex(ViewVertex * iViewVertex) +{ + for(vector<ViewVertex*>::iterator vv=_Vertices.begin(), vvend=_Vertices.end(); + vv!=vvend; + vv++) + { + if(iViewVertex == (*vv)) + { + _Vertices.erase(vv); + break; + } + } +} + + /**********************************/ + /* */ + /* */ + /* ViewEdge */ + /* */ + /* */ + /**********************************/ + + +void ViewEdge::UpdateFEdges() +{ + FEdge *currentEdge = _FEdgeA; + do + { + currentEdge->setViewEdge(this); + currentEdge = currentEdge->nextEdge(); + }while((currentEdge != NULL) && (currentEdge!= _FEdgeB)); + // last one + _FEdgeB->setViewEdge(this); + +} diff --git a/source/blender/freestyle/intern/view_map/ViewMap.h b/source/blender/freestyle/intern/view_map/ViewMap.h new file mode 100755 index 00000000000..623348b61a7 --- /dev/null +++ b/source/blender/freestyle/intern/view_map/ViewMap.h @@ -0,0 +1,1494 @@ +// +// Filename : ViewMap.h +// Author(s) : Stephane Grabli +// Purpose : Classes to define a View Map (ViewVertex, ViewEdge, etc.) +// Date of creation : 03/09/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef VIEWMAP_H +# define VIEWMAP_H + +# include "Interface0D.h" +# include "Interface1D.h" +# include "Silhouette.h" // defines the embedding +# include "../system/BaseIterator.h" +# include "../system/FreestyleConfig.h" +# include "../geometry/GeomUtils.h" +# include <map> + + /**********************************/ + /* */ + /* */ + /* ViewMap */ + /* */ + /* */ + /**********************************/ + + +/* Density + Mean area depth value + distance to a point + */ + +class ViewVertex; +class ViewEdge; +class ViewShape; +class TVertex; + +/*! Class defining the ViewMap.*/ +class LIB_VIEW_MAP_EXPORT ViewMap +{ +public: + + typedef vector<ViewEdge*> viewedges_container; + typedef vector<ViewVertex*> viewvertices_container; + typedef vector<ViewShape*> viewshapes_container; + typedef vector<SVertex*> svertices_container; + typedef vector<FEdge*> fedges_container; + typedef map<int,int> id_to_index_map; + +private: + + static ViewMap *_pInstance; + viewshapes_container _VShapes; // view shapes + viewedges_container _VEdges; // view edges + viewvertices_container _VVertices; // view vertices + fedges_container _FEdges; // feature edges (embedded edges) + svertices_container _SVertices; // embedded vertices + BBox<Vec3r> _scene3DBBox; + id_to_index_map _shapeIdToIndex; // Mapping between the WShape or VShape id to the VShape index in the + // _VShapes vector. Used in the method viewShape(int id) to access a shape from its id. + +public: + + /*! A field that can be used by the user to store any data. + * This field must be reseted afterwards using ResetUserData(). + */ + void* userdata; + + /*! Default constructor. */ + ViewMap() { + _pInstance = this; + userdata = 0; + } + /*! Destructor. */ + virtual ~ViewMap(); + + /*! Gets the viewedge the nearest to the + * 2D position specified as argument + */ + const ViewEdge * getClosestViewEdge(real x, real y) const ; + + /*! Gets the Fedge the nearest to the + * 2D position specified as argument + */ + const FEdge * getClosestFEdge(real x, real y) const ; + + /* accessors */ + /*! The ViewMap is a singleton class. This static method + * returns the instance of the ViewMap. + */ + static inline ViewMap * getInstance() {return _pInstance;} + /* Returns the list of ViewShapes of the scene. */ + inline viewshapes_container& ViewShapes() {return _VShapes;} + /* Returns the list of ViewEdges of the scene. */ + inline viewedges_container& ViewEdges() {return _VEdges;} + /* Returns the list of ViewVertices of the scene. */ + inline viewvertices_container& ViewVertices() {return _VVertices;} + /* Returns the list of FEdges of the scene. */ + inline fedges_container& FEdges() {return _FEdges;} + /* Returns the list of SVertices of the scene. */ + inline svertices_container& SVertices() {return _SVertices;} + /* Returns an iterator pointing onto the first ViewEdge of the list. */ + inline viewedges_container::iterator viewedges_begin() {return _VEdges.begin();} + inline viewedges_container::iterator viewedges_end() {return _VEdges.end();} + inline int viewedges_size() {return _VEdges.size();} + ViewShape * viewShape(unsigned index); + id_to_index_map& shapeIdToIndexMap() {return _shapeIdToIndex;} + + /*! Returns the scene 3D bounding box. */ + inline BBox<Vec3r> getScene3dBBox() const {return _scene3DBBox;} + + /* modifiers */ + void AddViewShape(ViewShape *iVShape); + inline void AddViewEdge(ViewEdge *iVEdge) {_VEdges.push_back(iVEdge);} + inline void AddViewVertex(ViewVertex *iVVertex) {_VVertices.push_back(iVVertex);} + inline void AddFEdge(FEdge *iFEdge) {_FEdges.push_back(iFEdge);} + inline void AddSVertex(SVertex *iSVertex) {_SVertices.push_back(iSVertex);} + /*! Sets the scene 3D bounding box. */ + inline void setScene3dBBox(const BBox<Vec3r>& bbox) {_scene3DBBox=bbox;} + + /* Creates a T vertex in the view map. + * A T vertex is the intersection between 2 + * FEdges (before these ones are splitted). + * The TVertex is a 2D intersection but it + * corresponds to a 3D point on each of the 2 FEdges. + * iA3D + * The 3D coordinates of the point corresponding + * to the intersection on the first edge. + * iA2D + * The x,y,z 2D coordinates of the projection + * of iA3D + * iFEdgeA + * The first FEdge + * iB3D + * The 3D coordinates of the point corresponding + * to the intersection on the second edge. + * iB2D + * The x,y,z 2D coordinates of the projection + * of iB3D + * iFEdgeB + * The second FEdge + * id + * The id that must be given to that TVertex + */ + TVertex* CreateTVertex(const Vec3r& iA3D, const Vec3r& iA2D, FEdge *iFEdgeA, + const Vec3r& iB3D, const Vec3r& iB2D, FEdge *iFEdgeB, + const Id& id); + + /* Updates the structures to take into account the fact + * that a SVertex must now be considered as a ViewVertex + * iVertex + * The SVertex on top of which the ViewVertex is built (it is necessarily + * a NonTVertex because it is a SVertex) + * newViewEdges + * The new ViewEdges that must be add to the ViewMap + */ + ViewVertex * InsertViewVertex(SVertex *iVertex, vector<ViewEdge*>& newViewEdges); + + /* connects a FEdge to the graph trough a SVertex */ + //FEdge * Connect(FEdge *ioEdge, SVertex *ioVertex); +}; + + /**********************************/ + /* */ + /* */ + /* ViewVertex */ + /* */ + /* */ + /**********************************/ + +class ViewEdge; +class SShape; + +namespace ViewVertexInternal { + class edge_const_traits; + class edge_nonconst_traits; + template<class Traits> class edge_iterator_base ; + class orientedViewEdgeIterator; +} // end of namespace ViewEdgeInternal +/*! Class to define a view vertex + * A view vertex is a feature vertex corresponding + * to a point of the image graph, where the characteristics of an + * edge might change (nature, visibility, ...). + * A ViewVertex can be of two kinds: a TVertex when + * it corresponds to the intersection between two + * ViewEdges or a NonTVertex when it corresponds to a + * vertex of the initial input mesh (it is the case + * for vertices such as corners for example). + * Thus, this class can be specialized into two classes, + * the TVertex class and the NonTVertex class. + */ +class LIB_VIEW_MAP_EXPORT ViewVertex : public Interface0D +{ +public: // Implementation of Interface0D + + /*! Returns the string "ViewVertex" .*/ + virtual string getExactTypeName() const { + return "ViewVertex"; + } + +public: + friend class ViewShape; + typedef pair<ViewEdge*, bool> directedViewEdge; // if bool = true, the ViewEdge is incoming + + typedef vector<directedViewEdge> edges_container; + + typedef ViewVertexInternal::edge_iterator_base<ViewVertexInternal::edge_nonconst_traits> edge_iterator; + typedef ViewVertexInternal::edge_iterator_base<ViewVertexInternal::edge_const_traits> const_edge_iterator; + +private: + + Nature::VertexNature _Nature; + +public: + /*! A field that can be used by the user to store any data. + * This field must be reseted afterwards using ResetUserData(). + */ + void * userdata; + /*! Default constructor.*/ + inline ViewVertex() {userdata = 0;_Nature = Nature::VIEW_VERTEX; } + inline ViewVertex(Nature::VertexNature nature) { + userdata = 0; + _Nature = Nature::VIEW_VERTEX | nature; + } + +protected: + /*! Copy constructor. */ + inline ViewVertex(ViewVertex& iBrother) + { + _Nature = iBrother._Nature; + iBrother.userdata = this; + userdata = 0; + } + /*! Cloning method. */ + virtual ViewVertex * duplicate() = 0; + +public: + /*! Destructor. */ + virtual ~ViewVertex() {} + + /* accessors */ + /*! Returns the nature of the vertex .*/ + virtual Nature::VertexNature getNature() const { + return _Nature; + } + + /* modifiers */ + /*! Sets the nature of the vertex. */ + inline void setNature(Nature::VertexNature iNature) {_Nature = iNature;} + + /* Replaces old edge by new edge */ + virtual void Replace(ViewEdge *, ViewEdge *) {} + +public: + + /* iterators access */ + // allows iteration on the edges that comes from/goes to + // this vertex in CCW order (order defined in 2D in the image plan) + virtual edge_iterator edges_begin() = 0; + virtual const_edge_iterator edges_begin() const = 0; + virtual edge_iterator edges_end() = 0; + virtual const_edge_iterator edges_end() const = 0; + virtual edge_iterator edges_iterator(ViewEdge *iEdge) = 0; + virtual const_edge_iterator edges_iterator(ViewEdge *iEdge) const = 0; + + + // Iterator access + /*! Returns an iterator over the ViewEdges that goes to or comes from + * this ViewVertex pointing to the first ViewEdge of the list. + * The orientedViewEdgeIterator allows to iterate in CCW order over these ViewEdges + * and to get the orientation for each ViewEdge (incoming/outgoing). + */ + virtual ViewVertexInternal::orientedViewEdgeIterator edgesBegin() = 0; + + /*! Returns an orientedViewEdgeIterator over the ViewEdges around this ViewVertex, + * pointing after the last ViewEdge. + */ + virtual ViewVertexInternal::orientedViewEdgeIterator edgesEnd() = 0; + + /*! Returns an orientedViewEdgeIterator pointing to the ViewEdge + * given as argument. + */ + virtual ViewVertexInternal::orientedViewEdgeIterator edgesIterator(ViewEdge *iEdge) = 0; + +}; + + /**********************************/ + /* */ + /* */ + /* TVertex */ + /* */ + /* */ + /**********************************/ + +/*! class to define a T vertex, i.e. an intersection between + * two edges. + * It points towards 2 SVertex and 4 View edges. + * Among these ViewEdges, 2 are front and 2 are back. + * Basically the front edge hides part of the back edge. + * So, among the back edges, 1 is of invisibility n + * and the other of visibility n+1 + */ +class LIB_VIEW_MAP_EXPORT TVertex : public ViewVertex +{ +public: + typedef vector<directedViewEdge*> edge_pointers_container; +public: // Implementation of Interface0D + + /*! Returns the string "TVertex" .*/ + virtual string getExactTypeName() const { + return "TVertex"; + } + + // Data access methods + /* Returns the 3D x coordinate of the vertex . + * Ambiguous in this case. + */ + virtual real getX() const { + cerr << "Warning: getX() undefined for this point" << endl; + return _FrontSVertex->point3D().x(); + } + + virtual real getY() const { + cerr << "Warning: getX() undefined for this point" << endl; + return _FrontSVertex->point3D().y(); + } + + virtual real getZ() const { + cerr << "Warning: getX() undefined for this point" << endl; + return _FrontSVertex->point3D().z(); + } + + /*! Returns the 3D point. */ + virtual Vec3f getPoint3D() const { + cerr << "Warning: getPoint3D() undefined for this point" << endl; + return _FrontSVertex->getPoint3D(); + } + + /*! Returns the projected 3D x coordinate of the vertex .*/ + virtual real getProjectedX() const { + return _FrontSVertex->point2D().x(); + } + + /*! Returns the projected 3D y coordinate of the vertex .*/ + virtual real getProjectedY() const { + return _FrontSVertex->point2D().y(); + } + + virtual real getProjectedZ() const { + return _FrontSVertex->point2D().z(); + } + + /*! Returns the 2D point. */ + virtual Vec2f getPoint2D() const { + return _FrontSVertex->getPoint2D(); + } + + /*! Returns the Id of the TVertex .*/ + virtual Id getId() const { + return _Id; + } + + /*! Cast the Interface0D in SVertex if it can be. */ + // it can't + /*! Cast the Interface0D in ViewVertex if it can be. */ + virtual ViewVertex * castToViewVertex(){ + return this; + } + + /*! Cast the Interface0D in TVertex if it can be. */ + virtual TVertex * castToTVertex(){ + return this; + } + +private: + SVertex *_FrontSVertex; + SVertex *_BackSVertex; + directedViewEdge _FrontEdgeA; + directedViewEdge _FrontEdgeB; + directedViewEdge _BackEdgeA; + directedViewEdge _BackEdgeB; + Id _Id; // id to identify t vertices . these id will be negative in order not to be mixed with NonTVertex ids. + edge_pointers_container _sortedEdges; // the list of the four ViewEdges, ordered in CCW order (in the image plan) + + +public: + /*! Default constructor.*/ + inline TVertex() : ViewVertex(Nature::T_VERTEX) + { + _FrontSVertex = 0; + _BackSVertex = 0; + _FrontEdgeA.first = 0; + _FrontEdgeB.first = 0; + _BackEdgeA.first = 0; + _BackEdgeB.first = 0; + + } + + inline TVertex(SVertex *svFront, SVertex *svBack) + : ViewVertex(Nature::T_VERTEX) + { + _FrontSVertex = svFront; + _BackSVertex = svBack; + _FrontEdgeA.first = 0; + _FrontEdgeB.first = 0; + _BackEdgeA.first = 0; + _BackEdgeB.first = 0; + svFront->setViewVertex(this); + svBack->setViewVertex(this); + } + +protected: + /*! Copy constructor. */ + inline TVertex(TVertex& iBrother) + : ViewVertex(iBrother) + { + _FrontSVertex = iBrother._FrontSVertex; + _BackSVertex = iBrother._BackSVertex; + _FrontEdgeA = iBrother._FrontEdgeA; + _FrontEdgeB = iBrother._FrontEdgeB; + _BackEdgeA = iBrother._BackEdgeA; + _BackEdgeB = iBrother._BackEdgeB; + _sortedEdges = iBrother._sortedEdges; + } + + /*! Cloning method. */ + virtual ViewVertex * duplicate() + { + TVertex *clone = new TVertex(*this); + return clone; + } + +public: + /* accessors */ + /*! Returns the SVertex that is closer to the viewpoint. */ + inline SVertex *frontSVertex() {return _FrontSVertex;} + /*! Returns the SVertex that is further away from the viewpoint. */ + inline SVertex *backSVertex() {return _BackSVertex;} + inline directedViewEdge& frontEdgeA() {return _FrontEdgeA;} + inline directedViewEdge& frontEdgeB() {return _FrontEdgeB;} + inline directedViewEdge& backEdgeA() {return _BackEdgeA;} + inline directedViewEdge& backEdgeB() {return _BackEdgeB;} + + /* modifiers */ + /*! Sets the SVertex that is closer to the viewpoint. */ + inline void setFrontSVertex(SVertex *iFrontSVertex) {_FrontSVertex = iFrontSVertex;_FrontSVertex->setViewVertex(this);} + /*! Sets the SVertex that is further away from the viewpoint. */ + inline void setBackSVertex(SVertex *iBackSVertex) {_BackSVertex = iBackSVertex;_BackSVertex->setViewVertex(this);} + void setFrontEdgeA(ViewEdge *iFrontEdgeA, bool incoming=true); + void setFrontEdgeB(ViewEdge *iFrontEdgeB, bool incoming=true) ; + void setBackEdgeA(ViewEdge *iBackEdgeA, bool incoming=true); + void setBackEdgeB(ViewEdge *iBackEdgeB, bool incoming=true) ; + /*! Sets the Id. */ + inline void setId(const Id& iId) {_Id = iId;} + + /*! Returns the SVertex (among the 2) belonging to the FEdge iFEdge */ + inline SVertex * getSVertex(FEdge *iFEdge) + { + const vector<FEdge*>& vfEdges = _FrontSVertex->fedges(); + vector<FEdge*>::const_iterator fe,fend; + for(fe=vfEdges.begin(),fend=vfEdges.end(); + fe!=fend; + fe++) + { + if((*fe) == iFEdge) + return _FrontSVertex; + } + + const vector<FEdge*>& vbEdges = _BackSVertex->fedges(); + for(fe=vbEdges.begin(),fend=vbEdges.end(); + fe!=fend; + fe++) + { + if((*fe) == iFEdge) + return _BackSVertex; + } + return 0; + } + + virtual void Replace(ViewEdge *iOld, ViewEdge *iNew); + + /*! returns the mate edge of iEdgeA. + * For example, if iEdgeA is frontEdgeA, + * then frontEdgeB is returned. If iEdgeA is + * frontEdgeB then frontEdgeA is returned. + * Same for back edges + */ + virtual ViewEdge * mate(ViewEdge* iEdgeA) + { + if(iEdgeA == _FrontEdgeA.first) + return _FrontEdgeB.first; + if(iEdgeA == _FrontEdgeB.first) + return _FrontEdgeA.first; + if(iEdgeA == _BackEdgeA.first) + return _BackEdgeB.first; + if(iEdgeA == _BackEdgeB.first) + return _BackEdgeA.first; + return 0; + } + + /* iterators access */ + virtual edge_iterator edges_begin(); + virtual const_edge_iterator edges_begin() const; + virtual edge_iterator edges_end(); + virtual const_edge_iterator edges_end() const; + virtual edge_iterator edges_iterator(ViewEdge *iEdge); + virtual const_edge_iterator edges_iterator(ViewEdge *iEdge) const; + + /*! Returns an iterator over the ViewEdges that goes to or comes from + * this ViewVertex pointing to the first ViewEdge of the list. + * The orientedViewEdgeIterator allows to iterate in CCW order over these ViewEdges + * and to get the orientation for each ViewEdge (incoming/outgoing). + */ + virtual ViewVertexInternal::orientedViewEdgeIterator edgesBegin() ; + /*! Returns an orientedViewEdgeIterator over the ViewEdges around this ViewVertex, + * pointing after the last ViewEdge. + */ + virtual ViewVertexInternal::orientedViewEdgeIterator edgesEnd() ; + /*! Returns an orientedViewEdgeIterator pointing to the ViewEdge + * given as argument. + */ + virtual ViewVertexInternal::orientedViewEdgeIterator edgesIterator(ViewEdge *iEdge) ; +}; + + + /**********************************/ + /* */ + /* */ + /* NonTVertex */ + /* */ + /* */ + /**********************************/ + + +// (non T vertex) +/*! View vertex for corners, cusps, etc... + * Associated to a single SVertex. + * Can be associated to 2 or several view edges + */ +class LIB_VIEW_MAP_EXPORT NonTVertex : public ViewVertex +{ +public: + typedef vector<directedViewEdge> edges_container; + +public: // Implementation of Interface0D + + /*! Returns the string "ViewVertex" .*/ + virtual string getExactTypeName() const { + return "NonTVertex"; + } + + // Data access methods + /*! Returns the 3D x coordinate of the vertex .*/ + virtual real getX() const { + return _SVertex->point3D().x(); + } + /*! Returns the 3D y coordinate of the vertex .*/ + virtual real getY() const { + return _SVertex->point3D().y(); + } + + /*! Returns the 3D z coordinate of the vertex .*/ + virtual real getZ() const { + return _SVertex->point3D().z(); + } + + /*! Returns the 3D point. */ + virtual Vec3f getPoint3D() const { + return _SVertex->getPoint3D(); + } + + /*! Returns the projected 3D x coordinate of the vertex .*/ + virtual real getProjectedX() const { + return _SVertex->point2D().x(); + } + + /*! Returns the projected 3D y coordinate of the vertex .*/ + virtual real getProjectedY() const { + return _SVertex->point2D().y(); + } + + /*! Returns the projected 3D z coordinate of the vertex .*/ + virtual real getProjectedZ() const { + return _SVertex->point2D().z(); + } + + /*! Returns the 2D point. */ + virtual Vec2f getPoint2D() const { + return _SVertex->getPoint2D(); + } + + /*! Returns the Id of the vertex .*/ + virtual Id getId() const { + return _SVertex->getId(); + } + + /*! Cast the Interface0D in SVertex if it can be. */ + virtual SVertex * castToSVertex(){ + return _SVertex; + } + + /*! Cast the Interface0D in ViewVertex if it can be. */ + virtual ViewVertex * castToViewVertex(){ + return this; + } + + /*! Cast the Interface0D in NonTVertex if it can be. */ + virtual NonTVertex * castToNonTVertex(){ + return this; + } + +private: + SVertex *_SVertex; + edges_container _ViewEdges; +public: + /*! Default constructor.*/ + inline NonTVertex() : ViewVertex(Nature::NON_T_VERTEX) { _SVertex = 0; } + /*! Builds a NonTVertex from a SVertex. */ + inline NonTVertex(SVertex* iSVertex) : ViewVertex(Nature::NON_T_VERTEX) + { + _SVertex = iSVertex; + _SVertex->setViewVertex(this); + } +protected: + /*! Copy constructor. */ + inline NonTVertex(NonTVertex& iBrother) + : ViewVertex(iBrother) + { + _SVertex = iBrother._SVertex; + _SVertex->setViewVertex(this); + _ViewEdges = iBrother._ViewEdges; + } + /*! Cloning method. */ + virtual ViewVertex * duplicate() + { + NonTVertex *clone = new NonTVertex(*this); + return clone; + } +public: + /*! destructor. */ + virtual ~NonTVertex() {} + + /* accessors */ + /*! Returns the SVertex on top of which this NonTVertex is built. */ + inline SVertex * svertex() {return _SVertex;} + inline edges_container& viewedges() {return _ViewEdges;} + + /* modifiers */ + /*! Sets the SVertex on top of which this NonTVertex is built. */ + inline void setSVertex(SVertex *iSVertex) {_SVertex = iSVertex;_SVertex->setViewVertex(this);} + inline void setViewEdges(const vector<directedViewEdge>& iViewEdges) {_ViewEdges = iViewEdges;} + void AddIncomingViewEdge(ViewEdge * iVEdge) ; + void AddOutgoingViewEdge(ViewEdge * iVEdge) ; + inline void AddViewEdge(ViewEdge * iVEdge, bool incoming=true) { + if(incoming) + AddIncomingViewEdge(iVEdge); + else + AddOutgoingViewEdge(iVEdge); + } + /* Replaces old edge by new edge */ + virtual void Replace(ViewEdge *iOld, ViewEdge *iNew) + { + + edges_container::iterator insertedve; + for(edges_container::iterator ve=_ViewEdges.begin(),vend=_ViewEdges.end(); + ve!=vend; + ve++) + { + if((ve)->first == iOld) + { + insertedve = _ViewEdges.insert(ve, directedViewEdge(iNew, ve->second));// inserts e2 before ve. + // returns an iterator pointing toward e2. ve is invalidated. + // we want to remove e1, but we can't use ve anymore: + insertedve++; // insertedve points now to e1 + _ViewEdges.erase(insertedve); + return; + } + } + } + + + /* iterators access */ + virtual edge_iterator edges_begin(); + virtual const_edge_iterator edges_begin() const; + virtual edge_iterator edges_end(); + virtual const_edge_iterator edges_end() const; + virtual edge_iterator edges_iterator(ViewEdge *iEdge); + virtual const_edge_iterator edges_iterator(ViewEdge *iEdge) const; + + /*! Returns an iterator over the ViewEdges that goes to or comes from + * this ViewVertex pointing to the first ViewEdge of the list. + * The orientedViewEdgeIterator allows to iterate in CCW order over these ViewEdges + * and to get the orientation for each ViewEdge (incoming/outgoing). + */ + virtual ViewVertexInternal::orientedViewEdgeIterator edgesBegin() ; + /*! Returns an orientedViewEdgeIterator over the ViewEdges around this ViewVertex, + * pointing after the last ViewEdge. + */ + virtual ViewVertexInternal::orientedViewEdgeIterator edgesEnd() ; + /*! Returns an orientedViewEdgeIterator pointing to the ViewEdge + * given as argument. + */ + virtual ViewVertexInternal::orientedViewEdgeIterator edgesIterator(ViewEdge *iEdge) ; +}; + + /**********************************/ + /* */ + /* */ + /* ViewEdge */ + /* */ + /* */ + /**********************************/ + +/* Geometry(normals...) + Nature of edges + 2D spaces (1or2, material, z...) + Parent Shape + 3D Shading, material + Importance + Occluders + */ +class ViewShape; + +namespace ViewEdgeInternal { + template<class Traits> class edge_iterator_base ; + template<class Traits> class fedge_iterator_base ; + template<class Traits> class vertex_iterator_base ; +} // end of namespace ViewEdgeInternal + +/*! Class defining a ViewEdge. A ViewEdge in an edge + * of the image graph. it connnects two ViewVertex. + * It is made by connecting a set of FEdges. + */ +class LIB_VIEW_MAP_EXPORT ViewEdge : public Interface1D +{ +public: // Implementation of Interface0D + + /*! Returns the string "ViewEdge" .*/ + virtual string getExactTypeName() const { + return "ViewEdge"; + } + + // Data access methods + /*! Returns the Id of the vertex .*/ + virtual Id getId() const { + return _Id; + } + + /*! Returns the nature of the ViewEdge. */ + virtual Nature::EdgeNature getNature() const { + return _Nature; + } + +public: + + typedef SVertex vertex_type; + friend class ViewShape; + // for ViewEdge iterator + typedef ViewEdgeInternal::edge_iterator_base<Nonconst_traits<ViewEdge*> > edge_iterator; + typedef ViewEdgeInternal::edge_iterator_base<Const_traits<ViewEdge*> > const_edge_iterator; + // for fedge iterator + typedef ViewEdgeInternal::fedge_iterator_base<Nonconst_traits<FEdge*> > fedge_iterator; + typedef ViewEdgeInternal::fedge_iterator_base<Const_traits<FEdge*> > const_fedge_iterator; + // for svertex iterator + typedef ViewEdgeInternal::vertex_iterator_base<Nonconst_traits<SVertex*> > vertex_iterator; + typedef ViewEdgeInternal::vertex_iterator_base<Const_traits<SVertex*> > const_vertex_iterator; +private: + + ViewVertex * __A; // edge starting vertex + ViewVertex * __B; // edge ending vertex + Nature::EdgeNature _Nature; // nature of view edge + ViewShape *_Shape; // shape to which the view edge belongs + FEdge * _FEdgeA; // first edge of the embedded fedges chain + FEdge * _FEdgeB; // last edge of the embedded fedges chain + Id _Id; + unsigned _ChainingTimeStamp; + ViewShape *_aShape; // The silhouette view edge separates 2 2D spaces. The one on the left is + // necessarly the Shape _Shape (the one to which this edge belongs to) + // and _aShape is the one on its right // NON GERE PAR LE COPY CONSTRUCTEUR + int _qi; + vector<ViewShape*> _Occluders; + + // tmp + Id * _splittingId; + +public: + /*! A field that can be used by the user to store any data. + * This field must be reseted afterwards using ResetUserData(). + */ + void * userdata; + /*! Default constructor.*/ + inline ViewEdge() { + __A=0; + __B=0; + _FEdgeA = 0; + _FEdgeB = 0; + _ChainingTimeStamp = 0; + _qi = 0; + _aShape=0; + userdata = 0; + _splittingId = 0; + } + inline ViewEdge(ViewVertex* iA, ViewVertex *iB) + { + __A = iA; + __B = iB; + _FEdgeA = 0; + _FEdgeB = 0; + _Shape = 0; + _ChainingTimeStamp = 0; + _aShape = 0; + _qi = 0; + userdata = 0; + _splittingId = 0; + } + inline ViewEdge(ViewVertex* iA, ViewVertex *iB, FEdge *iFEdgeA) + { + __A = iA; + __B = iB; + _FEdgeA = iFEdgeA; + _FEdgeB = 0; + _Shape = 0; + _ChainingTimeStamp = 0; + _aShape = 0; + _qi = 0; + userdata = 0; + _splittingId = 0; + } + inline ViewEdge(ViewVertex* iA, ViewVertex *iB, FEdge *iFEdgeA, FEdge *iFEdgeB, ViewShape *iShape) + { + __A = iA; + __B = iB; + _FEdgeA = iFEdgeA; + _FEdgeB = iFEdgeB; + _Shape = iShape; + _ChainingTimeStamp = 0; + _aShape = 0; + _qi = 0; + userdata = 0; + _splittingId = 0; + UpdateFEdges(); // tells every FEdge between iFEdgeA and iFEdgeB that this is theit ViewEdge + } + +//soc protected: + + /*! Copy constructor. */ + inline ViewEdge(ViewEdge& iBrother) + { + __A = iBrother.__A; + __B = iBrother.__B; + _FEdgeA = iBrother._FEdgeA; + _FEdgeB = iBrother._FEdgeB; + _Nature = iBrother._Nature; + _Shape = 0; + _Id = iBrother._Id; + _ChainingTimeStamp = iBrother._ChainingTimeStamp; + _aShape = iBrother._aShape; + _qi = iBrother._qi; + _splittingId = 0; + iBrother.userdata = this; + userdata = 0; + } + /*! Cloning method. */ + virtual ViewEdge * duplicate() + { + ViewEdge *clone = new ViewEdge(*this); + return clone; + } + +public: + /*! Destructor. */ + virtual ~ViewEdge() + { + // if(0 != _aFace) + // { + // delete _aFace; + // _aFace = 0; + // } + // only the last splitted deletes this id + if(_splittingId){ + if(*_splittingId == _Id) + delete _splittingId; + } + } + + /* accessors */ + /*! Returns the first ViewVertex. */ + inline ViewVertex* A() {return __A;} + /*! Returns the second ViewVertex. */ + inline ViewVertex* B() {return __B;} + /*! Returns the first FEdge that constitues this ViewEdge. */ + inline FEdge* fedgeA() {return _FEdgeA;} + /*! Returns the last FEdge that constitues this ViewEdge. */ + inline FEdge* fedgeB() {return _FEdgeB;} + /*! Returns the ViewShape to which this ViewEdge belongs to .*/ + inline ViewShape * viewShape() {return _Shape;} + /*! Returns the shape that is occluded by the ViewShape + * to which this ViewEdge belongs to. If no object is occluded, + * 0 is returned. + * \return The occluded ViewShape. + */ + inline ViewShape * aShape() {return _aShape;} + /*! Tells whether this ViewEdge forms a closed loop + * or not. + */ + inline bool isClosed() + { + if(__B == 0) + return true; + return false; + } + /*! Returns the time stamp of this ViewEdge. */ + inline unsigned getChainingTimeStamp() {return _ChainingTimeStamp;} + inline const ViewShape * aShape() const {return _aShape;} + inline const ViewShape * bShape() const {return _Shape;} + inline vector<ViewShape*>& occluders() {return _Occluders;} + inline Id * splittingId() {return _splittingId;} + + /* modifiers */ + /*! Sets the first ViewVertex of the ViewEdge. */ + inline void setA(ViewVertex* iA) { __A = iA; } + /*! Sets the last ViewVertex of the ViewEdge. */ + inline void setB(ViewVertex* iB) { __B = iB; } + /*! Sets the nature of the ViewEdge. */ + inline void setNature(Nature::EdgeNature iNature) { _Nature = iNature; } + /*! Sets the first FEdge of the ViewEdge. */ + inline void setFEdgeA(FEdge* iFEdge) { _FEdgeA = iFEdge; } + /*! Sets the last FEdge of the ViewEdge. */ + inline void setFEdgeB(FEdge* iFEdge) { _FEdgeB = iFEdge; } + /*! Sets the ViewShape to which this ViewEdge belongs to.*/ + inline void setShape(ViewShape *iVShape) + { + _Shape = iVShape; + } + /*! Sets the ViewEdge id. */ + inline void setId(const Id& id) {_Id = id;} + /*! Sets Viewedge to this for all embedded fedges */ + void UpdateFEdges(); + /*! Sets the occluded ViewShape */ + inline void setaShape(ViewShape * iShape) {_aShape = iShape;} + /*! Sets the quantitative invisibility value. */ + inline void setQI(int qi) {_qi = qi;} + /*! Sets the time stamp value. */ + inline void setChainingTimeStamp(unsigned ts) {_ChainingTimeStamp = ts;} + inline void AddOccluder(ViewShape *iShape) {_Occluders.push_back(iShape);} + inline void setSplittingId(Id * id) {_splittingId = id;} + + /* stroke interface definition */ + inline bool intersect_2d_area(const Vec2r& iMin, const Vec2r& iMax) const + { + // parse edges to check if one of them is intersection the region: + FEdge * current = _FEdgeA; + do + { + if(GeomUtils::intersect2dSeg2dArea(iMin,iMax, + Vec2r(current->vertexA()->point2D()[0],current->vertexA()->point2D()[1]), + Vec2r(current->vertexB()->point2D()[0],current->vertexB()->point2D()[1]))) + + return true; + current = current->nextEdge(); + }while((current != 0) && (current != _FEdgeA)); + + return false; + } + inline bool include_in_2d_area(const Vec2r& iMin, const Vec2r& iMax) const + { + // parse edges to check if all of them are intersection the region: + FEdge * current = _FEdgeA; + + do + { + if(!GeomUtils::include2dSeg2dArea(iMin,iMax, + Vec2r(current->vertexA()->point2D()[0],current->vertexA()->point2D()[1]), + Vec2r(current->vertexB()->point2D()[0],current->vertexB()->point2D()[1]))) + return false; + current = current->nextEdge(); + }while((current != 0) && (current != _FEdgeA)); + + return true; + } + + /* Information access interface */ + + //inline Nature::EdgeNature viewedge_nature() const {return getNature();} + //float viewedge_length() const ; + /*! Returns the 2D length of the Viewedge. */ + real getLength2D() const; + //inline Material material() const {return _FEdgeA->vertexA()->shape()->material();} + inline int qi() const {return _qi;} + inline occluder_container::const_iterator occluders_begin() const {return _Occluders.begin();} + inline occluder_container::const_iterator occluders_end() const {return _Occluders.end();} + inline int occluders_size() const {return _Occluders.size();} + inline bool occluders_empty() const {return _Occluders.empty();} + inline const Polygon3r& occludee() const {return (_FEdgeA->aFace());} + inline const SShape * occluded_shape() const ; + inline const bool occludee_empty() const {if(_aShape == 0) return true; return false;} + //inline real z_discontinuity(int iCombination = 0) const ; + inline Id shape_id() const {return _FEdgeA->vertexA()->shape()->getId();} + inline const SShape * shape() const {return _FEdgeA->vertexA()->shape();} + inline float shape_importance() const {return _FEdgeA->shape_importance();} + + /* iterators access */ + // view edge iterator + edge_iterator ViewEdge_iterator(); + const_edge_iterator ViewEdge_iterator() const; + // feature edge iterator + fedge_iterator fedge_iterator_begin(); + const_fedge_iterator fedge_iterator_begin() const; + fedge_iterator fedge_iterator_last(); + const_fedge_iterator fedge_iterator_last() const; + fedge_iterator fedge_iterator_end(); + const_fedge_iterator fedge_iterator_end() const; + // embedding vertex iterator + const_vertex_iterator vertices_begin() const; + vertex_iterator vertices_begin(); + const_vertex_iterator vertices_last() const; + vertex_iterator vertices_last(); + const_vertex_iterator vertices_end() const; + vertex_iterator vertices_end(); + + // Iterator access (Interface1D) + /*! Returns an Interface0DIterator to iterate over + * the SVertex constituing the embedding of this ViewEdge. + * The returned Interface0DIterator points to the first + * SVertex of the ViewEdge. + */ + virtual Interface0DIterator verticesBegin(); + /*! Returns an Interface0DIterator to iterate over + * the SVertex constituing the embedding of this ViewEdge. + * The returned Interface0DIterator points after the last + * SVertex of the ViewEdge. + */ + virtual Interface0DIterator verticesEnd(); + + /*! Returns an Interface0DIterator to iterate over + * the points of this ViewEdge at a given resolution. + * The returned Interface0DIterator points on the first + * Point of the ViewEdge. + * \param t + * the sampling value. + */ + virtual Interface0DIterator pointsBegin(float t=0.f); + /*! Returns an Interface0DIterator to iterate over + * the points of this ViewEdge at a given resolution. + * The returned Interface0DIterator points after the last + * Point of the ViewEdge. + * \param t + * the sampling value. + */ + virtual Interface0DIterator pointsEnd(float t=0.f); +}; + + + + /**********************************/ + /* */ + /* */ + /* ViewShape */ + /* */ + /* */ + /**********************************/ + +/*! Class gathering the elements of the ViewMap (ViewVertex, ViewEdge) + * that are issued from the same input shape. + */ +class LIB_VIEW_MAP_EXPORT ViewShape +{ +private: + vector<ViewVertex*> _Vertices; + vector<ViewEdge*> _Edges; + SShape * _SShape; + + +public: + /*! A field that can be used by the user to store any data. + * This field must be reseted afterwards using ResetUserData(). + */ + void* userdata; + /*! Default constructor.*/ + inline ViewShape() { userdata = 0; _SShape = 0;} + /*! Builds a ViewShape from a SShape. */ + inline ViewShape(SShape *iSShape) {userdata = 0; _SShape = iSShape;}//_SShape->setViewShape(this);} + /*! Copy constructor. */ + inline ViewShape(ViewShape& iBrother) + { + userdata = 0; + vector<ViewVertex*>::iterator vv,vvend; + vector<ViewEdge*>::iterator ve, veend; + + _SShape = iBrother._SShape; + + vector<ViewVertex*>& vvertices = iBrother.vertices(); + // duplicate vertices + for(vv=vvertices.begin(), vvend=vvertices.end(); + vv!=vvend; + vv++) + { + ViewVertex * newVertex = (*vv)->duplicate(); + AddVertex(newVertex); + } + + vector<ViewEdge*>& vvedges = iBrother.edges(); + // duplicate edges + for(ve=vvedges.begin(), veend=vvedges.end(); + ve!=veend; + ve++) + { + ViewEdge * newEdge = (*ve)->duplicate(); + AddEdge(newEdge); // here the shape is set as the edge's shape + } + + //------------------------- + // remap edges in vertices: + //------------------------- + for(vv=_Vertices.begin(), vvend=_Vertices.end(); + vv!=vvend; + vv++) + { + switch((*vv)->getNature()) + { + case Nature::T_VERTEX: + { + TVertex *v = (TVertex*)(*vv); + ViewEdge *veFrontA = (ViewEdge*)(v)->frontEdgeA().first->userdata; + ViewEdge *veFrontB = (ViewEdge*)(v)->frontEdgeB().first->userdata; + ViewEdge *veBackA = (ViewEdge*)(v)->backEdgeA().first->userdata; + ViewEdge *veBackB = (ViewEdge*)(v)->backEdgeB().first->userdata; + + v->setFrontEdgeA(veFrontA, v->frontEdgeA().second); + v->setFrontEdgeB(veFrontB, v->frontEdgeB().second); + v->setBackEdgeA(veBackA, v->backEdgeA().second); + v->setBackEdgeB(veBackB, v->backEdgeB().second); + } + break; + case Nature::NON_T_VERTEX: + { + NonTVertex * v = (NonTVertex*)(*vv); + vector<ViewVertex::directedViewEdge>& vedges = (v)->viewedges(); + vector<ViewVertex::directedViewEdge> newEdges; + for(vector<ViewVertex::directedViewEdge>::iterator ve=vedges.begin(), veend=vedges.end(); + ve!=veend; + ve++) + { + ViewEdge *current = (ViewEdge*)((ve)->first)->userdata; + newEdges.push_back(ViewVertex::directedViewEdge(current, ve->second)); + } + (v)->setViewEdges(newEdges); + } + break; + default: + ; + } + } + + //------------------------------------- + // remap vertices in edges: + //------------------------------------- + for(ve=_Edges.begin(),veend=_Edges.end(); + ve!=veend; + ve++) + { + (*ve)->setA((ViewVertex*)((*ve)->A()->userdata)); + (*ve)->setB((ViewVertex*)((*ve)->B()->userdata)); + //--------------------------------------- + // Update all embedded FEdges + //--------------------------------------- + (*ve)->UpdateFEdges(); + } + + + // reset all brothers userdata to NULL: + //------------------------------------- + //--------- + // vertices + //--------- + for(vv=vvertices.begin(),vvend=vvertices.end(); + vv!=vvend; + vv++) + { + (*vv)->userdata = NULL; + } + + //------ + // edges + //------ + for(ve=vvedges.begin(),veend=vvedges.end(); + ve!=veend; + ve++) + { + (*ve)->userdata = NULL; + } + } + + /*! Cloning method. */ + virtual ViewShape * duplicate() + { + ViewShape *clone = new ViewShape(*this); + return clone; + } + + /*! Destructor. */ + virtual ~ViewShape(); + + /* splits a view edge into several view edges. + * fe + * The FEdge that gets splitted + * iViewVertices + * The view vertices corresponding to the different intersections for the edge fe. + * This list need to be sorted such as the first view vertex is the + * farther away from fe->vertexA. + * ioNewEdges + * The feature edges that are newly created (the initial edges are not + * included) are added to this list. + * ioNewViewEdges + * The view edges that are newly created (the initial edges are not + * included) are added to this list. + */ + inline void SplitEdge(FEdge *fe, + const vector<TVertex*>& iViewVertices, + vector<FEdge*>& ioNewEdges, + vector<ViewEdge*>& ioNewViewEdges); + /* accessors */ + /*! Returns the SShape on top of which this ViewShape is built. */ + inline SShape * sshape() {return _SShape;} + /*! Returns the SShape on top of which this ViewShape is built. */ + inline const SShape * sshape() const {return _SShape;} + /*! Returns the list of ViewVertex contained in this ViewShape. */ + inline vector<ViewVertex*>& vertices() {return _Vertices;} + /*! Returns the list of ViewEdge contained in this ViewShape. */ + inline vector<ViewEdge*>& edges() {return _Edges;} + /*! Returns the ViewShape id. */ + inline Id getId() const {return _SShape->getId();} + /*! Returns the ViewShape id. */ + inline const string& getName() const {return _SShape->getName();} + + /* modifiers */ + /*! Sets the SShape on top of which the ViewShape is built. */ + inline void setSShape(SShape* iSShape) {_SShape = iSShape;} + /*! Sets the list of ViewVertex contained in this ViewShape. */ + inline void setVertices(const vector<ViewVertex*>& iVertices) {_Vertices = iVertices;} + /*! Sets the list of ViewEdge contained in this ViewShape. */ + inline void setEdges(const vector<ViewEdge*>& iEdges) {_Edges = iEdges;} + /*! Adds a ViewVertex to the list. */ + inline void AddVertex(ViewVertex *iVertex) + { + _Vertices.push_back(iVertex); + //_SShape->AddNewVertex(iVertex->svertex()); + } + /*! Adds a ViewEdge to the list */ + inline void AddEdge(ViewEdge *iEdge) + { + _Edges.push_back(iEdge); + iEdge->setShape(this); + //_SShape->AddNewEdge(iEdge->fedge()); + } + + /* removes the view edge iViewEdge in the + * View Shape and the associated FEdge chain entry + * in the underlying SShape + */ + void RemoveEdge(ViewEdge * iViewEdge); + + /* removes the view vertex iViewVertex in the + * View Shape. + */ + void RemoveVertex(ViewVertex * iViewVertex); +}; + + + +/* + + ############################################# + ############################################# + ############################################# + ###### ###### + ###### I M P L E M E N T A T I O N ###### + ###### ###### + ############################################# + ############################################# + ############################################# + +*/ +/* for inline functions */ + +void ViewShape::SplitEdge(FEdge *fe, + const vector<TVertex*>& iViewVertices, + vector<FEdge*>& ioNewEdges, + vector<ViewEdge*>& ioNewViewEdges) +{ + ViewEdge *vEdge = fe->viewedge(); + + + // We first need to sort the view vertices from farther to closer to fe->vertexA + + SVertex *sv, *sv2; + ViewVertex *vva, *vvb; + vector<TVertex*>::const_iterator vv, vvend; + for(vv=iViewVertices.begin(), vvend = iViewVertices.end(); + vv!=vvend; + vv++) + { + // Add the viewvertices to the ViewShape + AddVertex((*vv)); + + // retrieve the correct SVertex from the view vertex + //-------------------------------------------------- + sv = (*vv)->frontSVertex(); + sv2 = (*vv)->backSVertex(); + + if(sv->shape() != sv2->shape()) + { + if(sv->shape() != _SShape) + sv = sv2; + } + else + { + // if the shape is the same we can safely differ + // the two vertices using their ids: + if(sv->getId() != fe->vertexA()->getId()) + sv = sv2; + } + + vva = vEdge->A(); + vvb = vEdge->B(); + + // We split Fedge AB into AA' and A'B. A' and A'B are created. + // AB becomes (address speaking) AA'. B is updated. + //-------------------------------------------------- + SShape * shape = fe->shape(); + + // a new edge, A'B is created. + FEdge *newEdge = shape->SplitEdgeIn2(fe, sv); + + ioNewEdges.push_back(newEdge); + ViewEdge *newVEdge; + + if((vva == 0) || (vvb == 0)) // that means we're dealing with a closed viewedge (loop) + { + // remove the chain that was starting by the fedge A of vEdge (which is different from fe !!!!) + shape->RemoveEdgeFromChain(vEdge->fedgeA()); + // we set + vEdge->setA(*vv); + vEdge->setB(*vv); + vEdge->setFEdgeA(newEdge); + //FEdge *previousEdge = newEdge->previousEdge(); + vEdge->setFEdgeB(fe); + newVEdge = vEdge; + vEdge->fedgeA()->setViewEdge(newVEdge); + } + else + { + + // while we create the view edge, it updates the "ViewEdge" pointer + // of every underlying FEdges to this. + newVEdge = new ViewEdge((*vv),vvb);//, newEdge, vEdge->fedgeB()); + newVEdge->setNature((fe)->getNature()); + newVEdge->setFEdgeA(newEdge); + //newVEdge->setFEdgeB(fe); + // If our original viewedge is made of one FEdge, + // then + if((vEdge->fedgeA() == vEdge->fedgeB()) || (fe == vEdge->fedgeB())) + newVEdge->setFEdgeB(newEdge); + else + newVEdge->setFEdgeB(vEdge->fedgeB()); //MODIF + + Id * newId = vEdge->splittingId(); + if(newId == 0){ + newId = new Id(vEdge->getId()); + vEdge->setSplittingId(newId); + } + newId->setSecond(newId->getSecond()+1); + newVEdge->setId(*newId); + newVEdge->setSplittingId(newId); + // Id id(vEdge->getId().getFirst(), vEdge->getId().getSecond()+1); + // newVEdge->setId(vEdge->getId()); + // vEdge->setId(id); + + AddEdge(newVEdge); // here this shape is set as the edge's shape + + // add new edge to the list of new edges passed as argument: + ioNewViewEdges.push_back(newVEdge); + + + + if(0 != vvb) + vvb->Replace((vEdge), newVEdge); + + // we split the view edge: + vEdge->setB((*vv)); + vEdge->setFEdgeB(fe); //MODIF + + // Update fedges so that they point to the new viewedge: + newVEdge->UpdateFEdges(); + + } + // check whether this vertex is a front vertex or a back + // one + + if(sv == (*vv)->frontSVertex()) + { + // -- View Vertex A' -- + (*vv)->setFrontEdgeA(vEdge, true); + (*vv)->setFrontEdgeB(newVEdge, false); + } + else + { + // -- View Vertex A' -- + (*vv)->setBackEdgeA(vEdge, true); + (*vv)->setBackEdgeB(newVEdge, false); + } + } +} + + /**********************************/ + /* */ + /* */ + /* ViewEdge */ + /* */ + /* */ + /**********************************/ + + +// inline Vec3r ViewEdge::orientation2d(int iCombination) const +// { +// return edge_orientation2d_function<ViewEdge>(*this, iCombination); +// } + +// inline Vec3r ViewEdge::orientation3d(int iCombination) const +// { +// return edge_orientation3d_function<ViewEdge>(*this, iCombination); +// } + +// inline real ViewEdge::z_discontinuity(int iCombination) const +// { +// return z_discontinuity_edge_function<ViewEdge>(*this, iCombination); +// } + +// inline float ViewEdge::local_average_depth(int iCombination ) const +// { +// return local_average_depth_edge_function<ViewEdge>(*this, iCombination); +// } + +// inline float ViewEdge::local_depth_variance(int iCombination) const +// { +// return local_depth_variance_edge_function<ViewEdge>(*this, iCombination); +// } + +// inline real ViewEdge::local_average_density(float sigma, int iCombination) const +// { +// return density_edge_function<ViewEdge>(*this, iCombination); +// } + +inline const SShape * ViewEdge::occluded_shape() const +{ + if(0 == _aShape) + return 0; + return _aShape->sshape(); +} + +// inline Vec3r ViewEdge::curvature2d_as_vector(int iCombination) const +// { +// return curvature2d_as_vector_edge_function<ViewEdge>(*this, iCombination); +// } + +// inline real ViewEdge::curvature2d_as_angle(int iCombination) const +// { +// return curvature2d_as_angle_edge_function<ViewEdge>(*this, iCombination); +// } + + +#endif // VIEWMAP_H diff --git a/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h b/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h new file mode 100755 index 00000000000..31abefbfb97 --- /dev/null +++ b/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h @@ -0,0 +1,691 @@ +// +// Filename : ViewMapAdvancedIterators.h +// Author(s) : Stephane Grabli +// Purpose : Iterators used to iterate over the various elements of the ViewMap +// These iterators can't be exported to python. +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef VIEWMAPADVANCEDITERATORS_H +# define VIEWMAPADVANCEDITERATORS_H + +#include "ViewMap.h" +#include "../system/Iterator.h" //soc + + /**********************************/ + /* */ + /* */ + /* ViewMap */ + /* */ + /* */ + /**********************************/ + + /**********************************/ + /* */ + /* */ + /* ViewVertex */ + /* */ + /* */ + /**********************************/ + +namespace ViewVertexInternal{ + + class edge_const_traits : public Const_traits< ::ViewVertex::directedViewEdge> { + public: + typedef vector< ::ViewVertex::directedViewEdge> edges_container; + typedef edges_container::const_iterator edges_container_iterator ; + typedef vector< ::ViewVertex::directedViewEdge*> edge_pointers_container; + typedef edge_pointers_container::const_iterator edge_pointers_container_iterator ; + }; + class edge_nonconst_traits : public Nonconst_traits< ::ViewVertex::directedViewEdge> { + public: + typedef vector< ::ViewVertex::directedViewEdge> edges_container; + typedef edges_container::iterator edges_container_iterator ; + typedef vector< ::ViewVertex::directedViewEdge*> edge_pointers_container; + typedef edge_pointers_container::iterator edge_pointers_container_iterator ; + }; + +template<class Traits> + class edge_iterator_base : public IteratorBase<Traits,InputIteratorTag_Traits> + { + public: + typedef typename Traits::value_type value_type; + typedef typename Traits::difference_type difference_type; + typedef typename Traits::pointer pointer; + typedef typename Traits::reference reference; + typedef edge_iterator_base<Traits> Self; + typedef typename Traits::edges_container_iterator edges_container_iterator; + typedef typename Traits::edge_pointers_container_iterator edge_pointers_container_iterator; + typedef edge_iterator_base<edge_nonconst_traits> iterator; + typedef edge_iterator_base<edge_const_traits> const_iterator; + public: + friend class ViewVertex; + friend class TVertex; + friend class NonTVertex; + friend class ViewEdge; + friend class edge_iterator; + protected: + Nature::VertexNature _Nature; // the nature of the underlying vertex + // T vertex attributes + edge_pointers_container_iterator _tbegin; + edge_pointers_container_iterator _tend; + edge_pointers_container_iterator _tvertex_iter; + + // mutable value_type _tvertex_iter; + // value_type _feA; + // value_type _feB; + // value_type _beA; + // value_type _beB; + + // Non TVertex attributes + edges_container_iterator _begin; + edges_container_iterator _end; + edges_container_iterator _nontvertex_iter; + + typedef IteratorBase<Traits,InputIteratorTag_Traits> parent_class; + + public: + inline edge_iterator_base() : parent_class() {} + inline edge_iterator_base(Nature::VertexNature iNature) + : parent_class() + {_Nature = iNature;} + edge_iterator_base(const edge_iterator_base<edge_nonconst_traits>& iBrother) + : parent_class(iBrother) + { + _Nature = iBrother._Nature; + if(_Nature & Nature::T_VERTEX) + { + // _feA = iBrother._feA; + // _feB = iBrother._feB; + // _beA = iBrother._beA; + // _beB = iBrother._beB; + // _tvertex_iter = iBrother._tvertex_iter; + _tbegin = iBrother._tbegin; + _tend = iBrother._tend; + _tvertex_iter = iBrother._tvertex_iter; + } + else + { + _begin = iBrother._begin; + _end = iBrother._end; + _nontvertex_iter = iBrother._nontvertex_iter; + } + } + edge_iterator_base(const edge_iterator_base<edge_const_traits>& iBrother) + : parent_class(iBrother) + { + _Nature = iBrother._Nature; + if(_Nature & Nature::T_VERTEX) + { + // _feA = iBrother._feA; + // _feB = iBrother._feB; + // _beA = iBrother._beA; + // _beB = iBrother._beB; + // _tvertex_iter = iBrother._tvertex_iter; + _tbegin = iBrother._tbegin; + _tend = iBrother._tend; + _tvertex_iter = iBrother._tvertex_iter; + } + else + { + _begin = iBrother._begin; + _end = iBrother._end; + _nontvertex_iter = iBrother._nontvertex_iter; + } + } + virtual ~edge_iterator_base() {} + //protected://FIXME + public: + // inline edge_iterator_base(value_type ifeA, + // value_type ifeB, + // value_type ibeA, + // value_type ibeB, + // value_type iter) + // : parent_class() + // { + // _Nature = Nature::T_VERTEX; + // _feA = ifeA; + // _feB = ifeB; + // _beA = ibeA; + // _beB = ibeB; + // _tvertex_iter = iter; + // } + inline edge_iterator_base(edge_pointers_container_iterator begin, + edge_pointers_container_iterator end, + edge_pointers_container_iterator iter) + : parent_class() + { + _Nature = Nature::T_VERTEX; + _tbegin = begin; + _tend = end; + _tvertex_iter = iter; + } + inline edge_iterator_base(edges_container_iterator begin, + edges_container_iterator end, + edges_container_iterator iter) + : parent_class() + { + _Nature = Nature::NON_T_VERTEX; + _begin = begin; + _end = end; + _nontvertex_iter = iter; + } + + public: + + + virtual bool begin() const + { + if(_Nature & Nature::T_VERTEX) + return (_tvertex_iter == _tbegin); + //return (_tvertex_iter == _feA); + else + return (_nontvertex_iter == _begin); + } + virtual bool end() const + { + if(_Nature & Nature::T_VERTEX) + //return (_tvertex_iter.first == 0); + return (_tvertex_iter == _tend); + else + return (_nontvertex_iter == _end); + } + + // operators + virtual Self& operator++() // operator corresponding to ++i + { + increment(); + return *this; + } + virtual Self operator++(int) // opérateur correspondant à i++ + { // c.a.d qui renvoie la valeur *puis* incrémente. + Self tmp = *this; // C'est pour cela qu'on stocke la valeur + increment(); // dans un temporaire. + return tmp; + } + + // comparibility + virtual bool operator!=(const Self& b) const + { + if(_Nature & Nature::T_VERTEX) + return (_tvertex_iter != b._tvertex_iter); + else + return (_nontvertex_iter != b._nontvertex_iter); + } + + virtual bool operator==(const Self& b) const + {return !(*this != b);} + + // dereferencing + virtual reference operator*() const + { + if(_Nature & Nature::T_VERTEX) + //return _tvertex_iter; + return **_tvertex_iter; + else + return (*_nontvertex_iter); + } + virtual pointer operator->() const { return &(operator*());} + + protected: + inline void increment() + { + if(_Nature & Nature::T_VERTEX) + { + value_type tmp = (**_tvertex_iter); + ++_tvertex_iter; + value_type tmp2 = (**_tvertex_iter); + if(tmp2.first == tmp.first) + ++_tvertex_iter; + // // Hack to deal with cusp. the result of a cusp + // // is a TVertex having two identical viewedges. + // // In order to iterate properly, we chose to + // // to skip these last ones. + // if(_feB.first == _beA.first) + // { + // if(_feA.first == _beB.first) + // { + // _tvertex_iter.first = 0; + // return; + // } + // + // if(_tvertex_iter.first == _feA.first) + // _tvertex_iter.first = _beB.first; + // else if(_tvertex_iter.first == _beB.first) + // _tvertex_iter.first = 0; + // else + // _tvertex_iter.first = _feA.first; + // return; + // } + // if(_feA.first == _beB.first) + // { + // if(_feB.first == _beA.first) + // { + // _tvertex_iter.first = 0; + // return; + // } + // + // if(_tvertex_iter.first == _feB.first) + // _tvertex_iter.first = _beA.first; + // else if(_tvertex_iter.first == _beA.first) + // _tvertex_iter.first = 0; + // else + // _tvertex_iter.first = _feB.first; + // return; + // } + // // End of hack + // + // if(_tvertex_iter.first == _feA.first){ + // // we return bea or beb + // + // + // // choose one of them + // + // _tvertex_iter.first = _feB.first; + // return; + // } + // if(_tvertex_iter.first == _feB.first) + // { + // _tvertex_iter.first = _beA.first; + // return; + // } + // if(_tvertex_iter.first == _beA.first) + // { + // _tvertex_iter.first = _beB.first; + // return; + // } + // if(_tvertex_iter.first == _beB.first) + // { + // _tvertex_iter.first = 0; + // return; + // } + } + else + ++_nontvertex_iter; + } + }; + + } + /**********************************/ + /* */ + /* */ + /* ViewEdge */ + /* */ + /* */ + /**********************************/ + +namespace ViewEdgeInternal { + + /*!----------------------*/ + /*! Iterators definition */ + /*!----------------------*/ + template<class Traits> + class edge_iterator_base : public IteratorBase<Traits,BidirectionalIteratorTag_Traits> + { + public: + typedef typename Traits::value_type value_type; + typedef typename Traits::difference_type difference_type; + typedef typename Traits::pointer pointer; + typedef typename Traits::reference reference; + typedef edge_iterator_base<Traits> Self; + public: + mutable value_type _ViewEdge; + //friend class edge_iterator_base<Nonconst_traits<ViewEdge*> >; + //friend class edge_iterator_base<Const_traits<ViewEdge*> >; + value_type _first; + bool _orientation; + typedef IteratorBase<Traits,BidirectionalIteratorTag_Traits> parent_class; + + public: + friend class ViewEdge; + inline edge_iterator_base() + : parent_class() + {_orientation=true;_first=0;} + + inline edge_iterator_base(const edge_iterator_base<Nonconst_traits< ::ViewEdge*> >& iBrother) + : parent_class() + { + _ViewEdge = iBrother._ViewEdge; + _first = iBrother._first; + _orientation = iBrother._orientation; + } + + inline edge_iterator_base(const edge_iterator_base<Const_traits< ::ViewEdge*> >& iBrother) + : parent_class() + { + _ViewEdge = iBrother._ViewEdge; + _first = iBrother._first; + _orientation = iBrother._orientation; + } + + //protected://FIXME + public: + inline edge_iterator_base(value_type iEdge, bool orientation = true) + : parent_class() + { + _ViewEdge = iEdge; + _first = iEdge; + _orientation = orientation; + } + + + public: + virtual Self* clone() const + { + return new edge_iterator_base(*this); + } + virtual ~edge_iterator_base() {} + + public: + + virtual bool orientation() {return _orientation;} + virtual void set_edge(value_type iVE) {_ViewEdge=iVE;} + virtual void set_orientation(bool iOrientation) {_orientation = iOrientation;} + virtual void change_orientation() {_orientation = !_orientation;} + + // operators + inline Self& operator++() // operator corresponding to ++i + { + //++_ViewEdge->getTimeStamp(); + increment(); + return *this; + } + inline Self operator++(int) // opérateur correspondant à i++ + { // c.a.d qui renvoie la valeur *puis* incrémente. + //++_ViewEdge->getTimeStamp(); + Self tmp = *this; // C'est pour cela qu'on stocke la valeur + increment(); // dans un temporaire. + return tmp; + } + inline Self& operator--() // operator corresponding to ++i + { + //++_ViewEdge->getTimeStamp(); + decrement(); + return *this; + } + inline Self operator--(int) // opérateur correspondant à i++ + { // c.a.d qui renvoie la valeur *puis* incrémente. + //++_ViewEdge->getTimeStamp(); + Self tmp = *this; // C'est pour cela qu'on stocke la valeur + decrement(); // dans un temporaire. + return tmp; + } + + // comparibility + virtual bool operator!=(const Self& b) const + { + return (_ViewEdge != b._ViewEdge); + } + virtual bool operator==(const Self& b) const + { + return !(*this != b); + } + + // dereferencing + virtual reference operator*() const {return (_ViewEdge);} + virtual pointer operator->() const { return &(operator*());} + + public: + virtual bool begin() const {return _ViewEdge==_first ? true : false;} + virtual bool end() const {return _ViewEdge==0 ? true : false;} + + protected: + virtual void increment() {} + virtual void decrement() {} + }; + + template<class Traits> + class fedge_iterator_base : public IteratorBase<Traits,BidirectionalIteratorTag_Traits> + { + public: + typedef typename Traits::value_type value_type; + typedef typename Traits::difference_type difference_type; + typedef typename Traits::pointer pointer; + typedef typename Traits::reference reference; + typedef fedge_iterator_base<Traits> Self; + public: + typedef IteratorBase<Traits,BidirectionalIteratorTag_Traits> parent_class; + mutable value_type _FEdge; + value_type _first; + value_type _FEdgeB; // last fedge of the view edge + + public: + friend class ::ViewEdge; + friend class fedge_iterator; + inline fedge_iterator_base() + : parent_class() + {} + inline fedge_iterator_base(const fedge_iterator_base<Nonconst_traits<FEdge*> >& iBrother) + : parent_class() + { + _FEdge = iBrother._FEdge; + _first = iBrother._first; + _FEdgeB = iBrother._FEdgeB; + } + inline fedge_iterator_base(const fedge_iterator_base<Const_traits<FEdge*> >& iBrother) + : parent_class() + { + _FEdge = iBrother._FEdge; + _first = iBrother._first; + _FEdgeB = iBrother._FEdgeB; + } + //protected://FIXME + public: + inline fedge_iterator_base(value_type iEdge, value_type iFEdgeB) + : parent_class() + { + _FEdge = iEdge; + _first = iEdge; + _FEdgeB = iFEdgeB; + } + + public: + virtual ~fedge_iterator_base() {} + // operators + inline Self& operator++() // operator corresponding to ++i + { + increment(); + return *this; + } + inline Self operator++(int) // opérateur correspondant à i++ + { // c.a.d qui renvoie la valeur *puis* incrémente. + Self tmp = *this; // C'est pour cela qu'on stocke la valeur + increment(); // dans un temporaire. + return tmp; + } + inline Self& operator--() // operator corresponding to ++i + { + decrement(); + return *this; + } + inline Self operator--(int) // opérateur correspondant à i++ + { // c.a.d qui renvoie la valeur *puis* incrémente. + Self tmp = *this; // C'est pour cela qu'on stocke la valeur + decrement(); // dans un temporaire. + return tmp; + } + + // comparibility + virtual bool operator!=(const Self& b) const + { + return (_FEdge != b._FEdge); + } + virtual bool operator==(const Self& b) const + { + return !(*this != b); + } + + // dereferencing + virtual reference operator*() const {return (_FEdge);} + virtual pointer operator->() const { return &(operator*());} + + + public: + virtual bool begin() const {return _FEdge==_first ? true : false;} + virtual bool end() const {return _FEdge==0 ? true : false;} + protected: + virtual void increment() + { + _FEdge = _FEdge->nextEdge(); // we don't change or + } + + virtual void decrement() + { + if(0 == _FEdge) + { + _FEdge = _FEdgeB; + return; + } + _FEdge = _FEdge->previousEdge(); // we don't change or + } + }; + + template<class Traits> + class vertex_iterator_base : public IteratorBase<Traits,BidirectionalIteratorTag_Traits> + { + public: + typedef typename Traits::value_type value_type; + typedef typename Traits::difference_type difference_type; + typedef typename Traits::pointer pointer; + typedef typename Traits::reference reference; + typedef vertex_iterator_base<Traits> Self; + protected: + typedef IteratorBase<Traits,BidirectionalIteratorTag_Traits> parent_class; + public: + mutable value_type _SVertex; + FEdge *_NextFEdge; + FEdge *_PreviousFEdge; + public: + friend class ViewEdge; + friend class vertex_iterator; + inline vertex_iterator_base() + : parent_class() + {} + inline vertex_iterator_base(const vertex_iterator_base<Const_traits<SVertex*> >& iBrother) + : parent_class() + { + _SVertex = iBrother._SVertex; + _NextFEdge = iBrother._NextFEdge; + _PreviousFEdge = iBrother._PreviousFEdge; + } + inline vertex_iterator_base(const vertex_iterator_base<Nonconst_traits<SVertex*> >& iBrother) + : parent_class() + { + _SVertex = iBrother._SVertex; + _NextFEdge = iBrother._NextFEdge; + _PreviousFEdge = iBrother._PreviousFEdge; + } + + //protected://FIXME + public: + + inline vertex_iterator_base(value_type iVertex, FEdge *iPreviousFEdge, FEdge *iNextFEdge) + : parent_class() + { + _SVertex = iVertex; + _NextFEdge = iNextFEdge; + _PreviousFEdge = iPreviousFEdge; + } + + public: + virtual ~vertex_iterator_base() {} + + virtual bool begin() const {return _PreviousFEdge==0? true : false;} + virtual bool end() const {return _SVertex==0 ? true : false;} + + // operators + inline Self& operator++() // operator corresponding to ++i + { + increment(); + return *this; + } + inline Self operator++(int) // opérateur correspondant à i++ + { // c.a.d qui renvoie la valeur *puis* incrémente. + Self tmp = *this; // C'est pour cela qu'on stocke la valeur + increment(); // dans un temporaire. + return tmp; + } + inline Self& operator--() // operator corresponding to ++i + { + decrement(); + return *this; + } + inline Self operator--(int) // opérateur correspondant à i++ + { // c.a.d qui renvoie la valeur *puis* incrémente. + Self tmp = *this; // C'est pour cela qu'on stocke la valeur + decrement(); // dans un temporaire. + return tmp; + } + + // comparibility + virtual bool operator!=(const Self& b) const + { + return (_SVertex != b._SVertex); + } + virtual bool operator==(const Self& b) const + { + return !(*this != b); + } + + // dereferencing + virtual reference operator*() const {return (_SVertex);} + virtual pointer operator->() const { return &(operator*());} + + protected: + virtual void increment() + { + if(0 == _NextFEdge) + { + _SVertex = 0; + return; + } + + _SVertex = _NextFEdge->vertexB(); + _PreviousFEdge = _NextFEdge; + _NextFEdge = _NextFEdge->nextEdge(); + + } + virtual void decrement() + { + // if(0 == _SVertex) + // { + // _SVertex = _PreviousFEdge->vertexB(); + // return; + // } + if(0 == _PreviousFEdge) + { + _SVertex = 0; + return; + } + _SVertex = _PreviousFEdge->vertexA(); + _NextFEdge = _PreviousFEdge; + _PreviousFEdge = _PreviousFEdge->previousEdge(); + } + }; + + +} // end of namespace ViewEdgeInternal + +#endif // VIEWMAPADVANCEDITERATORS_H diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp new file mode 100755 index 00000000000..dbd046f050a --- /dev/null +++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp @@ -0,0 +1,1063 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "ViewMapBuilder.h" +#include <algorithm> + +using namespace std; + +ViewMap* ViewMapBuilder::BuildViewMap(WingedEdge& we, visibility_algo iAlgo, real epsilon) { + _ViewMap = new ViewMap; + _currentId = 1; + _currentFId = 0; + _currentSVertexId = 0; + + // Builds initial view edges + computeInitialViewEdges(we); + + // Detects cusps + computeCusps(_ViewMap); + + // Compute intersections + ComputeIntersections(_ViewMap, sweep_line, epsilon); + + // Compute visibility + ComputeEdgesVisibility(_ViewMap, iAlgo, _Grid, epsilon); + + return _ViewMap; +} + +void ViewMapBuilder::computeInitialViewEdges(WingedEdge& we) +{ + vector<WShape*> wshapes = we.getWShapes(); + SShape* psShape; + + for (vector<WShape*>::const_iterator it = wshapes.begin(); + it != wshapes.end(); + it++) { + // create the embedding + psShape = new SShape; + psShape->setId((*it)->GetId()); + psShape->setName((*it)->getName()); + psShape->setFrsMaterials((*it)->frs_materials()); // FIXME + + // create the view shape + ViewShape * vshape = new ViewShape(psShape); + // add this view shape to the view map: + _ViewMap->AddViewShape(vshape); + + _pViewEdgeBuilder->setCurrentViewId(_currentId); // we want to number the view edges in a unique way for the while scene. + _pViewEdgeBuilder->setCurrentFId(_currentFId); // we want to number the feature edges in a unique way for the while scene. + _pViewEdgeBuilder->setCurrentSVertexId(_currentFId); // we want to number the SVertex in a unique way for the while scene. + _pViewEdgeBuilder->BuildViewEdges(dynamic_cast<WXShape*>(*it), vshape, + _ViewMap->ViewEdges(), + _ViewMap->ViewVertices(), + _ViewMap->FEdges(), + _ViewMap->SVertices()); + + _currentId = _pViewEdgeBuilder->currentViewId()+1; + _currentFId = _pViewEdgeBuilder->currentFId()+1; + _currentSVertexId = _pViewEdgeBuilder->currentSVertexId()+1; + + psShape->ComputeBBox(); + } +} + +void ViewMapBuilder::computeCusps(ViewMap *ioViewMap){ + vector<ViewVertex*> newVVertices; + vector<ViewEdge*> newVEdges; + ViewMap::viewedges_container& vedges = ioViewMap->ViewEdges(); + ViewMap::viewedges_container::iterator ve=vedges.begin(), veend=vedges.end(); + for(; + ve!=veend; + ++ve){ + if((!((*ve)->getNature() & Nature::SILHOUETTE)) || (!((*ve)->fedgeA()->isSmooth()))) + continue; + FEdge *fe = (*ve)->fedgeA(); + FEdge * fefirst = fe; + bool first = true; + bool positive = true; + do{ + FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(fe); + Vec3r A((fes)->vertexA()->point3d()); + Vec3r B((fes)->vertexB()->point3d()); + Vec3r AB(B-A); + AB.normalize(); + Vec3r m((A+B)/2.0); + Vec3r crossP(AB^(fes)->normal()); + crossP.normalize(); + Vec3r viewvector; + if (_orthographicProjection) { + viewvector = Vec3r(0.0, 0.0, m.z()-_viewpoint.z()); + } else { + viewvector = Vec3r(m-_viewpoint); + } + viewvector.normalize(); + if(first){ + if(((crossP)*(viewvector)) > 0) + positive = true; + else + positive = false; + first = false; + } + // If we're in a positive part, we need + // a stronger negative value to change + NonTVertex *cusp = 0; + if(positive){ + if(((crossP)*(viewvector)) < -0.1){ + // state changes + positive = false; + // creates and insert cusp + cusp = dynamic_cast<NonTVertex*>(ioViewMap->InsertViewVertex(fes->vertexA(), newVEdges)); + if(cusp!=0) + cusp->setNature(cusp->getNature()|Nature::CUSP); + } + + }else{ + // If we're in a negative part, we need + // a stronger negative value to change + if(((crossP)*(viewvector)) > 0.1){ + positive = true; + cusp = dynamic_cast<NonTVertex*>(ioViewMap->InsertViewVertex(fes->vertexA(), newVEdges)); + if(cusp!=0) + cusp->setNature(cusp->getNature()|Nature::CUSP); + } + } + fe = fe->nextEdge(); + }while((fe!=0) && (fe!=fefirst)); + } + for(ve=newVEdges.begin(), veend=newVEdges.end(); + ve!=veend; + ++ve){ + (*ve)->viewShape()->AddEdge(*ve); + vedges.push_back(*ve); + } +} +void ViewMapBuilder::ComputeEdgesVisibility(ViewMap *ioViewMap, visibility_algo iAlgo, Grid *iGrid, real epsilon) +{ + if((iAlgo == ray_casting || + iAlgo == ray_casting_fast || + iAlgo == ray_casting_very_fast) && (NULL == iGrid)) + { + cerr << "Error: can't cast ray, no grid defined" << endl; + return; + } + + switch(iAlgo) + { + case ray_casting: + ComputeRayCastingVisibility(ioViewMap, iGrid, epsilon); + break; + case ray_casting_fast: + ComputeFastRayCastingVisibility(ioViewMap, iGrid, epsilon); + break; + case ray_casting_very_fast: + ComputeVeryFastRayCastingVisibility(ioViewMap, iGrid, epsilon); + break; + default: + break; + } +} + +static const unsigned gProgressBarMaxSteps = 10; +static const unsigned gProgressBarMinSize = 2000; + +void ViewMapBuilder::ComputeRayCastingVisibility(ViewMap *ioViewMap, Grid* iGrid, real epsilon) +{ + vector<ViewEdge*>& vedges = ioViewMap->ViewEdges(); + bool progressBarDisplay = false; + unsigned progressBarStep = 0; + unsigned vEdgesSize = vedges.size(); + unsigned fEdgesSize = ioViewMap->FEdges().size(); + + if(_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) { + unsigned progressBarSteps = min(gProgressBarMaxSteps, vEdgesSize); + progressBarStep = vEdgesSize / progressBarSteps; + _pProgressBar->reset(); + _pProgressBar->setLabelText("Computing Ray casting Visibility"); + _pProgressBar->setTotalSteps(progressBarSteps); + _pProgressBar->setProgress(0); + progressBarDisplay = true; + } + + unsigned counter = progressBarStep; + FEdge * fe, *festart; + int nSamples = 0; + vector<Polygon3r*> aFaces; + Polygon3r *aFace = 0; + unsigned tmpQI = 0; + unsigned qiClasses[256]; + unsigned maxIndex, maxCard; + unsigned qiMajority; + static unsigned timestamp = 1; + for(vector<ViewEdge*>::iterator ve=vedges.begin(), veend=vedges.end(); + ve!=veend; + ve++) + { + festart = (*ve)->fedgeA(); + fe = (*ve)->fedgeA(); + qiMajority = 1; + do { + qiMajority++; + fe = fe->nextEdge(); + } while (fe && fe != festart); + qiMajority >>= 1; + + tmpQI = 0; + maxIndex = 0; + maxCard = 0; + nSamples = 0; + fe = (*ve)->fedgeA(); + memset(qiClasses, 0, 256 * sizeof(*qiClasses)); + set<ViewShape*> occluders; + do + { + if((maxCard < qiMajority)) { + tmpQI = ComputeRayCastingVisibility(fe, iGrid, epsilon, occluders, &aFace, timestamp++); + + if(tmpQI >= 256) + cerr << "Warning: too many occluding levels" << endl; + + if (++qiClasses[tmpQI] > maxCard) { + maxCard = qiClasses[tmpQI]; + maxIndex = tmpQI; + } + } + FindOccludee(fe, iGrid, epsilon, &aFace, timestamp++); + + if(aFace) { + fe->setaFace(*aFace); + aFaces.push_back(aFace); + fe->setOccludeeEmpty(false); + } + else + fe->setOccludeeEmpty(true); + + ++nSamples; + fe = fe->nextEdge(); + } + while((maxCard < qiMajority) && (0!=fe) && (fe!=festart)); + + // ViewEdge + // qi -- + (*ve)->setQI(maxIndex); + // occluders -- + for(set<ViewShape*>::iterator o=occluders.begin(), oend=occluders.end(); + o!=oend; + ++o) + (*ve)->AddOccluder((*o)); + // occludee -- + if(!aFaces.empty()) + { + if(aFaces.size() <= (float)nSamples/2.f) + { + (*ve)->setaShape(0); + } + else + { + vector<Polygon3r*>::iterator p = aFaces.begin(); + WFace * wface = (WFace*)((*p)->userdata); + ViewShape *vshape = ioViewMap->viewShape(wface->GetVertex(0)->shape()->GetId()); + ++p; + (*ve)->setaShape(vshape); + } + } + + if(progressBarDisplay) { + counter--; + if (counter <= 0) { + counter = progressBarStep; + _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); + } + } + aFaces.clear(); + } +} + +void ViewMapBuilder::ComputeFastRayCastingVisibility(ViewMap *ioViewMap, Grid* iGrid, real epsilon) +{ + vector<ViewEdge*>& vedges = ioViewMap->ViewEdges(); + bool progressBarDisplay = false; + unsigned progressBarStep = 0; + unsigned vEdgesSize = vedges.size(); + unsigned fEdgesSize = ioViewMap->FEdges().size(); + + if(_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) { + unsigned progressBarSteps = min(gProgressBarMaxSteps, vEdgesSize); + progressBarStep = vEdgesSize / progressBarSteps; + _pProgressBar->reset(); + _pProgressBar->setLabelText("Computing Ray casting Visibility"); + _pProgressBar->setTotalSteps(progressBarSteps); + _pProgressBar->setProgress(0); + progressBarDisplay = true; + } + + unsigned counter = progressBarStep; + FEdge * fe, *festart; + unsigned nSamples = 0; + vector<Polygon3r*> aFaces; + Polygon3r *aFace = 0; + unsigned tmpQI = 0; + unsigned qiClasses[256]; + unsigned maxIndex, maxCard; + unsigned qiMajority; + static unsigned timestamp = 1; + bool even_test; + for(vector<ViewEdge*>::iterator ve=vedges.begin(), veend=vedges.end(); + ve!=veend; + ve++) + { + festart = (*ve)->fedgeA(); + fe = (*ve)->fedgeA(); + qiMajority = 1; + do { + qiMajority++; + fe = fe->nextEdge(); + } while (fe && fe != festart); + if (qiMajority >= 4) + qiMajority >>= 2; + else + qiMajority = 1; + + set<ViewShape*> occluders; + + even_test = true; + maxIndex = 0; + maxCard = 0; + nSamples = 0; + memset(qiClasses, 0, 256 * sizeof(*qiClasses)); + fe = (*ve)->fedgeA(); + do + { + if (even_test) + { + if((maxCard < qiMajority)) { + tmpQI = ComputeRayCastingVisibility(fe, iGrid, epsilon, occluders, &aFace, timestamp++); + + if(tmpQI >= 256) + cerr << "Warning: too many occluding levels" << endl; + + if (++qiClasses[tmpQI] > maxCard) { + maxCard = qiClasses[tmpQI]; + maxIndex = tmpQI; + } + } + FindOccludee(fe, iGrid, epsilon, &aFace, timestamp++); + + if(aFace) + { + fe->setaFace(*aFace); + aFaces.push_back(aFace); + } + ++nSamples; + even_test = false; + } + else + even_test = true; + fe = fe->nextEdge(); + } while ((maxCard < qiMajority) && (0!=fe) && (fe!=festart)); + + (*ve)->setQI(maxIndex); + + if(!aFaces.empty()) + { + if(aFaces.size() < nSamples / 2) + { + (*ve)->setaShape(0); + } + else + { + vector<Polygon3r*>::iterator p = aFaces.begin(); + WFace * wface = (WFace*)((*p)->userdata); + ViewShape *vshape = ioViewMap->viewShape(wface->GetVertex(0)->shape()->GetId()); + ++p; + // for(; + // p!=pend; + // ++p) + // { + // WFace *f = (WFace*)((*p)->userdata); + // ViewShape *vs = ioViewMap->viewShape(f->GetVertex(0)->shape()->GetId()); + // if(vs != vshape) + // { + // sameShape = false; + // break; + // } + // } + // if(sameShape) + (*ve)->setaShape(vshape); + } + } + + //(*ve)->setaFace(aFace); + + if(progressBarDisplay) { + counter--; + if (counter <= 0) { + counter = progressBarStep; + _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); + } + } + aFaces.clear(); + } +} + +void ViewMapBuilder::ComputeVeryFastRayCastingVisibility(ViewMap *ioViewMap, Grid* iGrid, real epsilon) +{ + vector<ViewEdge*>& vedges = ioViewMap->ViewEdges(); + bool progressBarDisplay = false; + unsigned progressBarStep = 0; + unsigned vEdgesSize = vedges.size(); + unsigned fEdgesSize = ioViewMap->FEdges().size(); + + if(_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) { + unsigned progressBarSteps = min(gProgressBarMaxSteps, vEdgesSize); + progressBarStep = vEdgesSize / progressBarSteps; + _pProgressBar->reset(); + _pProgressBar->setLabelText("Computing Ray casting Visibility"); + _pProgressBar->setTotalSteps(progressBarSteps); + _pProgressBar->setProgress(0); + progressBarDisplay = true; + } + + unsigned counter = progressBarStep; + FEdge* fe; + unsigned qi = 0; + Polygon3r *aFace = 0; + static unsigned timestamp = 1; + for(vector<ViewEdge*>::iterator ve=vedges.begin(), veend=vedges.end(); + ve!=veend; + ve++) + { + set<ViewShape*> occluders; + + fe = (*ve)->fedgeA(); + qi = ComputeRayCastingVisibility(fe, iGrid, epsilon, occluders, &aFace, timestamp++); + if(aFace) + { + fe->setaFace(*aFace); + WFace * wface = (WFace*)(aFace->userdata); + ViewShape *vshape = ioViewMap->viewShape(wface->GetVertex(0)->shape()->GetId()); + (*ve)->setaShape(vshape); + } + else + { + (*ve)->setaShape(0); + } + + (*ve)->setQI(qi); + + if(progressBarDisplay) { + counter--; + if (counter <= 0) { + counter = progressBarStep; + _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); + } + } + } +} + + +void ViewMapBuilder::FindOccludee(FEdge *fe, Grid* iGrid, real epsilon, Polygon3r** oaPolygon, unsigned timestamp, + Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edge, vector<WVertex*>& faceVertices) +{ + WFace *face = 0; + if(fe->isSmooth()){ + FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(fe); + face = (WFace*)fes->face(); + } + OccludersSet occluders; + WFace * oface; + bool skipFace; + + WVertex::incoming_edge_iterator ie; + OccludersSet::iterator p, pend; + + *oaPolygon = 0; + if(((fe)->getNature() & Nature::SILHOUETTE) || ((fe)->getNature() & Nature::BORDER)) + { + occluders.clear(); + // we cast a ray from A in the same direction but looking behind + Vec3r v(-u[0],-u[1],-u[2]); + iGrid->castInfiniteRay(A, v, occluders, timestamp); + + bool noIntersection = true; + real mint=FLT_MAX; + // we met some occluders, let us fill the aShape field + // with the first intersected occluder + for(p=occluders.begin(),pend=occluders.end(); + p!=pend; + p++) + { + // check whether the edge and the polygon plane are coincident: + //------------------------------------------------------------- + //first let us compute the plane equation. + oface = (WFace*)(*p)->userdata; + Vec3r v1(((*p)->getVertices())[0]); + Vec3r normal((*p)->getNormal()); + real d = -(v1 * normal); + real t,t_u,t_v; + + if(0 != face) + { + skipFace = false; + + if(face == oface) + continue; + + if(faceVertices.empty()) + continue; + + for(vector<WVertex*>::iterator fv=faceVertices.begin(), fvend=faceVertices.end(); + fv!=fvend; + ++fv) + { + if((*fv)->isBoundary()) + continue; + WVertex::incoming_edge_iterator iebegin=(*fv)->incoming_edges_begin(); + WVertex::incoming_edge_iterator ieend=(*fv)->incoming_edges_end(); + for(ie=iebegin;ie!=ieend; ++ie) + { + if((*ie) == 0) + continue; + + WFace * sface = (*ie)->GetbFace(); + if(sface == oface) + { + skipFace = true; + break; + } + } + if(skipFace) + break; + } + if(skipFace) + continue; + } + else + { + if(GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edge, normal, d, t, epsilon)) + continue; + } + if((*p)->rayIntersect(A, v, t,t_u,t_v)) + { + if (fabs(v * normal) > 0.0001) + if ((t>0.0)) // && (t<1.0)) + { + if (t<mint) + { + *oaPolygon = (*p); + mint = t; + noIntersection = false; + fe->setOccludeeIntersection(Vec3r(A+t*v)); + } + } + } + } + + if(noIntersection) + *oaPolygon = 0; + } +} + +void ViewMapBuilder::FindOccludee(FEdge *fe, Grid* iGrid, real epsilon, Polygon3r** oaPolygon, unsigned timestamp) +{ + OccludersSet occluders; + + Vec3r A; + Vec3r edge; + Vec3r origin; + A = Vec3r(((fe)->vertexA()->point3D() + (fe)->vertexB()->point3D())/2.0); + edge = Vec3r((fe)->vertexB()->point3D()-(fe)->vertexA()->point3D()); + origin = Vec3r((fe)->vertexA()->point3D()); + Vec3r u; + if (_orthographicProjection) { + u = Vec3r(0.0, 0.0, _viewpoint.z()-A.z()); + } else { + u = Vec3r(_viewpoint-A); + } + u.normalize(); + if(A < iGrid->getOrigin()) + cerr << "Warning: point is out of the grid for fedge " << fe->getId().getFirst() << "-" << fe->getId().getSecond() << endl; + + vector<WVertex*> faceVertices; + + WFace *face = 0; + if(fe->isSmooth()){ + FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(fe); + face = (WFace*)fes->face(); + } + if(0 != face) + face->RetrieveVertexList(faceVertices); + + return FindOccludee(fe,iGrid, epsilon, oaPolygon, timestamp, + u, A, origin, edge, faceVertices); +} + +int ViewMapBuilder::ComputeRayCastingVisibility(FEdge *fe, Grid* iGrid, real epsilon, set<ViewShape*>& oOccluders, + Polygon3r** oaPolygon, unsigned timestamp) +{ + OccludersSet occluders; + int qi = 0; + + Vec3r center; + Vec3r edge; + Vec3r origin; + + center = fe->center3d(); + edge = Vec3r(fe->vertexB()->point3D() - fe->vertexA()->point3D()); + origin = Vec3r(fe->vertexA()->point3D()); + // + // // Is the edge outside the view frustum ? + Vec3r gridOrigin(iGrid->getOrigin()); + Vec3r gridExtremity(iGrid->getOrigin()+iGrid->gridSize()); + + if( (center.x() < gridOrigin.x()) || (center.y() < gridOrigin.y()) || (center.z() < gridOrigin.z()) + ||(center.x() > gridExtremity.x()) || (center.y() > gridExtremity.y()) || (center.z() > gridExtremity.z())){ + cerr << "Warning: point is out of the grid for fedge " << fe->getId() << endl; + //return 0; + } + + + // Vec3r A(fe->vertexA()->point2d()); + // Vec3r B(fe->vertexB()->point2d()); + // int viewport[4]; + // SilhouetteGeomEngine::retrieveViewport(viewport); + // if( (A.x() < viewport[0]) || (A.x() > viewport[2]) || (A.y() < viewport[1]) || (A.y() > viewport[3]) + // ||(B.x() < viewport[0]) || (B.x() > viewport[2]) || (B.y() < viewport[1]) || (B.y() > viewport[3])){ + // cerr << "Warning: point is out of the grid for fedge " << fe->getId() << endl; + // //return 0; + // } + + Vec3r vp; + if (_orthographicProjection) { + vp = Vec3r(center.x(), center.y(), _viewpoint.z()); + } else { + vp = Vec3r(_viewpoint); + } + Vec3r u(vp - center); + real raylength = u.norm(); + u.normalize(); + //cout << "grid origin " << iGrid->getOrigin().x() << "," << iGrid->getOrigin().y() << "," << iGrid->getOrigin().z() << endl; + //cout << "center " << center.x() << "," << center.y() << "," << center.z() << endl; + + iGrid->castRay(center, vp, occluders, timestamp); + + WFace *face = 0; + if(fe->isSmooth()){ + FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(fe); + face = (WFace*)fes->face(); + } + vector<WVertex*> faceVertices; + WVertex::incoming_edge_iterator ie; + + WFace * oface; + bool skipFace; + OccludersSet::iterator p, pend; + if(face) + face->RetrieveVertexList(faceVertices); + + for(p=occluders.begin(),pend=occluders.end(); + p!=pend; + p++) + { + // If we're dealing with an exact silhouette, check whether + // we must take care of this occluder of not. + // (Indeed, we don't consider the occluders that + // share at least one vertex with the face containing + // this edge). + //----------- + oface = (WFace*)(*p)->userdata; + Vec3r v1(((*p)->getVertices())[0]); + Vec3r normal((*p)->getNormal()); + real d = -(v1 * normal); + real t, t_u, t_v; + + if(0 != face) + { + skipFace = false; + + if(face == oface) + continue; + + + for(vector<WVertex*>::iterator fv=faceVertices.begin(), fvend=faceVertices.end(); + fv!=fvend; + ++fv) + { + if((*fv)->isBoundary()) + continue; + + WVertex::incoming_edge_iterator iebegin=(*fv)->incoming_edges_begin(); + WVertex::incoming_edge_iterator ieend=(*fv)->incoming_edges_end(); + for(ie=iebegin;ie!=ieend; ++ie) + { + if((*ie) == 0) + continue; + + WFace * sface = (*ie)->GetbFace(); + //WFace * sfacea = (*ie)->GetaFace(); + //if((sface == oface) || (sfacea == oface)) + if(sface == oface) + { + skipFace = true; + break; + } + } + if(skipFace) + break; + } + if(skipFace) + continue; + } + else + { + // check whether the edge and the polygon plane are coincident: + //------------------------------------------------------------- + //first let us compute the plane equation. + + if(GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edge, normal, d, t, epsilon)) + continue; + } + + if((*p)->rayIntersect(center, u, t, t_u, t_v)) + { + if (fabs(u * normal) > 0.0001) + if ((t>0.0) && (t<raylength)) + { + WFace *f = (WFace*)((*p)->userdata); + ViewShape *vshape = _ViewMap->viewShape(f->GetVertex(0)->shape()->GetId()); + oOccluders.insert(vshape); + ++qi; + if(!_EnableQI) + break; + } + } + } + + // Find occludee + FindOccludee(fe,iGrid, epsilon, oaPolygon, timestamp, + u, center, edge, origin, faceVertices); + + return qi; +} + +void ViewMapBuilder::ComputeIntersections(ViewMap *ioViewMap, intersection_algo iAlgo, real epsilon) +{ + switch(iAlgo) + { + case sweep_line: + ComputeSweepLineIntersections(ioViewMap, epsilon); + break; + default: + break; + } + ViewMap::viewvertices_container& vvertices = ioViewMap->ViewVertices(); + for(ViewMap::viewvertices_container::iterator vv=vvertices.begin(), vvend=vvertices.end(); + vv!=vvend; + ++vv) + { + if((*vv)->getNature() == Nature::T_VERTEX) + { + TVertex *tvertex = (TVertex*)(*vv); + cout << "TVertex " << tvertex->getId() << " has :" << endl; + cout << "FrontEdgeA: " << tvertex->frontEdgeA().first << endl; + cout << "FrontEdgeB: " << tvertex->frontEdgeB().first << endl; + cout << "BackEdgeA: " << tvertex->backEdgeA().first << endl; + cout << "BackEdgeB: " << tvertex->backEdgeB().first << endl << endl; + } + } +} + +struct less_SVertex2D : public binary_function<SVertex*, SVertex*, bool> +{ + real epsilon; + less_SVertex2D(real eps) + : binary_function<SVertex*,SVertex*,bool>() + { + epsilon = eps; + } + bool operator()(SVertex* x, SVertex* y) + { + Vec3r A = x->point2D(); + Vec3r B = y->point2D(); + for(unsigned int i=0; i<3; i++) + { + if((fabs(A[i] - B[i])) < epsilon) + continue; + if(A[i] < B[i]) + return true; + if(A[i] > B[i]) + return false; + } + + return false; + } +}; + +typedef Segment<FEdge*,Vec3r > segment; +typedef Intersection<segment> intersection; + +struct less_Intersection : public binary_function<intersection*, intersection*, bool> +{ + segment *edge; + less_Intersection(segment *iEdge) + : binary_function<intersection*,intersection*,bool>() + { + edge = iEdge; + } + bool operator()(intersection* x, intersection* y) + { + real tx = x->getParameter(edge); + real ty = y->getParameter(edge); + if(tx > ty) + return true; + return false; + } +}; + +struct silhouette_binary_rule : public binary_rule<segment,segment> +{ + silhouette_binary_rule() : binary_rule<segment,segment>() {} + virtual bool operator() (segment& s1, segment& s2) + { + FEdge * f1 = s1.edge(); + FEdge * f2 = s2.edge(); + + if((!(((f1)->getNature() & Nature::SILHOUETTE) || ((f1)->getNature() & Nature::BORDER))) && (!(((f2)->getNature() & Nature::SILHOUETTE) || ((f2)->getNature() & Nature::BORDER)))) + return false; + + return true; + } +}; + +void ViewMapBuilder::ComputeSweepLineIntersections(ViewMap *ioViewMap, real epsilon) +{ + vector<SVertex*>& svertices = ioViewMap->SVertices(); + bool progressBarDisplay = false; + unsigned sVerticesSize = svertices.size(); + unsigned fEdgesSize = ioViewMap->FEdges().size(); + // ViewMap::fedges_container& fedges = ioViewMap->FEdges(); + // for(ViewMap::fedges_container::const_iterator f=fedges.begin(), end=fedges.end(); + // f!=end; + // ++f){ + // cout << (*f)->aMaterialIndex() << "-" << (*f)->bMaterialIndex() << endl; + // } + + unsigned progressBarStep = 0; + + if(_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) { + unsigned progressBarSteps = min(gProgressBarMaxSteps, sVerticesSize); + progressBarStep = sVerticesSize / progressBarSteps; + _pProgressBar->reset(); + _pProgressBar->setLabelText("Computing Sweep Line Intersections"); + _pProgressBar->setTotalSteps(progressBarSteps); + _pProgressBar->setProgress(0); + progressBarDisplay = true; + } + + unsigned counter = progressBarStep; + + sort(svertices.begin(), svertices.end(), less_SVertex2D(epsilon)); + + SweepLine<FEdge*,Vec3r> SL; + + vector<FEdge*>& ioEdges = ioViewMap->FEdges(); + + vector<segment* > segments; + + vector<FEdge*>::iterator fe,fend; + + for(fe=ioEdges.begin(), fend=ioEdges.end(); + fe!=fend; + fe++) + { + segment * s = new segment((*fe), (*fe)->vertexA()->point2D(), (*fe)->vertexB()->point2D()); + (*fe)->userdata = s; + segments.push_back(s); + } + + vector<segment*> vsegments; + for(vector<SVertex*>::iterator sv=svertices.begin(),svend=svertices.end(); + sv!=svend; + sv++) + { + const vector<FEdge*>& vedges = (*sv)->fedges(); + + for(vector<FEdge*>::const_iterator sve=vedges.begin(), sveend=vedges.end(); + sve!=sveend; + sve++) + { + vsegments.push_back((segment*)((*sve)->userdata)); + } + + Vec3r evt((*sv)->point2D()); + silhouette_binary_rule sbr; + SL.process(evt, vsegments, sbr, epsilon); + + if(progressBarDisplay) { + counter--; + if (counter <= 0) { + counter = progressBarStep; + _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); + } + } + vsegments.clear(); + } + + // reset userdata: + for(fe=ioEdges.begin(), fend=ioEdges.end(); + fe!=fend; + fe++) + (*fe)->userdata = NULL; + + // list containing the new edges resulting from splitting operations. + vector<FEdge*> newEdges; + + // retrieve the intersected edges: + vector<segment* >& iedges = SL.intersectedEdges(); + // retrieve the intersections: + vector<intersection*>& intersections = SL.intersections(); + + int id=0; + // create a view vertex for each intersection and linked this one + // with the intersection object + vector<intersection*>::iterator i, iend; + for(i=intersections.begin(),iend=intersections.end(); + i!=iend; + i++) + { + FEdge *fA = (*i)->EdgeA->edge(); + FEdge *fB = (*i)->EdgeB->edge(); + + Vec3r A1 = fA->vertexA()->point3D(); + Vec3r A2 = fA->vertexB()->point3D(); + Vec3r B1 = fB->vertexA()->point3D(); + Vec3r B2 = fB->vertexB()->point3D(); + + Vec3r a1 = fA->vertexA()->point2D(); + Vec3r a2 = fA->vertexB()->point2D(); + Vec3r b1 = fB->vertexA()->point2D(); + Vec3r b2 = fB->vertexB()->point2D(); + + real ta = (*i)->tA; + real tb = (*i)->tB; + + if((ta < -epsilon) || (ta > 1+epsilon)) + cerr << "Warning: 2D intersection out of range for edge " << fA->vertexA()->getId() << " - " << fA->vertexB()->getId() << endl; + + if((tb < -epsilon) || (tb > 1+epsilon)) + cerr << "Warning: 2D intersection out of range for edge " << fB->vertexA()->getId() << " - " << fB->vertexB()->getId() << endl; + + real Ta = SilhouetteGeomEngine::ImageToWorldParameter(fA, ta); + real Tb = SilhouetteGeomEngine::ImageToWorldParameter(fB, tb); + + if((Ta < -epsilon) || (Ta > 1+epsilon)) + cerr << "Warning: 3D intersection out of range for edge " << fA->vertexA()->getId() << " - " << fA->vertexB()->getId() << endl; + + if((Tb < -epsilon) || (Tb > 1+epsilon)) + cerr << "Warning: 3D intersection out of range for edge " << fB->vertexA()->getId() << " - " << fB->vertexB()->getId() << endl; + +#if 0 + if((Ta < -epsilon) || (Ta > 1+epsilon) || (Tb < -epsilon) || (Tb > 1+epsilon)) { + printf("ta %.12e\n", ta); + printf("tb %.12e\n", tb); + printf("a1 %e, %e -- b1 %e, %e\n", a1[0], a1[1], b1[0], b1[1]); + printf("a2 %e, %e -- b2 %e, %e\n", a2[0], a2[1], b2[0], b2[1]); + if((Ta < -epsilon) || (Ta > 1+epsilon)) + printf("Ta %.12e\n", Ta); + if((Tb < -epsilon) || (Tb > 1+epsilon)) + printf("Tb %.12e\n", Tb); + printf("A1 %e, %e, %e -- B1 %e, %e, %e\n", A1[0], A1[1], A1[2], B1[0], B1[1], B1[2]); + printf("A2 %e, %e, %e -- B2 %e, %e, %e\n", A2[0], A2[1], A2[2], B2[0], B2[1], B2[2]); + } +#endif + + TVertex * tvertex = ioViewMap->CreateTVertex(Vec3r(A1 + Ta*(A2-A1)), Vec3r(a1 + ta*(a2-a1)), fA, + Vec3r(B1 + Tb*(B2-B1)), Vec3r(b1 + tb*(b2-b1)), fB, id); + + (*i)->userdata = tvertex; + ++id; + } + + progressBarStep = 0; + + if(progressBarDisplay) { + unsigned iEdgesSize = iedges.size(); + unsigned progressBarSteps = min(gProgressBarMaxSteps, iEdgesSize); + progressBarStep = iEdgesSize / progressBarSteps; + _pProgressBar->reset(); + _pProgressBar->setLabelText("Splitting intersected edges"); + _pProgressBar->setTotalSteps(progressBarSteps); + _pProgressBar->setProgress(0); + } + + counter = progressBarStep; + + vector<TVertex*> edgeVVertices; + vector<ViewEdge*> newVEdges; + vector<segment* >::iterator s, send; + for(s=iedges.begin(),send=iedges.end(); + s!=send; + s++) + { + edgeVVertices.clear(); + newEdges.clear(); + newVEdges.clear(); + + FEdge* fedge = (*s)->edge(); + ViewEdge *vEdge = fedge->viewedge(); + ViewShape *shape = vEdge->viewShape(); + + vector<intersection*>& eIntersections = (*s)->intersections(); + // we first need to sort these intersections from farther to closer to A + sort(eIntersections.begin(), eIntersections.end(), less_Intersection(*s)); + for(i=eIntersections.begin(),iend=eIntersections.end(); + i!=iend; + i++) + edgeVVertices.push_back((TVertex*)(*i)->userdata); + + shape->SplitEdge(fedge, edgeVVertices, ioViewMap->FEdges(), ioViewMap->ViewEdges()); + + if(progressBarDisplay) { + counter--; + if (counter <= 0) { + counter = progressBarStep; + _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); + } + } + } + + // reset userdata: + for(fe=ioEdges.begin(), fend=ioEdges.end(); + fe!=fend; + fe++) + (*fe)->userdata = NULL; + + // delete segments + // if(!segments.empty()){ + // for(s=segments.begin(),send=segments.end(); + // s!=send; + // s++){ + // delete *s; + // } + // segments.clear(); + // } +} diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.h b/source/blender/freestyle/intern/view_map/ViewMapBuilder.h new file mode 100755 index 00000000000..12b1266fa12 --- /dev/null +++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.h @@ -0,0 +1,226 @@ +// +// Filename : ViewMapBuilder.h +// Author(s) : Stephane Grabli +// Purpose : Class to build silhouette edges from a +// Winged-Edge structure +// Date of creation : 25/03/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef VIEWMAPBUILDER_H +# define VIEWMAPBUILDER_H + +# include "Silhouette.h" +# include <vector> +# include "../system/FreestyleConfig.h" +# include "../geometry/Geom.h" +# include "../scene_graph/NodeGroup.h" +# include "../winged_edge/WXEdge.h" +# include "../geometry/GeomUtils.h" +# include "../geometry/Grid.h" +# include "../system/ProgressBar.h" +# include "../geometry/SweepLine.h" +# include "ViewMap.h" +# include "SilhouetteGeomEngine.h" +# include "../scene_graph/TriangleRep.h" +# include "../winged_edge/WEdge.h" +# include "ViewEdgeXBuilder.h" + + +using namespace Geometry; + +class LIB_VIEW_MAP_EXPORT ViewMapBuilder +{ +private: + + ViewMap * _ViewMap; // result + //SilhouetteGeomEngine _GeomEngine; + ProgressBar *_pProgressBar; + Vec3r _viewpoint; + bool _orthographicProjection; + Grid* _Grid; + ViewEdgeXBuilder *_pViewEdgeBuilder; + bool _EnableQI; + double _epsilon; + + // tmp values: + int _currentId; + int _currentFId; + int _currentSVertexId; + + +public: + + typedef enum { + sweep_line + } intersection_algo; + + typedef enum { + ray_casting, + ray_casting_fast, + ray_casting_very_fast + } visibility_algo; + + inline ViewMapBuilder() + { + _pProgressBar = 0; + _Grid = 0; + _currentId = 1; + _currentFId = 0; + _currentSVertexId = 0; + _pViewEdgeBuilder = new ViewEdgeXBuilder; + _EnableQI = true; + } + + inline ~ViewMapBuilder() + { + if(_pViewEdgeBuilder){ + delete _pViewEdgeBuilder; + _pViewEdgeBuilder = 0; + } + } + + /*! Compute Shapes from a WingedEdge containing a list of WShapes */ + void computeInitialViewEdges(WingedEdge&); + + /*! Compute Cusps */ + void computeCusps(ViewMap *ioViewMap); + /*! Detects cusps (for a single ViewEdge) among SVertices and builds a ViewVertex on top of + * each cusp SVertex + * We use a hysteresis approach to avoid noise. + */ + void DetectCusps(ViewEdge *ioEdge); + + + /*! Sets the current viewpoint */ + inline void setViewpoint(const Vec3r& ivp) {_viewpoint = ivp; SilhouetteGeomEngine::setViewpoint(ivp);} + + /*! Sets the current transformation + * iModelViewMatrix + * The 4x4 model view matrix, in column major order (openGL like). + * iProjection matrix + * The 4x4 projection matrix, in column major order (openGL like). + * iViewport + * The viewport. 4 real array: origin.x, origin.y, width, length + */ + inline void setTransform(const real iModelViewMatrix[4][4], + const real iProjectionMatrix[4][4], + const int iViewport[4], + real iFocalLength, + real iAspect, + real iFovy) { + _orthographicProjection = (iProjectionMatrix[3][3] != 0.0); + SilhouetteGeomEngine::setTransform(iModelViewMatrix, iProjectionMatrix, iViewport, iFocalLength); + } + + inline void setFrustum(real iZnear, real iZfar) { + SilhouetteGeomEngine::setFrustum(iZnear, iZfar); + } + + /*! Builds the scene view map + * returns the list the view map + * it is up to the caller to delete this ViewMap + * iWRoot + * The root group node containing the WEdge structured scene + */ + + ViewMap* BuildViewMap(WingedEdge& we, visibility_algo iAlgo = ray_casting, real epsilon=1e-06) ; + /*! computes the intersection between all 2D + * feature edges of the scene. + * ioViewMap + * The view map. It is modified by the method. + * The list of all features edges of the scene. + * Each time an intersection is found, the 2 intersecting + * edges are splitted (creating 2 new vertices) + * At the end, this list is updated with the adding + * of all new created edges (resulting from splitting). + * iAlgo + * The algo to use for computing the intersections + */ + void ComputeIntersections(ViewMap *ioViewMap, intersection_algo iAlgo = sweep_line, real epsilon=1e-06); + + /*! Computes the 2D scene silhouette edges visibility + * iGrid + * For the Ray Casting algorithm. + */ + void ComputeEdgesVisibility(ViewMap *ioViewMap, visibility_algo iAlgo= ray_casting, Grid* iGrid = 0, real epsilon=1e-6); + + void setGrid(Grid *iGrid) {_Grid = iGrid;} + + /*! accessors */ + + /*! Modifiers */ + inline void setProgressBar(ProgressBar *iProgressBar) {_pProgressBar = iProgressBar;} + inline void setEnableQI(bool iBool) {_EnableQI = iBool;} + +protected: + + /*! Computes intersections on all edges of the scene using a sweep line + * algorithm*/ + void ComputeSweepLineIntersections(ViewMap *ioViewMap, real epsilon = 1e-6); + + /*! Computes the 2D scene silhouette edges visibility + * using a ray casting. On each edge, a ray is cast + * to check its quantitative invisibility. The list + * of occluders are each time stored in the tested edge. + * ioViewMap + * The view map. + * The 2D scene silhouette edges as FEdges. + * These edges have already been splitted at their intersections points. + * Thus, these edges do not intersect anymore. + * The visibility corresponding to each edge of ioScene is set is this + * edge. + */ + void ComputeRayCastingVisibility(ViewMap *ioViewMap, Grid *iGrid, real epsilon=1e-6); + void ComputeFastRayCastingVisibility(ViewMap *ioViewMap, Grid *iGrid, real epsilon=1e-6); + void ComputeVeryFastRayCastingVisibility(ViewMap *ioViewMap, Grid *iGrid, real epsilon=1e-6); + + /*! Compute the visibility for the FEdge fe. + * The occluders are added to fe occluders list. + * fe + * The FEdge + * iGrid + * The grid used to compute the ray casting visibility + * epsilon + * The epsilon used for computation + * oShapeId + * fe is the border (in 2D) between 2 2D spaces. + * if fe is a silhouette, + * One of these 2D spaces is occupied by the shape + * to which fe belongs (on its left) and the other one is either occupied + * by another shape or empty or occupied by the same shape. + * We use this ray csating operation to determine which shape + * lies on fe's right. + * The result is the shape id stored in oShapeId + */ + int ComputeRayCastingVisibility(FEdge *fe, Grid* iGrid, real epsilon, set<ViewShape*>& oOccluders, + Polygon3r** oaPolygon, unsigned timestamp); + // FIXME + void FindOccludee(FEdge *fe, Grid* iGrid, real epsilon, Polygon3r** oaPolygon, unsigned timestamp); + void FindOccludee(FEdge *fe, Grid* iGrid, real epsilon, Polygon3r** oaPolygon, unsigned timestamp, + Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edge, vector<WVertex*>& faceVertices); + +}; + +#endif // VIEWMAPBUILDER_H diff --git a/source/blender/freestyle/intern/view_map/ViewMapIO.cpp b/source/blender/freestyle/intern/view_map/ViewMapIO.cpp new file mode 100755 index 00000000000..f99a574766b --- /dev/null +++ b/source/blender/freestyle/intern/view_map/ViewMapIO.cpp @@ -0,0 +1,1245 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "ViewMapIO.h" + +#ifdef IRIX +# define WRITE(n) Internal::write<sizeof((n))>(out, (const char*)(&(n))) +# define READ(n) Internal::read<sizeof((n))>(in, (char*)(&(n))) +#else +# define WRITE(n) out.write((const char*)(&(n)), sizeof((n))) +# define READ(n) in.read((char*)(&(n)), sizeof((n))) +#endif + +#define WRITE_IF_NON_NULL(ptr) if ((ptr) == NULL) { WRITE(ZERO); } else { WRITE((ptr)->userdata); } +#define READ_IF_NON_NULL(ptr, array) READ(tmp); if (tmp == ZERO) { (ptr) = NULL; } else { (ptr) = (array)[tmp]; } + +namespace ViewMapIO { + + namespace Internal { + + ViewMap* g_vm; + + //////////////////// 'load' Functions //////////////////// + + inline + int load(istream& in, Vec3r& v) { + + if (Options::getFlags() & Options::FLOAT_VECTORS) { + float tmp; + READ(tmp); + v[0] = tmp; + READ(tmp); + v[1] = tmp; + READ(tmp); + v[2] = tmp; + } else { + Vec3r::value_type tmp; + READ(tmp); + v[0] = tmp; + READ(tmp); + v[1] = tmp; + READ(tmp); + v[2] = tmp; + } + return 0; + } + + + inline + int load(istream& in, Polygon3r& p) { + + unsigned tmp; + + // Id + READ(tmp); + p.setId(tmp); + + // vertices (List) + vector<Vec3r> tmp_vec; + Vec3r v; + READ(tmp); + for (unsigned i = 0; i < tmp; i++) { + load(in, v); + tmp_vec.push_back(v); + } + p.setVertices(tmp_vec); + + // min & max + // Already computed (in the SetVertices() method) + + return 0; + } + + + inline + int load(istream& in, FrsMaterial& m) { + + float tmp_array[4]; + int i; + + // Diffuse + for (i = 0; i < 4; i++) + READ(tmp_array[i]); + m.setDiffuse(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]); + + // Specular + for (i = 0; i < 4; i++) + READ(tmp_array[i]); + m.setSpecular(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]); + + // Ambient + for (i = 0; i < 4; i++) + READ(tmp_array[i]); + m.setAmbient(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]); + + // Emission + for (i = 0; i < 4; i++) + READ(tmp_array[i]); + m.setEmission(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]); + + // Shininess + READ(tmp_array[0]); + m.setShininess(tmp_array[0]); + + return 0; + } + + + int load(istream& in, ViewShape* vs) { + + if (!vs || !vs->sshape()) + return 1; + + // SShape + + // -> Id + Id::id_type id1, id2; + READ(id1); + READ(id2); + vs->sshape()->setId(Id(id1, id2)); + + // -> Importance + float importance; + READ(importance); + vs->sshape()->setImportance(importance); + + // -> BBox + // Not necessary (only used during view map computatiom) + + unsigned i, size, tmp; + + // -> Material + READ(size); + vector<FrsMaterial> frs_materials; + FrsMaterial m; + for(i=0; i<size; ++i){ + load(in, m); + frs_materials.push_back(m); + } + vs->sshape()->setFrsMaterials(frs_materials); + + + + // -> VerticesList (List) + READ(size); + for (i = 0; i < size; i++) { + SVertex* sv; + READ_IF_NON_NULL(sv, g_vm->SVertices()); + vs->sshape()->AddNewVertex(sv); + } + + // -> Chains (List) + READ(size); + for (i = 0; i < size; i++) { + FEdge* fe; + READ_IF_NON_NULL(fe, g_vm->FEdges()); + vs->sshape()->AddChain(fe); + } + + // -> EdgesList (List) + READ(size); + for (i = 0; i < size; i++) { + FEdge* fe; + READ_IF_NON_NULL(fe, g_vm->FEdges()); + vs->sshape()->AddEdge(fe); + } + + // ViewEdges (List) + READ(size); + for (i = 0; i < size; i++) { + ViewEdge* ve; + READ_IF_NON_NULL(ve, g_vm->ViewEdges()); + vs->AddEdge(ve); + } + + // ViewVertices (List) + READ(size); + for (i = 0; i < size; i++) { + ViewVertex* vv; + READ_IF_NON_NULL(vv, g_vm->ViewVertices()); + vs->AddVertex(vv); + } + + return 0; + } + + + int load(istream& in, FEdge* fe) { + + if (!fe) + return 1; + + bool b; + + FEdgeSmooth *fesmooth = 0; + FEdgeSharp * fesharp = 0; + if(fe->isSmooth()){ + fesmooth = dynamic_cast<FEdgeSmooth*>(fe); + }else{ + fesharp = dynamic_cast<FEdgeSharp*>(fe); + } + + // Id + Id::id_type id1, id2; + READ(id1); + READ(id2); + fe->setId(Id(id1, id2)); + + // Nature + Nature::EdgeNature nature; + READ(nature); + fe->setNature(nature); + + // hasVisibilityPoint + // bool b; + // READ(b); + // fe->setHasVisibilityPoint(b); + + Vec3r v; + unsigned int matindex; + + // VisibilityPointA + // load(in, v); + // fe->setVisibilityPointA(v); + + // VisibilityPointB + // load(in, v); + // fe->setVisibilityPointB(v); + + if(fe->isSmooth()){ + // Normal + load(in, v); + fesmooth->setNormal(v); + + // Material + READ(matindex); + fesmooth->setFrsMaterialIndex(matindex); + }else{ + // aNormal + load(in, v); + fesharp->setNormalA(v); + + // bNormal + load(in, v); + fesharp->setNormalB(v); + + // Materials + READ(matindex); + fesharp->setaFrsMaterialIndex(matindex); + READ(matindex); + fesharp->setbFrsMaterialIndex(matindex); + } + + unsigned tmp; + + // VertexA + SVertex* sva; + READ_IF_NON_NULL(sva, g_vm->SVertices()); + fe->setVertexA(sva); + + // VertexB + SVertex* svb; + READ_IF_NON_NULL(svb, g_vm->SVertices()); + fe->setVertexB(svb); + + // NextEdge + FEdge* nfe; + READ_IF_NON_NULL(nfe, g_vm->FEdges()); + fe->setNextEdge(nfe); + + // PreviousEdge + FEdge* pfe; + READ_IF_NON_NULL(pfe, g_vm->FEdges()); + fe->setPreviousEdge(pfe); + + // ViewEdge + ViewEdge* ve; + READ_IF_NON_NULL(ve, g_vm->ViewEdges()); + fe->setViewEdge(ve); + + // Face + // Not necessary (only used during view map computatiom) + + Polygon3r p; + + // aFace + load(in, p); + fe->setaFace(p); + + // occludeeEmpty + READ(b); + fe->setOccludeeEmpty(b); + + // occludeeIntersection + load(in, v); + fe->setOccludeeIntersection(v); + + return 0; + } + + + int load(istream& in, SVertex* sv) { + + if (!sv) + return 1; + + // Id + Id::id_type id1, id2; + READ(id1); + READ(id2); + sv->setId(Id(id1, id2)); + + Vec3r v; + + // Point3D + load(in, v); + sv->setPoint3D(v); + + // Point2D + load(in, v); + sv->setPoint2D(v); + + unsigned tmp; + + // Shape + ViewShape* vs; + READ_IF_NON_NULL(vs, g_vm->ViewShapes()); + sv->setShape(vs->sshape()); + + // pViewVertex + ViewVertex* vv; + READ_IF_NON_NULL(vv, g_vm->ViewVertices()); + sv->setViewVertex(vv); + + unsigned i, size; + + // Normals (List) + READ(size); + for (i = 0; i < size; i++) { + load(in, v); + sv->AddNormal(v); + } + + // FEdges (List) + READ(size); + FEdge* fe; + for (i = 0; i < size; i++) { + READ_IF_NON_NULL(fe, g_vm->FEdges()); + sv->AddFEdge(fe); + } + + return 0; + } + + + int load(istream& in, ViewEdge* ve) { + + if (!ve) + return 1; + + unsigned tmp; + + // Id + Id::id_type id1, id2; + READ(id1); + READ(id2); + ve->setId(Id(id1, id2)); + + // Nature + Nature::EdgeNature nature; + READ(nature); + ve->setNature(nature); + + // QI + READ(tmp); + ve->setQI(tmp); + + // Shape + ViewShape* vs; + READ_IF_NON_NULL(vs, g_vm->ViewShapes()); + ve->setShape(vs); + + // aShape + ViewShape* avs; + READ_IF_NON_NULL(avs, g_vm->ViewShapes()); + ve->setaShape(avs); + + // FEdgeA + FEdge* fea; + READ_IF_NON_NULL(fea, g_vm->FEdges()); + ve->setFEdgeA(fea); + + // FEdgeB + FEdge* feb; + READ_IF_NON_NULL(feb, g_vm->FEdges()); + ve->setFEdgeB(feb); + + // A + ViewVertex* vva; + READ_IF_NON_NULL(vva, g_vm->ViewVertices()); + ve->setA(vva); + + // B + ViewVertex* vvb; + READ_IF_NON_NULL(vvb, g_vm->ViewVertices()); + ve->setB(vvb); + + // Occluders (List) + if (!(Options::getFlags() & Options::NO_OCCLUDERS)) { + unsigned size; + READ(size); + ViewShape* vso; + for (unsigned i = 0; i < size; i++) { + READ_IF_NON_NULL(vso, g_vm->ViewShapes()); + ve->AddOccluder(vso); + } + } + + return 0; + } + + + int load(istream& in, ViewVertex* vv) { + + if (!vv) + return 1; + + unsigned tmp; + bool b; + + // Nature + Nature::VertexNature nature; + READ(nature); + vv->setNature(nature); + + if (vv->getNature() & Nature::T_VERTEX) { + TVertex* tv = dynamic_cast<TVertex*>(vv); + + // Id + Id::id_type id1, id2; + READ(id1); + READ(id2); + tv->setId(Id(id1, id2)); + + // FrontSVertex + SVertex* fsv; + READ_IF_NON_NULL(fsv, g_vm->SVertices()); + tv->setFrontSVertex(fsv); + + // BackSVertex + SVertex* bsv; + READ_IF_NON_NULL(bsv, g_vm->SVertices()); + tv->setBackSVertex(bsv); + + // FrontEdgeA + ViewEdge* fea; + READ_IF_NON_NULL(fea, g_vm->ViewEdges()); + READ(b); + tv->setFrontEdgeA(fea, b); + + // FrontEdgeB + ViewEdge* feb; + READ_IF_NON_NULL(feb, g_vm->ViewEdges()); + READ(b); + tv->setFrontEdgeB(feb, b); + + // BackEdgeA + ViewEdge* bea; + READ_IF_NON_NULL(bea, g_vm->ViewEdges()); + READ(b); + tv->setBackEdgeA(bea, b); + + // BackEdgeB + ViewEdge* beb; + READ_IF_NON_NULL(beb, g_vm->ViewEdges()); + READ(b); + tv->setBackEdgeB(beb, b); + } + else if (vv->getNature() & Nature::NON_T_VERTEX) { + NonTVertex* ntv = dynamic_cast<NonTVertex*>(vv); + + // SVertex + SVertex* sv; + READ_IF_NON_NULL(sv, g_vm->SVertices()); + ntv->setSVertex(sv); + + // ViewEdges (List) + unsigned size; + READ(size); + ViewEdge* ve; + for (unsigned i = 0; i < size; i++) { + READ_IF_NON_NULL(ve, g_vm->ViewEdges()); + READ(b); + ntv->AddViewEdge(ve, b); + } + } + + return 0; + } + + //////////////////// 'save' Functions //////////////////// + + inline + int save(ostream& out, const Vec3r& v) { + + if (Options::getFlags() & Options::FLOAT_VECTORS) { + float tmp; + + tmp = v[0]; + WRITE(tmp); + tmp = v[1]; + WRITE(tmp); + tmp = v[2]; + WRITE(tmp); + } else { + Vec3r::value_type tmp; + + tmp = v[0]; + WRITE(tmp); + tmp = v[1]; + WRITE(tmp); + tmp = v[2]; + WRITE(tmp); + } + return 0; + } + + + inline + int save(ostream& out, const Polygon3r& p) { + + unsigned tmp; + + // Id + tmp = p.getId(); + WRITE(tmp); + + // vertices (List) + tmp = p.getVertices().size(); + WRITE(tmp); + for (vector<Vec3r>::const_iterator i = p.getVertices().begin(); + i != p.getVertices().end(); i++) { + save(out, *i); + } + + // min & max + // Do not need to be saved + + return 0; + } + + + inline + int save(ostream& out, const FrsMaterial& m) { + + unsigned i; + + // Diffuse + for (i = 0; i < 4; i++) + WRITE(m.diffuse()[i]); + + // Specular + for (i = 0; i < 4; i++) + WRITE(m.specular()[i]); + + // Ambient + for (i = 0; i < 4; i++) + WRITE(m.ambient()[i]); + + // Emission + for (i = 0; i < 4; i++) + WRITE(m.emission()[i]); + + // Shininess + float shininess = m.shininess(); + WRITE(shininess); + + return 0; + } + + + int save(ostream& out, ViewShape* vs) { + + if (!vs || !vs->sshape()) { + cerr << "Warning: null ViewShape" << endl; + return 1; + } + + unsigned tmp; + + // SShape + + // -> Id + Id::id_type id = vs->sshape()->getId().getFirst(); + WRITE(id); + id = vs->sshape()->getId().getSecond(); + WRITE(id); + + // -> Importance + float importance = vs->sshape()->importance(); + WRITE(importance); + + // -> BBox + // Not necessary (only used during view map computatiom) + + // -> Material + unsigned size = vs->sshape()->frs_materials().size(); + WRITE(size); + for(unsigned i=0; i<size; ++i) + save(out, vs->sshape()->frs_material(i)); + + // -> VerticesList (List) + tmp = vs->sshape()->getVertexList().size(); + WRITE(tmp); + for (vector<SVertex*>::const_iterator i1 = vs->sshape()->getVertexList().begin(); + i1 != vs->sshape()->getVertexList().end(); i1++) + WRITE_IF_NON_NULL(*i1); + + // -> Chains (List) + tmp = vs->sshape()->getChains().size(); + WRITE(tmp); + for (vector<FEdge*>::const_iterator i2 = vs->sshape()->getChains().begin(); + i2 != vs->sshape()->getChains().end(); i2++) + WRITE_IF_NON_NULL(*i2); + + // -> EdgesList (List) + tmp = vs->sshape()->getEdgeList().size(); + WRITE(tmp); + for (vector<FEdge*>::const_iterator i3 = vs->sshape()->getEdgeList().begin(); + i3 != vs->sshape()->getEdgeList().end(); i3++) + WRITE_IF_NON_NULL(*i3); + + // ViewEdges (List) + tmp = vs->edges().size(); + WRITE(tmp); + for (vector<ViewEdge*>::const_iterator i4 = vs->edges().begin(); + i4 != vs->edges().end(); i4++) + WRITE_IF_NON_NULL(*i4); + + // ViewVertices (List) + tmp = vs->vertices().size(); + WRITE(tmp); + for (vector<ViewVertex*>::const_iterator i5 = vs->vertices().begin(); + i5 != vs->vertices().end(); i5++) + WRITE_IF_NON_NULL(*i5); + + + return 0; + } + + + int save(ostream& out, FEdge* fe) { + + if (!fe) { + cerr << "Warning: null FEdge" << endl; + return 1; + } + + FEdgeSmooth * fesmooth = dynamic_cast<FEdgeSmooth*>(fe); + FEdgeSharp * fesharp = dynamic_cast<FEdgeSharp*>(fe); + + // Id + Id::id_type id = fe->getId().getFirst(); + WRITE(id); + id = fe->getId().getSecond(); + WRITE(id); + + // Nature + Nature::EdgeNature nature = fe->getNature(); + WRITE(nature); + + bool b; + + // hasVisibilityPoint + // b = fe->hasVisibilityPoint(); + // WRITE(b); + + // VisibilityPointA + // save(out, fe->visibilityPointA()); + // + // // VisibilityPointB + // save(out, fe->visibilityPointB()); + + unsigned index; + if(fe->isSmooth()){ + // normal + save(out, fesmooth->normal()); + // material + index = fesmooth->frs_materialIndex(); + WRITE(index); + }else{ + // aNormal + save(out, fesharp->normalA()); + // bNormal + save(out, fesharp->normalB()); + // aMaterial + index = fesharp->aFrsMaterialIndex(); + WRITE(index); + // bMaterial + index = fesharp->bFrsMaterialIndex(); + WRITE(index); + } + + + // VertexA + WRITE_IF_NON_NULL(fe->vertexA()); + + // VertexB + WRITE_IF_NON_NULL(fe->vertexB()); + + // NextEdge + WRITE_IF_NON_NULL(fe->nextEdge()); + + // PreviousEdge + WRITE_IF_NON_NULL(fe->previousEdge()); + + // ViewEdge + WRITE_IF_NON_NULL(fe->viewedge()); + + // Face + // Not necessary (only used during view map computatiom) + + // aFace + save(out, (Polygon3r&)fe->aFace()); + + // occludeeEmpty + b = fe->getOccludeeEmpty(); + WRITE(b); + + // occludeeIntersection + save(out, fe->getOccludeeIntersection()); + + return 0; + } + + + int save(ostream& out, SVertex* sv) { + + if (!sv) { + cerr << "Warning: null SVertex" << endl; + return 1; + } + + unsigned tmp; + + // Id + Id::id_type id = sv->getId().getFirst(); + WRITE(id); + id = sv->getId().getSecond(); + WRITE(id); + + Vec3r v; + + // Point3D + v = sv->point3D(); + save(out, sv->point3D()); + + // Point2D + v = sv->point2D(); + save(out, v); + + // Shape + WRITE_IF_NON_NULL(sv->shape()); + + // pViewVertex + WRITE_IF_NON_NULL(sv->viewvertex()); + + // Normals (List) + // Note: the 'size()' method of a set doesn't seem to return the + // actual size of the given set, so we have to hack it... + set<Vec3r>::const_iterator i; + for (i = sv->normals().begin(), tmp = 0; + i != sv->normals().end(); + i++, tmp++); + WRITE(tmp); + for (i = sv->normals().begin(); i != sv->normals().end(); i++) + save(out, *i); + + // FEdges (List) + tmp = sv->fedges().size(); + WRITE(tmp); + for (vector<FEdge*>::const_iterator j = sv->fedges_begin(); + j != sv->fedges_end(); j++) + WRITE_IF_NON_NULL(*j); + + return 0; + } + + + int save(ostream& out, ViewEdge* ve) { + + if (!ve) { + cerr << "Warning: null ViewEdge" << endl; + return 1; + } + + unsigned tmp; + + // Id + Id::id_type id = ve->getId().getFirst(); + WRITE(id); + id = ve->getId().getSecond(); + WRITE(id); + + // Nature + Nature::EdgeNature nature = ve->getNature(); + WRITE(nature); + + // QI + unsigned qi = ve->qi(); + WRITE(qi); + + // Shape + WRITE_IF_NON_NULL(ve->shape()); + + // aShape + WRITE_IF_NON_NULL(ve->aShape()); + + // FEdgeA + WRITE_IF_NON_NULL(ve->fedgeA()); + + // FEdgeB + WRITE_IF_NON_NULL(ve->fedgeB()); + + // A + WRITE_IF_NON_NULL(ve->A()); + + // B + WRITE_IF_NON_NULL(ve->B()); + + // Occluders (List) + if (!(Options::getFlags() & Options::NO_OCCLUDERS)) { + tmp = ve->occluders().size(); + WRITE(tmp); + for (vector<ViewShape*>::const_iterator i = ve->occluders().begin(); + i != ve->occluders().end(); i++) + WRITE_IF_NON_NULL((*i)); + } + + return 0; + } + + + int save(ostream& out, ViewVertex* vv) { + + if (!vv) { + cerr << "Warning: null ViewVertex" << endl; + return 1; + } + + // Nature + Nature::VertexNature nature = vv->getNature(); + WRITE(nature); + + if (vv->getNature() & Nature::T_VERTEX) { + TVertex* tv = dynamic_cast<TVertex*>(vv); + + // Id + Id::id_type id = tv->getId().getFirst(); + WRITE(id); + id = tv->getId().getSecond(); + WRITE(id); + + // FrontSVertex + WRITE_IF_NON_NULL(tv->frontSVertex()); + + // BackSVertex + WRITE_IF_NON_NULL(tv->backSVertex()); + + // FrontEdgeA + WRITE_IF_NON_NULL(tv->frontEdgeA().first); + WRITE(tv->frontEdgeA().second); + + // FrontEdgeB + WRITE_IF_NON_NULL(tv->frontEdgeB().first); + WRITE(tv->frontEdgeB().second); + + // BackEdgeA + WRITE_IF_NON_NULL(tv->backEdgeA().first); + WRITE(tv->backEdgeA().second); + + // BackEdgeB + WRITE_IF_NON_NULL(tv->backEdgeB().first); + WRITE(tv->backEdgeB().second); + + } + else if (vv->getNature() & Nature::NON_T_VERTEX) { + NonTVertex* ntv = dynamic_cast<NonTVertex*>(vv); + + // SVertex + WRITE_IF_NON_NULL(ntv->svertex()); + + // ViewEdges (List) + unsigned size = ntv->viewedges().size(); + WRITE(size); + vector<ViewVertex::directedViewEdge>::const_iterator i = ntv->viewedges().begin(); + for ( ; i != ntv->viewedges().end(); i++){ + WRITE_IF_NON_NULL(i->first); + WRITE(i->second); + } + + } else { + cerr << "Warning: unexpected ViewVertex nature" << endl; + return 1; + } + + return 0; + } + + } // End of namespace Internal + + + //////////////////// "Public" 'load' and 'save' functions //////////////////// + +#define SET_PROGRESS(n) if (pb) pb->setProgress((n)) + + int load(istream& in, ViewMap* vm, ProgressBar* pb) { + + if (!vm) + return 1; + + //soc unused - unsigned tmp; + + int err = 0; + + Internal::g_vm = vm; + + // Management of the progress bar (if present) + if (pb) { + pb->reset(); + pb->setLabelText("Loading View Map..."); + pb->setTotalSteps(6); + pb->setProgress(0); + } + + // Read and set the options + unsigned char flags; + READ(flags); + Options::setFlags(flags); + + // Read the size of the five ViewMap's lists (with some extra informations for the ViewVertices) + // and instantiate them (with default costructors) + unsigned vs_s, fe_s, fe_rle1, fe_rle2, sv_s, ve_s, vv_s, vv_rle1, vv_rle2; + READ(vs_s); + READ(fe_s); + + if (fe_s) { + bool b; + READ(b); + for (READ(fe_rle1), fe_rle2 = 0; + fe_rle1 < fe_s+1; + fe_rle2 = fe_rle1, READ(fe_rle1)) { + if (b) { + for (unsigned i = fe_rle2; i < fe_rle1; i++) { + FEdgeSmooth * fes = new FEdgeSmooth; + vm->AddFEdge(fes); + } + b = !b; + } + else if (!b) { + for (unsigned i = fe_rle2; i < fe_rle1; i++) { + FEdgeSharp * fes = new FEdgeSharp; + vm->AddFEdge(fes); + } + b = !b; + } + } + } + + READ(sv_s); + READ(ve_s); + READ(vv_s); + + if (vv_s) { + Nature::VertexNature nature; + READ(nature); + for (READ(vv_rle1), vv_rle2 = 0; + vv_rle1 < vv_s+1; + vv_rle2 = vv_rle1, READ(vv_rle1)) { + if (nature & Nature::T_VERTEX) { + for (unsigned i = vv_rle2; i < vv_rle1; i++) { + TVertex* tv = new TVertex(); + vm->AddViewVertex(tv); + } + nature = Nature::NON_T_VERTEX; + } + else if (nature & Nature::NON_T_VERTEX) { + for (unsigned i = vv_rle2; i < vv_rle1; i++) { + NonTVertex* ntv = new NonTVertex(); + vm->AddViewVertex(ntv); + } + nature = Nature::T_VERTEX; + } + } + } + + for (unsigned i0 = 0; i0 < vs_s; i0++) { + SShape* ss = new SShape(); + ViewShape* vs = new ViewShape(); + vs->setSShape(ss); + ss->setViewShape(vs); + vm->AddViewShape(vs); + } + // for (unsigned i1 = 0; i1 < fe_s; i1++) { + // FEdge* fe = new FEdge(); + // vm->AddFEdge(fe); + // } + for (unsigned i2 = 0; i2 < sv_s; i2++) { + SVertex* sv = new SVertex(); + vm->AddSVertex(sv); + } + for (unsigned i3 = 0; i3 < ve_s; i3++) { + ViewEdge* ve = new ViewEdge(); + vm->AddViewEdge(ve); + } + + + // Read the values for all the objects created above + SET_PROGRESS(1); + for (vector<ViewShape*>::const_iterator i4 = vm->ViewShapes().begin(); + i4 != vm->ViewShapes().end(); i4++) + err += Internal::load(in, *i4); + SET_PROGRESS(2); + for (vector<FEdge*>::const_iterator i5 = vm->FEdges().begin(); + i5 != vm->FEdges().end(); i5++) + err += Internal::load(in, *i5); + SET_PROGRESS(3); + for (vector<SVertex*>::const_iterator i6 = vm->SVertices().begin(); + i6 != vm->SVertices().end(); i6++) + err += Internal::load(in, *i6); + SET_PROGRESS(4); + for (vector<ViewEdge*>::const_iterator i7 = vm->ViewEdges().begin(); + i7 != vm->ViewEdges().end(); i7++) + err += Internal::load(in, *i7); + SET_PROGRESS(5); + for (vector<ViewVertex*>::const_iterator i8 = vm->ViewVertices().begin(); + i8 != vm->ViewVertices().end(); i8++) + err += Internal::load(in, *i8); + SET_PROGRESS(6); + + // Read the shape id to index mapping + unsigned map_s; + READ(map_s); + unsigned id,index; + for(unsigned i4=0;i4<map_s;++i4){ + READ(id); + READ(index); + vm->shapeIdToIndexMap()[id] = index; + } + + return err; + } + + + int save(ostream& out, ViewMap* vm, ProgressBar* pb) { + + if (!vm) + return 1; + + int err = 0; + + // Management of the progress bar (if present) + if (pb) { + pb->reset(); + pb->setLabelText("Saving View Map..."); + pb->setTotalSteps(6); + pb->setProgress(0); + } + + // For every object, initialize its userdata member to its index in the ViewMap list + for (unsigned i0 = 0; i0 < vm->ViewShapes().size(); i0++) { + vm->ViewShapes()[i0]->userdata = (void*)i0; + vm->ViewShapes()[i0]->sshape()->userdata = (void*)i0; + } + for (unsigned i1 = 0; i1 < vm->FEdges().size(); i1++) + vm->FEdges()[i1]->userdata = (void*)i1; + for (unsigned i2 = 0; i2 < vm->SVertices().size(); i2++) + vm->SVertices()[i2]->userdata = (void*)i2; + for (unsigned i3 = 0; i3 < vm->ViewEdges().size(); i3++) + vm->ViewEdges()[i3]->userdata = (void*)i3; + for (unsigned i4 = 0; i4 < vm->ViewVertices().size(); i4++) + vm->ViewVertices()[i4]->userdata = (void*)i4; + + // Write the current options + unsigned char flags = Options::getFlags(); + WRITE(flags); + + // Write the size of the five lists (with some extra informations for the ViewVertices) + unsigned size; + size = vm->ViewShapes().size(); + WRITE(size); + size = vm->FEdges().size(); + WRITE(size); + if (size) { + bool b = vm->FEdges()[0]->isSmooth(); + WRITE(b); + for (unsigned i = 0; i < size; i++) { + while (i < size && (vm->FEdges()[i]->isSmooth() == b)) + i++; + if (i < size) { + WRITE(i); + b = !b; + } + } + WRITE(size); + size++; + WRITE(size); + } + size = vm->SVertices().size(); + WRITE(size); + size = vm->ViewEdges().size(); + WRITE(size); + size = vm->ViewVertices().size(); + WRITE(size); + if (size) { + Nature::VertexNature nature = vm->ViewVertices()[0]->getNature(); + WRITE(nature); + nature &= ~Nature::VIEW_VERTEX; + for (unsigned i = 0; i < size; i++) { + while (i < size && (vm->ViewVertices()[i]->getNature() & nature)) + i++; + if (i < size) { + WRITE(i); + nature = vm->ViewVertices()[i]->getNature() & ~Nature::VIEW_VERTEX; + } + } + WRITE(size); + size++; + WRITE(size); + } + + + // Write all the elts of the ViewShapes List + SET_PROGRESS(1); + for (vector<ViewShape*>::const_iterator i5 = vm->ViewShapes().begin(); + i5 != vm->ViewShapes().end(); i5++) + err += Internal::save(out, *i5); + SET_PROGRESS(2); + for (vector<FEdge*>::const_iterator i6 = vm->FEdges().begin(); + i6 != vm->FEdges().end(); i6++) + err += Internal::save(out, *i6); + SET_PROGRESS(3); + for (vector<SVertex*>::const_iterator i7 = vm->SVertices().begin(); + i7 != vm->SVertices().end(); i7++) + err += Internal::save(out, *i7); + SET_PROGRESS(4); + for (vector<ViewEdge*>::const_iterator i8 = vm->ViewEdges().begin(); + i8 != vm->ViewEdges().end(); i8++) + err += Internal::save(out, *i8); + SET_PROGRESS(5); + for (vector<ViewVertex*>::const_iterator i9 = vm->ViewVertices().begin(); + i9 != vm->ViewVertices().end(); i9++) + err += Internal::save(out, *i9); + + // Write the shape id to index mapping + size = vm->shapeIdToIndexMap().size(); + WRITE(size); + unsigned id,index; + for(ViewMap::id_to_index_map::iterator mit=vm->shapeIdToIndexMap().begin(), mitend=vm->shapeIdToIndexMap().end(); mit!=mitend; ++mit){ + id = mit->first; + index = mit->second; + WRITE(id); + WRITE(index); + } + + // Reset 'userdata' members + for (vector<ViewShape*>::const_iterator j0 = vm->ViewShapes().begin(); + j0 != vm->ViewShapes().end(); j0++) { + (*j0)->userdata = 0; + (*j0)->sshape()->userdata = 0; + } + for (vector<FEdge*>::const_iterator j1 = vm->FEdges().begin(); + j1 != vm->FEdges().end(); j1++) + (*j1)->userdata = 0; + for (vector<SVertex*>::const_iterator j2 = vm->SVertices().begin(); + j2 != vm->SVertices().end(); j2++) + (*j2)->userdata = 0; + for (vector<ViewEdge*>::const_iterator j3 = vm->ViewEdges().begin(); + j3 != vm->ViewEdges().end(); j3++) + (*j3)->userdata = 0; + for (vector<ViewVertex*>::const_iterator j4 = vm->ViewVertices().begin(); + j4 != vm->ViewVertices().end(); j4++) + (*j4)->userdata = 0; + SET_PROGRESS(6); + + return err; + } + + + //////////////////// Options //////////////////// + + namespace Options { + + namespace Internal { + + static unsigned char g_flags = 0; + static string g_models_path; + + } // End of namespace Internal + + void setFlags(const unsigned char flags) { + Internal::g_flags = flags; + } + + void addFlags(const unsigned char flags) { + Internal::g_flags |= flags; + } + + void rmFlags(const unsigned char flags) { + Internal::g_flags &= ~flags; + } + + unsigned char getFlags() { + return Internal::g_flags; + } + + void setModelsPath(const string& path) { + Internal::g_models_path = path; + } + + string getModelsPath() { + return Internal::g_models_path; + } + + }; // End of namepace Options + +} // End of namespace ViewMapIO diff --git a/source/blender/freestyle/intern/view_map/ViewMapIO.h b/source/blender/freestyle/intern/view_map/ViewMapIO.h new file mode 100755 index 00000000000..185841a90ec --- /dev/null +++ b/source/blender/freestyle/intern/view_map/ViewMapIO.h @@ -0,0 +1,116 @@ +// +// Filename : ViewMapIO.h +// Author(s) : Emmanuel Turquin +// Purpose : Functions to manage I/O for the view map +// Date of creation : 09/01/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef VIEWMAPIO_H +# define VIEWMAPIO_H + +# include "ViewMap.h" +# include <fstream> +# include <string> +# include "../system/FreestyleConfig.h" +# include "../system/ProgressBar.h" + +namespace ViewMapIO { + + static const unsigned ZERO = UINT_MAX; + + LIB_VIEW_MAP_EXPORT + int load(istream& in, ViewMap* vm, ProgressBar* pb = NULL); + + LIB_VIEW_MAP_EXPORT + int save(ostream& out, ViewMap* vm, ProgressBar* pb = NULL); + + namespace Options { + + static const unsigned char FLOAT_VECTORS = 1; + static const unsigned char NO_OCCLUDERS = 2; + + LIB_VIEW_MAP_EXPORT + void setFlags(const unsigned char flags); + + LIB_VIEW_MAP_EXPORT + void addFlags(const unsigned char flags); + + LIB_VIEW_MAP_EXPORT + void rmFlags(const unsigned char flags); + + LIB_VIEW_MAP_EXPORT + unsigned char getFlags(); + + LIB_VIEW_MAP_EXPORT + void setModelsPath(const string& path); + + LIB_VIEW_MAP_EXPORT + string getModelsPath(); + + }; // End of namepace Options + +# ifdef IRIX + + namespace Internal { + + template <unsigned S> + ostream& write(ostream& out, const char* str) { + out.put(str[S - 1]); + return write<S - 1>(out, str); + } + + template<> + ostream& write<1>(ostream& out, const char* str) { + return out.put(str[0]); + } + + template<> + ostream& write<0>(ostream& out, const char*) { + return out; + } + + template <unsigned S> + istream& read(istream& in, char* str) { + in.get(str[S - 1]); + return read<S - 1>(in, str); + } + + template<> + istream& read<1>(istream& in, char* str) { + return in.get(str[0]); + } + + template<> + istream& read<0>(istream& in, char*) { + return in; + } + + } // End of namespace Internal + +# endif // IRIX + +} // End of namespace ViewMapIO + +#endif // VIEWMAPIO_H diff --git a/source/blender/freestyle/intern/view_map/ViewMapIterators.h b/source/blender/freestyle/intern/view_map/ViewMapIterators.h new file mode 100755 index 00000000000..789aec0d5c3 --- /dev/null +++ b/source/blender/freestyle/intern/view_map/ViewMapIterators.h @@ -0,0 +1,549 @@ +// +// Filename : ViewMapIterators.h +// Author(s) : Stephane Grabli +// Purpose : Iterators used to iterate over the various elements +// of the ViewMap +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef VIEWMAPITERATORS_H +# define VIEWMAPITERATORS_H + +#include "ViewMap.h" +#include "../system/Iterator.h" //soc + + + /**********************************/ + /* */ + /* */ + /* ViewMap */ + /* */ + /* */ + /**********************************/ + + /**********************************/ + /* */ + /* */ + /* ViewVertex */ + /* */ + /* */ + /**********************************/ + +namespace ViewVertexInternal{ + + /*! Class representing an iterator over oriented ViewEdges + * around a ViewVertex. This iterator allows a CCW iteration + * (in the image plane). + * An instance of an orientedViewEdgeIterator can only + * be obtained from a ViewVertex by calling edgesBegin() or edgesEnd(). + */ + class orientedViewEdgeIterator : public Iterator + { + public: + friend class ViewVertex; + friend class TVertex; + friend class NonTVertex; + friend class ViewEdge; + + // FIXME + typedef ::TVertex::edge_pointers_container edge_pointers_container; + typedef ::NonTVertex::edges_container edges_container; + protected: + + Nature::VertexNature _Nature; // the nature of the underlying vertex + // T vertex attributes + edge_pointers_container::iterator _tbegin; + edge_pointers_container::iterator _tend; + edge_pointers_container::iterator _tvertex_iter; + + // Non TVertex attributes + edges_container::iterator _begin; + edges_container::iterator _end; + edges_container::iterator _nontvertex_iter; + + public: + /*! Default constructor */ + inline orientedViewEdgeIterator() {} + inline orientedViewEdgeIterator(Nature::VertexNature iNature) + {_Nature = iNature;} + /*! Copy constructor */ + orientedViewEdgeIterator(const orientedViewEdgeIterator& iBrother) + { + _Nature = iBrother._Nature; + if(_Nature & Nature::T_VERTEX) + { + _tbegin = iBrother._tbegin; + _tend = iBrother._tend; + _tvertex_iter = iBrother._tvertex_iter; + } + else + { + _begin = iBrother._begin; + _end = iBrother._end; + _nontvertex_iter = iBrother._nontvertex_iter; + } + } + virtual ~orientedViewEdgeIterator() {} + + public: + inline orientedViewEdgeIterator(edge_pointers_container::iterator begin, + edge_pointers_container::iterator end, + edge_pointers_container::iterator iter) + { + _Nature = Nature::T_VERTEX; + _tbegin = begin; + _tend = end; + _tvertex_iter = iter; + } + inline orientedViewEdgeIterator(edges_container::iterator begin, + edges_container::iterator end, + edges_container::iterator iter) + { + _Nature = Nature::NON_T_VERTEX; + _begin = begin; + _end = end; + _nontvertex_iter = iter; + } + + public: + + + /*! Tells whether the ViewEdge pointed + * by this iterator is the first one of the + * iteration list or not. + */ + virtual bool isBegin() const + { + if(_Nature & Nature::T_VERTEX) + return (_tvertex_iter == _tbegin); + else + return (_nontvertex_iter == _begin); + } + /*! Tells whether the ViewEdge pointed + * by this iterator is after the last one of the + * iteration list or not. + */ + virtual bool isEnd() const + { + if(_Nature & Nature::T_VERTEX) + return (_tvertex_iter == _tend); + else + return (_nontvertex_iter == _end); + } + + // operators + /*! Increments.In the scripting language, call + * "increment()". + */ + virtual orientedViewEdgeIterator& operator++() // operator corresponding to ++i + { + increment(); + return *this; + } + /*! Increments.In the scripting language, call + * "increment()". + */ + virtual orientedViewEdgeIterator operator++(int) // opérateur correspondant à i++ + { // c.a.d qui renvoie la valeur *puis* incrémente. + orientedViewEdgeIterator tmp = *this; // C'est pour cela qu'on stocke la valeur + increment(); // dans un temporaire. + return tmp; + } + + // comparibility + /*! operator != */ + virtual bool operator!=(const orientedViewEdgeIterator& b) const + { + if(_Nature & Nature::T_VERTEX) + return (_tvertex_iter != b._tvertex_iter); + else + return (_nontvertex_iter != b._nontvertex_iter); + } + + /*! operator == */ + virtual bool operator==(const orientedViewEdgeIterator& b) const + {return !(*this != b);} + + // dereferencing + /*! Returns a reference to the pointed orientedViewEdge. + * In the scripting language, you must call + * "getObject()"instead. + */ + virtual ::ViewVertex::directedViewEdge& operator*() const + { + if(_Nature & Nature::T_VERTEX) + //return _tvertex_iter; + return **_tvertex_iter; + else + return (*_nontvertex_iter); + } + /*! Returns a pointer to the pointed orientedViewEdge. + * Can't be called in the scripting language. + */ + virtual ::ViewVertex::directedViewEdge* operator->() const { return &(operator*());} + + public: + /*! increments.*/ + virtual inline int increment() + { + if(_Nature & Nature::T_VERTEX) + { + ::ViewVertex::directedViewEdge tmp = (**_tvertex_iter); + ++_tvertex_iter; + if(_tvertex_iter != _tend){ + // FIXME : pquoi deja ? + ::ViewVertex::directedViewEdge tmp2 = (**_tvertex_iter); + if(tmp2.first == tmp.first) + ++_tvertex_iter; + } + } + else + ++_nontvertex_iter; + return 0; + } + }; + + } + /**********************************/ + /* */ + /* */ + /* ViewEdge */ + /* */ + /* */ + /**********************************/ + +namespace ViewEdgeInternal { +// +// SVertexIterator +// +///////////////////////////////////////////////// + + class SVertexIterator : public Interface0DIteratorNested + { + public: + + SVertexIterator() { + _vertex = NULL; + _begin = NULL; + _previous_edge = NULL; + _next_edge = NULL; + _t = 0; + } + + SVertexIterator(const SVertexIterator& vi) { + _vertex = vi._vertex; + _begin = vi._begin; + _previous_edge = vi._previous_edge; + _next_edge = vi._next_edge; + _t = vi._t; + } + + SVertexIterator(SVertex* v, SVertex* begin, FEdge* prev, FEdge* next, float t) { + _vertex = v; + _begin = begin; + _previous_edge = prev; + _next_edge = next; + _t = t; + } + + SVertexIterator& operator=(const SVertexIterator& vi) { + _vertex = vi._vertex; + _begin = vi._begin; + _previous_edge = vi._previous_edge; + _next_edge = vi._next_edge; + _t = vi._t; + return *this; + } + + virtual ~SVertexIterator() {} + + virtual string getExactTypeName() const { + return "SVertexIterator"; + } + + virtual SVertex& operator*() { + return *_vertex; + } + + virtual SVertex* operator->() { + return &(operator*()); + } + + virtual SVertexIterator& operator++() { + increment(); + return *this; + } + + virtual SVertexIterator operator++(int) { + SVertexIterator ret(*this); + increment(); + return ret; + } + + virtual SVertexIterator& operator--() { + decrement(); + return *this; + } + + virtual SVertexIterator operator--(int) { + SVertexIterator ret(*this); + decrement(); + return ret; + } + + virtual int increment(){ + if (!_next_edge) { + _vertex = 0; + return 0; + } + _t += (float)_next_edge->getLength2D(); + _vertex = _next_edge->vertexB(); + _previous_edge = _next_edge; + _next_edge = _next_edge->nextEdge(); + return 0; + + } + virtual int decrement(){ + if (!_previous_edge) { + _vertex = 0; + return 0; + } + if((!_next_edge) && (!_vertex)){ + _vertex = _previous_edge->vertexB(); + return 0; + } + _t -= (float)_previous_edge->getLength2D(); + _vertex = _previous_edge->vertexA(); + _next_edge = _previous_edge; + _previous_edge = _previous_edge->previousEdge(); + return 0; + } + + virtual bool isBegin() const { + return _vertex == _begin; + } + + virtual bool isEnd() const { + return (!_vertex) || (_vertex == _begin && _previous_edge); + } + + virtual float t() const { + return _t; + } + virtual float u() const { + return _t/(float)_next_edge->viewedge()->getLength2D(); + } + + virtual bool operator==(const Interface0DIteratorNested& it) const { + const SVertexIterator* it_exact = dynamic_cast<const SVertexIterator*>(&it); + if (!it_exact) + return false; + return (_vertex == it_exact->_vertex); + } + + virtual SVertexIterator* copy() const { + return new SVertexIterator(*this); + } + + private: + + SVertex* _vertex; + SVertex* _begin; + FEdge* _previous_edge; + FEdge* _next_edge; + float _t; // curvilinear abscissa + }; + + + +// +// ViewEdgeIterator (base class) +// +/////////////////////////////////////////////////////////// + + /*! Base class for iterators over ViewEdges of the ViewMap Graph. + * Basically the "increment()" operator of this class should + * be able to take the decision of "where" (on which ViewEdge) to go + * when pointing on a given ViewEdge. + * ::Caution::: the dereferencing operator returns a *pointer* to + * the pointed ViewEdge. + */ +class ViewEdgeIterator : public Iterator +{ +public: + + /*! Builds a ViewEdgeIterator from a starting ViewEdge and its orientation. + * \param begin + * The ViewEdge from where to start the iteration. + * \param orientation + * If true, we'll look for the next ViewEdge among the + * ViewEdges that surround the ending ViewVertex of begin. + * If false, we'll search over the ViewEdges surrounding + * the ending ViewVertex of begin. + */ + ViewEdgeIterator(ViewEdge* begin = 0, bool orientation = true) { + _orientation = orientation; + _edge = begin; + _begin = begin; + } + + /*! Copy constructor */ + ViewEdgeIterator(const ViewEdgeIterator& it) { + _orientation = it._orientation; + _edge = it._edge; + _begin = it._begin; + } + + virtual ~ViewEdgeIterator() {} + + /*! Returns the string "ViewEdgeIterator" */ + virtual string getExactTypeName() const { + return "ViewEdgeIterator"; + } + + /*! Returns the current pointed ViewEdge. */ + ViewEdge* getCurrentEdge() { + return _edge; + } + + /*! Sets the current pointed ViewEdge. */ + void setCurrentEdge(ViewEdge* edge) { + _edge = edge; + } + + /*! Returns the first ViewEdge used for the iteration. */ + ViewEdge* getBegin() { + return _begin; + } + + /*! Sets the first ViewEdge used for the iteration. */ + void setBegin(ViewEdge* begin) { + _begin = begin; + } + + /*! Gets the orientation of the pointed ViewEdge in the iteration. */ + bool getOrientation() const { + return _orientation; + } + + /*! Sets the orientation of the pointed ViewEdge in the iteration. */ + void setOrientation(bool orientation) { + _orientation = orientation; + } + + /*! Changes the current orientation. */ + void changeOrientation() { + _orientation = !_orientation; + } + + /*! Returns a *pointer* to the pointed ViewEdge. */ + virtual ViewEdge* operator*() { + return _edge; + } + + virtual ViewEdge* operator->() { + return operator*(); + } + + /*! Increments. In the scripting language, call + * "increment()". + */ + virtual ViewEdgeIterator& operator++() { + increment(); + return *this; + } + + /*! Increments. In the scripting language, call + * "increment()". + */ + virtual ViewEdgeIterator operator++(int) { + ViewEdgeIterator tmp(*this); + increment(); + return tmp; + } + + /*! increments. */ + virtual int increment() { + cerr << "Warning: method increment() not implemented" << endl; + return 0; + } + + /*! Decrements. In the scripting language, call + * "decrement()". + */ + virtual ViewEdgeIterator& operator--() { + decrement(); + return *this; + } + + /*! Decrements. In the scripting language, call + * "decrement()". + */ + virtual ViewEdgeIterator operator--(int) { + ViewEdgeIterator tmp(*this); + decrement(); + return tmp; + } + + /*! decrements. */ + virtual int decrement(){ + cerr << "Warning: method decrement() not implemented" << endl; + return 0; + } + + /*! Returns true if the pointed ViewEdge is the + * first one used for the iteration. + */ + virtual bool isBegin() const { + return _edge == _begin; + } + + /*! Returns true if the pointed ViewEdge* equals 0. + */ + virtual bool isEnd() const { + return !_edge; + } + + /*! operator == */ + virtual bool operator==(ViewEdgeIterator& it) const { + return _edge == it._edge; + } + + /*! operator != */ + virtual bool operator!=(ViewEdgeIterator& it) const { + return !(*this == it); + } + +protected: + + bool _orientation; + ViewEdge* _edge; + ViewEdge* _begin; +}; + +} // end of namespace ViewEdgeInternal + +#endif // VIEWMAPITERATORS_H + diff --git a/source/blender/freestyle/intern/view_map/ViewMapTesselator.cpp b/source/blender/freestyle/intern/view_map/ViewMapTesselator.cpp new file mode 100755 index 00000000000..6041f527d17 --- /dev/null +++ b/source/blender/freestyle/intern/view_map/ViewMapTesselator.cpp @@ -0,0 +1,36 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "ViewMapTesselator.h" + +NodeGroup* ViewMapTesselator::Tesselate(ViewMap *iViewMap) +{ + if(0 == iViewMap->ViewEdges().size()) + return NULL; + + const vector<ViewEdge*>& viewedges = iViewMap->ViewEdges(); + return Tesselate(viewedges.begin(), viewedges.end()); +} + +NodeGroup* ViewMapTesselator::Tesselate(WShape *) +{ + return NULL; +} diff --git a/source/blender/freestyle/intern/view_map/ViewMapTesselator.h b/source/blender/freestyle/intern/view_map/ViewMapTesselator.h new file mode 100755 index 00000000000..0177dc630b8 --- /dev/null +++ b/source/blender/freestyle/intern/view_map/ViewMapTesselator.h @@ -0,0 +1,196 @@ +// +// Filename : ViewMapTesselator.h +// Author(s) : Stephane Grabli +// Purpose : Class to build a Node Tree designed to be displayed +// from a Silhouette View Map structure. +// Date of creation : 26/03/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef VIEWMAPTESSELATOR_H +# define VIEWMAPTESSELATOR_H + +# include "Silhouette.h" +# include "ViewMap.h" +# include "../scene_graph/NodeShape.h" +# include "../winged_edge/WEdge.h" +# include "../scene_graph/NodeGroup.h" +# include "../scene_graph/LineRep.h" +# include "../scene_graph/OrientedLineRep.h" +# include "../scene_graph/VertexRep.h" + +class NodeShape; +class NodeGroup; +class SShape; +class WShape; + +class LIB_VIEW_MAP_EXPORT ViewMapTesselator +{ +public: + + inline ViewMapTesselator() {_nature = Nature::SILHOUETTE | Nature::BORDER | Nature::CREASE;_FrsMaterial.setDiffuse(0,0,0,1);_overloadFrsMaterial=false;} + virtual ~ViewMapTesselator() {} + + /*! Builds a set of lines rep contained under a + * a NodeShape, itself contained under a NodeGroup from a ViewMap + */ + NodeGroup* Tesselate(ViewMap* iViewMap) ; + + /*! Builds a set of lines rep contained under a + * a NodeShape, itself contained under a NodeGroup from a + * set of view edges + */ + template<class ViewEdgesIterator> + NodeGroup* Tesselate(ViewEdgesIterator begin, ViewEdgesIterator end) ; + + /*! Builds a set of lines rep contained among a + * a NodeShape, from a WShape + */ + NodeGroup* Tesselate(WShape* iWShape); + + + inline void setNature(Nature::EdgeNature iNature) {_nature = iNature;} + inline void setFrsMaterial(const FrsMaterial& iMaterial) {_FrsMaterial=iMaterial;_overloadFrsMaterial=true;} + inline Nature::EdgeNature nature() {return _nature;} + inline const FrsMaterial& frs_material() const {return _FrsMaterial;} + +protected: + virtual void AddVertexToLine(LineRep *iLine, SVertex *v) = 0; + +private: + Nature::EdgeNature _nature; + FrsMaterial _FrsMaterial; + bool _overloadFrsMaterial; +}; + +/*! Class to tesselate the 2D projected silhouette */ +class ViewMapTesselator2D : public ViewMapTesselator +{ +public: + inline ViewMapTesselator2D() : ViewMapTesselator() {} + virtual ~ViewMapTesselator2D() {} + +protected: + virtual void AddVertexToLine(LineRep *iLine, SVertex *v) + { + iLine->AddVertex(v->point2D()); + } +}; + +/*! Class to tesselate the 3D silhouette */ +class ViewMapTesselator3D : public ViewMapTesselator +{ +public: + inline ViewMapTesselator3D() : ViewMapTesselator() {} + virtual ~ViewMapTesselator3D() {} + +protected: + virtual void AddVertexToLine(LineRep *iLine, SVertex *v) + { + iLine->AddVertex(v->point3D()); + } +}; + +// +// Implementation +// +/////////////////////////////////////////////// + +template<class ViewEdgesIterator> +NodeGroup * ViewMapTesselator::Tesselate(ViewEdgesIterator begin, ViewEdgesIterator end) +{ + NodeGroup *group = new NodeGroup; + NodeShape *tshape = new NodeShape; + group->AddChild(tshape); + //tshape->frs_material().setDiffuse(0.f, 0.f, 0.f, 1.f); + tshape->setFrsMaterial(_FrsMaterial); + + LineRep* line; + + + FEdge *firstEdge; + FEdge *nextFEdge, *currentEdge; + + int id=0; + // for(vector<ViewEdge*>::const_iterator c=viewedges.begin(),cend=viewedges.end(); + // c!=cend; + // c++) + for(ViewEdgesIterator c=begin, cend=end; + c!=cend; + c++) + { + // if((*c)->qi() > 0){ + // continue; + // } + // if(!((*c)->nature() & (_nature))) + // continue; + // + firstEdge = (*c)->fedgeA(); + + // if(firstEdge->invisibility() > 0) + // continue; + + line = new OrientedLineRep(); + if(_overloadFrsMaterial) + line->setFrsMaterial(_FrsMaterial); + + // there might be chains containing a single element + if(0 == (firstEdge)->nextEdge()) + { + line->setStyle(LineRep::LINES); + // line->AddVertex((*c)->vertexA()->point3D()); + // line->AddVertex((*c)->vertexB()->point3D()); + AddVertexToLine(line, firstEdge->vertexA()); + AddVertexToLine(line, firstEdge->vertexB()); + } + else + { + line->setStyle(LineRep::LINE_STRIP); + + //firstEdge = (*c); + nextFEdge = firstEdge; + currentEdge = firstEdge; + do + { + //line->AddVertex(nextFEdge->vertexA()->point3D()); + AddVertexToLine(line, nextFEdge->vertexA()); + currentEdge = nextFEdge; + nextFEdge = nextFEdge->nextEdge(); + }while((nextFEdge != NULL) && (nextFEdge != firstEdge)); + // Add the last vertex + //line->AddVertex(currentEdge->vertexB()->point3D()); + AddVertexToLine(line, currentEdge->vertexB()); + + } + + line->setId((*c)->getId().getFirst()); + line->ComputeBBox(); + tshape->AddRep(line); + id++; + } + + return group; +} + +#endif // VIEWMAPTESSELATOR_H diff --git a/source/blender/freestyle/intern/winged_edge/Curvature.cpp b/source/blender/freestyle/intern/winged_edge/Curvature.cpp new file mode 100755 index 00000000000..2997d9b6922 --- /dev/null +++ b/source/blender/freestyle/intern/winged_edge/Curvature.cpp @@ -0,0 +1,648 @@ +/* GTS - Library for the manipulation of triangulated surfaces + * Copyright (C) 1999-2002 Ray Jones, Stéphane Popinet + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <cstdlib> // for malloc and free +#include "Curvature.h" +#include <math.h> +#include "WEdge.h" +#include "../system/FreestyleConfig.h" +#include "../geometry/normal_cycle.h" +#include <set> +#include <stack> + +static bool angle_obtuse (WVertex * v, WFace * f) +{ + WOEdge * e; + f->getOppositeEdge (v, e); + + Vec3r vec1(e->GetaVertex()->GetVertex()-v->GetVertex()); + Vec3r vec2(e->GetbVertex()->GetVertex()-v->GetVertex()); + return ((vec1 * vec2) < 0); +} + +// FIXME +// WVvertex is useless but kept for history reasons +static bool triangle_obtuse (WVertex*, WFace * f) +{ + bool b=false; + for (int i=0; i<3; i++) + b = b || + ((f->getEdgeList()[i]->getVec3r() * f->getEdgeList()[(i+1)%3]->getVec3r()) < 0); + return b; +} + +static real cotan (WVertex * vo, WVertex * v1, WVertex * v2) +{ + /* cf. Appendix B of [Meyer et al 2002] */ + real udotv, denom; + + Vec3r u(v1->GetVertex()- vo->GetVertex()); + Vec3r v(v2->GetVertex()- vo->GetVertex()); + + udotv = u * v; + denom = sqrt(u.squareNorm() * v.squareNorm() - udotv * udotv); + + /* denom can be zero if u==v. Returning 0 is acceptable, based on + * the callers of this function below. */ + if (denom == 0.0) return (0.0); + + return (udotv / denom); +} + +static real angle_from_cotan (WVertex * vo, WVertex * v1, WVertex * v2) +{ + /* cf. Appendix B and the caption of Table 1 from [Meyer et al 2002] */ + real udotv, denom; + + Vec3r u (v1->GetVertex()-vo->GetVertex()); + Vec3r v(v2->GetVertex()-vo->GetVertex()); + + udotv = u * v; + denom = sqrt(u.squareNorm() * v.squareNorm() - udotv * udotv); + + /* Note: I assume this is what they mean by using atan2 (). -Ray Jones */ + + /* tan = denom/udotv = y/x (see man page for atan2) */ + return (fabs (atan2 (denom, udotv))); +} + +/** + * gts_vertex_mean_curvature_normal: + * @v: a #WVertex. + * @s: a #GtsSurface. + * @Kh: the Mean Curvature Normal at @v. + * + * Computes the Discrete Mean Curvature Normal approximation at @v. + * The mean curvature at @v is half the magnitude of the vector @Kh. + * + * Note: the normal computed is not unit length, and may point either + * into or out of the surface, depending on the curvature at @v. It + * is the responsibility of the caller of the function to use the mean + * curvature normal appropriately. + * + * This approximation is from the paper: + * Discrete Differential-Geometry Operators for Triangulated 2-Manifolds + * Mark Meyer, Mathieu Desbrun, Peter Schroder, Alan H. Barr + * VisMath '02, Berlin (Germany) + * http://www-grail.usc.edu/pubs.html + * + * Returns: %TRUE if the operator could be evaluated, %FALSE if the + * evaluation failed for some reason (@v is boundary or is the + * endpoint of a non-manifold edge.) + */ +bool gts_vertex_mean_curvature_normal (WVertex * v, Vec3r &Kh) +{ + real area = 0.0; + + if (!v) return false; + + /* this operator is not defined for boundary edges */ + if (v->isBoundary()) return false; + + WVertex::incoming_edge_iterator itE; + + for (itE=v->incoming_edges_begin(); + itE!=v->incoming_edges_end(); itE++) + area+=(*itE)->GetaFace()->getArea(); + + Kh=Vec3r(0.0, 0.0, 0.0); + + for (itE=v->incoming_edges_begin(); + itE!=v->incoming_edges_end(); itE++) + { + WOEdge * e = (*itE)->getPrevOnFace(); + //if ((e->GetaVertex()==v) || (e->GetbVertex()==v)) cerr<< "BUG "; + + WVertex * v1 = e->GetaVertex(); + WVertex * v2 = e->GetbVertex(); + real temp; + + temp = cotan (v1, v, v2); + Kh = Vec3r(Kh+temp*(v2->GetVertex()-v->GetVertex())); + + temp = cotan (v2, v, v1); + Kh = Vec3r(Kh+temp*(v1->GetVertex()-v->GetVertex())); + } + if (area > 0.0) + { + Kh[0] /= 2*area; + Kh[1] /= 2*area; + Kh[2] /= 2*area; + } + else return false; + + return true; +} + +/** + * gts_vertex_gaussian_curvature: + * @v: a #WVertex. + * @s: a #GtsSurface. + * @Kg: the Discrete Gaussian Curvature approximation at @v. + * + * Computes the Discrete Gaussian Curvature approximation at @v. + * + * This approximation is from the paper: + * Discrete Differential-Geometry Operators for Triangulated 2-Manifolds + * Mark Meyer, Mathieu Desbrun, Peter Schroder, Alan H. Barr + * VisMath '02, Berlin (Germany) + * http://www-grail.usc.edu/pubs.html + * + * Returns: %TRUE if the operator could be evaluated, %FALSE if the + * evaluation failed for some reason (@v is boundary or is the + * endpoint of a non-manifold edge.) + */ +bool gts_vertex_gaussian_curvature (WVertex * v, real * Kg) +{ + real area = 0.0; + real angle_sum = 0.0; + + if (!v) return false; + if (!Kg) return false; + + /* this operator is not defined for boundary edges */ + if (v->isBoundary()) {*Kg=0.0 ;return false;} + + WVertex::incoming_edge_iterator itE; + for (itE=v->incoming_edges_begin(); + itE!=v->incoming_edges_end(); itE++) + area+=(*itE)->GetaFace()->getArea(); + + for (itE=v->incoming_edges_begin(); + itE!=v->incoming_edges_end(); itE++) + { + WOEdge * e = (*itE)->getPrevOnFace(); + WVertex * v1 = e->GetaVertex(); + WVertex * v2 = e->GetbVertex(); + angle_sum += angle_from_cotan (v, v1, v2); + } + + *Kg = (2.0*M_PI - angle_sum)/area; + + return true; +} + +/** + * gts_vertex_principal_curvatures: + * @Kh: mean curvature. + * @Kg: Gaussian curvature. + * @K1: first principal curvature. + * @K2: second principal curvature. + * + * Computes the principal curvatures at a point given the mean and + * Gaussian curvatures at that point. + * + * The mean curvature can be computed as one-half the magnitude of the + * vector computed by gts_vertex_mean_curvature_normal(). + * + * The Gaussian curvature can be computed with + * gts_vertex_gaussian_curvature(). + */ +void gts_vertex_principal_curvatures (real Kh, real Kg, + real * K1, real * K2) +{ + real temp = Kh*Kh - Kg; + + if (!K1) return; + if (!K1) return; + + if (temp < 0.0) temp = 0.0; + temp = sqrt (temp); + *K1 = Kh + temp; + *K2 = Kh - temp; +} + +/* from Maple */ +static void linsolve (real m11, real m12, real b1, + real m21, real m22, real b2, + real * x1, real * x2) +{ + real temp; + + temp = 1.0 / (m21*m12 - m11*m22); + *x1 = (m12*b2 - m22*b1)*temp; + *x2 = (m11*b2 - m21*b1)*temp; +} + +/* from Maple - largest eigenvector of [a b; b c] */ +static void eigenvector (real a, real b, real c, + Vec3r e) +{ + if (b == 0.0) { + e[0] = 0.0; + } else { + e[0] = -(c - a - sqrt (c*c - 2*a*c + a*a + 4*b*b))/(2*b); + } + e[1] = 1.0; + e[2] = 0.0; +} + +/** + * gts_vertex_principal_directions: + * @v: a #WVertex. + * @s: a #GtsSurface. + * @Kh: mean curvature normal (a #Vec3r). + * @Kg: Gaussian curvature (a real). + * @e1: first principal curvature direction (direction of largest curvature). + * @e2: second principal curvature direction. + * + * Computes the principal curvature directions at a point given @Kh + * and @Kg, the mean curvature normal and Gaussian curvatures at that + * point, computed with gts_vertex_mean_curvature_normal() and + * gts_vertex_gaussian_curvature(), respectively. + * + * Note that this computation is very approximate and tends to be + * unstable. Smoothing of the surface or the principal directions may + * be necessary to achieve reasonable results. + */ +void gts_vertex_principal_directions (WVertex * v, + Vec3r Kh, real Kg, + Vec3r &e1, Vec3r &e2) +{ + Vec3r N; + real normKh; + + Vec3r basis1, basis2, d, eig; + real ve2, vdotN; + real aterm_da, bterm_da, cterm_da, const_da; + real aterm_db, bterm_db, cterm_db, const_db; + real a, b, c; + real K1, K2; + real *weights, *kappas, *d1s, *d2s; + int edge_count; + real err_e1, err_e2; + int e; + WVertex::incoming_edge_iterator itE; + + /* compute unit normal */ + normKh = Kh.norm(); + + if (normKh > 0.0) { + Kh.normalize(); + } else { + /* This vertex is a point of zero mean curvature (flat or saddle + * point). Compute a normal by averaging the adjacent triangles + */ + N[0] = N[1] = N[2] = 0.0; + + for (itE=v->incoming_edges_begin(); + itE!=v->incoming_edges_end(); itE++) + N=Vec3r(N+(*itE)->GetaFace()->GetNormal()); + real normN = N.norm(); + if (normN <= 0.0) + return; + N.normalize(); + } + + + /* construct a basis from N: */ + /* set basis1 to any component not the largest of N */ + basis1[0] = basis1[1] = basis1[2] = 0.0; + if (fabs (N[0]) > fabs (N[1])) + basis1[1] = 1.0; + else + basis1[0] = 1.0; + + /* make basis2 orthogonal to N */ + basis2 = (N ^ basis1); + basis2.normalize(); + + /* make basis1 orthogonal to N and basis2 */ + basis1 = (N ^ basis2); + basis1.normalize(); + + aterm_da = bterm_da = cterm_da = const_da = 0.0; + aterm_db = bterm_db = cterm_db = const_db = 0.0; + int nb_edges=v->GetEdges().size(); + + weights = (real *) malloc (sizeof (real)*nb_edges); + kappas = (real*) malloc (sizeof (real)*nb_edges); + d1s = (real*) malloc (sizeof (real)*nb_edges); + d2s = (real*) malloc (sizeof (real)*nb_edges); + edge_count = 0; + + for (itE=v->incoming_edges_begin(); + itE!=v->incoming_edges_end(); itE++) + { + WOEdge * e; + WFace * f1, * f2; + real weight, kappa, d1, d2; + Vec3r vec_edge; + if (! *itE) continue; + e = *itE; + + /* since this vertex passed the tests in + * gts_vertex_mean_curvature_normal(), this should be true. */ + //g_assert (gts_edge_face_number (e, s) == 2); + + /* identify the two triangles bordering e in s */ + f1=e->GetaFace(); + f2=e->GetbFace(); + + /* We are solving for the values of the curvature tensor + * B = [ a b ; b c ]. + * The computations here are from section 5 of [Meyer et al 2002]. + * + * The first step is to calculate the linear equations governing + * the values of (a,b,c). These can be computed by setting the + * derivatives of the error E to zero (section 5.3). + * + * Since a + c = norm(Kh), we only compute the linear equations + * for dE/da and dE/db. (NB: [Meyer et al 2002] has the + * equation a + b = norm(Kh), but I'm almost positive this is + * incorrect.) + * + * Note that the w_ij (defined in section 5.2) are all scaled by + * (1/8*A_mixed). We drop this uniform scale factor because the + * solution of the linear equations doesn't rely on it. + * + * The terms of the linear equations are xterm_dy with x in + * {a,b,c} and y in {a,b}. There are also const_dy terms that are + * the constant factors in the equations. + */ + + /* find the vector from v along edge e */ + vec_edge=Vec3r(-1*e->getVec3r()); + + ve2 = vec_edge.squareNorm(); + vdotN = vec_edge * N; + + /* section 5.2 - There is a typo in the computation of kappa. The + * edges should be x_j-x_i. + */ + kappa = 2.0 * vdotN / ve2; + + /* section 5.2 */ + + /* I don't like performing a minimization where some of the + * weights can be negative (as can be the case if f1 or f2 are + * obtuse). To ensure all-positive weights, we check for + * obtuseness. */ + weight = 0.0; + if (! triangle_obtuse(v, f1)) { + weight += ve2 * + cotan (f1->GetNextOEdge(e->twin())->GetbVertex(), + e->GetaVertex(), e->GetbVertex()) / 8.0; + } else { + if (angle_obtuse (v, f1)) { + weight += ve2 * f1->getArea() / 4.0; + } else { + weight += ve2 * f1->getArea() / 8.0; + } + } + + if (! triangle_obtuse(v, f2)) { + weight += ve2 * + cotan (f2->GetNextOEdge(e)->GetbVertex(), + e->GetaVertex(), e->GetbVertex()) / 8.0; + } else { + if (angle_obtuse (v, f2)) { + weight += ve2 * f1->getArea() / 4.0; + } else { + weight += ve2 * f1->getArea() / 8.0; + } + } + + /* projection of edge perpendicular to N (section 5.3) */ + d[0] = vec_edge[0] - vdotN * N[0]; + d[1] = vec_edge[1] - vdotN * N[1]; + d[2] = vec_edge[2] - vdotN * N[2]; + d.normalize(); + + /* not explicit in the paper, but necessary. Move d to 2D basis. */ + d1 = d * basis1; + d2 = d * basis2; + + /* store off the curvature, direction of edge, and weights for later use */ + weights[edge_count] = weight; + kappas[edge_count] = kappa; + d1s[edge_count] = d1; + d2s[edge_count] = d2; + edge_count++; + + /* Finally, update the linear equations */ + aterm_da += weight * d1 * d1 * d1 * d1; + bterm_da += weight * d1 * d1 * 2 * d1 * d2; + cterm_da += weight * d1 * d1 * d2 * d2; + const_da += weight * d1 * d1 * (- kappa); + + aterm_db += weight * d1 * d2 * d1 * d1; + bterm_db += weight * d1 * d2 * 2 * d1 * d2; + cterm_db += weight * d1 * d2 * d2 * d2; + const_db += weight * d1 * d2 * (- kappa); + + } + + /* now use the identity (Section 5.3) a + c = |Kh| = 2 * kappa_h */ + aterm_da -= cterm_da; + const_da += cterm_da * normKh; + + aterm_db -= cterm_db; + const_db += cterm_db * normKh; + + /* check for solvability of the linear system */ + if (((aterm_da * bterm_db - aterm_db * bterm_da) != 0.0) && + ((const_da != 0.0) || (const_db != 0.0))) { + linsolve (aterm_da, bterm_da, -const_da, + aterm_db, bterm_db, -const_db, + &a, &b); + + c = normKh - a; + + eigenvector (a, b, c, eig); + } else { + /* region of v is planar */ + eig[0] = 1.0; + eig[1] = 0.0; + } + + /* Although the eigenvectors of B are good estimates of the + * principal directions, it seems that which one is attached to + * which curvature direction is a bit arbitrary. This may be a bug + * in my implementation, or just a side-effect of the inaccuracy of + * B due to the discrete nature of the sampling. + * + * To overcome this behavior, we'll evaluate which assignment best + * matches the given eigenvectors by comparing the curvature + * estimates computed above and the curvatures calculated from the + * discrete differential operators. */ + + gts_vertex_principal_curvatures (0.5 * normKh, Kg, &K1, &K2); + + err_e1 = err_e2 = 0.0; + /* loop through the values previously saved */ + for (e = 0; e < edge_count; e++) { + real weight, kappa, d1, d2; + real temp1, temp2; + real delta; + + weight = weights[e]; + kappa = kappas[e]; + d1 = d1s[e]; + d2 = d2s[e]; + + temp1 = fabs (eig[0] * d1 + eig[1] * d2); + temp1 = temp1 * temp1; + temp2 = fabs (eig[1] * d1 - eig[0] * d2); + temp2 = temp2 * temp2; + + /* err_e1 is for K1 associated with e1 */ + delta = K1 * temp1 + K2 * temp2 - kappa; + err_e1 += weight * delta * delta; + + /* err_e2 is for K1 associated with e2 */ + delta = K2 * temp1 + K1 * temp2 - kappa; + err_e2 += weight * delta * delta; + } + free (weights); + free (kappas); + free (d1s); + free (d2s); + + /* rotate eig by a right angle if that would decrease the error */ + if (err_e2 < err_e1) { + real temp = eig[0]; + + eig[0] = eig[1]; + eig[1] = -temp; + } + + e1[0] = eig[0] * basis1[0] + eig[1] * basis2[0]; + e1[1] = eig[0] * basis1[1] + eig[1] * basis2[1]; + e1[2] = eig[0] * basis1[2] + eig[1] * basis2[2]; + e1.normalize(); + + /* make N,e1,e2 a right handed coordinate sytem */ + e2 = N ^ e1; + e2.normalize(); +} + +namespace OGF { + static real angle(WOEdge* h) { + Vec3r e(h->GetbVertex()->GetVertex()-h->GetaVertex()->GetVertex()) ; + Vec3r n1 = h->GetbFace()->GetNormal(); + Vec3r n2 = h->GetaFace()->GetNormal(); + real sine = (n1 ^ n2) * e / e.norm() ; + if(sine >= 1.0) { + return M_PI / 2.0 ; + } + if(sine <= -1.0) { + return -M_PI / 2.0 ; + } + return ::asin(sine) ; + } + + // precondition1: P is inside the sphere + // precondition2: P,V points to the outside of + // the sphere (i.e. OP.V > 0) + static bool sphere_clip_vector( + const Vec3r& O, real r, + const Vec3r& P, Vec3r& V + ) { + + Vec3r W = P - O ; + real a = V.squareNorm() ; + real b = 2.0 * V * W ; + real c = W.squareNorm() - r*r ; + real delta = b*b - 4*a*c ; + if(delta < 0) { + // Should not happen, but happens sometimes (numerical precision) + return true ; + } + real t = - b + ::sqrt(delta) / (2.0 * a) ; + if(t < 0.0) { + // Should not happen, but happens sometimes (numerical precision) + return true ; + } + if(t >= 1.0) { + // Inside the sphere + return false ; + } + + V[0] = (t * V.x()) ; + V[1] = (t * V.y()) ; + V[2] = (t * V.z()) ; + + return true ; + } + + // TODO: check optimizations: + // use marking ? (measure *timings* ...) + void compute_curvature_tensor( + WVertex* start, real radius, NormalCycle& nc + ) { + // in case we have a non-manifold vertex, skip it... + if(start->isBoundary()) + return; + + std::set<WVertex*> vertices ; + const Vec3r& O = start->GetVertex() ; + std::stack<WVertex*> S ; + S.push(start) ; + vertices.insert(start) ; + while(!S.empty()) { + WVertex* v = S.top() ; + S.pop() ; + if(v->isBoundary()) + continue; + const Vec3r& P = v->GetVertex() ; + WVertex::incoming_edge_iterator woeit = v->incoming_edges_begin(); + WVertex::incoming_edge_iterator woeitend = v->incoming_edges_end(); + for(;woeit!=woeitend; ++woeit){ + WOEdge *h = *woeit; + Vec3r V(h->GetaVertex()->GetVertex()-h->GetbVertex()->GetVertex()) ; + if((v == start) || V * (P - O) > 0.0) { + bool isect = sphere_clip_vector(O, radius, P, V) ; + if(h->GetOwner()->GetNumberOfOEdges() == 2) { + real beta = angle(h) ; + nc.accumulate_dihedral_angle(V, beta) ; + } + if(!isect) { + WVertex* w = h->GetaVertex() ; + if(vertices.find(w) == vertices.end()) { + vertices.insert(w) ; + S.push(w) ; + } + } + } + } + } + } + + + void compute_curvature_tensor_one_ring( + WVertex* start, NormalCycle& nc + ) { + // in case we have a non-manifold vertex, skip it... + if(start->isBoundary()) + return; + + WVertex::incoming_edge_iterator woeit = start->incoming_edges_begin(); + WVertex::incoming_edge_iterator woeitend = start->incoming_edges_end(); + for(;woeit!=woeitend; ++woeit){ + WOEdge *h = (*woeit)->twin(); + Vec3r hvec(h->GetbVertex()->GetVertex()-h->GetaVertex()->GetVertex()); + nc.accumulate_dihedral_angle(hvec, angle(h)) ; + WOEdge *hprev = h->getPrevOnFace(); + Vec3r hprevvec(hprev->GetbVertex()->GetVertex()-hprev->GetaVertex()->GetVertex()); + nc.accumulate_dihedral_angle(hprevvec, angle(hprev)) ; + } + } + +} diff --git a/source/blender/freestyle/intern/winged_edge/Curvature.h b/source/blender/freestyle/intern/winged_edge/Curvature.h new file mode 100755 index 00000000000..214a32ca922 --- /dev/null +++ b/source/blender/freestyle/intern/winged_edge/Curvature.h @@ -0,0 +1,156 @@ + +/* GTS - Library for the manipulation of triangulated surfaces + * Copyright (C) 1999 Stéphane Popinet + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __CURVATURE_H__ +#define __CURVATURE_H__ + +# include "../system/FreestyleConfig.h" +# include "../system/Precision.h" +# include "../geometry/Geom.h" +using namespace Geometry; + +class WVertex; + +class LIB_WINGED_EDGE_EXPORT CurvatureInfo +{ +public: + + CurvatureInfo() + { + K1 = 0.0; + K2 = 0.0; + e1 = Vec3r(0.0,0.0,0.0); + e2 = Vec3r(0.0,0.0,0.0); + Kr = 0.0; + dKr = 0.0; + er = Vec3r(0.0,0.0,0.0); + } + + CurvatureInfo(const CurvatureInfo& iBrother){ + K1 = iBrother.K1; + K2 = iBrother.K2; + e1 = iBrother.e1; + e2 = iBrother.e2; + Kr = iBrother.Kr; + dKr = iBrother.dKr; + er = iBrother.er; + } + + CurvatureInfo(const CurvatureInfo& ca, const CurvatureInfo& cb, real t) { + K1 = ca.K1 + t * (cb.K1 - ca.K1); + K2 = ca.K2 + t * (cb.K2 - ca.K2); + e1 = ca.e1 + t * (cb.e1 - ca.e1); + e2 = ca.e2 + t * (cb.e2 - ca.e2); + Kr = ca.Kr + t * (cb.Kr - ca.Kr); + dKr = ca.dKr + t * (cb.dKr - ca.dKr); + er = ca.er + t * (cb.er - ca.er); + } + + real K1; // maximum curvature + real K2; // minimum curvature + Vec3r e1; // maximum curvature direction + Vec3r e2; // minimum curvature direction + real Kr; // radial curvature + real dKr; // radial curvature + Vec3r er; // radial curvature direction +}; + +class Face_Curvature_Info{ +public: + Face_Curvature_Info() {} + ~Face_Curvature_Info(){ + for(vector<CurvatureInfo*>::iterator ci=vec_curvature_info.begin(), ciend=vec_curvature_info.end(); + ci!=ciend; + ++ci){ + delete (*ci); + } + vec_curvature_info.clear(); + } + vector<CurvatureInfo *> vec_curvature_info; +}; + +bool LIB_WINGED_EDGE_EXPORT gts_vertex_mean_curvature_normal (WVertex * v, + Vec3r &n); + +bool LIB_WINGED_EDGE_EXPORT gts_vertex_gaussian_curvature (WVertex * v, + real * Kg); + +void LIB_WINGED_EDGE_EXPORT gts_vertex_principal_curvatures (real Kh, + real Kg, + real * K1, + real * K2); + +void LIB_WINGED_EDGE_EXPORT gts_vertex_principal_directions (WVertex * v, + Vec3r Kh, + real Kg, + Vec3r &e1, + Vec3r &e2); + +/* + * OGF/Graphite: Geometry and Graphics Programming Library + Utilities + * Copyright (C) 2000-2003 Bruno Levy + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * If you modify this software, you should include a notice giving the + * name of the person performing the modification, the date of modification, + * and the reason for such modification. + * + * Contact: Bruno Levy + * + * levy@loria.fr + * + * ISA Project + * LORIA, INRIA Lorraine, + * Campus Scientifique, BP 239 + * 54506 VANDOEUVRE LES NANCY CEDEX + * FRANCE + * + * Note that the GNU General Public License does not permit incorporating + * the Software into proprietary programs. + */ + namespace OGF { + + class NormalCycle ; + + void LIB_WINGED_EDGE_EXPORT compute_curvature_tensor( + WVertex* start, double radius, NormalCycle& nc + ) ; + + void LIB_WINGED_EDGE_EXPORT compute_curvature_tensor_one_ring( + WVertex* start, NormalCycle& nc + ) ; + } + + +#endif /* __CURVATURE_H__ */ + diff --git a/source/blender/freestyle/intern/winged_edge/Nature.h b/source/blender/freestyle/intern/winged_edge/Nature.h new file mode 100755 index 00000000000..52c9c60d8c7 --- /dev/null +++ b/source/blender/freestyle/intern/winged_edge/Nature.h @@ -0,0 +1,77 @@ +// +// Filename : Nature.h +// Author(s) : Emmanuel Turquin +// Purpose : Different natures for both vertices and edges +// Date of creation : 01/07/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef NATURE_H +# define NATURE_H + +/*! \file Nature.h + * Definitions of Natures of the ViewMap's elements + */ + +/*! Namespace gathering the different possible + * natures of 0D and 1D elements of the ViewMap + */ +namespace Nature { + + typedef unsigned short VertexNature; + + /*! true for any 0D element */ + static const VertexNature POINT = 0; // 0 + /*! true for SVertex */ + static const VertexNature S_VERTEX = (1 << 0); // 1 + /*! true for ViewVertex */ + static const VertexNature VIEW_VERTEX = (1 << 1); // 2 + /*! true for NonTVertex */ + static const VertexNature NON_T_VERTEX = (1 << 2); // 4 + /*! true for TVertex */ + static const VertexNature T_VERTEX = (1 << 3); // 8 + /*! true for CUSP */ + static const VertexNature CUSP = (1 << 4); // 16 + + typedef unsigned short EdgeNature; + /*! true for non feature edges (always false for 1D elements of the ViewMap) */ + static const EdgeNature NO_FEATURE = 0; // 0 + /*! true for silhouettes */ + static const EdgeNature SILHOUETTE = (1 << 0); // 1 + /*! true for borders */ + static const EdgeNature BORDER = (1 << 1); // 2 + /*! true for creases */ + static const EdgeNature CREASE = (1 << 2); // 4 + /*! true for ridges */ + static const EdgeNature RIDGE = (1 << 3); // 8 + /*! true for valleys */ + static const EdgeNature VALLEY = (1 << 4); // 16 + /*! true for suggestive contours */ + static const EdgeNature SUGGESTIVE_CONTOUR = (1 << 5); // 32 + /*! true for material boundaries */ + static const EdgeNature MATERIAL_BOUNDARY = (1 << 6); // 64 + +} // end of namespace Nature + +#endif // NATURE_H diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.cpp b/source/blender/freestyle/intern/winged_edge/WEdge.cpp new file mode 100755 index 00000000000..31082e3376f --- /dev/null +++ b/source/blender/freestyle/intern/winged_edge/WEdge.cpp @@ -0,0 +1,738 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include <iostream> +#include "WEdge.h" + +/*! Temporary structures */ +class vertexdata +{ +public: + WVertex *_copy; +}; + +class oedgedata +{ +public: + WOEdge *_copy; +}; + +class edgedata +{ +public: + WEdge *_copy; +}; + +class facedata +{ +public: + WFace *_copy; +}; + + + /**********************************/ + /* */ + /* */ + /* WVertex */ + /* */ + /* */ + /**********************************/ + +WVertex::WVertex(WVertex& iBrother) +{ + _Id = iBrother._Id; + _Vertex = iBrother._Vertex; + _EdgeList = iBrother._EdgeList; + + _Shape = iBrother._Shape; + _Smooth = iBrother._Smooth; + _Border = iBrother._Border; + userdata = NULL; + iBrother.userdata = new vertexdata; + ((vertexdata*)(iBrother.userdata))->_copy = this; +} + +WVertex* WVertex::duplicate() +{ + WVertex *clone = new WVertex(*this); + return clone; +} + + +WOEdge* WVertex::incoming_edge_iterator::operator*() + +{ + return _current; +} +void WVertex::incoming_edge_iterator::increment(){ + WOEdge *twin = _current->twin(); + if(!twin){ + // we reached a hole + _current = 0; + return; + } + WOEdge *next = twin->getPrevOnFace(); + if(next == _begin){ + next = 0; + } + _current = next; +} + +WFace* WVertex::face_iterator::operator*(){ + WOEdge * woedge = *_edge_it; + if(woedge == 0) + return 0; + return (woedge)->GetbFace(); +} + +//bool WVertex::isBoundary () const{ +// return _Border; +//} +bool WVertex::isBoundary () +{ + if(_Border == 1) + return true; + else if(_Border == 0) + return false; + + vector<WEdge *>::const_iterator it; + for(it=_EdgeList.begin(); it!=_EdgeList.end(); it++){ + if((*it)->GetNumberOfOEdges() == 1){ + _Border = 1; + return true; + } + } + //if (!(*it)->GetaOEdge()->GetaFace()) return true; + _Border = 0; + return false; +} + +void WVertex::AddEdge(WEdge *iEdge) { + _EdgeList.push_back(iEdge); +} + +WVertex::incoming_edge_iterator WVertex::incoming_edges_begin(){ + WOEdge *begin; + WEdge * wedge = _EdgeList.front(); + WOEdge* aOEdge = wedge->GetaOEdge(); + if(aOEdge->GetbVertex() == this) + begin = aOEdge; + else + begin = _EdgeList.front()->GetbOEdge(); + return incoming_edge_iterator(this, begin, begin); +} +WVertex::incoming_edge_iterator WVertex::incoming_edges_end(){ + WOEdge *begin; + WOEdge* aOEdge = _EdgeList.front()->GetaOEdge(); + if(aOEdge->GetbVertex() == this) + begin = aOEdge; + else + begin = _EdgeList.front()->GetbOEdge(); + return incoming_edge_iterator(this, begin, 0); +} +//WOEdge** WVertex::incoming_edge_iterator::operator->() +//{ +// WOEdge ** ppaOEdge = (*_iter)->GetaOEdge(); +// if(aOEdge->GetbVertex() == _vertex) +// return ppaOEdge; +// else +// { +// WOEdge *bOEdge = (*_iter)->GetbOEdge(); +// return &bOEdge; +// } +// +//} + /**********************************/ + /* */ + /* */ + /* WOEdge */ + /* */ + /* */ + /**********************************/ + +WOEdge::WOEdge(WOEdge& iBrother) +{ + _paVertex = iBrother.GetaVertex(); + _pbVertex = iBrother.GetbVertex(); + _paFace = iBrother.GetaFace(); + _pbFace = iBrother.GetbFace(); + _pOwner = iBrother.GetOwner(); + userdata = NULL; + iBrother.userdata = new oedgedata; + ((oedgedata*)(iBrother.userdata))->_copy = this; +} + +WOEdge * WOEdge::duplicate() +{ + WOEdge *clone = new WOEdge(*this); + return clone; +} + +Vec3r +WOEdge::getVec3r () +{ + return Vec3r(_pbVertex->GetVertex() - _paVertex->GetVertex()); +} + +WOEdge * WOEdge::twin () +{ + return GetOwner()->GetOtherOEdge(this); +} + +WOEdge * +WOEdge::getPrevOnFace() +{ + return _pbFace->GetPrevOEdge(this); +} + + /**********************************/ + /* */ + /* */ + /* WEdge */ + /* */ + /* */ + /**********************************/ + +WEdge::WEdge(WEdge& iBrother) +{ + _paOEdge = NULL; + _pbOEdge = NULL; + WOEdge *aoedge = iBrother.GetaOEdge(); + WOEdge *boedge = iBrother.GetbOEdge(); + userdata = NULL; + + if(NULL != aoedge) + //_paOEdge = new WOEdge(*aoedge); + _paOEdge = aoedge->duplicate(); + if(NULL != boedge) + //_pbOEdge = new WOEdge(*boedge); + _pbOEdge = boedge->duplicate(); + + _nOEdges = iBrother.GetNumberOfOEdges(); + _Id = iBrother.GetId(); + iBrother.userdata = new edgedata; + ((edgedata*)(iBrother.userdata))->_copy = this; +} + +WEdge * WEdge::duplicate() +{ + WEdge *clone = new WEdge(*this); + return clone; +} + + /**********************************/ + /* */ + /* */ + /* WFace */ + /* */ + /* */ + /**********************************/ + + +WFace::WFace(WFace& iBrother) +{ + _OEdgeList = iBrother.getEdgeList(); + _Normal = iBrother.GetNormal(); + _VerticesNormals = iBrother._VerticesNormals; + _VerticesTexCoords = iBrother._VerticesTexCoords; + _Id = iBrother.GetId(); + _FrsMaterialIndex = iBrother._FrsMaterialIndex; + userdata = NULL; + iBrother.userdata = new facedata; + ((facedata*)(iBrother.userdata))->_copy = this; +} + +WFace * WFace::duplicate() +{ + WFace * clone = new WFace(*this); + return clone; +} + +const FrsMaterial& WFace::frs_material() { + return getShape()->frs_material(_FrsMaterialIndex); +} + +WOEdge * WFace::MakeEdge(WVertex *v1, WVertex *v2) +{ + // First check whether the same oriented edge already exists + // or not: + vector<WEdge *>& v1Edges = v1->GetEdges(); + for(vector<WEdge*>::iterator it1=v1Edges.begin(), end=v1Edges.end(); + it1!=end; + it1++) + { + + WEdge *we=(*it1); + + WOEdge *woea = we->GetaOEdge(); + + if((woea->GetaVertex() == v1) && (woea->GetbVertex() == v2)) + //if((*it1)->GetbVertex() == v2) + { + // The oriented edge already exists + cerr << "Warning: edge " << v1->GetId() << " - " << v2->GetId() << " appears twice, correcting" << endl; + // Adds the edge to the face + //AddEdge((*it1)->GetaOEdge()); + AddEdge(woea); + (*it1)->setNumberOfOEdges((*it1)->GetNumberOfOEdges()+1); + //sets these vertices as border: + v1->setBorder(true); + v2->setBorder(true); + //return (*it1)->GetaOEdge(); + return woea; + } + + WOEdge *woeb = we->GetbOEdge(); + if((woeb != 0) && (woeb->GetaVertex() == v1) && (woeb->GetbVertex() == v2)) + + //if((*it1)->GetbVertex() == v2) + + { + // The oriented edge already exists + cerr << "Warning: edge " << v1->GetId() << " - " << v2->GetId() << " appears twice, correcting" << endl; + // Adds the edge to the face + //AddEdge((*it1)->GetaOEdge()); + AddEdge(woeb); + (*it1)->setNumberOfOEdges((*it1)->GetNumberOfOEdges()+1); + //sets these vertices as border: + v1->setBorder(true); + v2->setBorder(true); + //return (*it1)->GetaOEdge(); + return woeb; + } + } + + // the oriented edge we're about to build + WOEdge *pOEdge = new WOEdge; + + WEdge * edge; // The edge containing the oriented edge. + + // checks whether this edge already exists or not + // If it exists, it points outward v2 + + bool exist = false; + WOEdge *pInvertEdge = NULL; // The inverted edge if it exists + vector<WEdge *>& v2Edges = v2->GetEdges(); + vector<WEdge *>::iterator it; + for(it=v2Edges.begin(); it!=v2Edges.end(); it++) + { + if((*it)->GetbVertex() == v1) + { + // The invert edge already exists + exist = true; + pInvertEdge = (*it)->GetaOEdge(); + break; + } + } + + //DEBUG: + + + if(true == exist) // The invert edge already exists + { + // Retrieves the corresponding edge + edge = pInvertEdge->GetOwner(); + + // Sets the a Face (retrieved from pInvertEdge + pOEdge->setaFace(pInvertEdge->GetbFace()); + + // Updates the invert edge: + pInvertEdge->setaFace(this); + } + else // The invert edge does not exist yet + { + // we must create a new edge + //edge = new WEdge; + edge = instanciateEdge(); + + // updates the a,b vertex edges list: + v1->AddEdge(edge); + v2->AddEdge(edge); + + } + + pOEdge->setOwner(edge); + // Add the vertices: + pOEdge->setaVertex(v1); + pOEdge->setbVertex(v2); + + // Debug: + if(v1->GetId() == v2->GetId()) + cerr << "Warning: edge " << this << " null with vertex " << v1->GetId() << endl; + + edge->AddOEdge(pOEdge); + //edge->setNumberOfOEdges(edge->GetNumberOfOEdges()+1); + + // Add this face (the b face) + pOEdge->setbFace(this); + + // Adds the edge to the face + AddEdge(pOEdge); + + return pOEdge; +} + + +bool +WFace::getOppositeEdge (const WVertex *v, WOEdge* &e) +{ + if (_OEdgeList.size()!=3) return false; + + vector<WOEdge *>::iterator it; + e=NULL; + for(it=_OEdgeList.begin(); it!=_OEdgeList.end(); it++) + if ((*it)->GetaVertex()==v) e=*it; + if (!e) return false; + e=NULL; + for(it=_OEdgeList.begin(); it!=_OEdgeList.end(); it++) + if (((*it)->GetaVertex()!=v) && ((*it)->GetbVertex()!=v)) e=*it; + if (!e) return false; + else return true; +} + +real +WFace::getArea () +{ + vector<WOEdge *>::iterator it; + Vec3r origin=(*(_OEdgeList.begin()))->GetaVertex()->GetVertex(); + it=_OEdgeList.begin(); + real a=0; + for (it=it++; it!=_OEdgeList.end(); it++) { + Vec3r v1=Vec3r((*it)->GetaVertex()->GetVertex() - origin); + Vec3r v2=Vec3r((*it)->GetbVertex()->GetVertex() - origin); + a += (v1 ^ v2).norm() / 2.0; + } + return a; +} + + +WOEdge* +WFace::GetPrevOEdge(WOEdge* iOEdge) + { + vector<WOEdge*>::iterator woe,woend, woefirst; + woefirst = _OEdgeList.begin(); + woend=_OEdgeList.end(); + WOEdge *prev =*woefirst; + woe=woefirst; + woe++; + for(; + woe!=woend; + woe++) + { + if((*woe) == iOEdge) + return prev; + prev= *woe; + } + // We left the loop. That means that the first + // OEdge was the good one: + if((*woefirst)==iOEdge) + return prev; + + return NULL; + } + +WShape * WFace::getShape() +{ + return GetVertex(0)->shape(); +} + + /**********************************/ + /* */ + /* */ + /* WShape */ + /* */ + /* */ + /**********************************/ + + +LIB_WINGED_EDGE_EXPORT +unsigned WShape::_SceneCurrentId = 0; + +WShape * WShape::duplicate() +{ + WShape *clone = new WShape(*this); + return clone; +} + +WShape::WShape(WShape& iBrother) +{ + _Id = iBrother.GetId(); + _Name = iBrother._Name; + _FrsMaterials = iBrother._FrsMaterials; + _meanEdgeSize = iBrother._meanEdgeSize; + iBrother.bbox(_min, _max); + vector<WVertex*>& vertexList = iBrother.getVertexList(); + vector<WVertex*>::iterator v=vertexList.begin(), vend=vertexList.end(); + for(; + v!=vend; + v++) + { + //WVertex *newVertex = new WVertex(*(*v)); + WVertex *newVertex = (*v)->duplicate(); + + newVertex->setShape(this); + AddVertex(newVertex); + } + + vector<WEdge*>& edgeList = iBrother.getEdgeList(); + vector<WEdge*>::iterator e=edgeList.begin(), eend=edgeList.end(); + for(; + e!=eend; + e++) + { + //WEdge *newEdge = new WEdge(*(*e)); + WEdge *newEdge = (*e)->duplicate(); + AddEdge(newEdge); + } + + vector<WFace*>& faceList = iBrother.GetFaceList(); + vector<WFace*>::iterator f=faceList.begin(), fend=faceList.end(); + for(; + f!=fend; + f++) + { + //WFace *newFace = new WFace(*(*f)); + WFace *newFace = (*f)->duplicate(); + AddFace(newFace); + } + + // update all pointed addresses thanks to the newly created objects: + vend=_VertexList.end(); + for(v=_VertexList.begin(); + v!=vend; + v++) + { + const vector<WEdge*>& vedgeList = (*v)->GetEdges(); + vector<WEdge*> newvedgelist; + unsigned int i; + for(i=0; i<vedgeList.size(); i++) + { + WEdge *current = vedgeList[i]; + edgedata * currentvedata = (edgedata*)current->userdata; + newvedgelist.push_back(currentvedata->_copy); + } + (*v)->setEdges(newvedgelist); + } + + eend = _EdgeList.end(); + for(e=_EdgeList.begin(); + e!=eend; + e++) + { + // update aOedge: + WOEdge *aoEdge = (*e)->GetaOEdge(); + aoEdge->setaVertex(((vertexdata*)(aoEdge->GetaVertex()->userdata))->_copy); + aoEdge->setbVertex(((vertexdata*)(aoEdge->GetbVertex()->userdata))->_copy); + if(NULL != aoEdge->GetaFace()) + aoEdge->setaFace(((facedata*)(aoEdge->GetaFace()->userdata))->_copy); + aoEdge->setbFace(((facedata*)(aoEdge->GetbFace()->userdata))->_copy); + aoEdge->setOwner(((edgedata*)(aoEdge->GetOwner()->userdata))->_copy); + // update bOedge: + + WOEdge *boEdge = (*e)->GetbOEdge(); + if(boEdge != 0) + { + boEdge->setaVertex(((vertexdata*)(boEdge->GetaVertex()->userdata))->_copy); + boEdge->setbVertex(((vertexdata*)(boEdge->GetbVertex()->userdata))->_copy); + if(NULL != boEdge->GetaFace()) + boEdge->setaFace(((facedata*)(boEdge->GetaFace()->userdata))->_copy); + boEdge->setbFace(((facedata*)(boEdge->GetbFace()->userdata))->_copy); + boEdge->setOwner(((edgedata*)(boEdge->GetOwner()->userdata))->_copy); + } + } + + fend = _FaceList.end(); + for(f=_FaceList.begin(); + f!=fend; + f++) + { + unsigned i; + const vector<WOEdge*>& oedgeList = (*f)->getEdgeList(); + vector<WOEdge*> newoedgelist; + + unsigned n = oedgeList.size(); + for(i=0; i<n; i++) + { + WOEdge *current = oedgeList[i]; + oedgedata * currentoedata = (oedgedata*)current->userdata; + newoedgelist.push_back(currentoedata->_copy); + //oedgeList[i] = currentoedata->_copy; + //oedgeList[i] = ((oedgedata*)(oedgeList[i]->userdata))->_copy; + } + (*f)->setEdgeList(newoedgelist); + } + + // Free all memory (arghh!) + // Vertex + vend = iBrother.getVertexList().end(); + for(v=iBrother.getVertexList().begin(); + v!=vend; + v++) + { + delete (vertexdata*)((*v)->userdata); + (*v)->userdata = NULL; + } + + // Edges and OEdges: + eend = iBrother.getEdgeList().end(); + for(e=iBrother.getEdgeList().begin(); + e!=eend; + e++) + { + delete (edgedata*)((*e)->userdata); + (*e)->userdata = NULL; + // OEdge a : + delete (oedgedata*)((*e)->GetaOEdge()->userdata); + (*e)->GetaOEdge()->userdata = NULL; + // OEdge b: + WOEdge* oedgeb = (*e)->GetbOEdge(); + if(NULL != oedgeb) + { + delete (oedgedata*)(oedgeb->userdata); + oedgeb->userdata = NULL; + } + } + // Faces + fend = iBrother.GetFaceList().end(); + for(f=iBrother.GetFaceList().begin(); + f!=fend; + f++) + { + delete (facedata*)((*f)->userdata); + (*f)->userdata = NULL; + } +} + +WFace* WShape::MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterial) +{ + // allocate the new face + WFace *face = instanciateFace(); + + WFace *result = MakeFace(iVertexList, iMaterial, face); + if (0 == result) { + delete face; + return 0; + } + return result; +} + +WFace * WShape::MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList, unsigned iMaterial) +{ + // allocate the new face + WFace *face = MakeFace(iVertexList, iMaterial); + + if(0 == face) + + return 0; + + // set the list of per-vertex normals + face->setNormalList(iNormalsList); + // set the list of per-vertex tex coords + face->setTexCoordsList(iTexCoordsList); + + return face; +} + +WFace* WShape::MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterial, WFace *face) +{ + + int id = _FaceList.size(); + + face->setFrsMaterialIndex(iMaterial); + + // Check whether we have a degenerated face: + + // LET'S HACK IT FOR THE TRIANGLE CASE: + + if(3 == iVertexList.size()) + + { + + if((iVertexList[0] == iVertexList[1]) + + || (iVertexList[0] == iVertexList[2]) + + || (iVertexList[2] == iVertexList[1])) + + { + + cerr << "Warning: degenerated triangle detected, correcting" << endl; + return 0; + + } + + } + // vertex pointers used to build each edge + vector<WVertex*>::iterator va, vb, it; + + va = iVertexList.begin(); + vb = va; + for(; va != iVertexList.end(); va = vb) + { + vb++; + // Adds va to the vertex list: + //face->AddVertex(*va); + + WOEdge * oedge; + if(*va == iVertexList.back()) + oedge = face->MakeEdge(*va, iVertexList.front()); //for the last (closing) edge + else + oedge = face->MakeEdge(*va, *vb); + + + if(oedge == 0) + return 0; + + + WEdge *edge = oedge->GetOwner(); + if(1 == edge->GetNumberOfOEdges()) + { + // means that we just created a new edge and that we must add it to the + // shape's edges list + edge->setId(_EdgeList.size()); + AddEdge(edge); + // compute the mean edge value: + _meanEdgeSize += edge->GetaOEdge()->getVec3r().norm(); + } + } + + // compute the face normal (v1v2 ^ v1v3) + WVertex *v1, *v2, *v3; + it = iVertexList.begin(); + v1 = *it; + it++; + v2 = *it; + it++; + v3 = *it; + + Vec3r vector1(v2->GetVertex()-v1->GetVertex()); + Vec3r vector2(v3->GetVertex()-v1->GetVertex()); + + Vec3r normal(vector1 ^ vector2); + normal.normalize(); + face->setNormal(normal); + + // Add the face to the shape's faces list: + face->setId(id); + AddFace(face); + + return face; +} diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.h b/source/blender/freestyle/intern/winged_edge/WEdge.h new file mode 100755 index 00000000000..ebf26cd6d23 --- /dev/null +++ b/source/blender/freestyle/intern/winged_edge/WEdge.h @@ -0,0 +1,958 @@ +// +// Filename : WEdge.h +// Author(s) : Stephane Grabli +// Purpose : Classes to define a Winged Edge data structure. +// Date of creation : 18/02/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef WEDGE_H +# define WEDGE_H + +# include <vector> +# include <iterator> +# include "../system/FreestyleConfig.h" +# include "../geometry/Geom.h" +# include "../scene_graph/FrsMaterial.h" + +using namespace std; +using namespace Geometry; + + + /**********************************/ + /* */ + /* */ + /* WVertex */ + /* */ + /* */ + /**********************************/ + + +class WOEdge; +class WEdge; +class WShape; +class WFace; +class LIB_WINGED_EDGE_EXPORT WVertex +{ +protected: + int _Id; // an identificator + Vec3r _Vertex; + vector<WEdge*> _EdgeList; + WShape * _Shape; // the shape to which the vertex belongs + bool _Smooth; // flag to indicate whether the Vertex belongs to a smooth edge or not + int _Border; // 1 -> border, 0 -> no border, -1 -> not set + +public: + void * userdata; // designed to store specific user data + inline WVertex(const Vec3r &v) {_Id = 0; _Vertex = v; userdata = NULL; _Shape = NULL;_Smooth=true;_Border=-1;} + /*! Copy constructor */ + WVertex(WVertex& iBrother); + virtual WVertex * duplicate(); + virtual ~WVertex() {} + + /*! accessors */ + inline Vec3r& GetVertex() {return _Vertex;} + inline vector<WEdge*>& GetEdges() {return _EdgeList;} + inline int GetId() {return _Id;} + inline WShape * shape() const {return _Shape;} + inline bool isSmooth() const {return _Smooth;} + bool isBoundary(); + + /*! modifiers */ + inline void setVertex(const Vec3r& v) {_Vertex = v;} + inline void setEdges(const vector<WEdge *>& iEdgeList) {_EdgeList = iEdgeList;} + inline void setId(int id) {_Id = id;} + inline void setShape(WShape *iShape) {_Shape = iShape;} + inline void setSmooth(bool b) {_Smooth = b;} + inline void setBorder(bool b) {if(b) _Border= 1; else _Border = 0;} + + /*! Adds an edge to the edges list */ + void AddEdge(WEdge *iEdge) ; + + virtual void ResetUserData() {userdata = 0;} + + + +public: + + + + /*! Iterator to iterate over a vertex incoming edges in the CCW order*/ +# if defined(__GNUC__) && (__GNUC__ < 3) + class incoming_edge_iterator : public input_iterator<WOEdge*,ptrdiff_t> +# else + class LIB_WINGED_EDGE_EXPORT incoming_edge_iterator : public iterator<input_iterator_tag, WOEdge*,ptrdiff_t> +# endif + { + private: + WVertex *_vertex; + // + WOEdge *_begin; + WOEdge *_current; + + public: +# if defined(__GNUC__) && (__GNUC__ < 3) + inline incoming_edge_iterator() : input_iterator<WOEdge*,ptrdiff_t>() {} +# else + inline incoming_edge_iterator() : iterator<input_iterator_tag, WOEdge*,ptrdiff_t>() {} +# endif + virtual ~incoming_edge_iterator() {}; //soc + + protected: + friend class WVertex; + inline incoming_edge_iterator( + WVertex *iVertex, + WOEdge * iBegin, + WOEdge * iCurrent) +# if defined(__GNUC__) && (__GNUC__ < 3) + : input_iterator<WOEdge*,ptrdiff_t>() +# else + : iterator<input_iterator_tag, WOEdge*,ptrdiff_t>() +# endif + { + _vertex = iVertex; + _begin = iBegin; + _current = iCurrent; + } + + public: + inline incoming_edge_iterator(const incoming_edge_iterator& iBrother) +# if defined(__GNUC__) && (__GNUC__ < 3) + : input_iterator<WOEdge*,ptrdiff_t>(iBrother) +# else + : iterator<input_iterator_tag, WOEdge*,ptrdiff_t>(iBrother) +# endif + { + _vertex = iBrother._vertex; + _begin = iBrother._begin; + _current = iBrother._current; + } + + public: + // operators + virtual incoming_edge_iterator& operator++() // operator corresponding to ++i + { + increment(); + return *this; + } + virtual incoming_edge_iterator operator++(int) // operator corresponding to i++ + { + incoming_edge_iterator tmp = *this; + increment(); + return tmp; + } + + // comparibility + virtual bool operator!=(const incoming_edge_iterator& b) const + { + return ((_current) != (b._current)); + } + + virtual bool operator==(const incoming_edge_iterator& b) const + { + return ((_current)== (b._current)); + } + + // dereferencing + virtual WOEdge* operator*(); + //virtual WOEdge** operator->(); + protected: + virtual void increment(); + }; + + + /*! Iterator to iterate over a vertex faces in the CCW order */ +# if defined(__GNUC__) && (__GNUC__ < 3) + class face_iterator : public input_iterator<WFace*,ptrdiff_t> +# else + class LIB_WINGED_EDGE_EXPORT face_iterator : public iterator<input_iterator_tag, WFace*,ptrdiff_t> +# endif + { + private: + incoming_edge_iterator _edge_it; + + public: +# if defined(__GNUC__) && (__GNUC__ < 3) + inline face_iterator() : input_iterator<WFace*,ptrdiff_t>() {} +# else + inline face_iterator() : iterator<input_iterator_tag, WFace*,ptrdiff_t>() {} +# endif + virtual ~face_iterator() {}; //soc + + protected: + friend class WVertex; + inline face_iterator( + incoming_edge_iterator it) +# if defined(__GNUC__) && (__GNUC__ < 3) + : input_iterator<WFace*,ptrdiff_t>() +# else + : iterator<input_iterator_tag, WFace*,ptrdiff_t>() +# endif + { + _edge_it = it; + } + + public: + inline face_iterator(const face_iterator& iBrother) +# if defined(__GNUC__) && (__GNUC__ < 3) + : input_iterator<WFace*,ptrdiff_t>(iBrother) +# else + : iterator<input_iterator_tag, WFace*,ptrdiff_t>(iBrother) +# endif + { + _edge_it = iBrother._edge_it; + } + + public: + // operators + virtual face_iterator& operator++() // operator corresponding to ++i + { + increment(); + return *this; + } + virtual face_iterator operator++(int) // operator corresponding to i++ + { + face_iterator tmp = *this; + increment(); + return tmp; + } + + // comparibility + virtual bool operator!=(const face_iterator& b) const + { + return ((_edge_it) != (b._edge_it)); + } + + virtual bool operator==(const face_iterator& b) const + { + return ((_edge_it)== (b._edge_it)); + } + + // dereferencing + virtual WFace* operator*(); + //virtual WOEdge** operator->(); + protected: + inline void increment(){ + ++_edge_it; + } + }; + +public: + /*! iterators access */ + virtual incoming_edge_iterator incoming_edges_begin(); + virtual incoming_edge_iterator incoming_edges_end() ; + + virtual face_iterator faces_begin() { + return face_iterator(incoming_edges_begin()); + } + virtual face_iterator faces_end() { + return face_iterator(incoming_edges_end()); + } +}; + + + /**********************************/ + /* */ + /* */ + /* WOEdge */ + /* */ + /* */ + /**********************************/ +class WFace; +class WEdge; + +class LIB_WINGED_EDGE_EXPORT WOEdge +{ +protected: + // WOEdge *_paCWEdge; // edge reached when traveling clockwise on aFace from the edge + // WOEdge *_pbCWEdge; // edge reached when traveling clockwise on bFace from the edge + // WOEdge *_paCCWEdge; // edge reached when traveling counterclockwise on aFace from the edge + // WOEdge *_pbCCWEdge; // edge reached when traveling counterclockwise on bFace from the edge + WVertex *_paVertex; // starting vertex + WVertex *_pbVertex; // ending vertex + WFace *_paFace; // when following the edge, face on the right + WFace *_pbFace; // when following the edge, face on the left + WEdge *_pOwner; // Edge + +public: + void *userdata; + inline WOEdge() + { + // _paCWEdge = NULL; + // _pbCWEdge = NULL; + // _paCCWEdge = NULL; + // _pbCCWEdge = NULL; + _paVertex = NULL; + _pbVertex = NULL; + _paFace = NULL; + _pbFace = NULL; + _pOwner = NULL; + userdata = NULL; + } + virtual ~WOEdge() {}; //soc + + /*! copy constructor */ + WOEdge(WOEdge& iBrother); + virtual WOEdge * duplicate(); + + /*! accessors */ + // inline WOEdge *GetaCWEdge() {return _paCWEdge;} + // inline WOEdge *GetbCWEdge() {return _pbCWEdge;} + // inline WOEdge *GetaCCWEdge() {return _paCCWEdge;} + // inline WOEdge *GetbCCWEdge() {return _pbCCWEdge;} + inline WVertex *GetaVertex() {return _paVertex;} + inline WVertex *GetbVertex() {return _pbVertex;} + inline WFace *GetaFace() {return _paFace;} + inline WFace *GetbFace() {return _pbFace;} + inline WEdge *GetOwner() {return _pOwner;} + + + /*! modifiers */ + // inline void SetaCWEdge(WOEdge *pe) {_paCWEdge = pe;} + // inline void SetbCWEdge(WOEdge *pe) {_pbCWEdge = pe;} + // inline void SetaCCWEdge(WOEdge *pe) {_paCCWEdge = pe;} + // inline void SetbCCCWEdge(WOEdge *pe) {_pbCCWEdge = pe;} + inline void setaVertex(WVertex *pv) {_paVertex = pv;} + inline void setbVertex(WVertex *pv) {_pbVertex = pv;} + inline void setaFace(WFace *pf) {_paFace = pf;} + inline void setbFace(WFace *pf) {_pbFace = pf;} + inline void setOwner(WEdge *pe) {_pOwner = pe;} + + /*! Retrieves the list of edges in CW order */ + inline void RetrieveCWOrderedEdges(vector<WEdge*>& oEdges); + /*! returns the vector between the two vertices */ + Vec3r getVec3r (); + WOEdge * twin (); + WOEdge * getPrevOnFace(); + virtual void ResetUserData() {userdata = 0;} +}; + + + /**********************************/ + /* */ + /* */ + /* WEdge */ + /* */ + /* */ + /**********************************/ + +class LIB_WINGED_EDGE_EXPORT WEdge +{ +protected: + WOEdge *_paOEdge; // first oriented edge + WOEdge *_pbOEdge; // second oriented edge + int _nOEdges; // number of oriented edges associated with this edge. (1 means border edge) + int _Id; // Identifier for the edge + +public: + void * userdata; // designed to store specific user data + inline WEdge() + { + _paOEdge = NULL; + _pbOEdge = NULL; + _nOEdges = 0; + userdata = NULL; + } + + inline WEdge(WOEdge *iOEdge) + { + _paOEdge = iOEdge; + _pbOEdge = NULL; + _nOEdges = 1; + userdata = NULL; + } + + inline WEdge(WOEdge *iaOEdge, WOEdge *ibOEdge) + { + _paOEdge = iaOEdge; + _pbOEdge = ibOEdge; + _nOEdges = 2; + userdata = NULL; + } + + /*! Copy constructor */ + WEdge(WEdge& iBrother); + virtual WEdge * duplicate(); + + virtual ~WEdge() + { + if(NULL != _paOEdge) + { + delete _paOEdge; + _paOEdge = NULL; + } + + if(NULL != _pbOEdge) + { + delete _pbOEdge; + _pbOEdge = NULL; + } + } + + /*! checks whether two WEdge have a common vertex. + * Returns a pointer on the common vertex if it exists, + * NULL otherwise. + */ + static inline WVertex* CommonVertex(WEdge *iEdge1, WEdge* iEdge2) + { + if((NULL == iEdge1) || (NULL == iEdge2)) + return NULL; + + WVertex *wv1 = iEdge1->GetaOEdge()->GetaVertex(); + WVertex *wv2 = iEdge1->GetaOEdge()->GetbVertex(); + WVertex *wv3 = iEdge2->GetaOEdge()->GetaVertex(); + WVertex *wv4 = iEdge2->GetaOEdge()->GetbVertex(); + + if((wv1 == wv3) || (wv1 == wv4)) + { + return wv1; + } + else if((wv2 == wv3) || (wv2 == wv4)) + { + return wv2; + } + + return NULL; + } + /*! accessors */ + inline WOEdge * GetaOEdge() {return _paOEdge;} + inline WOEdge * GetbOEdge() {return _pbOEdge;} + inline int GetNumberOfOEdges() {return _nOEdges;} + inline int GetId() {return _Id;} + inline WVertex * GetaVertex() {return _paOEdge->GetaVertex();} + inline WVertex * GetbVertex() {return _paOEdge->GetbVertex();} + inline WFace * GetaFace() {return _paOEdge->GetaFace();} + inline WFace * GetbFace() {return _paOEdge->GetbFace();} + inline WOEdge* GetOtherOEdge(WOEdge* iOEdge) + { + if(iOEdge == _paOEdge) + return _pbOEdge; + else + return _paOEdge; + } + + /*! modifiers */ + inline void setaOEdge(WOEdge *iEdge) {_paOEdge = iEdge;} + inline void setbOEdge(WOEdge *iEdge) {_pbOEdge = iEdge;} + inline void AddOEdge(WOEdge *iEdge) + { + if(NULL == _paOEdge) + { + _paOEdge = iEdge; + _nOEdges++; + return; + } + if(NULL == _pbOEdge) + { + _pbOEdge = iEdge; + _nOEdges++; + return; + } + } + inline void setNumberOfOEdges(int n) {_nOEdges = n;} + inline void setId(int id) {_Id = id;} + virtual void ResetUserData() {userdata = 0;} +}; + + /**********************************/ + /* */ + /* */ + /* WFace */ + /* */ + /* */ + /**********************************/ + + +class LIB_WINGED_EDGE_EXPORT WFace +{ +protected: + vector<WOEdge *> _OEdgeList; // list of oriented edges of bording the face + Vec3r _Normal; // normal to the face + vector<Vec3r> _VerticesNormals; // in case there is a normal per vertex. + // The normal number i corresponds to the + // aVertex of the oedge number i, for that face + vector<Vec2r> _VerticesTexCoords; + + int _Id; + unsigned _FrsMaterialIndex; + +public: + void *userdata; + inline WFace() {userdata = NULL;_FrsMaterialIndex = 0;} + /*! copy constructor */ + WFace(WFace& iBrother); + virtual WFace * duplicate(); + virtual ~WFace() {} + + /*! accessors */ + inline const vector<WOEdge*>& getEdgeList() {return _OEdgeList;} + inline WOEdge * GetOEdge(int i) {return _OEdgeList[i];} + inline Vec3r& GetNormal() {return _Normal;} + inline int GetId() {return _Id;} + inline unsigned frs_materialIndex() const {return _FrsMaterialIndex;} + const FrsMaterial& frs_material() ; + + /*! The vertex of index i corresponds to the a vertex + * of the edge of index i + */ + inline WVertex* GetVertex(unsigned int index) + { + // if(index >= _OEdgeList.size()) + // return NULL; + return _OEdgeList[index]->GetaVertex(); + } + /*! returns the index at which iVertex is stored in the + * array. + * returns -1 if iVertex doesn't belong to the face. + */ + inline int GetIndex(WVertex *iVertex){ + int index = 0; + for(vector<WOEdge*>::iterator woe=_OEdgeList.begin(), woend=_OEdgeList.end(); + woe!=woend; + woe++){ + if((*woe)->GetaVertex() == iVertex) + return index; + ++index; + } + return -1; + } + inline void RetrieveVertexList(vector<WVertex*>& oVertices) + { + for(vector<WOEdge*>::iterator woe=_OEdgeList.begin(), woend=_OEdgeList.end(); + woe!=woend; + woe++) + { + oVertices.push_back((*woe)->GetaVertex()); + } + } + inline void RetrieveBorderFaces(vector<const WFace*>& oWFaces) + { + for(vector<WOEdge*>::iterator woe=_OEdgeList.begin(), woend=_OEdgeList.end(); + woe!=woend; + woe++) + { + WFace *af; + if(NULL != (af = (*woe)->GetaFace())) + oWFaces.push_back(af); + } + } + inline WFace * GetBordingFace(int index) + { + // if(index >= _OEdgeList.size()) + // return 0; + return _OEdgeList[index]->GetaFace(); + } + inline WFace * GetBordingFace(WOEdge *iOEdge) + { + return iOEdge->GetaFace(); + } + inline vector<Vec3r>& GetPerVertexNormals() + { + return _VerticesNormals; + } + inline vector<Vec2r>& GetPerVertexTexCoords() + { + return _VerticesTexCoords; + } + /*! Returns the normal of the vertex of index index */ + inline Vec3r& GetVertexNormal(int index) + { + return _VerticesNormals[index]; + } + /*! Returns the tex coords of the vertex of index index */ + inline Vec2r& GetVertexTexCoords(int index) + { + return _VerticesTexCoords[index]; + } + /*! Returns the normal of the vertex iVertex for that face */ + inline Vec3r& GetVertexNormal(WVertex *iVertex) + { + int i = 0; + int index = 0; + for(vector<WOEdge*>::const_iterator woe=_OEdgeList.begin(), woend=_OEdgeList.end(); + woe!=woend; + woe++) + { + if((*woe)->GetaVertex() == iVertex) + { + index = i; + break; + } + ++i; + } + + return _VerticesNormals[index]; + } + inline WOEdge* GetNextOEdge(WOEdge* iOEdge) + { + bool found = false; + vector<WOEdge*>::iterator woe,woend, woefirst; + woefirst = _OEdgeList.begin(); + for(woe=woefirst,woend=_OEdgeList.end(); + woe!=woend; + woe++) + { + if(true == found) + return (*woe); + + if((*woe) == iOEdge) + { + found = true; + } + } + + // We left the loop. That means that the first + // OEdge was the good one: + if(found) + return (*woefirst); + + return NULL; + } + WOEdge* GetPrevOEdge(WOEdge* iOEdge); + + inline int numberOfEdges() const { return _OEdgeList.size();} + inline int numberOfVertices() const { return _OEdgeList.size();} + /*! Returns true if the face has one ot its edge which is a border + * edge + */ + inline bool isBorder() const + { + for(vector<WOEdge*>::const_iterator woe=_OEdgeList.begin(), woeend=_OEdgeList.end(); + woe!=woeend; + ++woe) + { + if((*woe)->GetOwner()->GetbOEdge() == 0) + return true; + } + return false; + } + /*! modifiers */ + inline void setEdgeList(const vector<WOEdge*>& iEdgeList) {_OEdgeList = iEdgeList;} + inline void setNormal(const Vec3r& iNormal) {_Normal = iNormal;} + inline void setNormalList(const vector<Vec3r>& iNormalsList) {_VerticesNormals = iNormalsList;} + inline void setTexCoordsList(const vector<Vec2r>& iTexCoordsList) {_VerticesTexCoords = iTexCoordsList;} + inline void setId(int id) {_Id = id;} + inline void setFrsMaterialIndex(unsigned iMaterialIndex) {_FrsMaterialIndex = iMaterialIndex;} + + /*! designed to build a specialized WEdge + * for use in MakeEdge + */ + virtual WEdge * instanciateEdge() const {return new WEdge;} + + /*! Builds an oriented edge + * Returns the built edge. + * v1, v2 + * Vertices at the edge's extremities + * The edge is oriented from v1 to v2. + */ + virtual WOEdge * MakeEdge(WVertex *v1, WVertex *v2); + + /*! Adds an edge to the edges list */ + inline void AddEdge(WOEdge *iEdge) {_OEdgeList.push_back(iEdge);} + + /*! For triangles, returns the edge opposite to the vertex in e. + returns flase if the face is not a triangle or if the vertex is not found*/ + bool getOppositeEdge (const WVertex *v, WOEdge* &e); + + /*! compute the area of the face */ + real getArea (); + + WShape * getShape() ; + virtual void ResetUserData() {userdata = 0;} +}; + + + /**********************************/ + /* */ + /* */ + /* WShape */ + /* */ + /* */ + /**********************************/ + + +class LIB_WINGED_EDGE_EXPORT WShape +{ +protected: + vector<WVertex*> _VertexList; + vector<WEdge*> _EdgeList; + vector<WFace*> _FaceList; + int _Id; + string _Name; + static unsigned _SceneCurrentId; + Vec3r _min; + Vec3r _max; + vector<FrsMaterial> _FrsMaterials; + real _meanEdgeSize; + +public: + inline WShape() {_meanEdgeSize = 0;_Id = _SceneCurrentId; _SceneCurrentId++;} + /*! copy constructor */ + WShape(WShape& iBrother); + virtual WShape * duplicate(); + virtual ~WShape() + { + if(_EdgeList.size() != 0) + { + vector<WEdge *>::iterator e; + for(e=_EdgeList.begin(); e!=_EdgeList.end(); e++) + { + delete (*e); + } + _EdgeList.clear(); + } + + if(_VertexList.size() != 0) + { + vector<WVertex *>::iterator v; + for(v=_VertexList.begin(); v!=_VertexList.end(); v++) + { + delete (*v); + } + _VertexList.clear(); + } + + if(_FaceList.size() != 0) + { + vector<WFace *>::iterator f; + for(f=_FaceList.begin(); f!=_FaceList.end(); f++) + { + delete (*f); + } + _FaceList.clear(); + } + } + + /*! accessors */ + inline vector<WEdge *>& getEdgeList() {return _EdgeList;} + inline vector<WVertex*>& getVertexList() {return _VertexList;} + inline vector<WFace*>& GetFaceList() {return _FaceList;} + inline unsigned GetId() {return _Id;} + inline void bbox(Vec3r& min, Vec3r& max) {min=_min; max=_max;} + inline const FrsMaterial& frs_material(unsigned i) const {return _FrsMaterials[i];} + inline const vector<FrsMaterial>& frs_materials() const {return _FrsMaterials;} + inline const real getMeanEdgeSize() const {return _meanEdgeSize;} + inline const string& getName() const {return _Name;} + /*! modifiers */ + static inline void setCurrentId(const unsigned id) { _SceneCurrentId = id; } + inline void setEdgeList(const vector<WEdge*>& iEdgeList) {_EdgeList = iEdgeList;} + inline void setVertexList(const vector<WVertex*>& iVertexList) {_VertexList = iVertexList;} + inline void setFaceList(const vector<WFace*>& iFaceList) {_FaceList = iFaceList;} + inline void setId(int id) {_Id = id;} + inline void setBBox(const Vec3r& min, const Vec3r& max) {_min = min; _max=max;} + inline void setFrsMaterial(const FrsMaterial& frs_material, unsigned i) {_FrsMaterials[i]=frs_material;} + inline void setFrsMaterials(const vector<FrsMaterial>& iMaterials) {_FrsMaterials = iMaterials;} + inline void setName(const string& name) {_Name = name;} + + /*! designed to build a specialized WFace + * for use in MakeFace + */ + virtual WFace * instanciateFace() const {return new WFace;} + + /*! adds a new face to the shape + * returns the built face. + * iVertexList + * List of face's vertices. These vertices are + * not added to the WShape vertex list; they are + * supposed to be already stored when calling MakeFace. + * The order in which the vertices are stored in the list + * determines the face's edges orientation and (so) the + * face orientation. + * iMaterialIndex + * The material index for this face + */ + virtual WFace * MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterialIndex); + + /*! adds a new face to the shape. The difference with + * the previous method is that this one is designed + * to build a WingedEdge structure for which there are + * per vertex normals, opposed to per face normals. + * returns the built face. + * iVertexList + * List of face's vertices. These vertices are + * not added to the WShape vertex list; they are + * supposed to be already stored when calling MakeFace. + * The order in which the vertices are stored in the list + * determines the face's edges orientation and (so) the + * face orientation. + * iMaterialIndex + * The materialIndex for this face + * iNormalsList + * The list of normals, iNormalsList[i] corresponding to the + * normal of the vertex iVertexList[i] for that face. + * iTexCoordsList + * The list of tex coords, iTexCoordsList[i] corresponding to the + * normal of the vertex iVertexList[i] for that face. + */ + virtual WFace * MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList, unsigned iMaterialIndex); + + inline void AddEdge(WEdge *iEdge) {_EdgeList.push_back(iEdge);} + inline void AddFace(WFace* iFace) {_FaceList.push_back(iFace);} + inline void AddVertex(WVertex *iVertex) {iVertex->setShape(this); _VertexList.push_back(iVertex);} + + inline void ResetUserData() + { + for(vector<WVertex*>::iterator v=_VertexList.begin(),vend=_VertexList.end(); + v!=vend; + v++) + { + (*v)->ResetUserData(); + } + + for(vector<WEdge*>::iterator e=_EdgeList.begin(),eend=_EdgeList.end(); + e!=eend; + e++) + { + (*e)->ResetUserData(); + // manages WOEdge: + WOEdge *oe = (*e)->GetaOEdge(); + if(oe != NULL) + oe->ResetUserData(); + oe = (*e)->GetbOEdge(); + if(oe != NULL) + oe->ResetUserData(); + } + + for(vector<WFace*>::iterator f=_FaceList.begin(),fend=_FaceList.end(); + f!=fend; + f++) + { + (*f)->ResetUserData(); + } + + } + + inline void ComputeBBox() + { + _min = _VertexList[0]->GetVertex(); + _max = _VertexList[0]->GetVertex(); + + Vec3r v; + for(vector<WVertex*>::iterator wv=_VertexList.begin(), wvend=_VertexList.end(); + wv!=wvend; + wv++) + { + for(unsigned int i=0; i<3; i++) + { + v = (*wv)->GetVertex(); + if(v[i] < _min[i]) + _min[i] = v[i]; + if(v[i] > _max[i]) + _max[i] = v[i]; + } + } + } + + inline real ComputeMeanEdgeSize(){ + _meanEdgeSize = _meanEdgeSize/(_EdgeList.size()); + return _meanEdgeSize; + } + +protected: + /*! Builds the face passed as argument (which as already been allocated) + * iVertexList + * List of face's vertices. These vertices are + * not added to the WShape vertex list; they are + * supposed to be already stored when calling MakeFace. + * The order in which the vertices are stored in the list + * determines the face's edges orientation and (so) the + * face orientation. + * iMaterialIndex + * The material index for this face + * face + * The Face that is filled in + */ + virtual WFace * MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterialIndex, WFace *face); +}; + + + /**********************************/ + /* */ + /* */ + /* WingedEdge */ + /* */ + /* */ + /**********************************/ + +class WingedEdge { + + public: + + WingedEdge() {} + + ~WingedEdge() { + clear(); + } + + void clear() { + for (vector<WShape*>::iterator it = _wshapes.begin(); + it != _wshapes.end(); + it++) + delete *it; + _wshapes.clear(); + } + + void addWShape(WShape* wshape) { + _wshapes.push_back(wshape); + } + + vector<WShape*>& getWShapes() { + return _wshapes; + } + + private: + + vector<WShape*> _wshapes; +}; + + + +/* + + ############################################# + ############################################# + ############################################# + ###### ###### + ###### I M P L E M E N T A T I O N ###### + ###### ###### + ############################################# + ############################################# + ############################################# + +*/ +/* for inline functions */ +void WOEdge::RetrieveCWOrderedEdges(vector<WEdge*>& oEdges) +{ + + WOEdge *currentOEdge = this; + do + { + WOEdge* nextOEdge = currentOEdge->GetbFace()->GetNextOEdge(currentOEdge); + oEdges.push_back(nextOEdge->GetOwner()); + currentOEdge = nextOEdge->GetOwner()->GetOtherOEdge(nextOEdge); + + } while((currentOEdge != NULL) && (currentOEdge->GetOwner() != GetOwner())); +} + +#endif // WEDGE_H diff --git a/source/blender/freestyle/intern/winged_edge/WFillGrid.cpp b/source/blender/freestyle/intern/winged_edge/WFillGrid.cpp new file mode 100755 index 00000000000..7d0a2d3c561 --- /dev/null +++ b/source/blender/freestyle/intern/winged_edge/WFillGrid.cpp @@ -0,0 +1,60 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "WEdge.h" +#include "WFillGrid.h" + +void WFillGrid::fillGrid() { + if (!_winged_edge || !_grid) + return; + + vector<WShape*> wshapes = _winged_edge->getWShapes(); + vector<WVertex*> fvertices; + vector<Vec3r> vectors; + vector<WFace*> faces; + + for (vector<WShape*>::const_iterator it = wshapes.begin(); + it != wshapes.end(); + it++) { + faces = (*it)->GetFaceList(); + + for (vector<WFace*>::const_iterator f = faces.begin(); + f != faces.end(); + f++) { + (*f)->RetrieveVertexList(fvertices); + + for (vector<WVertex*>::const_iterator wv = fvertices.begin(); + wv != fvertices.end(); + wv++) + vectors.push_back(Vec3r((*wv)->GetVertex())); + + // occluder will be deleted by the grid + Polygon3r *occluder = + new Polygon3r(vectors, (*f)->GetNormal()); + occluder->setId(_polygon_id++); + occluder->userdata = (void*)(*f); + _grid->insertOccluder(occluder); + vectors.clear(); + fvertices.clear(); + } + faces.clear(); + } +} diff --git a/source/blender/freestyle/intern/winged_edge/WFillGrid.h b/source/blender/freestyle/intern/winged_edge/WFillGrid.h new file mode 100755 index 00000000000..2ebbc2f359a --- /dev/null +++ b/source/blender/freestyle/intern/winged_edge/WFillGrid.h @@ -0,0 +1,80 @@ +// +// Filename : WFillGrid.h +// Author(s) : Stephane Grabli +// Emmanuel Turquin +// Purpose : Class to fill in a grid from a SceneGraph +// (uses only the WingedEdge structures) +// Date of creation : 03/05/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef W_FILL_GRID_H +# define W_FILL_GRID_H + +# include "../geometry/Grid.h" +# include "../geometry/Polygon.h" +# include "WEdge.h" + +class LIB_WINGED_EDGE_EXPORT WFillGrid +{ +public: + + inline WFillGrid(Grid* grid = 0, WingedEdge* winged_edge = 0) { + _winged_edge = winged_edge; + _grid = grid; + _polygon_id = 0; + } + + virtual ~WFillGrid() {} + + void fillGrid(); + + /*! Accessors */ + WingedEdge* getWingedEdge() { + return _winged_edge; + } + + Grid* getGrid() { + return _grid; + } + + /*! Modifiers */ + void setWingedEdge(WingedEdge* winged_edge) { + if (winged_edge) + _winged_edge = winged_edge; + } + + void setGrid(Grid* grid) { + if (grid) + _grid = grid; + } + +private: + + Grid* _grid; + WingedEdge* _winged_edge; + unsigned _polygon_id; +}; + +#endif // WS_FILL_GRID_H diff --git a/source/blender/freestyle/intern/winged_edge/WSFillGrid.cpp b/source/blender/freestyle/intern/winged_edge/WSFillGrid.cpp new file mode 100755 index 00000000000..55fa418d4f5 --- /dev/null +++ b/source/blender/freestyle/intern/winged_edge/WSFillGrid.cpp @@ -0,0 +1,60 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "WEdge.h" +#include "WSFillGrid.h" + +void WSFillGrid::fillGrid() { + if (!_winged_edge || !_grid) + return; + + vector<WShape*> wshapes = _winged_edge->getWShapes(); + vector<WVertex*> fvertices; + vector<Vec3r> vectors; + vector<WFace*> faces; + + for (vector<WShape*>::const_iterator it = wshapes.begin(); + it != wshapes.end(); + it++) { + faces = (*it)->GetFaceList(); + + for (vector<WFace*>::const_iterator f = faces.begin(); + f != faces.end(); + f++) { + (*f)->RetrieveVertexList(fvertices); + + for (vector<WVertex*>::const_iterator wv = fvertices.begin(); + wv != fvertices.end(); + wv++) + vectors.push_back(Vec3r((*wv)->GetVertex())); + + // occluder will be deleted by the grid + Polygon3r *occluder = + new Polygon3r(vectors, (*f)->GetNormal()); + occluder->setId(_polygon_id++); + occluder->userdata = (void*)(*f); + _grid->insertOccluder(occluder); + vectors.clear(); + fvertices.clear(); + } + faces.clear(); + } +} diff --git a/source/blender/freestyle/intern/winged_edge/WSFillGrid.h b/source/blender/freestyle/intern/winged_edge/WSFillGrid.h new file mode 100755 index 00000000000..2ea5bc6c621 --- /dev/null +++ b/source/blender/freestyle/intern/winged_edge/WSFillGrid.h @@ -0,0 +1,79 @@ +// +// Filename : WSFillGrid.h +// Author(s) : Stephane Grabli +// Purpose : Class to fill in a grid from a SceneGraph +// (uses only the WingedEdge structures) +// Date of creation : 03/05/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef WS_FILL_GRID_H +# define WS_FILL_GRID_H + +# include "../geometry/Grid.h" +# include "../geometry/Polygon.h" +# include "WEdge.h" + +class LIB_WINGED_EDGE_EXPORT WSFillGrid +{ +public: + + inline WSFillGrid(Grid* grid = 0, WingedEdge* winged_edge = 0) { + _winged_edge = winged_edge; + _grid = grid; + _polygon_id = 0; + } + + virtual ~WSFillGrid() {} + + void fillGrid(); + + /*! Accessors */ + WingedEdge* getWingedEdge() { + return _winged_edge; + } + + Grid* getGrid() { + return _grid; + } + + /*! Modifiers */ + void setWingedEdge(WingedEdge* winged_edge) { + if (winged_edge) + _winged_edge = winged_edge; + } + + void setGrid(Grid* grid) { + if (grid) + _grid = grid; + } + +private: + + Grid* _grid; + WingedEdge* _winged_edge; + unsigned _polygon_id; +}; + +#endif // WS_FILL_GRID_H diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp new file mode 100755 index 00000000000..ff567aee06a --- /dev/null +++ b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp @@ -0,0 +1,296 @@ +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "WXEdge.h" + + /**********************************/ + /* */ + /* */ + /* WXFace */ + /* */ + /* */ + /**********************************/ + +unsigned int WXFaceLayer::Get0VertexIndex() const { + int i = 0; + int nEdges = _pWXFace->numberOfEdges(); + for(i=0; i<nEdges; ++i){ + if(_DotP[i] == 0){ + return i; + } + } + return -1; +} +unsigned int WXFaceLayer::GetSmoothEdgeIndex() const{ + int i = 0; + int nEdges = _pWXFace->numberOfEdges(); + for(i=0; i<nEdges; ++i){ + if((_DotP[i] == 0) && (_DotP[(i+1)%nEdges] == 0)){ + return i; + } + } + return -1; +} + +void WXFaceLayer::RetrieveCuspEdgesIndices(vector<int>& oCuspEdges){ + int i = 0; + int nEdges = _pWXFace->numberOfEdges(); + for(i=0; i<nEdges; ++i){ + if(_DotP[i]*_DotP[(i+1)%nEdges] < 0){ + // we got one + oCuspEdges.push_back(i); + } + } +} + +WXSmoothEdge* WXFaceLayer::BuildSmoothEdge(){ + // if the smooth edge has already been + // built: exit + if(0 != _pSmoothEdge) + return _pSmoothEdge; + real ta, tb; + WOEdge *woea(0), *woeb(0); + bool ok = false; + vector<int> cuspEdgesIndices; + int indexStart, indexEnd; + unsigned nedges = _pWXFace->numberOfEdges(); + if(_nNullDotP == nedges){ + _pSmoothEdge = 0; + return _pSmoothEdge; + } + if((_nPosDotP != 0) && (_nPosDotP != _DotP.size()) && (_nNullDotP == 0)){ + // that means that we have a smooth edge that starts from + // an edge and ends at an edge + //----------------------------- + // We retrieve the 2 edges for which we have + // opposite signs for each extremity + RetrieveCuspEdgesIndices(cuspEdgesIndices); + if(cuspEdgesIndices.size() != 2) // we necessarly have 2 cusp edges + return 0; + + // let us determine which cusp edge corresponds to the starting: + // We can do that because we defined that + // a silhouette edge had the back facing part on its right. + // So if the WOEdge woea is such that woea[0].dotp > 0 and + // woea[1].dotp < 0, it is the starting edge. + //------------------------------------------- + + if(_DotP[cuspEdgesIndices[0]] > 0){ + woea = _pWXFace->GetOEdge(cuspEdgesIndices[0]); + woeb = _pWXFace->GetOEdge(cuspEdgesIndices[1]); + indexStart = cuspEdgesIndices[0]; + indexEnd = cuspEdgesIndices[1]; + }else{ + woea = _pWXFace->GetOEdge(cuspEdgesIndices[1]); + woeb = _pWXFace->GetOEdge(cuspEdgesIndices[0]); + indexStart = cuspEdgesIndices[1]; + indexEnd = cuspEdgesIndices[0]; + } + + // Compute the interpolation: + ta = _DotP[indexStart]/(_DotP[indexStart]-_DotP[(indexStart+1)%nedges]); + tb = _DotP[indexEnd]/(_DotP[indexEnd]-_DotP[(indexEnd+1)%nedges]); + ok = true; + }else if(_nNullDotP == 1){ + // that means that we have exactly one of the + // 2 extremities of our silhouette edge is + // a vertex of the mesh + if((_nPosDotP == 2) || (_nPosDotP == 0)){ + _pSmoothEdge = 0; + return _pSmoothEdge; + } + RetrieveCuspEdgesIndices(cuspEdgesIndices); + // We should have only one EdgeCusp: + if(cuspEdgesIndices.size() != 1){ + cout << "Warning in BuildSmoothEdge: weird WXFace configuration" << endl; + _pSmoothEdge = 0; + return 0; + } + unsigned index0 = Get0VertexIndex(); // retrieve the 0 vertex index + unsigned nedges = _pWXFace->numberOfEdges(); + if(_DotP[cuspEdgesIndices[0]] > 0){ + woea = _pWXFace->GetOEdge(cuspEdgesIndices[0]); + woeb = _pWXFace->GetOEdge(index0); + indexStart = cuspEdgesIndices[0]; + ta = _DotP[indexStart]/(_DotP[indexStart]-_DotP[(indexStart+1)%nedges]); + tb = 0.0; + }else{ + woea = _pWXFace->GetOEdge(index0); + woeb = _pWXFace->GetOEdge(cuspEdgesIndices[0]); + indexEnd = cuspEdgesIndices[0]; + ta = 0.0; + tb = _DotP[indexEnd]/(_DotP[indexEnd]-_DotP[(indexEnd+1)%nedges]); + } + ok = true; + }else if(_nNullDotP == 2){ + // that means that the silhouette edge + // is an edge of the mesh + int index = GetSmoothEdgeIndex(); + if(!_pWXFace->front()) {// is it in the right order ? + // the order of the WOEdge index is wrong + woea = _pWXFace->GetOEdge((index+1)%nedges); + woeb = _pWXFace->GetOEdge((index-1)%nedges); + ta = 0; + tb = 1; + ok = true; + }else{ + // here it's not good, our edge is a single point -> skip that face + ok = false; + // the order of the WOEdge index is good + // woea = _pWXFace->GetOEdge((index-1)%nedges); + // woeb = _pWXFace->GetOEdge((index+1)%nedges); + // ta = 1; + // tb = 0; + } + } + if(ok){ + _pSmoothEdge = new WXSmoothEdge; + _pSmoothEdge->setWOeA(woea); + _pSmoothEdge->setWOeB(woeb); + _pSmoothEdge->setTa(ta); + _pSmoothEdge->setTb(tb); + if(_Nature & Nature::SILHOUETTE){ + if(_nNullDotP != 2){ + if(_DotP[_ClosestPointIndex] + 0.01 > 0) + _pSmoothEdge->setFront(true); + else + _pSmoothEdge->setFront(false); + } + } + } + + // check bording edges to see if they have different dotp values + // in bording faces. + // for(int i=0; i<numberOfEdges(); i++) + // { + // WSFace * bface = (WSFace*)GetBordingFace(i); + // if(bface != 0) + // { + // if((front())^(bface->front())) // fA->front XOR fB->front (true if one is 0 and the other is 1) + // { + // // that means that the edge i of the face is + // // a silhouette edge + // // TESTER D'ABORD SI LE EXACTSILHOUETTEEDGE N'A PAS + // // ETE CONSTRUIT SUR L'AUTRE FACE.(1 suffit) + // if(0 != ((WSExactFace*)bface)->exactSilhouetteEdge()) + // { + // // that means that this silhouette edge has already been built + // return ((WSExactFace*)bface)->exactSilhouetteEdge(); + // } + // // Else we must build it + // WOEdge *woea, *woeb; + // real ta, tb; + // if(!front()) // is it in the right order ? + // { + // // the order of the WOEdge index is wrong + // woea = _OEdgeList[(i+1)%numberOfEdges()]; + // if(0 == i) + // woeb = _OEdgeList[numberOfEdges()-1]; + // else + // woeb = _OEdgeList[(i-1)]; + // ta = 0; + // tb = 1; + // } + // else + // { + // // the order of the WOEdge index is good + // if(0 == i) + // woea = _OEdgeList[numberOfEdges()-1]; + // else + // woea = _OEdgeList[(i-1)]; + // woeb = _OEdgeList[(i+1)%numberOfEdges()]; + // ta = 1; + // tb = 0; + // } + // + // _pSmoothEdge = new ExactSilhouetteEdge(ExactSilhouetteEdge::VERTEX_VERTEX); + // _pSmoothEdge->setWOeA(woea); + // _pSmoothEdge->setWOeA(woeb); + // _pSmoothEdge->setTa(ta); + // _pSmoothEdge->setTb(tb); + // + // return _pSmoothEdge; + // } + // } + //} + return _pSmoothEdge; +} + + +void WXFace::ComputeCenter() +{ + vector<WVertex*> iVertexList; + RetrieveVertexList(iVertexList); + Vec3r center; + for(vector<WVertex*>::iterator wv=iVertexList.begin(),wvend=iVertexList.end(); + wv!=wvend; + wv++) + { + center += (*wv)->GetVertex(); + } + center /= (real)iVertexList.size(); + setCenter(center); +} + + /**********************************/ + /* */ + /* */ + /* WXShape */ + /* */ + /* */ + /**********************************/ + + +WFace* WXShape::MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterialIndex) +{ + WFace *face = WShape::MakeFace(iVertexList, iMaterialIndex); + if(0 == face) + return 0; + + Vec3r center; + for(vector<WVertex*>::iterator wv=iVertexList.begin(),wvend=iVertexList.end(); + wv!=wvend; + wv++) + { + center += (*wv)->GetVertex(); + } + center /= (real)iVertexList.size(); + ((WXFace*)face)->setCenter(center); + + return face; +} + +WFace * WXShape::MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList, unsigned iMaterialIndex) +{ + WFace *face = WShape::MakeFace(iVertexList, iNormalsList, iTexCoordsList, iMaterialIndex); + + // Vec3r center; + // for(vector<WVertex*>::iterator wv=iVertexList.begin(),wvend=iVertexList.end(); + // wv!=wvend; + // wv++) + // { + // center += (*wv)->GetVertex(); + // } + // center /= (real)iVertexList.size(); + // ((WSFace*)face)->setCenter(center); + + return face; +} + diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.h b/source/blender/freestyle/intern/winged_edge/WXEdge.h new file mode 100755 index 00000000000..9ec8fd4bddb --- /dev/null +++ b/source/blender/freestyle/intern/winged_edge/WXEdge.h @@ -0,0 +1,582 @@ +// +// Filename : WXEdge.h +// Author(s) : Stephane Grabli +// Purpose : Classes to define an Extended Winged Edge data structure. +// Date of creation : 26/10/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef WXEDGE_H +# define WXEDGE_H + +# include "WEdge.h" +# include "Nature.h" +# include "Curvature.h" + +typedef Nature::EdgeNature WXNature; + + /**********************************/ + /* */ + /* */ + /* WXVertex */ + /* */ + /* */ + /**********************************/ + +class WXVertex : public WVertex +{ +private: + // Curvature info + CurvatureInfo *_curvatures; + +public: + inline WXVertex(const Vec3r &v) + : WVertex(v) + {_curvatures = 0;} + /*! Copy constructor */ + WXVertex(WXVertex& iBrother) + : WVertex(iBrother) + {_curvatures = new CurvatureInfo(*iBrother._curvatures);} + virtual WVertex * duplicate() + { + WXVertex *clone = new WXVertex(*this); + return clone; + } + virtual ~WXVertex() {if(_curvatures) delete _curvatures;} + virtual void Reset() {if(_curvatures) _curvatures->Kr = 0.0;} + inline void setCurvatures(CurvatureInfo *ci) {_curvatures = ci;} + + inline bool isFeature(); + inline CurvatureInfo* curvatures() {return _curvatures;} + +}; + + + + /**********************************/ + /* */ + /* */ + /* WXEdge */ + /* */ + /* */ + /**********************************/ +class WXEdge : public WEdge +{ +private: + WXNature _nature; // flag to indicate whether the edge is a silhouette edge or not + int _order; // 0: the order doesn't matter. 1: the order is the orginal one. -1: the order is not good + bool _front; // a front facing edge is an edge for which the bording face which is the nearest + // from the viewpoint is front. A back facing edge is the opposite. + +public: + inline WXEdge() + : WEdge(){ + _nature = Nature::NO_FEATURE; + _front = false; + _order=0; + } + + inline WXEdge(WOEdge *iOEdge) + : WEdge(iOEdge) + { _nature = Nature::NO_FEATURE;_front = false;_order=0;} + + inline WXEdge(WOEdge *iaOEdge, WOEdge *ibOEdge) + : WEdge(iaOEdge, ibOEdge) + { _nature = Nature::NO_FEATURE;_front = false;_order=0;} + + /*! Copy constructor */ + inline WXEdge(WXEdge& iBrother) + : WEdge(iBrother) + {_nature = iBrother.nature();_front = iBrother._front;_order = iBrother._order;} + virtual WEdge * duplicate() + { + WXEdge *clone = new WXEdge(*this); + return clone; + } + + virtual ~WXEdge() + {} + + virtual void Reset(){ + _nature = _nature & ~Nature::SILHOUETTE; + _nature = _nature & ~Nature::SUGGESTIVE_CONTOUR; + } + + /*! accessors */ + inline WXNature nature() {return _nature;} + inline bool front() {return _front;} + inline int order() const {return _order;} + + /*! modifiers */ + inline void setFront(bool iFront) {_front = iFront;} + inline void setNature(WXNature iNature) {_nature = iNature;} + inline void AddNature(WXNature iNature) {_nature = _nature|iNature;} + inline void setOrder(int i) {_order = i;} + +}; + + /**********************************/ + /* */ + /* */ + /* WXFace */ + /* */ + /* */ + /**********************************/ + +/*! Class to store a smooth edge (i.e Hertzman & Zorin smooth silhouette edges) */ +class WXSmoothEdge{ +public: + typedef enum{ + EDGE_EDGE, + VERTEX_EDGE, + EDGE_VERTEX + } Configuration; + + WOEdge *_woea; // Oriented edge from which the silhouette edge starts + WOEdge *_woeb; // Oriented edge where the silhouette edge ends + real _ta; // The silhouette starting point's coordinates are : _woea[0]+ta*(_woea[1]-_woea[0]) + real _tb; // The silhouette ending point's coordinates are : _woeb[0]+ta*(_woeb[1]-_woeb[0]) + bool _front; + Configuration _config; + + WXSmoothEdge(){ + _woea = 0; + _woeb = 0; + _ta = 0; + _tb = 0; + _front = false; + _config = EDGE_EDGE; + } + WXSmoothEdge(const WXSmoothEdge& iBrother){ + _woea = iBrother._woea; + _woeb = iBrother._woeb; + _ta = iBrother._ta; + _tb = iBrother._tb; + _config = iBrother._config; + _front = iBrother._front; + } + ~WXSmoothEdge() {} + + inline WOEdge * woea() {return _woea;} + inline WOEdge * woeb() {return _woeb;} + inline real ta() const {return _ta;} + inline real tb() const {return _tb;} + inline bool front() const {return _front;} + inline Configuration configuration() const {return _config;} + + /*! modifiers */ + inline void setWOeA(WOEdge *iwoea) {_woea = iwoea;} + inline void setWOeB(WOEdge *iwoeb) {_woeb = iwoeb;} + inline void setTa(real ta) {_ta = ta;} + inline void setTb(real tb) {_tb = tb;} + inline void setFront(bool iFront) {_front = iFront;} + inline void setConfiguration(Configuration iConf) {_config = iConf;} + +}; +/* Class to store a value per vertex and a smooth edge. + * The WXFace stores a list of these + */ +class WXFace; +class LIB_WINGED_EDGE_EXPORT WXFaceLayer{ +public: + void * userdata; + WXFace * _pWXFace; + vector<real> _DotP;// in case of silhouette: the values obtained when computing the normal-view direction + // dot product. _DotP[i] is this value for the vertex i for that + // face. + WXSmoothEdge * _pSmoothEdge; + WXNature _Nature; + + //oldtmp values + unsigned _nPosDotP; // count the number of positive dot products for vertices. + // if this number is != 0 and !=_DotP.size() -> it is a silhouette fac + + unsigned _nNullDotP; // count the number of null dot products for vertices. + unsigned _ClosestPointIndex; + bool _viewDependant; + + WXFaceLayer(WXFace *iFace, WXNature iNature, bool viewDependant){ + _pWXFace = iFace; + _pSmoothEdge = 0; + _nPosDotP = 0; + _nNullDotP=0; + _Nature = iNature; + _viewDependant = viewDependant; + userdata = 0; + } + WXFaceLayer(const WXFaceLayer& iBrother){ + _pWXFace = iBrother._pWXFace; + _pSmoothEdge = 0; + _DotP = iBrother._DotP; + _nPosDotP = iBrother._nPosDotP; + _nNullDotP = iBrother._nNullDotP; + _Nature = iBrother._Nature; + if(0 != iBrother._pSmoothEdge) + { + _pSmoothEdge = new WXSmoothEdge(*(iBrother._pSmoothEdge)); + } + _viewDependant = iBrother._viewDependant; + userdata = 0; + } + virtual ~WXFaceLayer() { + if(!_DotP.empty()) + _DotP.clear(); + if(0 != _pSmoothEdge){ + delete _pSmoothEdge; + _pSmoothEdge = 0; + } + } + inline const real dotP(int i) const {return _DotP[i];} + inline unsigned nPosDotP() const {return _nPosDotP;} + inline unsigned nNullDotP() const {return _nNullDotP;} + inline int closestPointIndex() const {return _ClosestPointIndex;} + inline Nature::EdgeNature nature() const {return _Nature;} + inline bool hasSmoothEdge() const {if(_pSmoothEdge) return true; return false;} + inline WXFace * getFace() {return _pWXFace;} + inline WXSmoothEdge * getSmoothEdge() {return _pSmoothEdge;} + inline bool isViewDependant() const {return _viewDependant;} + inline void setClosestPointIndex(int iIndex) {_ClosestPointIndex = iIndex;} + + inline void removeSmoothEdge() { + if(!_DotP.empty()) + _DotP.clear(); + if (_pSmoothEdge) { + delete _pSmoothEdge; + _pSmoothEdge = 0; + } + } + + /*! If one of the face layer vertex has a DotP equal + * to 0, this method returns the vertex where it happens + */ + unsigned int Get0VertexIndex() const ; + + /*! In case one of the edge of the triangle + * is a smooth edge, this method + * allows to retrieve the concerned edge + */ + unsigned int GetSmoothEdgeIndex() const; + /*! retrieves the edges of the triangle for which + * the signs are different (a null value is not considered) for the dotp + * values at each edge extrimity + */ + void RetrieveCuspEdgesIndices(vector<int>& oCuspEdges); + WXSmoothEdge * BuildSmoothEdge(); + inline void setDotP(const vector<real>& iDotP) {_DotP = iDotP;} + inline void PushDotP(real iDotP) { + _DotP.push_back(iDotP); + if(iDotP > 0) + ++_nPosDotP; + if(iDotP == 0) + ++_nNullDotP; + } + inline void ReplaceDotP(unsigned int index, real newDotP){ + _DotP[index] = newDotP; + updateDotPInfos(); + } + inline void updateDotPInfos() { + for(vector<real>::iterator d=_DotP.begin(), dend=_DotP.end(); + d!=dend; + ++d){ + _nPosDotP = 0; + _nNullDotP = 0; + if((*d) > 0) + ++_nPosDotP; + if((*d) == 0) + ++_nNullDotP; + } + } +}; + + +class WXFace : public WFace +{ +protected: + Vec3r _center; // center of the face + real _Z; // distance from viewpoint to the center of the face + bool _front; // flag to tell whether the face is front facing or back facing + real _dotp; // value obtained when computing the normal-viewpoint dot product + + vector<WXFaceLayer*> _SmoothLayers; // The data needed to store one or several smooth edges that traverse the face +public: + inline WXFace() : WFace() {_Z=0.0;_front = false;} + /*! Copy constructor */ + WXFace(WXFace& iBrother) + : WFace(iBrother) + { + _center = iBrother.center(); + _Z = iBrother.Z(); + _front = iBrother.front(); + for(vector<WXFaceLayer*>::iterator wxf = iBrother._SmoothLayers.begin(), wxfend = iBrother._SmoothLayers.end(); + wxf != wxfend; + ++wxf){ + _SmoothLayers.push_back(new WXFaceLayer(**wxf)); + } + } + virtual WFace * duplicate() + { + WXFace * clone = new WXFace(*this); + return clone; + } + + virtual ~WXFace() { + if(!_SmoothLayers.empty()){ + for(vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); + wxf != wxfend; + ++wxf){ + delete (*wxf); + } + _SmoothLayers.clear(); + } + } + + /*! designed to build a specialized WEdge + * for use in MakeEdge + */ + virtual WEdge * instanciateEdge() const {return new WXEdge;} + + /*! accessors */ + inline Vec3r& center() {return _center;} + inline real Z() {return _Z;} + inline bool front() {return _front;} + inline real dotp() {return _dotp;} + inline bool hasSmoothEdges() const { + for(vector<WXFaceLayer*>::const_iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); + wxf != wxfend; + ++wxf){ + if( ((*wxf)->hasSmoothEdge())){ + return true; + } + } + return false; + } + vector<WXFaceLayer*>& getSmoothLayers() {return _SmoothLayers;} + /*! retrieve the smooth edges that match the Nature given as argument */ + void retrieveSmoothEdges(WXNature iNature, vector<WXSmoothEdge*>& oSmoothEdges){ + for(vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); + wxf != wxfend; + ++wxf){ + if( ((*wxf)->hasSmoothEdge()) && ((*wxf)->_Nature & iNature) ){ + oSmoothEdges.push_back((*wxf)->_pSmoothEdge); + } + } + } + void retrieveSmoothEdgesLayers(WXNature iNature, vector<WXFaceLayer*>& oSmoothEdgesLayers){ + for(vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); + wxf != wxfend; + ++wxf){ + if( ((*wxf)->hasSmoothEdge()) && ((*wxf)->_Nature & iNature) ){ + oSmoothEdgesLayers.push_back((*wxf)); + } + } + } + void retrieveSmoothLayers(WXNature iNature, vector<WXFaceLayer*>& oSmoothLayers){ + for(vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); + wxf != wxfend; + ++wxf){ + if((*wxf)->_Nature & iNature){ + oSmoothLayers.push_back(*wxf); + } + } + } + /*! modifiers */ + inline void setCenter(const Vec3r& iCenter) {_center = iCenter;} + void ComputeCenter(); + inline void setZ(real z) {_Z = z;} + inline void setFront(bool iFront) {_front = iFront;} + inline void setDotP(real iDotP) + { + _dotp = iDotP; + if(_dotp > 0) + _front = true; + else + _front = false; + } + inline void AddSmoothLayer(WXFaceLayer * iLayer){ + _SmoothLayers.push_back(iLayer); + } + inline void Reset() { + vector<WXFaceLayer*> layersToKeep; + for(vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); + wxf != wxfend; + ++wxf){ + if((*wxf)->isViewDependant()) + delete (*wxf); + else + layersToKeep.push_back(*wxf); + } + _SmoothLayers = layersToKeep; + } + /*! Clears everything */ + inline void Clear() { + for(vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); + wxf != wxfend; + ++wxf){ + delete (*wxf); + } + _SmoothLayers.clear(); + } + virtual void ResetUserData() { + WFace::ResetUserData(); + for(vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); + wxf != wxfend; + ++wxf){ + (*wxf)->userdata = 0; + } + } +}; + + + /**********************************/ + /* */ + /* */ + /* WXShape */ + /* */ + /* */ + /**********************************/ + + +class WXShape : public WShape +{ +public: + typedef WXShape type_name; +protected: + bool _computeViewIndependant; // flag to indicate whether the view independant stuff must be computed or not +public: + inline WXShape() : WShape() {_computeViewIndependant = true;} + /*! copy constructor */ + inline WXShape(WXShape& iBrother) + :WShape(iBrother) + { + _computeViewIndependant = iBrother._computeViewIndependant; + } + virtual WShape * duplicate() + { + WXShape *clone = new WXShape(*this); + return clone; + } + + virtual ~WXShape() + { + } + + inline bool getComputeViewIndependantFlag() const {return _computeViewIndependant;} + inline void setComputeViewIndependantFlag(bool iFlag) {_computeViewIndependant = iFlag;} + + /*! designed to build a specialized WFace + * for use in MakeFace + */ + virtual WFace * instanciateFace() const {return new WXFace;} + + /*! adds a new face to the shape + * returns the built face. + * iVertexList + * List of face's vertices. These vertices are + * not added to the WShape vertex list; they are + * supposed to be already stored when calling MakeFace. + * The order in which the vertices are stored in the list + * determines the face's edges orientation and (so) the + * face orientation. + */ + virtual WFace * MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterialIndex); + + /*! adds a new face to the shape. The difference with + * the previous method is that this one is designed + * to build a WingedEdge structure for which there are + * per vertex normals, opposed to per face normals. + * returns the built face. + * iVertexList + * List of face's vertices. These vertices are + * not added to the WShape vertex list; they are + * supposed to be already stored when calling MakeFace. + * The order in which the vertices are stored in the list + * determines the face's edges orientation and (so) the + * face orientation. + * iNormalsList + * The list of normals, iNormalsList[i] corresponding to the + * normal of the vertex iVertexList[i] for that face. + * iTexCoordsList + * The list of tex coords, iTexCoordsList[i] corresponding to the + * normal of the vertex iVertexList[i] for that face. + */ + virtual WFace * MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList, unsigned iMaterialIndex); + + /*! Reset all edges and vertices flags (which might + * have been set up on a previous pass) + */ + virtual void Reset(){ + // Reset Edges + vector<WEdge*>& wedges = getEdgeList(); + for(vector<WEdge*>::iterator we=wedges.begin(),weend=wedges.end(); + we!=weend; + we++){ + ((WXEdge*)(*we))->Reset(); + } + + //Reset faces: + vector<WFace*>& wfaces = GetFaceList(); + for(vector<WFace*>::iterator wf=wfaces.begin(),wfend=wfaces.end(); + wf!=wfend; + wf++){ + ((WXFace*)(*wf))->Reset(); + } + } + /*! accessors */ +}; + +/* + + ############################################# + ############################################# + ############################################# + ###### ###### + ###### I M P L E M E N T A T I O N ###### + ###### ###### + ############################################# + ############################################# + ############################################# + +*/ +/* for inline functions */ + +bool WXVertex::isFeature() +{ + int counter = 0; + vector<WEdge*>& vedges = GetEdges(); + for(vector<WEdge*>::iterator ve=vedges.begin(), vend=vedges.end(); + ve!=vend; + ve++) + { + if(((WXEdge*)(*ve))->nature() != Nature::NO_FEATURE) + counter++; + } + + if((counter == 1) || (counter > 2)) + return true; + + return false; +} + + +#endif diff --git a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp new file mode 100755 index 00000000000..80e06fc2b7b --- /dev/null +++ b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp @@ -0,0 +1,44 @@ +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "WXEdgeBuilder.h" +#include "WXEdge.h" + +void WXEdgeBuilder::visitIndexedFaceSet(IndexedFaceSet& ifs) +{ + WXShape *shape = new WXShape; + buildWShape(*shape, ifs); + shape->setId(ifs.getId().getFirst()); + shape->setName(ifs.getName()); + //ifs.setId(shape->GetId()); +} + +void WXEdgeBuilder::buildWVertices(WShape& shape, + const real *vertices, + unsigned vsize) { + WXVertex *vertex; + for (unsigned i = 0; i < vsize; i += 3) { + vertex = new WXVertex(Vec3r(vertices[i], + vertices[i + 1], + vertices[i + 2])); + vertex->setId(i / 3); + shape.AddVertex(vertex); + } +} diff --git a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h new file mode 100755 index 00000000000..b646d66a285 --- /dev/null +++ b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h @@ -0,0 +1,51 @@ +#ifndef WXEDGEBUILDER_H +# define WXEDGEBUILDER_H + +// +// Filename : WSBuilder.h +// Author(s) : Stephane Grabli +// Purpose : Class inherited from WingedEdgeBuilder and +// designed to build a WX (WingedEdge + extended info(silhouette etc...)) +// structure from a polygonal model +// Date of creation : 28/05/03 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +# include "WingedEdgeBuilder.h" +# include "../scene_graph/IndexedFaceSet.h" + +class LIB_WINGED_EDGE_EXPORT WXEdgeBuilder : public WingedEdgeBuilder +{ +public: + WXEdgeBuilder() : WingedEdgeBuilder() {} + virtual ~WXEdgeBuilder() {} + VISIT_DECL(IndexedFaceSet) + +protected: + virtual void buildWVertices(WShape& shape, + const real *vertices, + unsigned vsize); +}; + +#endif // WXEDGEBUILDER_H diff --git a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp new file mode 100755 index 00000000000..9f3da4707e3 --- /dev/null +++ b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp @@ -0,0 +1,362 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "../geometry/GeomUtils.h" +#include "../scene_graph/NodeShape.h" +#include "WingedEdgeBuilder.h" +#include <set> +using namespace std; + +void WingedEdgeBuilder::visitIndexedFaceSet(IndexedFaceSet& ifs) { + WShape *shape = new WShape; + buildWShape(*shape, ifs); + shape->setId(ifs.getId().getFirst()); + //ifs.setId(shape->GetId()); +} + +void WingedEdgeBuilder::visitNodeShape(NodeShape& ns) { + //Sets the current material to iShapeode->material: + _current_frs_material = &(ns.frs_material()); +} + +void WingedEdgeBuilder::visitNodeTransform(NodeTransform& tn) { + if(!_current_matrix) { + _current_matrix = new Matrix44r(tn.matrix()); + return; + } + + _matrices_stack.push_back(_current_matrix); + Matrix44r *new_matrix = new Matrix44r(*_current_matrix * tn.matrix()); + _current_matrix = new_matrix; +} + +void WingedEdgeBuilder::visitNodeTransformAfter(NodeTransform&) { + if(_current_matrix) + delete _current_matrix; + + if(_matrices_stack.empty()) { + _current_matrix = NULL; + return; + } + + _current_matrix = _matrices_stack.back(); + _matrices_stack.pop_back(); +} + +void WingedEdgeBuilder::buildWShape(WShape& shape, IndexedFaceSet& ifs) { + unsigned vsize = ifs.vsize(); + unsigned nsize = ifs.nsize(); + //soc unused - unsigned tsize = ifs.tsize(); + + const real* vertices = ifs.vertices(); + const real* normals = ifs.normals(); + const real* texCoords = ifs.texCoords(); + + real* new_vertices; + real* new_normals; + + new_vertices = new real[vsize]; + new_normals = new real[nsize]; + + // transform coordinates from local to world system + if(_current_matrix) { + transformVertices(vertices, vsize, *_current_matrix, new_vertices); + transformNormals(normals, nsize, *_current_matrix, new_normals); + } + else { + memcpy(new_vertices, vertices, vsize * sizeof(*new_vertices)); + memcpy(new_normals, normals, nsize * sizeof(*new_normals)); + } + + const IndexedFaceSet::TRIANGLES_STYLE* faceStyle = ifs.trianglesStyle(); + + vector<FrsMaterial> frs_materials; + if(ifs.msize()){ + const FrsMaterial*const* mats = ifs.frs_materials(); + for(unsigned i=0; i<ifs.msize(); ++i) + frs_materials.push_back(*(mats[i])); + shape.setFrsMaterials(frs_materials); + } + + // const FrsMaterial * mat = (ifs.frs_material()); + // if (mat) + // shape.setFrsMaterial(*mat); + // else if(_current_frs_material) + // shape.setFrsMaterial(*_current_frs_material); + + // sets the current WShape to shape + _current_wshape = &shape; + + // create a WVertex for each vertex + buildWVertices(shape, new_vertices, vsize); + + const unsigned* vindices = ifs.vindices(); + const unsigned* nindices = ifs.nindices(); + const unsigned* tindices = 0; + if(ifs.tsize()){ + tindices = ifs.tindices(); + } + + const unsigned *mindices = 0; + if(ifs.msize()) + mindices = ifs.mindices(); + const unsigned* numVertexPerFace = ifs.numVertexPerFaces(); + const unsigned numfaces = ifs.numFaces(); + + for (unsigned index = 0; index < numfaces; index++) { + switch(faceStyle[index]) { + case IndexedFaceSet::TRIANGLE_STRIP: + buildTriangleStrip(new_vertices, + new_normals, + frs_materials, + texCoords, + vindices, + nindices, + mindices, + tindices, + numVertexPerFace[index]); + break; + case IndexedFaceSet::TRIANGLE_FAN: + buildTriangleFan(new_vertices, + new_normals, + frs_materials, + texCoords, + vindices, + nindices, + mindices, + tindices, + numVertexPerFace[index]); + break; + case IndexedFaceSet::TRIANGLES: + buildTriangles(new_vertices, + new_normals, + frs_materials, + texCoords, + vindices, + nindices, + mindices, + tindices, + numVertexPerFace[index]); + break; + } + vindices += numVertexPerFace[index]; + nindices += numVertexPerFace[index]; + if(mindices) + mindices += numVertexPerFace[index]; + if(tindices) + tindices += numVertexPerFace[index]; + } + + delete[] new_vertices; + delete[] new_normals; + + // compute bbox + shape.ComputeBBox(); + // compute mean edge size: + shape.ComputeMeanEdgeSize(); + + // Parse the built winged-edge shape to update post-flags + set<Vec3r> normalsSet; + vector<WVertex*>& wvertices = shape.getVertexList(); + for(vector<WVertex*>::iterator wv=wvertices.begin(), wvend=wvertices.end(); + wv!=wvend; + ++wv){ + if((*wv)->isBoundary()) + continue; + normalsSet.clear(); + WVertex::face_iterator fit = (*wv)->faces_begin(); + WVertex::face_iterator fitend = (*wv)->faces_end(); + while(fit!=fitend){ + WFace *face = *fit; + normalsSet.insert(face->GetVertexNormal(*wv)); + if(normalsSet.size()!=1){ + break; + } + ++fit; + } + if(normalsSet.size()!=1){ + (*wv)->setSmooth(false); + } + } + // Adds the new WShape to the WingedEdge structure + _winged_edge->addWShape(&shape); +} + +void WingedEdgeBuilder::buildWVertices(WShape& shape, + const real *vertices, + unsigned vsize) { + WVertex *vertex; + for (unsigned i = 0; i < vsize; i += 3) { + vertex = new WVertex(Vec3r(vertices[i], + vertices[i + 1], + vertices[i + 2])); + vertex->setId(i / 3); + shape.AddVertex(vertex); + } +} + +void WingedEdgeBuilder::buildTriangleStrip( const real *vertices, + const real *normals, + vector<FrsMaterial>& iMaterials, + const real *texCoords, + const unsigned *vindices, + const unsigned *nindices, + const unsigned *mindices, + const unsigned *tindices, + const unsigned nvertices) { + unsigned nDoneVertices = 2; // number of vertices already treated + unsigned nTriangle = 0; // number of the triangle currently being treated + //int nVertex = 0; // vertex number + + WShape* currentShape = _current_wshape; // the current shape being built + vector<WVertex *> triangleVertices; + vector<Vec3r> triangleNormals; + vector<Vec2r> triangleTexCoords; + + while(nDoneVertices < nvertices) + { + //clear the vertices list: + triangleVertices.clear(); + //Then rebuild it: + if(0 == nTriangle%2) // if nTriangle is even + { + triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle]/3]); + triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle+1]/3]); + triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle+2]/3]); + + triangleNormals.push_back(Vec3r(normals[nindices[nTriangle]],normals[nindices[nTriangle]+1], normals[nindices[nTriangle]+2])); + triangleNormals.push_back(Vec3r(normals[nindices[nTriangle+1]],normals[nindices[nTriangle+1]+1],normals[nindices[nTriangle+1]+2])); + triangleNormals.push_back(Vec3r(normals[nindices[nTriangle+2]], normals[nindices[nTriangle+2]+1], normals[nindices[nTriangle+2]+2])); + + if(texCoords){ + triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle]],texCoords[tindices[nTriangle]+1])); + triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle+1]],texCoords[tindices[nTriangle+1]+1])); + triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle+2]], texCoords[tindices[nTriangle+2]+1])); + } + } + else // if nTriangle is odd + { + triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle]/3]); + triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle+2]/3]); + triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle+1]/3]); + + triangleNormals.push_back(Vec3r(normals[nindices[nTriangle]],normals[nindices[nTriangle]+1], normals[nindices[nTriangle]+2])); + triangleNormals.push_back(Vec3r(normals[nindices[nTriangle+2]],normals[nindices[nTriangle+2]+1],normals[nindices[nTriangle+2]+2])); + triangleNormals.push_back(Vec3r(normals[nindices[nTriangle+1]], normals[nindices[nTriangle+1]+1], normals[nindices[nTriangle+1]+2])); + + if(texCoords){ + triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle]],texCoords[tindices[nTriangle]+1])); + triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle+2]],texCoords[tindices[nTriangle+2]+1])); + triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle+1]], texCoords[tindices[nTriangle+1]+1])); + } + } + if(mindices) + currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, mindices[nTriangle/3]); + else + currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, 0); + nDoneVertices++; // with a strip, each triangle is one vertex more + nTriangle++; + } +} + +void WingedEdgeBuilder::buildTriangleFan( const real *vertices, + const real *normals, + vector<FrsMaterial>& iMaterials, + const real *texCoords, + const unsigned *vindices, + const unsigned *nindices, + const unsigned *mindices, + const unsigned *tindices, + const unsigned nvertices) { + // Nothing to be done +} + +void WingedEdgeBuilder::buildTriangles(const real *vertices, + const real *normals, + vector<FrsMaterial>& iMaterials, + const real *texCoords, + const unsigned *vindices, + const unsigned *nindices, + const unsigned *mindices, + const unsigned *tindices, + const unsigned nvertices) { + WShape * currentShape = _current_wshape; // the current shape begin built + vector<WVertex *> triangleVertices; + vector<Vec3r> triangleNormals; + vector<Vec2r> triangleTexCoords; + + // Each triplet of vertices is considered as an independent triangle + for(unsigned i = 0; i < nvertices / 3; i++) + { + triangleVertices.push_back(currentShape->getVertexList()[vindices[3*i]/3]); + triangleVertices.push_back(currentShape->getVertexList()[vindices[3*i+1]/3]); + triangleVertices.push_back(currentShape->getVertexList()[vindices[3*i+2]/3]); + + triangleNormals.push_back(Vec3r(normals[nindices[3*i]],normals[nindices[3*i]+1], normals[nindices[3*i]+2])); + triangleNormals.push_back(Vec3r(normals[nindices[3*i+1]],normals[nindices[3*i+1]+1],normals[nindices[3*i+1]+2])); + triangleNormals.push_back(Vec3r(normals[nindices[3*i+2]], normals[nindices[3*i+2]+1], normals[nindices[3*i+2]+2])); + + if(texCoords){ + triangleTexCoords.push_back(Vec2r(texCoords[tindices[3*i]],texCoords[tindices[3*i]+1])); + triangleTexCoords.push_back(Vec2r(texCoords[tindices[3*i+1]],texCoords[tindices[3*i+1]+1])); + triangleTexCoords.push_back(Vec2r(texCoords[tindices[3*i+2]], texCoords[tindices[3*i+2]+1])); + } + } + if(mindices) + currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, mindices[0]); + else + currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords,0); + +} + +void WingedEdgeBuilder::transformVertices(const real *vertices, + unsigned vsize, + const Matrix44r& transform, + real *res) { + const real *v = vertices; + real *pv = res; + + for (unsigned i = 0; i < vsize / 3; i++) { + HVec3r hv_tmp(v[0], v[1], v[2]); + HVec3r hv(transform * hv_tmp); + for (unsigned j = 0; j < 3; j++) + pv[j] = hv[j] / hv[3]; + v += 3; + pv += 3; + } +} + +void WingedEdgeBuilder::transformNormals(const real *normals, + unsigned nsize, + const Matrix44r& transform, + real* res) { + const real *n = normals; + real *pn = res; + + for (unsigned i = 0; i < nsize / 3; i++) { + Vec3r hn(n[0], n[1], n[2]); + hn = GeomUtils::rotateVector(transform, hn); + for (unsigned j = 0; j < 3; j++) + pn[j] = hn[j]; + n += 3; + pn += 3; + } +} diff --git a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h new file mode 100755 index 00000000000..6bd515aef0b --- /dev/null +++ b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h @@ -0,0 +1,160 @@ +// +// Filename : WingedEdgeBuilder.h +// Author(s) : Stephane Grabli +// Purpose : Class to render a WingedEdge data structure +// from a polyhedral data structure organized in +// nodes of a scene graph +// Date of creation : 28/05/03 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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 2 +// 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef WINGED_EDGE_BUILDER_H +# define WINGED_EDGE_BUILDER_H + +# include "../system/FreestyleConfig.h" +# include "../scene_graph/SceneVisitor.h" +# include "WEdge.h" +# include "../scene_graph/IndexedFaceSet.h" +# include "../scene_graph/NodeTransform.h" + +class LIB_WINGED_EDGE_EXPORT WingedEdgeBuilder : public SceneVisitor +{ + public: + + inline WingedEdgeBuilder() : SceneVisitor() { + _current_wshape = NULL; + _current_frs_material = NULL; + _current_matrix = NULL; + _winged_edge = new WingedEdge; // Not deleted by the destructor + } + + virtual ~WingedEdgeBuilder() { + for (vector<Matrix44r*>::iterator it = _matrices_stack.begin(); + it != _matrices_stack.end(); + it++) + delete *it; + _matrices_stack.clear(); + } + + VISIT_DECL(IndexedFaceSet) + VISIT_DECL(NodeShape) + VISIT_DECL(NodeTransform) + + virtual void visitNodeTransformAfter(NodeTransform&); + + // + // Accessors + // + ///////////////////////////////////////////////////////////////////////////// + + inline WingedEdge* getWingedEdge() { + return _winged_edge; + } + + inline WShape* getCurrentWShape() { + return _current_wshape; + } + + inline FrsMaterial* getCurrentFrsMaterial() { + return _current_frs_material; + } + + inline Matrix44r* getCurrentMatrix() { + return _current_matrix; + } + + // + // Modifiers + // + ///////////////////////////////////////////////////////////////////////////// + + inline void setCurrentWShape(WShape* wshape) { + _current_wshape = wshape; + } + + inline void setCurrentFrsMaterial(FrsMaterial* mat) { + _current_frs_material = mat; + } + + // inline void setCurrentMatrix(Matrix44r* matrix) { + // _current_matrix = matrix; + // } + + protected: + + virtual void buildWShape(WShape& shape, IndexedFaceSet& ifs); + virtual void buildWVertices(WShape& shape, + const real *vertices, + unsigned vsize); + + private: + + void buildTriangleStrip(const real *vertices, + const real *normals, + vector<FrsMaterial>& iMaterials, + const real *texCoords, + const unsigned *vindices, + const unsigned *nindices, + const unsigned *mindices, + const unsigned *tindices, + const unsigned nvertices); + + void buildTriangleFan(const real *vertices, + const real *normals, + vector<FrsMaterial>& iMaterials, + const real *texCoords, + const unsigned *vindices, + const unsigned *nindices, + const unsigned *mindices, + const unsigned *tindices, + const unsigned nvertices); + + void buildTriangles(const real *vertices, + const real *normals, + vector<FrsMaterial>& iMaterials, + const real *texCoords, + const unsigned *vindices, + const unsigned *nindices, + const unsigned *mindices, + const unsigned *tindices, + const unsigned nvertices); + + void transformVertices(const real *vertices, + unsigned vsize, + const Matrix44r& transform, + real *res); + + void transformNormals(const real *normals, + unsigned nsize, + const Matrix44r& transform, + real *res); + + WShape* _current_wshape; + FrsMaterial* _current_frs_material; + WingedEdge* _winged_edge; + Matrix44r* _current_matrix; + vector<Matrix44r*> _matrices_stack; +}; + +#endif // WINGED_EDGE_BUILDER_H diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 76468ada523..5ce7f2b933e 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -186,6 +186,7 @@ typedef struct PreviewImage { #define ID_PA MAKE_ID2('P', 'A') /* ParticleSettings */ #define ID_GD MAKE_ID2('G', 'D') /* GreasePencil */ #define ID_WM MAKE_ID2('W', 'M') /* WindowManager */ +#define ID_LS MAKE_ID2('L', 'S') /* FreestyleLineStyle */ /* NOTE! Fake IDs, needed for g.sipo->blocktype or outliner */ #define ID_SEQ MAKE_ID2('S', 'Q') diff --git a/source/blender/makesdna/DNA_freestyle_types.h b/source/blender/makesdna/DNA_freestyle_types.h new file mode 100644 index 00000000000..e415d580c4d --- /dev/null +++ b/source/blender/makesdna/DNA_freestyle_types.h @@ -0,0 +1,89 @@ +#ifndef DNA_FREESTYLE_TYPES_H +#define DNA_FREESTYLE_TYPES_H + +#include "DNA_listBase.h" +#include "DNA_ID.h" + +/* FreestyleConfig::flags */ +#define FREESTYLE_SUGGESTIVE_CONTOURS_FLAG 1 +#define FREESTYLE_RIDGES_AND_VALLEYS_FLAG 2 +#define FREESTYLE_MATERIAL_BOUNDARIES_FLAG 4 + +/* FreestyleConfig::mode */ +#define FREESTYLE_CONTROL_SCRIPT_MODE 1 +#define FREESTYLE_CONTROL_EDITOR_MODE 2 + +/* FreestyleLineSet::flags */ +#define FREESTYLE_LINESET_CURRENT 1 +#define FREESTYLE_LINESET_ENABLED 2 +#define FREESTYLE_LINESET_FE_NOT 4 +#define FREESTYLE_LINESET_FE_OR 8 + +/* FreestyleLineSet::selection */ +#define FREESTYLE_SEL_VISIBILITY 1 +#define FREESTYLE_SEL_EDGE_TYPES 2 + +/* FreestyleLineSet::fedge_types */ +#define FREESTYLE_FE_SILHOUETTE 1 +#define FREESTYLE_FE_BORDER 2 +#define FREESTYLE_FE_CREASE 4 +#define FREESTYLE_FE_RIDGE 8 +#define FREESTYLE_FE_VALLEY 16 +#define FREESTYLE_FE_SUGGESTIVE_CONTOUR 32 +#define FREESTYLE_FE_MATERIAL_BOUNDARY 64 +#define FREESTYLE_FE_CONTOUR 128 +#define FREESTYLE_FE_EXTERNAL_CONTOUR 512 + +/* FreestyleLineSet::qi */ +#define FREESTYLE_QI_VISIBLE 1 +#define FREESTYLE_QI_HIDDEN 2 +#define FREESTYLE_QI_RANGE 3 + +typedef struct FreestyleLineStyle { + ID id; + +} FreestyleLineStyle; + +typedef struct FreestyleLineSet { + struct FreestyleLineSet *next, *prev; + + char name[32]; /* line set name */ + int flags; + + int selection; /* selection criteria */ + short qi; /* quantitative invisibility */ + short pad1; + int qi_start, qi_end; + int edge_types; /* feature edge types */ + + FreestyleLineStyle *linestyle; /* line style */ + + ListBase objects; /* target objects on which stylized lines are drawn */ + +} FreestyleLineSet; + +typedef struct FreestyleModuleConfig { + struct FreestyleModuleConfig *next, *prev; + + char module_path[256]; + short is_displayed; + short pad[3]; + +} FreestyleModuleConfig; + +typedef struct FreestyleConfig { + ListBase modules; + + int mode; /* scripting, editor */ + int flags; /* suggestive contours, ridges/valleys, material boundaries */ + float sphere_radius; + float dkr_epsilon; + float crease_angle; + int pad; + + ListBase linesets; + +} FreestyleConfig; + +#endif + diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index f8eb6e76693..9d87f618ec4 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -158,7 +158,7 @@ typedef struct Material { short sss_flag, sss_preset; int mapto_textured; /* render-time cache to optimise texture lookups */ - int pad4; + short vcol_alpha, pad4; ListBase gpumaterial; /* runtime */ } Material; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 3ac11eabe54..2a8e3d4b3af 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -40,6 +40,7 @@ extern "C" { #include "DNA_vec_types.h" #include "DNA_listBase.h" #include "DNA_ID.h" +#include "DNA_freestyle_types.h" struct Object; struct World; @@ -161,6 +162,9 @@ typedef struct SceneRenderLayer { int passflag; /* pass_xor has to be after passflag */ int pass_xor; + + struct FreestyleConfig freestyleConfig; + } SceneRenderLayer; /* srl->layflag */ @@ -170,7 +174,8 @@ typedef struct SceneRenderLayer { #define SCE_LAY_EDGE 8 #define SCE_LAY_SKY 16 #define SCE_LAY_STRAND 32 - /* flags between 32 and 0x8000 are set to 1 already, for future options */ +#define SCE_LAY_FRS 64 + /* flags between 64 and 0x8000 are set to 1 already, for future options */ #define SCE_LAY_ALL_Z 0x8000 #define SCE_LAY_XOR 0x10000 @@ -863,6 +868,7 @@ typedef struct Scene { #define R_NO_OVERWRITE 0x400000 /* skip existing files */ #define R_TOUCH 0x800000 /* touch files before rendering */ #define R_SIMPLIFY 0x1000000 +#define R_EDGE_FRS 0x2000000 /* R_EDGE for Freestyle */ /* seq_flag */ #define R_SEQ_GL_PREV 1 diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index fc5307000e3..ba038869027 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -129,6 +129,7 @@ char *includefiles[] = { "DNA_anim_types.h", "DNA_boid_types.h", "DNA_smoke_types.h", + "DNA_freestyle_types.h", // empty string to indicate end of includefiles "" @@ -1173,4 +1174,5 @@ int main(int argc, char ** argv) #include "DNA_anim_types.h" #include "DNA_boid_types.h" #include "DNA_smoke_types.h" +#include "DNA_freestyle_types.h" /* end of list */ diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 30cbc512f5a..8e12ad588d0 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -219,6 +219,10 @@ extern StructRNA RNA_FModifierNoise; extern StructRNA RNA_FModifierPython; extern StructRNA RNA_FModifierStepped; extern StructRNA RNA_FollowPathConstraint; +extern StructRNA RNA_FreestyleLineStyle; +extern StructRNA RNA_FreestyleLineSet; +extern StructRNA RNA_FreestyleModuleSettings; +extern StructRNA RNA_FreestyleSettings; extern StructRNA RNA_Function; extern StructRNA RNA_GameBooleanProperty; extern StructRNA RNA_GameFloatProperty; diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h index 88058769f4b..1f08f76661c 100644 --- a/source/blender/makesrna/RNA_types.h +++ b/source/blender/makesrna/RNA_types.h @@ -343,6 +343,7 @@ typedef struct ExtensionRNA { #define MainLamps Main #define MainLattices Main #define MainLibraries Main +#define MainLineStyles Main #define MainMaterials Main #define MainMeshes Main #define MainMetaBalls Main diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript index 1558eef713e..4eb566f6570 100644 --- a/source/blender/makesrna/SConscript +++ b/source/blender/makesrna/SConscript @@ -9,6 +9,7 @@ objs += o incs = '#/intern/guardedalloc #/intern/audaspace/intern ../blenkernel ../blenlib ../makesdna intern .' incs += ' ../windowmanager ../editors/include ../gpu ../imbuf ../ikplugin' incs += ' ../render/extern/include' +incs += ' ../freestyle' defs = [] diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 207e4e15a72..34ddf842aaa 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -53,6 +53,7 @@ INCLUDE_DIRECTORIES( ../../imbuf ../../render/extern/include ../../../../extern/glew/include + ../../freestyle . ) FILE(GLOB INC_FILES ../*.h ../../makesdna/*.h) diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 40f6c1de67e..baceec28fc3 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -2256,6 +2256,7 @@ RNAProcessItem PROCESS_ITEMS[]= { {"rna_key.c", NULL, RNA_def_key}, {"rna_lamp.c", NULL, RNA_def_lamp}, {"rna_lattice.c", NULL, RNA_def_lattice}, + {"rna_linestyle.c", NULL, RNA_def_linestyle}, {"rna_main.c", "rna_main_api.c", RNA_def_main}, {"rna_material.c", "rna_material_api.c", RNA_def_material}, {"rna_mesh.c", "rna_mesh_api.c", RNA_def_mesh}, diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 009afec2ded..d07432c96fa 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -50,6 +50,7 @@ EnumPropertyItem id_type_items[] = { {ID_KE, "KEY", ICON_SHAPEKEY_DATA, "Key", ""}, {ID_LA, "LAMP", ICON_LAMP_DATA, "Lamp", ""}, {ID_LI, "LIBRARY", ICON_LIBRARY_DATA_DIRECT, "Library", ""}, + {ID_LS, "LINESTYLE", ICON_PARTICLE_DATA, "FreestyleLineStyle", ""}, /* FIXME proper icon */ {ID_LT, "LATTICE", ICON_LATTICE_DATA, "Lattice", ""}, {ID_MA, "MATERIAL", ICON_MATERIAL_DATA, "Material", ""}, {ID_MB, "META", ICON_META_DATA, "MetaBall", ""}, @@ -117,6 +118,7 @@ short RNA_type_to_ID_code(StructRNA *type) if(RNA_struct_is_a(type, &RNA_Key)) return ID_KE; if(RNA_struct_is_a(type, &RNA_Lamp)) return ID_LA; if(RNA_struct_is_a(type, &RNA_Library)) return ID_LI; + if(RNA_struct_is_a(type, &RNA_FreestyleLineStyle)) return ID_LS; if(RNA_struct_is_a(type, &RNA_Lattice)) return ID_LT; if(RNA_struct_is_a(type, &RNA_Material)) return ID_MA; if(RNA_struct_is_a(type, &RNA_MetaBall)) return ID_MB; @@ -150,6 +152,7 @@ StructRNA *ID_code_to_RNA_type(short idcode) case ID_KE: return &RNA_Key; case ID_LA: return &RNA_Lamp; case ID_LI: return &RNA_Library; + case ID_LS: return &RNA_FreestyleLineStyle; case ID_LT: return &RNA_Lattice; case ID_MA: return &RNA_Material; case ID_MB: return &RNA_MetaBall; diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 806a22dd3b8..f92918fbbb3 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -142,6 +142,7 @@ void RNA_def_image(struct BlenderRNA *brna); void RNA_def_key(struct BlenderRNA *brna); void RNA_def_lamp(struct BlenderRNA *brna); void RNA_def_lattice(struct BlenderRNA *brna); +void RNA_def_linestyle(struct BlenderRNA *brna); void RNA_def_main(struct BlenderRNA *brna); void RNA_def_material(struct BlenderRNA *brna); void RNA_def_mesh(struct BlenderRNA *brna); @@ -267,6 +268,7 @@ void RNA_def_main_armatures(BlenderRNA *brna, PropertyRNA *cprop); void RNA_def_main_actions(BlenderRNA *brna, PropertyRNA *cprop); void RNA_def_main_particles(BlenderRNA *brna, PropertyRNA *cprop); void RNA_def_main_gpencil(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_linestyles(BlenderRNA *brna, PropertyRNA *cprop); /* ID Properties */ diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c new file mode 100644 index 00000000000..f686d0cecda --- /dev/null +++ b/source/blender/makesrna/intern/rna_linestyle.c @@ -0,0 +1,57 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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 2 + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Foundation (2008). + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "RNA_define.h" + +#include "rna_internal.h" + +#include "DNA_freestyle_types.h" + +#include "WM_types.h" +#include "WM_api.h" + +#ifdef RNA_RUNTIME + +#else + +static void rna_def_linestyle(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "FreestyleLineStyle", "ID"); + RNA_def_struct_ui_text(srna, "Freestyle Line Style", "Freestyle line style, reusable by multiple line sets"); + +} + +void RNA_def_linestyle(BlenderRNA *brna) +{ + rna_def_linestyle(brna); +} + +#endif + diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c index 052c9fb3453..c2f3953e627 100644 --- a/source/blender/makesrna/intern/rna_main.c +++ b/source/blender/makesrna/intern/rna_main.c @@ -239,6 +239,12 @@ static void rna_Main_wm_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) rna_iterator_listbase_begin(iter, &bmain->wm, NULL); } +static void rna_Main_linestyle_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + Main *bmain= (Main*)ptr->data; + rna_iterator_listbase_begin(iter, &bmain->linestyle, NULL); +} + #ifdef UNIT_TEST static PointerRNA rna_Test_test_get(PointerRNA *ptr) @@ -300,6 +306,7 @@ void RNA_def_main(BlenderRNA *brna) {"actions", "Action", "rna_Main_action_begin", "Actions", "Action datablocks.", RNA_def_main_actions}, {"particles", "ParticleSettings", "rna_Main_particle_begin", "Particles", "Particle datablocks.", RNA_def_main_particles}, {"gpencil", "GreasePencil", "rna_Main_gpencil_begin", "Grease Pencil", "Grease Pencil datablocks.", RNA_def_main_gpencil}, + {"linestyles", "FreestyleLineStyle", "rna_Main_linestyle_begin", "Line Styles", "Line Style datablocks.", RNA_def_main_linestyles}, {NULL, NULL, NULL, NULL, NULL, NULL}}; int i; diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index 49359e03985..f28751f6e19 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -58,6 +58,7 @@ #include "BKE_particle.h" #include "BKE_font.h" #include "BKE_node.h" +#include "BKE_linestyle.h" #include "DNA_armature_types.h" #include "DNA_camera_types.h" @@ -474,6 +475,22 @@ void rna_Main_particles_remove(Main *bmain, ReportList *reports, ParticleSetting /* XXX python now has invalid pointer? */ } +FreestyleLineStyle *rna_Main_linestyles_new(Main *bmain, char* name) +{ + FreestyleLineStyle *linestyle = FRS_new_linestyle(name, bmain); + linestyle->id.us--; + return linestyle; +} +void rna_Main_linestyles_remove(Main *bmain, ReportList *reports, FreestyleLineStyle *linestyle) +{ + if(ID_REAL_USERS(linestyle) <= 0) + free_libblock(&bmain->linestyle, linestyle); + else + BKE_reportf(reports, RPT_ERROR, "Line style \"%s\" must have zero users to be removed, found %d.", linestyle->id.name+2, ID_REAL_USERS(linestyle)); + + /* XXX python now has invalid pointer? */ +} + #else void RNA_api_main(StructRNA *srna) @@ -1040,6 +1057,30 @@ void RNA_def_main_gpencil(BlenderRNA *brna, PropertyRNA *cprop) { } +void RNA_def_main_linestyles(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "MainLineStyles"); + srna= RNA_def_struct(brna, "MainLineStyles", NULL); + RNA_def_struct_ui_text(srna, "Main Line Styles", "Collection of line styles"); + + func= RNA_def_function(srna, "new", "rna_Main_linestyles_new"); + RNA_def_function_ui_description(func, "Add a new line style instance to the main database"); + parm= RNA_def_string(func, "name", "FreestyleLineStyle", 0, "", "New name for the datablock."); + RNA_def_property_flag(parm, PROP_REQUIRED); + /* return type */ + parm= RNA_def_pointer(func, "linestyle", "FreestyleLineStyle", "", "New line style datablock."); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "remove", "rna_Main_linestyles_remove"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_ui_description(func, "Remove a line style instance from the current blendfile."); + parm= RNA_def_pointer(func, "linestyle", "FreestyleLineStyle", "", "Line style to remove."); + RNA_def_property_flag(parm, PROP_REQUIRED); +} #endif diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 7c2037be6e0..2e4b0ee1c66 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -173,6 +173,8 @@ EnumPropertyItem image_type_items[] = { #include "RE_pipeline.h" +#include "FRS_freestyle.h" + static PointerRNA rna_Scene_objects_get(CollectionPropertyIterator *iter) { ListBaseIterator *internal= iter->internal; @@ -904,6 +906,49 @@ static void rna_TimeLine_remove(Scene *scene, ReportList *reports, TimeMarker *m MEM_freeN(marker); } +static PointerRNA rna_FreestyleLineSet_linestyle_get(PointerRNA *ptr) +{ + FreestyleLineSet *lineset= (FreestyleLineSet *)ptr->data; + + return rna_pointer_inherit_refine(ptr, &RNA_FreestyleLineStyle, lineset->linestyle); +} + +static void rna_FreestyleLineSet_linestyle_set(PointerRNA *ptr, PointerRNA value) +{ + FreestyleLineSet *lineset= (FreestyleLineSet*)ptr->data; + + lineset->linestyle->id.us--; + lineset->linestyle = (FreestyleLineStyle *)value.data; + lineset->linestyle->id.us++; +} + +static PointerRNA rna_FreestyleSettings_active_lineset_get(PointerRNA *ptr) +{ + FreestyleConfig *config= (FreestyleConfig *)ptr->data; + FreestyleLineSet *lineset= FRS_get_active_lineset(config); + return rna_pointer_inherit_refine(ptr, &RNA_FreestyleLineSet, lineset); +} + +static void rna_FreestyleSettings_active_lineset_index_range(PointerRNA *ptr, int *min, int *max) +{ + FreestyleConfig *config= (FreestyleConfig *)ptr->data; + *min= 0; + *max= BLI_countlist(&config->linesets)-1; + *max= MAX2(0, *max); +} + +static int rna_FreestyleSettings_active_lineset_index_get(PointerRNA *ptr) +{ + FreestyleConfig *config= (FreestyleConfig *)ptr->data; + return FRS_get_active_lineset_index(config); +} + +static void rna_FreestyleSettings_active_lineset_index_set(PointerRNA *ptr, int value) +{ + FreestyleConfig *config= (FreestyleConfig *)ptr->data; + FRS_set_active_lineset_index(config, value); +} + #else static void rna_def_transform_orientation(BlenderRNA *brna) @@ -1319,6 +1364,12 @@ void rna_def_render_layer_common(StructRNA *srna, int scene) if(scene) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); else RNA_def_property_clear_flag(prop, PROP_EDITABLE); + prop= RNA_def_property(srna, "freestyle", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "layflag", SCE_LAY_FRS); + RNA_def_property_ui_text(prop, "Freestyle", "Render stylized strokes in this Layer."); + if(scene) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + else RNA_def_property_clear_flag(prop, PROP_EDITABLE); + /* passes */ prop= RNA_def_property(srna, "pass_combined", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_COMBINED); @@ -1479,6 +1530,231 @@ void rna_def_render_layer_common(StructRNA *srna, int scene) else RNA_def_property_clear_flag(prop, PROP_EDITABLE); } +static void rna_def_freestyle_settings(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem negation_items[] = { + {0, "INCLUSIVE", 0, "Inclusive", "Select feature edges satisfying the given edge type conditions."}, + {FREESTYLE_LINESET_FE_NOT, "EXCLUSIVE", 0, "Exclusive", "Select feature edges not satisfying the given edge type conditions."}, + {0, NULL, 0, NULL, NULL}}; + + static EnumPropertyItem combination_items[] = { + {0, "AND", 0, "Logical AND", "Combine feature edge type conditions by logical AND (logical conjunction)."}, + {FREESTYLE_LINESET_FE_OR, "OR", 0, "Logical OR", "Combine feature edge type conditions by logical OR (logical disjunction)."}, + {0, NULL, 0, NULL, NULL}}; + + static EnumPropertyItem freestyle_ui_mode_items[] = { + {FREESTYLE_CONTROL_SCRIPT_MODE, "SCRIPT", 0, "Python Scripting Mode", "Advanced mode for using style modules in Python"}, + {FREESTYLE_CONTROL_EDITOR_MODE, "EDITOR", 0, "Parameter Editor Mode", "Basic mode for interactive style parameter editing"}, + {0, NULL, 0, NULL, NULL}}; + + static EnumPropertyItem visibility_items[] ={ + {FREESTYLE_QI_VISIBLE, "VISIBLE", 0, "Visible", "Select visible feature edges."}, + {FREESTYLE_QI_HIDDEN, "HIDDEN", 0, "Hidden", "Select hidden feature edges."}, + {FREESTYLE_QI_RANGE, "RANGE", 0, "QI Range", "Select feature edges within a range of quantitative invisibility (QI) values."}, + {0, NULL, 0, NULL, NULL}}; + + /* FreestyleLineSet */ + + srna= RNA_def_struct(brna, "FreestyleLineSet", NULL); + RNA_def_struct_ui_text(srna, "Freestyle Line Set", "Line set for associating lines and style parameters."); + + /* access to line style settings is redirected through functions */ + /* to allow proper id-buttons functionality */ + prop= RNA_def_property(srna, "linestyle", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "FreestyleLineStyle"); + RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_NULL); + RNA_def_property_pointer_funcs(prop, "rna_FreestyleLineSet_linestyle_get", "rna_FreestyleLineSet_linestyle_set", NULL); + RNA_def_property_ui_text(prop, "Line Style", "Line style settings"); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "name"); + RNA_def_property_ui_text(prop, "Line Set Name", "Line set name"); + RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_struct_name_property(srna, prop); + + prop= RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_LINESET_ENABLED); + RNA_def_property_ui_text(prop, "Enabled", "Enable or disable the line set."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "select_by_visibility", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_VISIBILITY); + RNA_def_property_ui_text(prop, "Selection by Visibility", "Select feature edges based on visibility."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "select_by_edge_types", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_EDGE_TYPES); + RNA_def_property_ui_text(prop, "Selection by Edge Types", "Select feature edges based on edge types."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "edge_type_negation", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags"); + RNA_def_property_enum_items(prop, negation_items); + RNA_def_property_ui_text(prop, "Edge Type Negation", "Set the negation operation for conditions on feature edge types."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "edge_type_combination", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags"); + RNA_def_property_enum_items(prop, combination_items); + RNA_def_property_ui_text(prop, "Edge Type Combination", "Set the combination operation for conditions on feature edge types."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "objects", NULL); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_ui_text(prop, "Target Objects", "A list of objects on which stylized lines are drawn."); + + prop= RNA_def_property(srna, "select_silhouette", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_SILHOUETTE); + RNA_def_property_ui_text(prop, "Silhouette", "Select silhouette edges."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "select_border", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_BORDER); + RNA_def_property_ui_text(prop, "Border", "Select border edges."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "select_crease", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_CREASE); + RNA_def_property_ui_text(prop, "Crease", "Select crease edges."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "select_ridge", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_RIDGE); + RNA_def_property_ui_text(prop, "Ridge", "Select ridges."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "select_valley", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_VALLEY); + RNA_def_property_ui_text(prop, "Valley", "Select valleys."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "select_suggestive_contour", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_SUGGESTIVE_CONTOUR); + RNA_def_property_ui_text(prop, "Suggestive Contour", "Select suggestive contours."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "select_material_boundary", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_MATERIAL_BOUNDARY); + RNA_def_property_ui_text(prop, "Material Boundary", "Select edges at material boundaries."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "select_contour", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_CONTOUR); + RNA_def_property_ui_text(prop, "Contour", "Select contours."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "select_external_contour", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_EXTERNAL_CONTOUR); + RNA_def_property_ui_text(prop, "External Contour", "Select external contours."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "visibility", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "qi"); + RNA_def_property_enum_items(prop, visibility_items); + RNA_def_property_ui_text(prop, "Visibility", "Determine how to use visibility for feature edge selection."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "qi_start", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "qi_start"); + RNA_def_property_range(prop, 0, INT_MAX); + RNA_def_property_ui_text(prop, "Start", "First QI value of the QI range"); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "qi_end", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "qi_end"); + RNA_def_property_range(prop, 0, INT_MAX); + RNA_def_property_ui_text(prop, "End", "Last QI value of the QI range"); + RNA_def_property_update(prop, NC_SCENE, NULL); + + /* FreestyleModuleSettings */ + + srna= RNA_def_struct(brna, "FreestyleModuleSettings", NULL); + RNA_def_struct_sdna(srna, "FreestyleModuleConfig"); + RNA_def_struct_ui_text(srna, "Freestyle Module", "Style module configuration for specifying a style module."); + + prop= RNA_def_property(srna, "module_path", PROP_STRING, PROP_FILEPATH); + RNA_def_property_string_sdna(prop, NULL, "module_path"); + RNA_def_property_ui_text(prop, "Module Path", "Path to a style module file."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "is_displayed", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "is_displayed", 1); + RNA_def_property_ui_text(prop, "Is Displayed", "Enable this style module during the rendering."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + /* FreestyleSettings */ + + srna= RNA_def_struct(brna, "FreestyleSettings", NULL); + RNA_def_struct_sdna(srna, "FreestyleConfig"); + RNA_def_struct_nested(brna, srna, "SceneRenderLayer"); + RNA_def_struct_ui_text(srna, "Frestyle Settings", "Freestyle settings for a SceneRenderLayer datablock."); + + prop= RNA_def_property(srna, "modules", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "modules", NULL); + RNA_def_property_struct_type(prop, "FreestyleModuleSettings"); + RNA_def_property_ui_text(prop, "Style modules", "A list of style modules (to be applied from top to bottom)."); + + prop= RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "mode"); + RNA_def_property_enum_items(prop, freestyle_ui_mode_items); + RNA_def_property_ui_text(prop, "Control Mode", "Select the Freestyle control mode"); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "suggestive_contours", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_SUGGESTIVE_CONTOURS_FLAG); + RNA_def_property_ui_text(prop, "Suggestive Contours", "Enable suggestive contours."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "ridges_and_valleys", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_RIDGES_AND_VALLEYS_FLAG); + RNA_def_property_ui_text(prop, "Ridges and Valleys", "Enable ridges and valleys."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "material_boundaries", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_MATERIAL_BOUNDARIES_FLAG); + RNA_def_property_ui_text(prop, "Material Boundaries", "Enable material boundaries."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "sphere_radius", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "sphere_radius"); + RNA_def_property_range(prop, 0.0, 1000.0); + RNA_def_property_ui_text(prop, "Sphere Radius", "Sphere radius for computing curvatures."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "dkr_epsilon", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "dkr_epsilon"); + RNA_def_property_range(prop, 0.0, 1000.0); + RNA_def_property_ui_text(prop, "Kr Derivative Epsilon", "Kr derivative epsilon for computing suggestive contours."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "crease_angle", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "crease_angle"); + RNA_def_property_range(prop, 0.0, 180.0); + RNA_def_property_ui_text(prop, "Crease Angle", "Angular threshold in degrees (between 0 and 180) for detecting crease edges."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "linesets", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "linesets", NULL); + RNA_def_property_struct_type(prop, "FreestyleLineSet"); + RNA_def_property_ui_text(prop, "Line Sets", "Line sets for associating lines and style parameters"); + + prop= RNA_def_property(srna, "active_lineset", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "FreestyleLineSet"); + RNA_def_property_pointer_funcs(prop, "rna_FreestyleSettings_active_lineset_get", NULL, NULL); + RNA_def_property_ui_text(prop, "Active Line Set", "Active line set being displayed"); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "active_lineset_index", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_funcs(prop, "rna_FreestyleSettings_active_lineset_index_get", "rna_FreestyleSettings_active_lineset_index_set", "rna_FreestyleSettings_active_lineset_index_range"); + RNA_def_property_ui_text(prop, "Active Line Set Index", "Index of active line set slot"); + RNA_def_property_update(prop, NC_SCENE, NULL); +} + static void rna_def_scene_game_data(BlenderRNA *brna) { StructRNA *srna; @@ -1770,12 +2046,23 @@ static void rna_def_scene_game_data(BlenderRNA *brna) static void rna_def_scene_render_layer(BlenderRNA *brna) { StructRNA *srna; + PropertyRNA *prop; srna= RNA_def_struct(brna, "SceneRenderLayer", NULL); RNA_def_struct_ui_text(srna, "Scene Render Layer", "Render layer"); RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS); rna_def_render_layer_common(srna, 1); + + /* Freestyle */ + + rna_def_freestyle_settings(brna); + + prop= RNA_def_property(srna, "freestyle_settings", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "freestyleConfig"); + RNA_def_property_struct_type(prop, "FreestyleSettings"); + RNA_def_property_ui_text(prop, "Freestyle Settings", ""); } static void rna_def_scene_render_data(BlenderRNA *brna) @@ -2403,6 +2690,11 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Edge Color", ""); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + prop= RNA_def_property(srna, "freestyle", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "mode", R_EDGE_FRS); + RNA_def_property_ui_text(prop, "Edge", "Draw stylized strokes using Freestyle."); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + /* threads */ prop= RNA_def_property(srna, "threads", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "threads"); @@ -3169,7 +3461,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_struct_type(prop, "GreasePencil"); RNA_def_property_ui_text(prop, "Grease Pencil Data", "Grease Pencil datablock"); - + /* Transform Orientations */ prop= RNA_def_property(srna, "orientations", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "transform_spaces", NULL); diff --git a/source/blender/python/CMakeLists.txt b/source/blender/python/CMakeLists.txt index 3c79e9d3056..39c28fe2b94 100644 --- a/source/blender/python/CMakeLists.txt +++ b/source/blender/python/CMakeLists.txt @@ -35,6 +35,7 @@ SET(INC ../blenkernel ../windowmanager ../editors/include + ../freestyle/intern/python ../../../intern/guardedalloc ${PYTHON_INC} ) diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript index ca742a3646a..b4ce9898b1b 100644 --- a/source/blender/python/SConscript +++ b/source/blender/python/SConscript @@ -5,6 +5,7 @@ sources = env.Glob('intern/*.c') incs = '. ../editors/include ../makesdna ../makesrna ../blenlib ../blenkernel ../nodes' incs += ' ../imbuf ../blenloader ../render/extern/include ../windowmanager' +incs += ' ../freestyle/intern/python' incs += ' #intern/guardedalloc #intern/memutil #extern/glew/include' incs += ' ' + env['BF_PYTHON_INC'] diff --git a/source/blender/python/doc/sphinx_doc_gen.py b/source/blender/python/doc/sphinx_doc_gen.py index 27524c66c36..9e667a4b7b2 100644 --- a/source/blender/python/doc/sphinx_doc_gen.py +++ b/source/blender/python/doc/sphinx_doc_gen.py @@ -47,6 +47,7 @@ reload(rna_info) # lame, python wont give some access MethodDescriptorType = type(dict.get) GetSetDescriptorType = type(int.real) +StaticMethodType = type(staticmethod(lambda: None)) EXAMPLE_SET = set() EXAMPLE_SET_USED = set() @@ -275,6 +276,12 @@ def pymodule2sphinx(BASEPATH, module_name, module, title): if type(descr) == GetSetDescriptorType: py_descr2sphinx(" ", fw, descr, module_name, type_name, key) + for key, descr in descr_items: + if type(descr) == StaticMethodType: + descr = getattr(value, key) + write_indented_lines(" ", fw, descr.__doc__ or "Undocumented", False) + fw("\n") + fw("\n\n") file.close() @@ -374,6 +381,7 @@ def rna2sphinx(BASEPATH): fw(" mathutils.rst\n\n") + fw(" Freestyle.rst\n\n") fw(" blf.rst\n\n") # game engine @@ -451,6 +459,10 @@ def rna2sphinx(BASEPATH): pymodule2sphinx(BASEPATH, "mathutils", module, "Math Types & Utilities (mathutils)") del module + import Freestyle as module + pymodule2sphinx(BASEPATH, "Freestyle", module, "Freestyle Operators & Rules (Freestyle)") + del module + import blf as module pymodule2sphinx(BASEPATH, "blf", module, "Font Drawing (blf)") del module diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index b978e46f6da..4763f555937 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -41,6 +41,8 @@ #include "../generic/blf_api.h" #include "../generic/IDProp.h" +#include "BPy_Freestyle.h" + static char bpy_home_paths_doc[] = ".. function:: home_paths(subfolder)\n" "\n" @@ -162,6 +164,7 @@ void BPy_init_modules( void ) BGL_Init(); BLF_Init(); IDProp_Init_Types(); + Freestyle_Init(); mod = PyModule_New("_bpy"); diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt index 9199a0a33ba..c78e09dae10 100644 --- a/source/blender/render/CMakeLists.txt +++ b/source/blender/render/CMakeLists.txt @@ -29,7 +29,7 @@ FILE(GLOB SRC intern/source/*.c intern/raytrace/*.cpp) SET(INC intern/include ../../../intern/guardedalloc ../blenlib ../makesdna extern/include ../blenkernel ../imbuf - ../include ../../kernel/gen_messaging ../blenloader + ../include ../../kernel/gen_messaging ../blenloader ../freestyle ../../../intern/smoke/extern ../makesrna ) diff --git a/source/blender/render/SConscript b/source/blender/render/SConscript index 366f6bd723c..7f80731e26d 100644 --- a/source/blender/render/SConscript +++ b/source/blender/render/SConscript @@ -6,7 +6,7 @@ raysources = env.Glob('intern/raytrace/*.cpp') incs = 'intern/include #/intern/guardedalloc ../blenlib ../makesdna ../makesrna' incs += ' extern/include ../blenkernel ../radiosity/extern/include ../imbuf' -incs += ' ../include ../blenloader ../../../intern/smoke/extern' +incs += ' ../include ../blenloader ../freestyle ../../../intern/smoke/extern' cflags = env['CCFLAGS'] cxxflags = env['CXXFLAGS'] diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 802703d476c..378a386478d 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -210,6 +210,7 @@ void RE_TileProcessor(struct Render *re); /* only RE_NewRender() needed, main Blender render calls */ void RE_BlenderFrame(struct Render *re, struct Scene *scene, struct SceneRenderLayer *srl, unsigned int lay, int frame); void RE_BlenderAnim(struct Render *re, struct Scene *scene, unsigned int lay, int sfra, int efra, int tfra, struct ReportList *reports); +void RE_RenderFreestyleStrokes(struct Render *re, struct Scene *scene); /* main preview render call */ void RE_PreviewRender(struct Render *re, struct Scene *scene); diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 331474a85e3..62a82dafbe2 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -220,6 +220,8 @@ struct Render ListBase volumes; ListBase volume_precache_parts; + ListBase freestyle_renders; + /* arena for allocating data for use during render, for * example dynamic TFaces to go in the VlakRen structure. */ diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index fd91bf8a2c2..6ffa856f62b 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -42,6 +42,7 @@ #include "BKE_utildefines.h" #include "BKE_global.h" #include "BKE_image.h" +#include "BKE_library.h" #include "BKE_main.h" #include "BKE_node.h" #include "BKE_object.h" @@ -67,6 +68,9 @@ #include "RE_pipeline.h" +#include "FRS_freestyle.h" +#include "FRS_freestyle_config.h" + /* internal */ #include "render_types.h" #include "renderpipeline.h" @@ -646,6 +650,7 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop, int rl->lay= (1<<20) -1; rl->layflag= 0x7FFF; /* solid ztra halo strand */ rl->passflag= SCE_PASS_COMBINED; + FRS_add_freestyle_config( srl ); re->r.actlay= 0; } @@ -1754,6 +1759,7 @@ void RE_TileProcessor(Render *re) /* ************ This part uses API, for rendering Blender scenes ********** */ static int external_render_3d(Render *re, int do_all); +static void add_freestyle(Render *re); static void do_render_3d(Render *re) { @@ -1779,6 +1785,11 @@ static void do_render_3d(Render *re) if(!re->test_break(re->tbh)) add_halo_flare(re); + /* Freestyle */ + if( re->r.mode & R_EDGE_FRS && re->r.renderer==R_INTERN) + if(!re->test_break(re->tbh)) + add_freestyle(re); + /* free all render verts etc */ RE_Database_Free(re); @@ -2233,6 +2244,64 @@ static void render_composit_stats(void *unused, char *str) } +/* invokes Freestyle stroke rendering */ +static void add_freestyle(Render *re) +{ + SceneRenderLayer *srl; + LinkData *link; + + FRS_init_stroke_rendering(re); + + for(srl= (SceneRenderLayer *)re->scene->r.layers.first; srl; srl= srl->next) { + + link = (LinkData *)MEM_callocN(sizeof(LinkData), "LinkData to Freestyle render"); + BLI_addtail(&re->freestyle_renders, link); + + if( FRS_is_freestyle_enabled(srl) ) { + link->data = (void *)FRS_do_stroke_rendering(re, srl); + } + } +} + +/* merges the results of Freestyle stroke rendering into a given render result */ +static void composite_freestyle_renders(Render *re, int sample) +{ + Render *freestyle_render; + SceneRenderLayer *srl; + LinkData *link; + + link = (LinkData *)re->freestyle_renders.first; + for(srl= (SceneRenderLayer *)re->scene->r.layers.first; srl; srl= srl->next) { + if( FRS_is_freestyle_enabled(srl) ) { + freestyle_render = (Render *)link->data; + read_render_result(freestyle_render, sample); + FRS_composite_result(re, srl, freestyle_render); + RE_FreeRenderResult(freestyle_render->result); + freestyle_render->result = NULL; + } + link = link->next; + } +} + +/* releases temporary scenes and renders for Freestyle stroke rendering */ +static void free_all_freestyle_renders(void) +{ + Render *re1, *freestyle_render; + LinkData *link; + + for(re1= RenderGlobal.renderlist.first; re1; re1= re1->next) { + for (link = (LinkData *)re1->freestyle_renders.first; link; link = link->next) { + if (link->data) { + freestyle_render = (Render *)link->data; + free_libblock(&G.main->scene, freestyle_render->scene); + RE_FreeRender(freestyle_render); + } + } + BLI_freelistN( &re1->freestyle_renders ); + } +} + + /* reads all buffers, calls optional composite, merges in first result->rectf */ static void do_merge_fullsample(Render *re, bNodeTree *ntree) { @@ -2256,9 +2325,12 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) tag_scenes_for_render(re); for(re1= RenderGlobal.renderlist.first; re1; re1= re1->next) { - if(re1->scene->id.flag & LIB_DOIT) - if(re1->r.scemode & R_FULL_SAMPLE) + if(re1->scene->id.flag & LIB_DOIT) { + if(re1->r.scemode & R_FULL_SAMPLE) { read_render_result(re1, sample); + composite_freestyle_renders(re1, sample); + } + } } } @@ -2412,6 +2484,8 @@ static void do_render_composite_fields_blur_3d(Render *re) do_merge_fullsample(re, NULL); } + free_all_freestyle_renders(); + /* weak... the display callback wants an active renderlayer pointer... */ re->result->renlay= render_get_active_layer(re, re->result); re->display_draw(re->ddh, re->result, NULL); @@ -2773,6 +2847,16 @@ void RE_BlenderFrame(Render *re, Scene *scene, SceneRenderLayer *srl, unsigned i G.rendering= 0; } +void RE_RenderFreestyleStrokes(Render *re, Scene *scene) +{ + re->result_ok= 0; + scene->r.cfra= 1; + if(render_initialize_from_scene(re, scene, NULL, scene->lay, 0, 0)) { + do_render_fields_blur_3d(re); + } + re->result_ok= 1; +} + static int do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh, ReportList *reports) { char name[FILE_MAX]; diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index 5938e2ce2e0..3696855a6a3 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -1043,6 +1043,7 @@ void shade_input_set_shade_texco(ShadeInput *shi) shi->actcol= obr->actmcol; if(mode & (MA_VERTEXCOL|MA_VERTEXCOLP)) { + float alpha[8]; for (i=0; (mcol=RE_vlakren_get_mcol(obr, vlr, i, &name, 0)); i++) { ShadeInputCol *scol= &shi->col[i]; char *cp1, *cp2, *cp3; @@ -1057,13 +1058,15 @@ void shade_input_set_shade_texco(ShadeInput *shi) scol->col[0]= (l*((float)cp3[3]) - u*((float)cp1[3]) - v*((float)cp2[3]))/255.0f; scol->col[1]= (l*((float)cp3[2]) - u*((float)cp1[2]) - v*((float)cp2[2]))/255.0f; scol->col[2]= (l*((float)cp3[1]) - u*((float)cp1[1]) - v*((float)cp2[1]))/255.0f; + + alpha[i]= (l*((float)cp3[0]) - u*((float)cp1[0]) - v*((float)cp2[0]))/255.0f; } if(shi->totcol) { shi->vcol[0]= shi->col[shi->actcol].col[0]; shi->vcol[1]= shi->col[shi->actcol].col[1]; shi->vcol[2]= shi->col[shi->actcol].col[2]; - shi->vcol[3]= 1.0f; + shi->vcol[3]= shi->mat->vcol_alpha ? alpha[shi->actcol] : 1.0f; } else { shi->vcol[0]= 0.0f; diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 806cafaf89b..449d3da0b6d 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -1590,7 +1590,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) shi->r= shi->vcol[0]; shi->g= shi->vcol[1]; shi->b= shi->vcol[2]; - if(ma->mode & (MA_FACETEXTURE_ALPHA)) + if((ma->mode & (MA_FACETEXTURE_ALPHA)) || ma->vcol_alpha) shi->alpha= shi->vcol[3]; } if(ma->texco) diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 36fd67c85c6..fe524b6cfcc 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -39,6 +39,7 @@ INCLUDE_DIRECTORIES( ../blender/render/extern/include ../blender/makesdna ../blender/gpu + ../blender/freestyle ../blender/windowmanager ../kernel/gen_messaging ../kernel/gen_system @@ -392,6 +393,7 @@ ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux") bf_editor_animation bf_editor_datafiles + bf_freestyle blender_BSP blender_render blender_ONL diff --git a/source/creator/SConscript b/source/creator/SConscript index 815bd351f69..7f359b2f5a8 100644 --- a/source/creator/SConscript +++ b/source/creator/SConscript @@ -8,7 +8,7 @@ incs = '#/intern/guardedalloc ../blender/blenlib ../blender/blenkernel' incs += ' ../blender/editors/include ../blender/blenloader ../blender/imbuf' incs += ' ../blender/renderconverter ../blender/render/extern/include ../blender/windowmanager' incs += ' ../blender/makesdna ../blender/makesrna ../kernel/gen_messaging' -incs += ' ../kernel/gen_system #/extern/glew/include ../blender/gpu' +incs += ' ../kernel/gen_system #/extern/glew/include ../blender/gpu ../blender/freestyle' incs += ' ' + env['BF_OPENGL_INC'] defs = [] diff --git a/source/creator/creator.c b/source/creator/creator.c index c3499a5788c..4a502355579 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -96,6 +96,8 @@ #include "GPU_draw.h" #include "GPU_extensions.h" +#include "FRS_freestyle.h" + /* for passing information between creator and gameengine */ #include "SYS_System.h" @@ -1138,6 +1140,10 @@ int main(int argc, char **argv) CTX_py_init_set(C, 1); WM_keymap_init(C); + /* initialize Freestyle */ + FRS_initialize(); + FRS_set_context(C); + /* OK we are ready for it */ BLI_argsParse(ba, 4, load_file, C); |