~jtaylor/ubuntu/oneiric/soya/fix-780305

« back to all changes in this revision

Viewing changes to model/cellshading.pyx

  • Committer: Bazaar Package Importer
  • Author(s): Marc Dequènes (Duck)
  • Date: 2005-01-30 09:55:06 UTC
  • mfrom: (1.2.1 upstream) (2.1.1 hoary)
  • Revision ID: james.westby@ubuntu.com-20050130095506-f21p6v6cgaobhn5j
Tags: 0.9.2-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Soya 3D
 
2
# Copyright (C) 2004 Jean-Baptiste LAMY -- jiba@tuxfamily.org
 
3
#
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; either version 2 of the License, or
 
7
# (at your option) any later version.
 
8
#
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public License
 
15
# along with this program; if not, write to the Free Software
 
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
 
 
18
 
 
19
cdef class _CellShadingShape(_SimpleShape):
 
20
  #cdef _Material _shader
 
21
  #cdef float     _outline_color[4]
 
22
  #cdef float     _outline_width, _outline_attenuation
 
23
  
 
24
  cdef __getcstate__(self):
 
25
    cdef Chunk* chunk
 
26
    chunk = get_chunk()
 
27
    chunk_add_float_endian_safe (chunk, self._outline_width)
 
28
    chunk_add_float_endian_safe (chunk, self._outline_attenuation)
 
29
    chunk_add_floats_endian_safe(chunk, self._outline_color, 4)
 
30
    return _SimpleShape.__getcstate__(self), drop_chunk_to_string(chunk), self._shader
 
31
    
 
32
  cdef void __setcstate__(self, cstate):
 
33
    _SimpleShape.__setcstate_data__(self, cstate[0])
 
34
    
 
35
    cdef Chunk* chunk
 
36
    chunk = string_to_chunk(cstate[1])
 
37
    chunk_get_float_endian_safe (chunk, &self._outline_width)
 
38
    chunk_get_float_endian_safe (chunk, &self._outline_attenuation)
 
39
    chunk_get_floats_endian_safe(chunk,  self._outline_color, 4)
 
40
    drop_chunk(chunk)
 
41
    self._shader = cstate[2]
 
42
    
 
43
    # Build the display list data, but don't create the corresponding OpenGL display list
 
44
    self._build_display_list()
 
45
    
 
46
  cdef void _build_cellshading(self, _Material shader, outline_color, float outline_width, float outline_attenuation):
 
47
    cdef int i
 
48
    self._shader              = shader
 
49
    self._outline_width       = outline_width
 
50
    self._outline_attenuation = outline_attenuation
 
51
    for i from 0 <= i < 4: self._outline_color[i] = outline_color[i]
 
52
    
 
53
  cdef void _batch(self, CoordSyst coordsyst):
 
54
    if quality == QUALITY_LOW:
 
55
      _SimpleShape._batch(self, coordsyst)
 
56
      return
 
57
    
 
58
    
 
59
    cdef int      i
 
60
    cdef Frustum* frustum
 
61
    frustum = renderer._frustum(coordsyst)
 
62
    if (self._option & SHAPE_HAS_SPHERE) and (sphere_in_frustum(frustum, self._sphere) == 0): return
 
63
    
 
64
    if self._display_lists.nb_opaque_list != 0: renderer._batch(renderer.opaque, self, coordsyst, -1)
 
65
    if self._display_lists.nb_alpha_list  != 0: renderer._batch(renderer.alpha , self, coordsyst, -1)
 
66
    
 
67
#    # batch each face
 
68
#    for i from 0 <= i < self._nb_faces: self._batch_face(self._faces + i)
 
69
#    pack_batch_end(self, coordsyst)
 
70
 
 
71
    # For outline
 
72
    if self._outline_width > 0.0: renderer._batch(renderer.secondpass, self, coordsyst, 0)
 
73
 
 
74
        
 
75
#   cdef void _render(self, CoordSyst coordsyst):
 
