source: src/atoms/Face.pym @ 1345:ff8ef9c6bbb7

Revision 1345:ff8ef9c6bbb7, 9.3 KB checked in by Arc Riley <arcriley@…>, 5 years ago (diff)

Happy New Year! (copyright string update)

RevLine 
[408]1# PySoy's atoms.Face class
[204]2#
[1345]3# Copyright (C) 2006,2007,2008,2009 PySoy Group
[204]4#
5#  This program is free software; you can redistribute it and/or modify
[1144]6#  it under the terms of the GNU Affero General Public License as published
[1145]7#  by the Free Software Foundation, either version 3 of the License, or
[204]8#  (at your option) any later version.
9#
10#  This program is distributed in the hope that it will be useful,
11#  but WITHOUT ANY WARRANTY; without even the implied warranty of
12#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
[1144]13#  GNU Affero General Public License for more details.
[204]14#
[1144]15#  You should have received a copy of the GNU Affero General Public License
[204]16#  along with this program; if not, see http://www.gnu.org/licenses
17#
[1345]18# $Id: Face.pym 1393 2008-12-31 23:51:25Z ArcRiley $
[204]19
[211]20cdef class Face :
[1327]21  '''soy.atoms.Face
[204]22
[868]23    An element of FaceList with .verts property
[204]24  '''
[1156]25
26  ############################################################################
27  #
28  # Python functions
29  #
30
[1047]31  def __cinit__(self, soy.models.Mesh mesh,
[587]32                verts=None, material=None,
33                index=-1, *args, **keywords) :
[423]34    cdef int i, _mindex
[408]35    self._index = -1
36    self._list = mesh._faces
[1020]37    self._mutex = mesh._mutex
38   
[408]39    if index >= 0 :
[423]40      # For an instance of an existing face
[408]41      if index >= self._list._arraySize :
42        raise ValueError('index out of range')
[1016]43      self._list._children._append(<void*> self)
[408]44      self._index = index
45    else :
46      # For a brand new face
[423]47      if not (verts and material) :
48        raise TypeError('must provide verticies and material for a new Face')
49      if not isinstance(material, soy.materials.Material) :
50        raise TypeError('material must be of type soy.materials.Material')
[1020]51      py.PyThread_acquire_lock(self._mutex, 1)
[1018]52      self._list._children._append(<void*> self)
[423]53      self._list._allocArray(self._list._arraySize + 1)
[1018]54      _mindex = mesh._mates._children._index(<void*> material)
[423]55      if _mindex == -1 :
56        #
57        # New material, add face to end of array
58        self._index = self._list._arraySize
[1014]59        _mindex = mesh._mates._children._current
[1018]60        mesh._mates._children._append(<void*> material)
[1232]61        if (<soy.materials.Material> material)._needsTSLVs() :
[1142]62          mesh._mates._hasBumps = mesh._mates._hasBumps + 1
[443]63        py.Py_INCREF(material)
[1014]64        mesh._mates._allocRanges(mesh._mates._children._current)
[423]65        mesh._mates._ranges[_mindex].offset = self._index
66        mesh._mates._ranges[_mindex].length = 1
67        self._list._arraySize = self._list._arraySize + 1
68        self._list._flagUpdated(self._index, 1)
69        #
70      else :
71        #
72        # Existing material, insert face into center of array
73        self._index = mesh._mates._ranges[_mindex].offset + \
74                      mesh._mates._ranges[_mindex].length
75        mesh._mates._ranges[_mindex].length = \
76          mesh._mates._ranges[_mindex].length + 1
77        for i from self._list._arraySize > i >= self._index :
78          self._list._array[i+1] = self._list._array[i]
[1014]79        for i from _mindex < i < mesh._mates._children._current :
[423]80          mesh._mates._ranges[i].offset = mesh._mates._ranges[i].offset + 1
81        self._list._arraySize = self._list._arraySize + 1
82        self._list._flagUpdated(self._index, self._list._arraySize-self._index)
83        #
[1020]84      py.PyThread_release_lock(self._mutex)
[408]85      self.verts = verts
[204]86
[205]87
[408]88  def __dealloc__(self) :
89    if self._index >= 0 :
[1016]90      self._list._children._remove(<void*> self)
[408]91
[217]92
93  def __repr__(self) :
[1156]94    return '<%s>' % self.__class__.__name__
[211]95
96
[1156]97  ############################################################################
98  #
99  # Properties
100  #
101
[211]102  property verts :
[204]103    def __get__(self) :
[408]104      cdef float a, b, c
105      cdef object t
106      cdef soy._datatypes.VertexList _verts
[1047]107      _verts = (<soy.models.Mesh> self._list._mesh)._verts
[1020]108      py.PyThread_acquire_lock(self._mutex, 1)
[408]109      t = (_verts[self._list._array[self._index].a],
110           _verts[self._list._array[self._index].b],
111           _verts[self._list._array[self._index].c])
[1020]112      py.PyThread_release_lock(self._mutex)     
[408]113      return t
[1156]114
[204]115    def __set__(self, value) :
[211]116      cdef int i
[408]117      if type(value) != tuple and type(value) != list :
[204]118        raise TypeError('Must provide a tuple or list')
[408]119      if len(value) != 3 :
[204]120        raise TypeError('Must provide (x,y,z)')
[211]121      for i from 0 <= i < 3 :
122        if type(value[i]) != Vertex :
[408]123          raise TypeError('All three elements must be of type Vertex')
[1020]124      py.PyThread_acquire_lock(self._mutex, 1)
[408]125      self._list._array[self._index].a = (<Vertex> value[0])._index
126      self._list._array[self._index].b = (<Vertex> value[1])._index
127      self._list._array[self._index].c = (<Vertex> value[2])._index
[423]128      self._list._flagUpdated(self._index, 1)
[1020]129      py.PyThread_release_lock(self._mutex)
[443]130
[444]131
[443]132  property material :
133    def __get__(self) :
134      cdef int i
[444]135      cdef soy.materials.Material material
136      cdef soy._datatypes.MaterialList mlist
137      cdef soy._datatypes.Face _face
[1047]138      mlist = (<soy.models.Mesh> self._list._mesh)._mates
[1020]139      py.PyThread_acquire_lock(self._mutex, 1)
[1014]140      for i from 0 <= i < mlist._children._current :
[444]141        if self._index >= mlist._ranges[i].offset and \
142           self._index < mlist._ranges[i].offset + mlist._ranges[i].length :
[1018]143          material = <soy.materials.Material> mlist._children._list[i]
[444]144          break
[1020]145      py.PyThread_release_lock(self._mutex)
[444]146      if material :
147        return material
[443]148      else :
149        return None
[1156]150
[444]151    def __set__(self, soy.materials.Material material) :
152      cdef int i, _mindex, _oldindex
153      cdef soy._datatypes.Face _face
154      cdef soy._datatypes.MaterialList mlist
[1047]155      mlist = (<soy.models.Mesh> self._list._mesh)._mates
[1020]156      py.PyThread_acquire_lock(self._mutex, 1)
[444]157      _mindex = -1
158      _oldindex = self._index
159      _face = self._list._array[self._index]
[1014]160      for i from 0 <= i < mlist._children._current :
[444]161        if self._index >= mlist._ranges[i].offset and \
162           self._index < mlist._ranges[i].offset + mlist._ranges[i].length :
163          _mindex = i
164          break
165      if _mindex == -1 :
[1021]166        py.PyThread_release_lock(self._mutex)
[444]167        raise RuntimeError('This error should never happen.  ' + \
168                           'Please file a ticket on www.pysoy.org')
169      #
170      # First we're going to tackle the MaterialList since it will determine
171      # where in FaceList we need to be.  We start by removing ourselves from
172      # our current location.
173      mlist._ranges[_mindex].length = mlist._ranges[_mindex].length - 1
[1014]174      for i from _mindex < i < mlist._children._current :
[444]175        mlist._ranges[i].offset = mlist._ranges[i].offset - 1
176      if mlist._ranges[_mindex].offset == self._index :
177        if mlist._ranges[_mindex].length == 0 :
178          # If this was the only face using that material, remove it
[1014]179          for i from _mindex < i < mlist._children._current :
[444]180            mlist._ranges[i-1] = mlist._ranges[i]
[1232]181          if (<soy.materials.Material> material)._needsTSLVs() :
[1142]182            mesh._mates._hasBumps = mesh._mates._hasBumps - 1
[1018]183          py.Py_DECREF(<object> mlist._children._list[_mindex])
184          mlist._children._remove(mlist._children._list[_mindex])
[444]185        #else :
186        #  mlist._ranges[_mindex].offset = mlist._ranges[_mindex].offset + 1
187      _mindex = -1
188      #
189      # Now to see if the material we're setting is already in MaterialList
[1014]190      for i from 0 <= i < mlist._children._current :
[1018]191        if <soy.materials.Material> mlist._children._list[i] == material :
[444]192          _mindex = i
193          break
194      if _mindex == -1 :
195        #
[587]196        # New material, add face to end of array (look familiar? see __cinit__)
[444]197        self._index = self._list._arraySize - 1
[1014]198        _mindex = mlist._children._current
[1018]199        mlist._children._append(<void*> material)
[1232]200        if (<soy.materials.Material> material)._needsTSLVs() :
[1142]201          mesh._mates._hasBumps = mesh._mates._hasBumps + 1
[444]202        py.Py_INCREF(material)
[1014]203        mlist._allocRanges(mlist._children._current)
[444]204        mlist._ranges[_mindex].offset = self._index
205        mlist._ranges[_mindex].length = 1
206      else :
207        #
208        # Existing material, make room for ourselves and slide into that group
209        self._index = mlist._ranges[_mindex].offset + \
210                      mlist._ranges[_mindex].length
211        mlist._ranges[_mindex].length = mlist._ranges[_mindex].length + 1
[1014]212        for i from _mindex < i < mlist._children._current :
[444]213          mlist._ranges[i].offset = mlist._ranges[i].offset + 1
214      #
215      # Now that we know where we're going, shift the face array in the
216      # correct direction and flag the array for update.  Oh, and if for some
217      # reason we ended up with the same index, we don't need to do anything
218      if _oldindex < self._index :
219        # We've moved to a later position in the array
220        for i from _oldindex < i <= self._index :
221          self._list._array[i-1] = self._list._array[i]
222        self._list._array[self._index] = _face
223        self._list._flagUpdated(_oldindex, self._index - _oldindex + 1)
224      elif _oldindex > self._index :
225        # We've moved to an earlier position in the array
226        for i from _oldindex > i >= self._index :
227          self._list._array[i+1] = self._list._array[i]
228        self._list._array[self._index] = _face
229        self._list._flagUpdated(self._index, _oldindex - self._index + 1)
[1020]230      py.PyThread_release_lock(self._mutex)
Note: See TracBrowser for help on using the repository browser.