source: src/atoms/Face.pym @ 1232:b81162dc2d12

Revision 1232:b81162dc2d12, 9.3 KB checked in by Arc Riley <arcriley@…>, 7 years ago (diff)

Ticket #955 :

  • enabled basic render cycle for new material system
  • updated models.Shape and shapes example - needs more work for texcoords
  • Canvas now takes responsibility to turn it's own texture on
  • a few additional Pyrex 0.9.8.2 fixes
Line 
1# PySoy's atoms.Face class
2#
3# Copyright (C) 2006,2007,2008 PySoy Group
4#
5#  This program is free software; you can redistribute it and/or modify
6#  it under the terms of the GNU Affero General Public License as published
7#  by the Free Software Foundation, either version 3 of the License, or
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
13#  GNU Affero General Public License for more details.
14#
15#  You should have received a copy of the GNU Affero General Public License
16#  along with this program; if not, see http://www.gnu.org/licenses
17#
18# $Id: Face.pym 1278 2008-05-19 22:57:46Z ArcRiley $
19
20cdef class Face :
21  '''PySoy Face
22
23    An element of FaceList with .verts property
24  '''
25
26  ############################################################################
27  #
28  # Python functions
29  #
30
31  def __cinit__(self, soy.models.Mesh mesh,
32                verts=None, material=None,
33                index=-1, *args, **keywords) :
34    cdef int i, _mindex
35    self._index = -1
36    self._list = mesh._faces
37    self._mutex = mesh._mutex
38   
39    if index >= 0 :
40      # For an instance of an existing face
41      if index >= self._list._arraySize :
42        raise ValueError('index out of range')
43      self._list._children._append(<void*> self)
44      self._index = index
45    else :
46      # For a brand new face
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')
51      py.PyThread_acquire_lock(self._mutex, 1)
52      self._list._children._append(<void*> self)
53      self._list._allocArray(self._list._arraySize + 1)
54      _mindex = mesh._mates._children._index(<void*> material)
55      if _mindex == -1 :
56        #
57        # New material, add face to end of array
58        self._index = self._list._arraySize
59        _mindex = mesh._mates._children._current
60        mesh._mates._children._append(<void*> material)
61        if (<soy.materials.Material> material)._needsTSLVs() :
62          mesh._mates._hasBumps = mesh._mates._hasBumps + 1
63        py.Py_INCREF(material)
64        mesh._mates._allocRanges(mesh._mates._children._current)
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]
79        for i from _mindex < i < mesh._mates._children._current :
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        #
84      py.PyThread_release_lock(self._mutex)
85      self.verts = verts
86
87
88  def __dealloc__(self) :
89    if self._index >= 0 :
90      self._list._children._remove(<void*> self)
91
92
93  def __repr__(self) :
94    return '<%s>' % self.__class__.__name__
95
96
97  ############################################################################
98  #
99  # Properties
100  #
101
102  property verts :
103    def __get__(self) :
104      cdef float a, b, c
105      cdef object t
106      cdef soy._datatypes.VertexList _verts
107      _verts = (<soy.models.Mesh> self._list._mesh)._verts
108      py.PyThread_acquire_lock(self._mutex, 1)
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])
112      py.PyThread_release_lock(self._mutex)     
113      return t
114
115    def __set__(self, value) :
116      cdef int i
117      if type(value) != tuple and type(value) != list :
118        raise TypeError('Must provide a tuple or list')
119      if len(value) != 3 :
120        raise TypeError('Must provide (x,y,z)')
121      for i from 0 <= i < 3 :
122        if type(value[i]) != Vertex :
123          raise TypeError('All three elements must be of type Vertex')
124      py.PyThread_acquire_lock(self._mutex, 1)
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
128      self._list._flagUpdated(self._index, 1)
129      py.PyThread_release_lock(self._mutex)
130
131
132  property material :
133    def __get__(self) :
134      cdef int i
135      cdef soy.materials.Material material
136      cdef soy._datatypes.MaterialList mlist
137      cdef soy._datatypes.Face _face
138      mlist = (<soy.models.Mesh> self._list._mesh)._mates
139      py.PyThread_acquire_lock(self._mutex, 1)
140      for i from 0 <= i < mlist._children._current :
141        if self._index >= mlist._ranges[i].offset and \
142           self._index < mlist._ranges[i].offset + mlist._ranges[i].length :
143          material = <soy.materials.Material> mlist._children._list[i]
144          break
145      py.PyThread_release_lock(self._mutex)
146      if material :
147        return material
148      else :
149        return None
150
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
155      mlist = (<soy.models.Mesh> self._list._mesh)._mates
156      py.PyThread_acquire_lock(self._mutex, 1)
157      _mindex = -1
158      _oldindex = self._index
159      _face = self._list._array[self._index]
160      for i from 0 <= i < mlist._children._current :
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 :
166        py.PyThread_release_lock(self._mutex)
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
174      for i from _mindex < i < mlist._children._current :
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
179          for i from _mindex < i < mlist._children._current :
180            mlist._ranges[i-1] = mlist._ranges[i]
181          if (<soy.materials.Material> material)._needsTSLVs() :
182            mesh._mates._hasBumps = mesh._mates._hasBumps - 1
183          py.Py_DECREF(<object> mlist._children._list[_mindex])
184          mlist._children._remove(mlist._children._list[_mindex])
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
190      for i from 0 <= i < mlist._children._current :
191        if <soy.materials.Material> mlist._children._list[i] == material :
192          _mindex = i
193          break
194      if _mindex == -1 :
195        #
196        # New material, add face to end of array (look familiar? see __cinit__)
197        self._index = self._list._arraySize - 1
198        _mindex = mlist._children._current
199        mlist._children._append(<void*> material)
200        if (<soy.materials.Material> material)._needsTSLVs() :
201          mesh._mates._hasBumps = mesh._mates._hasBumps + 1
202        py.Py_INCREF(material)
203        mlist._allocRanges(mlist._children._current)
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
212        for i from _mindex < i < mlist._children._current :
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)
230      py.PyThread_release_lock(self._mutex)
Note: See TracBrowser for help on using the repository browser.