76
#     cdef int      i, start, end
 
77
#     cdef Frustum* frustum
 
78
#     cdef Chunk*   chunk
 
79
#     cdef float*   shades
 
80
    
 
81
#     if renderer.state == RENDERER_STATE_SECONDPASS:
 
82
#       frustum = renderer._frustum(coordsyst)
 
83
#       self._render_outline(frustum)
 
84
#     else:
 
85
#       shape_option_activate(self._option)
 
86
      
 
87
#       chunk = get_chunk()
 
88
#       chunk_register(chunk, self._nb_vnormals * sizeof(float))
 
89
#       shades = <float*> chunk.content
 
90
#       self._prepare_cellshading(coordsyst, shades)
 
91
      
 
92
#       self._pack_render_cellshading(shades)
 
93
#       drop_chunk(chunk)
 
94
#       shape_option_inactivate(self._option)
 
95
      
 
96
      
 
97
#   cdef void _pack_render_cellshading(self, float* shades):
 
98
#     cdef Pack*      pack
 
99
#     cdef ShapeFace* face
 
100
#     cdef _Material  material
 
101
 
 
102
#     # Activate shader texture
 
103
#     glActiveTexture(GL_TEXTURE1)
 
104
#     if self._shader._id == 0: self._shader._init_texture()
 
105
#     glEnable       (GL_TEXTURE_2D)
 
106
#     glTexEnvi      (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)
 
107
#     glBindTexture  (GL_TEXTURE_2D, self._shader._id)
 
108
#     glActiveTexture(GL_TEXTURE0)
 
109
    
 
110
#     pack = <Pack*> chunk_get_ptr(renderer.data)
 
111
#     while pack:
 
112
#       material = <_Material> (pack.material_id)
 
113
#       material._activate()
 
114
      
 
115
#       face_option_activate(pack.option)
 
116
      
 
117
#       face = <ShapeFace*> chunk_get_ptr(renderer.data)
 
118
#       if   pack.option & FACE_TRIANGLE:
 
119
#         glBegin(GL_TRIANGLES)
 
120
#         while face:
 
121
#           self._render_triangle_cellshading(face, shades)
 
122
#           face = <ShapeFace*> chunk_get_ptr(renderer.data)
 
123
          
 
124
#       elif pack.option & FACE_QUAD:
 
125
#         glBegin(GL_QUADS)
 
126
#         while face:
 
127
#           self._render_quad_cellshading(face, shades)
 
128
#           face = <ShapeFace*> chunk_get_ptr(renderer.data)
 
129
          
 
130
#       glEnd()
 
131
      
 
132
#       face_option_inactivate(pack.option)
 
133
#       pack = <Pack*> chunk_get_ptr(renderer.data)
 
134
    
 
135
#     # Unactivate shader texture
 
136
#     glActiveTexture(GL_TEXTURE1)
 
137
#     glDisable(GL_TEXTURE_2D)
 
138
#     glActiveTexture(GL_TEXTURE0)
 
139
    
 
140
    
 
141
  cdef void _render(self, CoordSyst coordsyst):
 
142
    if quality == QUALITY_LOW:
 
143
      _SimpleShape._render(self, coordsyst)
 
144
      return
 
145
    
 
146
    cdef int          i, start, end
 
147
    cdef int*         face_id
 
148
    cdef Frustum*     frustum
 
149
    cdef Chunk*       chunk
 
150
    cdef float*       shades
 
151
    cdef _Material    material
 
152
    cdef DisplayList* display_list
 
153
    
 
154
    if renderer.state == RENDERER_STATE_SECONDPASS:
 
155
      frustum = renderer._frustum(coordsyst)
 
156
      self._render_outline(frustum)
 
157
    else:
 
158
      shape_option_activate(self._option)
 
159
      
 
160
      chunk = get_chunk()
 
161
      chunk_register(chunk, self._nb_vnormals * sizeof(float))
 
162
      shades = <float*> chunk.content
 
163
      self._prepare_cellshading(coordsyst, shades)
 
164
      
 
165
      if renderer.state == RENDERER_STATE_OPAQUE:
 
166
        start = 0
 
167
        end   = self._display_lists.nb_opaque_list
 
168
      else: # Alpha
 
169
        start = self._display_lists.nb_opaque_list
 
170
        end   = start + self._display_lists.nb_alpha_list
 
171
        
 
172
      # Activate shader texture
 
173
      glActiveTexture(GL_TEXTURE1)
 
174
      if self._shader._id == 0: self._shader._init_texture()
 
175
      glEnable       (GL_TEXTURE_2D)
 
176
      glTexEnvi      (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)
 
177
      glBindTexture  (GL_TEXTURE_2D, self._shader._id)
 
178
      glActiveTexture(GL_TEXTURE0)
 
179
      
 
180
      for i from start <= i < end:
 
181
        display_list = self._display_lists.display_lists + i
 
182
        
 
183
        material = <_Material> (display_list.material_id)
 
184
        material._activate()
 
185
        
 
186
        face_option_activate(display_list.option)
 
187
        
 
188
        face_id = display_list.faces_id
 
189
        if   display_list.option & FACE_TRIANGLE:
 
190
          glBegin(GL_TRIANGLES)
 
191
          while face_id[0] != -1:
 
192
            self._render_triangle_cellshading(self._faces + face_id[0], shades)
 
193
            face_id = face_id + 1
 
194
            
 
195
        elif display_list.option & FACE_QUAD:
 
196
          glBegin(GL_QUADS)
 
197
          while face_id[0] != -1:
 
198
            self._render_quad_cellshading(self._faces + face_id[0], shades)
 
199
            face_id = face_id + 1
 
200
            
 
201
        glEnd()
 
202
        
 
203
        face_option_inactivate(display_list.option)
 
204
      
 
205
      # Unactivate shader texture
 
206
      glActiveTexture(GL_TEXTURE1)
 
207
      glDisable      (GL_TEXTURE_2D)
 
208
      glActiveTexture(GL_TEXTURE0)
 
209
        
 
210
        
 
211
      drop_chunk(chunk)
 
212
      shape_option_inactivate(self._option)
 
213
      
 
214
      
 
215
  cdef void _render_outline(self, Frustum* frustum):
 
216
    cdef int        i, j, k, ns, nb
 
217
    cdef float      d
 
218
    cdef float*     plane
 
219
    cdef ShapeFace* face, neighbor_face
 
220
    
 
221
    # Compute outline width, which depends on distance to camera
 
222
    d = sphere_distance_point(self._sphere, frustum.position) * self._outline_attenuation
 
223
    if d < 1.0: d = self._outline_width
 
224
    else:
 
225
      d = self._outline_width / d
 
226
      if d < 2.0: d = 2.0
 
227
      
 
228
    _DEFAULT_MATERIAL._activate()
 
229
    glLineWidth(d)
 
230
    glColor4fv (self._outline_color)
 
231
    glDisable  (GL_LIGHTING)
 
232
    glDepthFunc(GL_LEQUAL)
 
233
    
 
234
    # mark faces as either front or back
 
235
    for i from 0 <= i < self._nb_faces:
 
236
      face = self._faces + i
 
237
      plane = self._values + face.normal
 
238
      if plane[0] * frustum.position[0] + plane[1] * frustum.position[1] + plane[2] * frustum.position[2] + plane[3] > 0.0:
 
239
        face.option = (face.option & ~FACE_BACK ) | FACE_FRONT
 
240
      else:
 
241
        face.option = (face.option & ~FACE_FRONT) | FACE_BACK
 
242
        
 
243
        
 
244
#     # find and draw edges   
 
245
#     glBegin(GL_LINES)
 
246
#     for i from 0 <= i < self._nb_faces:
 
247
#       face = self._faces + i
 
248
#       if face.option & FACE_FRONT:
 
249
#         # test if neighbors are back
 
250
#         for j from 0 <= j < 4:
 
251
#           k = self._neighbors[4 * i + j]
 
252
#           if k != -1:
 
253
#             neighbor_face = self._faces[k]
 
254
#             if neighbor_face.option & FACE_BACK:
 
255
#               # draw edge between vertices k and k + 1
 
256
#               #print "an edge", (face.option & FACE_QUAD), 
 
257
#               #print "  ", i, j, k
 
258
#               #print "  ", face.v[j]
 
259
#               #print "  ", self._vertex_coords[face.v[j]]
 
260
#               glVertex3fv(self._coords + self._vertex_coords[face.v[j]])
 
261
#               #print "  ..."
 
262
              
 
263
#               if ((face.option & FACE_QUAD) and (j < 3)) or (j < 2):
 
264
#                 glVertex3fv(self._coords + self._vertex_coords[face.v[j + 1]])
 
265
#               else:
 
266
#                 glVertex3fv(self._coords + self._vertex_coords[face.v[    0]])
 
267
                
 
268
#     glEnd()
 
269
 
 
270
 
 
271
#     cdef Chunk* chunk
 
272
#     chunk = get_chunk()
 
273
#     chunk_register(chunk, self._nb_coords * sizeof(int))
 
274
#     cdef int* vertex2next
 
275
#     vertex2next = <int*> (chunk.content)
 
276
#     for i from 0 <= i < self._nb_coords: vertex2next[i] = -1
 
277
 
 
278
#     # find edges   
 
279
#     #print "draw edges", self._nb_coords
 
280
#     for i from 0 <= i < self._nb_faces:
 
281
#       face = self._faces + i
 
282
#       if face.option & FACE_FRONT:
 
283
#         # test if neighbors are back
 
284
#         for j from 0 <= j < 4:
 
285
#           k = self._neighbors[4 * i + j]
 
286
#           if k != -1:
 
287
#             neighbor_face = self._faces[k]
 
288
#             if neighbor_face.option & FACE_BACK:
 
289
#               # draw edge between vertices k and k + 1
 
290
#               if ((face.option & FACE_QUAD) and (j < 3)) or (j < 2):
 
291
#                 vertex2next[self._vertex_coords[face.v[j]] / 3] = self._vertex_coords[face.v[j + 1]] / 3
 
292
#               else:
 
293
#                 vertex2next[self._vertex_coords[face.v[j]] / 3] = self._vertex_coords[face.v[0]] / 3
 
294
                
 
295
#     # draw edges
 
296
#     for i from 0 <= i < self._nb_coords:
 
297
#       if vertex2next[i] >= 0:
 
298
#         j = i
 
299
#         glBegin(GL_LINE_STRIP)
 
300
#         while vertex2next[j] >= 0:
 
301
#           glVertex3fv(self._coords + j * 3)
 
302
#           k = vertex2next[j] # Next vertex
 
303
#           vertex2next[j] = -2
 
304
#           j = k
 
305
          
 
306
#         glVertex3fv(self._coords + j * 3)
 
307
#         glEnd()
 
308
        
 
309
 
 
310
 
 
311
 
 
312
 
 
313
    cdef Chunk* chunk
 
314
    chunk = get_chunk()
 
315
    chunk_register(chunk, self._nb_coords * sizeof(int))
 
316
    cdef int* vertex_used
 
317
    vertex_used = <int*> (chunk.content)
 
318
    for i from 0 <= i < self._nb_coords: vertex_used[i] = -1
 
319
    
 
320
    
 
321
    # find and draw edges   
 
322
    glBegin(GL_LINES)
 
323
    for i from 0 <= i < self._nb_faces:
 
324
      face = self._faces + i
 
325
      if face.option & FACE_ALPHA: continue
 
326
      
 
327
      if face.option & FACE_QUAD: nb = 4
 
328
      else:                       nb = 3
 
329
      
 
330
      if face.option & FACE_SMOOTH_LIT:
 
331
        if face.option & FACE_DOUBLE_SIDED:
 
332
          for j from 0 <= j < nb:
 
333
            k = self._neighbors[4 * i + j]
 
334
            if k == -1: # No neighbor, but double-sided face => the face is its own neighbor
 
335
              vertex_used[self._vertex_coords[face.v[j]] / 3] = 1
 
336
 
 
337
              # draw edge between vertices j and j + 1
 
338
              glVertex3fv(self._coords + self._vertex_coords[face.v[j]])
 
339
              if j < nb - 1: glVertex3fv(self._coords + self._vertex_coords[face.v[j + 1]])
 
340
              else:          glVertex3fv(self._coords + self._vertex_coords[face.v[    0]])
 
341
                
 
342
            else:
 
343
              ns = self._neighbors_side[4 * i + j]
 
344
              neighbor_face = self._faces[k]
 
345
              if (
 
346
                (ns == -1) and (((face.option & FACE_FRONT) and (neighbor_face.option & FACE_BACK )) or ((face.option & FACE_BACK) and (neighbor_face.option & FACE_FRONT)))
 
347
                  ) or (
 
348
                (ns ==  1) and (((face.option & FACE_FRONT) and (neighbor_face.option & FACE_FRONT)) or ((face.option & FACE_BACK) and (neighbor_face.option & FACE_BACK)))
 
349
                ):
 
350
                vertex_used[self._vertex_coords[face.v[j]] / 3] = 1
 
351
                
 
352
                # draw edge between vertices j and j + 1
 
353
                glVertex3fv(self._coords + self._vertex_coords[face.v[j]])
 
354
                if j < nb - 1: glVertex3fv(self._coords + self._vertex_coords[face.v[j + 1]])
 
355
                else:          glVertex3fv(self._coords + self._vertex_coords[face.v[    0]])
 
356
                
 
357
        else:
 
358
          if face.option & FACE_FRONT:
 
359
            # test if neighbors are back
 
360
            for j from 0 <= j < nb:
 
361
              k = self._neighbors[4 * i + j]
 
362
              if (k == -1) or (self._faces[k].option & FACE_BACK):
 
363
                vertex_used[self._vertex_coords[face.v[j]] / 3] = 1
 
364
                
 
365
                # draw edge between vertices j and j + 1
 
366
                glVertex3fv(self._coords + self._vertex_coords[face.v[j]])
 
367
                if j < nb - 1: glVertex3fv(self._coords + self._vertex_coords[face.v[j + 1]])
 
368
                else:          glVertex3fv(self._coords + self._vertex_coords[face.v[    0]])
 
369
                
 
370
      else: # Not smoothlit
 
371
        if (face.option & FACE_FRONT) or (face.option & FACE_DOUBLE_SIDED):
 
372
          for j from 0 <= j < nb:
 
373
            # draw edge between vertices j and j + 1
 
374
            glVertex3fv(self._coords + self._vertex_coords[face.v[j]])
 
375
            if j < nb - 1: glVertex3fv(self._coords + self._vertex_coords[face.v[j + 1]])
 
376
            else:          glVertex3fv(self._coords + self._vertex_coords[face.v[    0]])
 
377
            
 
378
    glEnd()
 
379
    
 
380
    glPointSize(d / 2)
 
381
        
 
382
    glBegin(GL_POINTS)
 
383
    for i from 0 <= i < self._nb_coords:
 
384
      if vertex_used[i] == 1: glVertex3fv(self._coords + i * 3)
 
385
    glEnd()
 
386
    
 
387
    
 
388
    drop_chunk(chunk)
 
389
    
 
390
    glLineWidth(1.0) # Reset to default
 
391
    glPointSize(1.0) # Reset to default
 
392
    glEnable   (GL_LIGHTING)
 
393
    glDepthFunc(GL_LESS)
 
394
    glColor4fv (white)
 
395
 
 
396
 
 
397
  cdef float _vertex_compute_cellshading(self, float* coord, float* normal, lights, float shade):
 
398
    cdef _Light light
 
399
    cdef float  ptr[3]
 
400
    cdef float  tmp
 
401
    cdef int    i
 
402
    
 
403
    for light in lights:
 
404
      if light._w == 0.0: # directional light
 
405
        tmp = -vector_dot_product(normal, light._data)
 
406
      else: # positional light
 
407
        ptr[0] = light._data[0] - coord[0]
 
408
        ptr[1] = light._data[1] - coord[1]
 
409
        ptr[2] = light._data[2] - coord[2]
 
410
        vector_normalize(ptr)
 
411
        tmp = vector_dot_product(normal, ptr)
 
412
        
 
413
      shade = shade + tmp
 
414
      
 
415
    return shade
 
416
 
 
417
  cdef void _prepare_cellshading_shades(self, float* shades, lights):
 
418
    cdef _Light light
 
419
    cdef float* ptr1, *ptr2
 
420
    cdef float  v[3]
 
421
    cdef float  tmp
 
422
    cdef int    i, j, k
 
423
    
 
424
    for light in lights:
 
425
      ptr1 = self._vnormals
 
426
      if light._w == 0.0: # directional light
 
427
        for j from 0 <= j < self._nb_vnormals:
 
428
          tmp = -vector_dot_product(ptr1, light._data)
 
429
          shades[j] = shades[j] + tmp
 
430
          ptr1 = ptr1 + 3
 
431
          
 
432
      else: # positional light
 
433
        ptr2 = self._coords
 
434
        for j from 0 <= j < self._nb_vnormals:
 
435
          v[0] = light._data[0] - ptr2[0]
 
436
          v[1] = light._data[1] - ptr2[1]
 
437
          v[2] = light._data[2] - ptr2[2]
 
438
          vector_normalize(v)
 
439
          tmp = vector_dot_product(ptr1, v)
 
440
          shades[j] = shades[j] + tmp
 
441
          ptr1 = ptr1 + 3
 
442
          ptr2 = ptr2 + 3
 
443
          
 
444
  cdef void _prepare_cellshading(self, CoordSyst coordsyst, float* shades):
 
445
    cdef int    n
 
446
    cdef _Light light
 
447
    for light in renderer.top_lights:             light._cast_into(coordsyst)
 
448
    for light in renderer.current_context.lights: light._cast_into(coordsyst)
 
449
    
 
450
    if self._nb_vnormals > 0: # Else the shades are computed at the vertex rendering time, since the shades are not shared (all (coord,normal) couples are different)
 
451
      for n from 0 <= n < self._nb_vnormals: shades[n] = 0.5
 
452
      self._prepare_cellshading_shades(shades, renderer.top_lights)
 
453
      self._prepare_cellshading_shades(shades, renderer.current_context.lights)
 
454
      
 
455
      # clip shade texcoord values
 
456
      for n from 0 <= n < self._nb_vnormals:
 
457
        # do not clip with interval [0, 1] because smooth magnification of texture
 
458
        # causes visual bugs
 
459
        if   shades[n] > 0.95: shades[n] = 0.95
 
460
        elif shades[n] < 0.05: shades[n] = 0.05
 
461
 
 
462
 
 
463
  cdef void _render_triangle_cellshading(self, ShapeFace* face, float* shades):
 
464
    if face.option & FACE_SMOOTH_LIT:
 
465
      self._render_vertex_cellshading_smoothlit(face.v[0], face.option, shades)
 
466
      self._render_vertex_cellshading_smoothlit(face.v[1], face.option, shades)
 
467
      self._render_vertex_cellshading_smoothlit(face.v[2], face.option, shades)
 
468
    else:
 
469
      glNormal3fv(self._values + face.normal)
 
470
      self._render_vertex_cellshading(face.v[0], face.option, self._values + face.normal)
 
471
      self._render_vertex_cellshading(face.v[1], face.option, self._values + face.normal)
 
472
      self._render_vertex_cellshading(face.v[2], face.option, self._values + face.normal)
 
473
 
 
474
  cdef void _render_quad_cellshading(self, ShapeFace* face, float* shades):
 
475
    if face.option & FACE_SMOOTH_LIT:
 
476
      self._render_vertex_cellshading_smoothlit(face.v[0], face.option, shades)
 
477
      self._render_vertex_cellshading_smoothlit(face.v[1], face.option, shades)
 
478
      self._render_vertex_cellshading_smoothlit(face.v[2], face.option, shades)
 
479
      self._render_vertex_cellshading_smoothlit(face.v[3], face.option, shades)
 
480
    else:
 
481
      glNormal3fv(self._values + face.normal)
 
482
      self._render_vertex_cellshading(face.v[0], face.option, self._values + face.normal)
 
483
      self._render_vertex_cellshading(face.v[1], face.option, self._values + face.normal)
 
484
      self._render_vertex_cellshading(face.v[2], face.option, self._values + face.normal)
 
485
      self._render_vertex_cellshading(face.v[3], face.option, self._values + face.normal)
 
486
 
 
487
 
 
488
  # XXX face_option arg is useless
 
489
  cdef void _render_vertex_cellshading_smoothlit (self, int index, int face_option, float* shades):
 
490
    cdef int    n
 
491
    cdef float* coord
 
492
    cdef float  shade
 
493
    n     = self._vertex_coords[index]
 
494
    coord = self._coords + n
 
495
    
 
496
    if face_option & FACE_NON_LIT:
 
497
      shade = 0.5 # Medium shade
 
498
    else:
 
499
      shade = shades[n / 3]
 
500
    
 
501
    if self._option & SHAPE_DIFFUSES : glColor4fv   (self._colors   + self._vertex_diffuses [index])
 
502
    if self._option & SHAPE_EMISSIVES: glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, self._colors + self._vertex_emissives[index]) # XXX use glColorMaterial when emissive color but no diffuse ?
 
503
    if self._option & SHAPE_TEXCOORDS:
 
504
      glMultiTexCoord2fv(GL_TEXTURE0, self._values + self._vertex_texcoords[index])
 
505
      glMultiTexCoord2f (GL_TEXTURE1, shade, shade)
 
506
    else: glTexCoord2f(shade, shade)
 
507
    
 
508
    glNormal3fv(self._vnormals + n)
 
509
    glVertex3fv(coord)
 
510
    
 
511
  # XXX face_option arg is useless
 
512
  cdef void _render_vertex_cellshading(self, int index, int face_option, float* fnormal):
 
513
    cdef float* coord
 
514
    cdef float  shade
 
515
    coord = self._coords + self._vertex_coords[index]
 
516
    
 
517
    if face_option & FACE_NON_LIT:
 
518
      shade = 0.5 # Medium value
 
519
    else:
 
520
      shade = self._vertex_compute_cellshading(coord, fnormal, renderer.top_lights, 0.5)
 
521
      shade = self._vertex_compute_cellshading(coord, fnormal, renderer.current_context.lights, shade)
 
522
      if   shade < 0.05: shade = 0.05
 
523
      elif shade > 0.95: shade = 0.95
 
524
      
 
525
    if self._option & SHAPE_DIFFUSES : glColor4fv  (self._colors   + self._vertex_diffuses [index])
 
526
    if self._option & SHAPE_EMISSIVES: glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, self._colors + self._vertex_emissives[index]) # XXX use glColorMaterial when emissive color but no diffuse ?
 
527
    if self._option & SHAPE_TEXCOORDS:
 
528
      glMultiTexCoord2fv(GL_TEXTURE0, self._values + self._vertex_texcoords[index])
 
529
      glMultiTexCoord2f (GL_TEXTURE1, shade, shade)
 
530
    else: glTexCoord2f(shade, shade)
 
531
    
 
532
    glVertex3fv(coord)
 
533
    
 
534
  
 
535