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

« back to all changes in this revision

Viewing changes to c_src/python/i_face.c

  • 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
 
/*
2
 
 * P3 python wrapper
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
 
/**********************************************
20
 
 * Copyright (C) 2002-2003 Bertrand 'blam' LAMY
21
 
 **********************************************/
22
 
 
23
 
/*================================*
24
 
 * FACE: Python object definition *
25
 
 *================================*/
26
 
 
27
 
void P3_face_raypick (PyObject* face, P3_raypick_data* data, P3_raypickable* parent) {
28
 
  PyObject* o; PyObject* w; PyObject* c;
29
 
  GLfloat* raydata;
30
 
  GLfloat* p;
31
 
  GLfloat r;
32
 
  GLfloat normal[3];
33
 
  int nb; int i;
34
 
  int option;
35
 
  int double_sided = P3_FALSE;
36
 
  o = PyObject_GetAttrString (face, "vertices");
37
 
  nb = PySequence_Size (o);
38
 
  if (nb < 3) return;
39
 
  option = data->option;
40
 
  w = PyObject_GetAttrString (face, "double_sided");
41
 
  if (PyObject_IsTrue (w) == 1) {
42
 
    option &= ~P3_RAYPICK_CULL_FACE;
43
 
    double_sided = P3_TRUE;
44
 
  }
45
 
  Py_DECREF (w);
46
 
  /* get vertices coordinates */
47
 
  c = PyObject_GetAttrString (face, "parent");
48
 
  p = (GLfloat*) malloc (nb * 3 * sizeof (GLfloat));
49
 
  for (i = 0; i < nb; i++) {
50
 
    PyP3_GetPositionInto (PySequence_Fast_GET_ITEM (o, i), (P3_coordsys*) c, p + i * 3);
51
 
  }
52
 
  P3_face_normal (normal, p, p + 3, p + 6); 
53
 
  P3_vector_normalize (normal);
54
 
  raydata = P3_raypickable_get_raypick_data ((P3_raypickable*) c, data);
55
 
  if (nb == 3) {
56
 
    i = P3_triangle_raypick (raydata, p, p + 3, p + 6, normal, option, &r);
57
 
  } else if (nb == 4) {
58
 
    i = P3_quad_raypick (raydata, p, p + 3, p + 6, p + 9, normal, option, &r);
59
 
  } else {
60
 
// TO DO ?
61
 
    P3_error ("raypicking on face with more than 4 vertices is not supported");
62
 
    i = P3_FALSE;
63
 
  }
64
 
  if (data->ret_csys == NULL || fabs (r) < fabs (data->result)) {
65
 
    if (i == P3_RAYPICK_DIRECT) {
66
 
      data->result = r;
67
 
      data->ret_csys = c;
68
 
      memcpy (data->normal, normal, 3 * sizeof (GLfloat));
69
 
    } else if (i == P3_RAYPICK_INDIRECT) {
70
 
      data->result = r;
71
 
      data->ret_csys = c;
72
 
      if (double_sided == P3_TRUE) {
73
 
        data->normal[0] = -normal[0];
74
 
        data->normal[1] = -normal[1];
75
 
        data->normal[2] = -normal[2];
76
 
      } else {
77
 
        memcpy (data->normal, normal, 3 * sizeof (GLfloat));
78
 
      }
79
 
    }
80
 
  }
81
 
  free (p);
82
 
  Py_DECREF (c);
83
 
  Py_DECREF (o);
84
 
}
85
 
 
86
 
int P3_face_raypick_b (PyObject* face, P3_raypick_data* data, P3_raypickable* parent) {
87
 
  PyObject* o; PyObject* w; PyObject* c;
88
 
  GLfloat* raydata;
89
 
  GLfloat* p;
90
 
  GLfloat r; GLfloat normal[3];
91
 
  int nb; int i;
92
 
  int option;
93
 
  o = PyObject_GetAttrString (face, "vertices");
94
 
  nb = PySequence_Size (o);
95
 
  if (nb < 3) { return P3_FALSE; }
96
 
  option = data->option;
97
 
  if (option & P3_RAYPICK_CULL_FACE) {
98
 
    w = PyObject_GetAttrString (face, "double_sided");
99
 
    if (PyObject_IsTrue (w) == 1) option &= ~P3_RAYPICK_CULL_FACE;
100
 
    Py_DECREF (w);
101
 
  }
102
 
  /* get vertices coordinates */
103
 
  p = (GLfloat*) malloc (nb * 3 * sizeof (GLfloat));
104
 
  c = PyObject_GetAttrString (face, "parent");
105
 
  for (i = 0; i < nb; i++) {
106
 
    PyP3_GetPositionInto (PySequence_Fast_GET_ITEM (o, i), (P3_coordsys*) c, p + i * 3);
107
 
  }
108
 
  P3_face_normal (normal, p, p + 3, p + 6); 
109
 
  P3_vector_normalize (normal);
110
 
  raydata = P3_raypickable_get_raypick_data (parent, data);
111
 
  if (nb == 3) {
112
 
    i = P3_triangle_raypick (raydata, p, p + 3, p + 6, normal, option, &r);
113
 
  } else if (nb == 4) {
114
 
    i = P3_quad_raypick (raydata, p, p + 3, p + 6, p + 9, normal, option, &r);
115
 
  } else {
116
 
// TO DO ?
117
 
    P3_error ("raypicking on face with more than 4 vertices is not supported");
118
 
    i = P3_FALSE;
119
 
  }
120
 
  free (p);
121
 
  Py_DECREF (o);
122
 
  return i;
123
 
}
124
 
 
125
 
P3_class P3_class_face = { 
126
 
  P3_ID_FACE,
127
 
  (batch_func)     P3_shape_batch,
128
 
  (render_func)    P3_shape_render,
129
 
  (shadow_func)    0,
130
 
  (raypick_func)   P3_face_raypick,
131
 
  (raypick_b_func) P3_face_raypick_b,
132
 
};
133
 
 
134
 
static int PyP3Face_Init (PyObject* self, PyObject* args, PyObject* kwds) {
135
 
  ((P3_any_object*) self)->class = &P3_class_face;
136
 
        return 0;
137
 
}
138
 
 
139
 
PyTypeObject PyP3Face_Type = {
140
 
  PyObject_HEAD_INIT(NULL)
141
 
  0,
142
 
  "_Face",
143
 
  sizeof(P3_any_object),
144
 
  0,
145
 
  (destructor) PyP3Object_Dealloc,/* tp_dealloc */
146
 
  0,/* tp_print */
147
 
  0,/* tp_getattr */
148
 
  0,/* tp_setattr */
149
 
  0,/* tp_compare */
150
 
  0,/* tp_repr */
151
 
  0,/* tp_as_number */
152
 
  0,/* tp_as_sequence */
153
 
  0,/* tp_as_mapping */
154
 
  0,/* tp_hash */
155
 
  0,/* tp_call */
156
 
  0,/* tp_str */
157
 
  PYP3_GENERIC_GETATTR,/* tp_getattro */
158
 
  0,/* tp_setattro */
159
 
  0,/* tp_as_buffer */
160
 
  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,/* tp_flags */
161
 
  0,/* tp_doc */
162
 
  (traverseproc) 0,/* tp_traverse */
163
 
  (inquiry) 0,/* tp_clear */
164
 
  0,/* tp_richcompare */
165
 
  0,/* tp_weaklistoffset */
166
 
  0,/* tp_iter */
167
 
  0,/* tp_iternext */
168
 
  (PyMethodDef*) 0,//&PyP3Renderable_Methods,/* tp_methods */
169
 
  0,/* tp_members */
170
 
  (PyGetSetDef*) 0,/* tp_getset */
171
 
  0,/* tp_base */
172
 
  0,/* tp_dict */
173
 
  0,/* tp_descr_get */
174
 
  0,/* tp_descr_set */
175
 
  0,/* tp_dictoffset */
176
 
  (initproc) PyP3Face_Init,/* tp_init */
177
 
  PYP3_GENERIC_ALLOC,/* tp_alloc */
178
 
  (newfunc) PyP3Object_New,/* tp_new */
179
 
  PYP3_GENERIC_FREE,/* tp_free */
180
 
};
181
 
 
182
 
 
183
 
/*=====================================*
184
 
 * FACE: C functions about Python face *
185
 
 *=====================================*/
186
 
 
187
 
/*
188
 
int P3_face_get_option (P3_face* f1) {
189
 
  int opt;
190
 
  opt = 0;
191
 
  if (P3_face_is_smoothlit (f1))         { opt |= P3_R_SMOOTHLIT; }
192
 
  if (P3_face_is_alpha (f1))             { opt |= P3_R_ALPHA; }
193
 
  if (P3_face_is_double_sided (f1))      { opt |= P3_R_FRONT_AND_BACK; }
194
 
  if (P3_face_is_static_lit (f1))        { opt |= P3_R_STATIC_LIT; }
195
 
  if (P3_face_is_colored (f1))           { opt |= P3_R_COLORED; }
196
 
  if (!(P3_face_is_solid (f1)))          { opt |= P3_OBJECT_NON_SOLID; }
197
 
  if (!(P3_face_can_be_lit (f1)))        { opt |= P3_R_NEVER_LIT; }
198
 
  if (P3_face_get_material (f1) != NULL) { opt |= P3_R_TEXTURED; }
199
 
  return opt;
200
 
}
201
 
*/
202
 
 
203
 
P3_material* P3_face_get_material (PyObject* face) {
204
 
  PyObject* m;
205
 
  m = PyObject_GetAttrString (face, "material");
206
 
  Py_XDECREF (m);
207
 
  if (m == Py_None) {
208
 
    return NULL;
209
 
  } else {
210
 
    return (P3_material*) m;
211
 
  }
212
 
}
213
 
 
214
 
P3_coordsys* P3_face_get_coordsys (PyObject* face) {
215
 
  P3_coordsys* c;
216
 
  c = (P3_coordsys*) PyObject_GetAttrString (face, "parent");
217
 
  Py_XDECREF (c);
218
 
  if ((PyObject*) c == Py_None) {
219
 
    return NULL;
220
 
  } else {
221
 
    return c;
222
 
  }
223
 
}
224
 
 
225
 
void P3_face_get_box (PyObject* face, GLfloat* box, int* edited) {
226
 
  PyObject* vertex;
227
 
  int nbv;
228
 
  GLfloat coord[3];
229
 
  P3_coordsys* csys;
230
 
  int i;
231
 
  nbv = P3_face_get_vertices_number (face);
232
 
  for (i = 0; i < nbv; i++) {
233
 
    vertex = P3_face_get_vertex (face, i);
234
 
    csys = P3_vertex_get_coordsys (vertex);
235
 
    P3_vertex_get_coord (vertex, coord);
236
 
    P3_point_by_matrix (coord, P3_coordsys_get_root_matrix (csys));
237
 
    if (*edited == P3_FALSE) {
238
 
      *edited = P3_TRUE;
239
 
      memcpy (box,     coord, 3 * sizeof (GLfloat));
240
 
      memcpy (box + 3, coord, 3 * sizeof (GLfloat));
241
 
    } else {
242
 
      if (coord[0] < box[0]) { box[0] = coord[0]; }
243
 
      if (coord[1] < box[1]) { box[1] = coord[1]; }
244
 
      if (coord[2] < box[2]) { box[2] = coord[2]; }
245
 
      if (coord[0] > box[3]) { box[3] = coord[0]; }
246
 
      if (coord[1] > box[4]) { box[4] = coord[1]; }
247
 
      if (coord[2] > box[5]) { box[5] = coord[2]; }
248
 
    }
249
 
  }
250
 
}
251
 
 
252
 
P3_coordsys* P3_vertex_get_coordsys (PyObject* vertex) {
253
 
  P3_coordsys* c;
254
 
  c = (P3_coordsys*) PyObject_GetAttrString (vertex, "parent");
255
 
  Py_XDECREF (c);
256
 
  if ((PyObject*) c == Py_None) {
257
 
    return NULL;
258
 
  } else {
259
 
    return c;
260
 
  }
261
 
}
262
 
 
263
 
void P3_vertex_set_diffuse (PyObject* o, GLfloat* c) {
264
 
  PyObject* tuple;
265
 
  tuple = PyTuple_New (4);
266
 
  PyTuple_SET_ITEM (tuple, 0, PyFloat_FromDouble ((double) c[0]));
267
 
  PyTuple_SET_ITEM (tuple, 1, PyFloat_FromDouble ((double) c[1]));
268
 
  PyTuple_SET_ITEM (tuple, 2, PyFloat_FromDouble ((double) c[2]));
269
 
  PyTuple_SET_ITEM (tuple, 3, PyFloat_FromDouble ((double) c[3]));
270
 
  PyObject_SetAttrString (o, "color", tuple);
271
 
  Py_DECREF (tuple);
272
 
}
273
 
 
274
 
void P3_vertex_set_emissive (PyObject* o, GLfloat* c) {
275
 
  PyObject* tuple;
276
 
  tuple = PyTuple_New (4);
277
 
  PyTuple_SET_ITEM (tuple, 0, PyFloat_FromDouble ((double) c[0]));
278
 
  PyTuple_SET_ITEM (tuple, 1, PyFloat_FromDouble ((double) c[1]));
279
 
  PyTuple_SET_ITEM (tuple, 2, PyFloat_FromDouble ((double) c[2]));
280
 
  PyTuple_SET_ITEM (tuple, 3, PyFloat_FromDouble ((double) c[3]));
281
 
  PyObject_SetAttrString (o, "emissive", tuple);
282
 
  Py_DECREF (tuple);
283
 
}
284
 
 
285
 
PyObject* P3_face_new (P3_world* w, P3_material* material, int nb_v, ...) {
286
 
  va_list ap;
287
 
  PyObject* f;
288
 
  PyObject* list;
289
 
  int i;
290
 
  va_start (ap, nb_v);
291
 
  if (material == NULL) { material = (P3_material*) Py_None; }
292
 
  list = PyList_New (0);
293
 
  for (i = 0; i < nb_v; i++) {
294
 
    PyList_Append (list, va_arg (ap, PyObject*));
295
 
  }
296
 
  f = PyObject_CallMethod (P3Module, "new_face", "OOO", w, list, material);
297
 
#ifdef SAFE_MODE
298
 
  if (PyErr_Occurred () != NULL) { PyErr_Print (); }
299
 
#endif /* SAFE_MODE */
300
 
  va_end (ap);
301
 
  return f;
302
 
}
303
 
 
304
 
PyObject* P3_vertex_new (P3_world* w, GLfloat x, GLfloat y, GLfloat z) {
305
 
  PyObject* v;
306
 
  v = PyObject_CallMethod (P3Module, "new_vertex", "Offf", w, x, y, z);
307
 
  PyObject_SetAttrString (v, "color", Py_None);
308
 
#ifdef SAFE_MODE
309
 
  if (PyErr_Occurred () != NULL) { PyErr_Print (); }
310
 
#endif /* SAFE_MODE */
311
 
  return v;
312
 
}
313
 
 
314
 
#define FUNC_FACE_GET(name, attr) \
315
 
  int P3_face_##name (PyObject* face) { \
316
 
    PyObject* o; \
317
 
    int i = 0; \
318
 
    o = PyObject_GetAttrString (face, attr); \
319
 
    if (o != NULL) { \
320
 
      i = (PyObject_IsTrue (o) == 1); \
321
 
      Py_DECREF (o); \
322
 
    } \
323
 
    return i; \
324
 
  }
325
 
#define FUNC_FACE_IS(name, attr) \
326
 
  int P3_face_##name (PyObject* face) { \
327
 
    PyObject* o; \
328
 
    int i = 0; \
329
 
    o = PyObject_CallMethod (face, attr, NULL); \
330
 
    if (o != NULL) { \
331
 
      i = (PyObject_IsTrue (o) == 1); \
332
 
      Py_DECREF (o); \
333
 
    } \
334
 
    return i; \
335
 
  }
336
 
#define FUNC_FACE_SET(name, attr) \
337
 
  void P3_face_set_##name (PyObject* face, int value) { \
338
 
    PyObject* o; \
339
 
    o = PyInt_FromLong ((long) value); \
340
 
    PyObject_SetAttrString (face, attr, o); \
341
 
    Py_DECREF (o); \
342
 
  }
343
 
#define FUNC_FACE_TRY(name, attr) \
344
 
  int P3_face_##name (PyObject* face) { \
345
 
    PyObject* o; \
346
 
    int i = 0; \
347
 
    if (PyObject_HasAttrString (face, attr)) { \
348
 
      o = PyObject_GetAttrString (face, attr); \
349
 
      i = PyObject_IsTrue (o); \
350
 
      Py_XDECREF (o); \
351
 
    } \
352
 
    return i; \
353
 
  }
354
 
 
355
 
FUNC_FACE_GET (is_smoothlit, "smooth_lit")
356
 
FUNC_FACE_GET (is_double_sided, "double_sided")
357
 
FUNC_FACE_GET (is_solid, "solid")
358
 
FUNC_FACE_GET (is_static_lit, "static_lit")
359
 
FUNC_FACE_GET (can_be_lit, "lit")
360
 
FUNC_FACE_IS  (is_alpha, "is_alpha")
361
 
FUNC_FACE_IS  (is_colored, "is_colored")
362
 
FUNC_FACE_SET (smoothlit, "smooth_lit")
363
 
FUNC_FACE_SET (double_sided, "double_sided")
364
 
FUNC_FACE_SET (solid, "solid")
365
 
FUNC_FACE_SET (static_lit, "static_lit")
366
 
FUNC_FACE_SET (can_be_lit, "lit")
367
 
FUNC_FACE_SET (cell_shading, "cell_shading")
368
 
FUNC_FACE_TRY (cell_shading, "cell_shading")
369
 
 
370
 
#undef FUNC_FACE_GET
371
 
#undef FUNC_FACE_IS
372
 
#undef FUNC_FACE_SET
373
 
#undef FUNC_FACE_TRY
374
 
 
375
 
int P3_face_get_vertices_number (PyObject* face) {
376
 
  PyObject* o;
377
 
  int i = 0;
378
 
  o = PyObject_GetAttrString (face, "vertices");
379
 
  if (o != NULL) {
380
 
    i = PySequence_Size (o);
381
 
    Py_DECREF (o);
382
 
  }
383
 
  return i;
384
 
}
385
 
 
386
 
PyObject* P3_face_get_vertex (PyObject* face, int index) {
387
 
  PyObject* o;
388
 
  PyObject* v = NULL;
389
 
  o = PyObject_GetAttrString (face, "vertices");
390
 
  if (o != NULL) {
391
 
    v = PySequence_Fast_GET_ITEM (o, index);
392
 
    Py_DECREF (o);
393
 
  }
394
 
  return v;
395
 
}
396
 
 
397
 
void P3_face_add_vertex (PyObject* face, PyObject* vertex) {
398
 
  PyObject* o;
399
 
  o = PyObject_GetAttrString (face, "vertices");
400
 
  if (o != NULL) {
401
 
    Py_INCREF (vertex);
402
 
    PyList_Append (o, vertex);
403
 
    Py_DECREF (o);
404
 
  }
405
 
}
406
 
 
407
 
void P3_vertex_get_coord (PyObject* v, GLfloat* ptr) {
408
 
  PyObject* o;
409
 
  o = PyObject_GetAttrString (v, "x");
410
 
  if (o != NULL) {
411
 
    ptr[0] = (GLfloat) PyFloat_AS_DOUBLE (o);
412
 
    Py_DECREF (o);
413
 
  }
414
 
  o = PyObject_GetAttrString (v, "y");
415
 
  if (o != NULL) {
416
 
    ptr[1] = (GLfloat) PyFloat_AS_DOUBLE (o);
417
 
    Py_DECREF (o);
418
 
  }
419
 
  o = PyObject_GetAttrString (v, "z");
420
 
  if (o != NULL) {
421
 
    ptr[2] = (GLfloat) PyFloat_AS_DOUBLE (o);
422
 
    Py_DECREF (o);
423
 
  }
424
 
}
425
 
 
426
 
void P3_vertex_get_texcoord (PyObject* v, GLfloat* ptr) {
427
 
  PyObject* o;
428
 
  o = PyObject_GetAttrString (v, "tex_x");
429
 
  if (o != NULL) {
430
 
    ptr[0] = (GLfloat) PyFloat_AS_DOUBLE (o);
431
 
    Py_DECREF (o);
432
 
  }
433
 
  o = PyObject_GetAttrString (v, "tex_y");
434
 
  if (o != NULL) {
435
 
    ptr[1] = (GLfloat) PyFloat_AS_DOUBLE (o);
436
 
    Py_DECREF (o);
437
 
  }
438
 
}
439
 
 
440
 
void P3_vertex_get_diffuse (PyObject* v, GLfloat* ptr) {
441
 
  PyObject* o;
442
 
  o = PyObject_GetAttrString (v, "color");
443
 
  if (o != NULL && o != Py_None) {
444
 
    PY_TUPLE_FLOAT_TO_ARRAY_4 (ptr, o);
445
 
    Py_DECREF (o);
446
 
  } else {
447
 
    ptr[0] = 1.0;
448
 
    ptr[1] = 1.0;
449
 
    ptr[2] = 1.0;
450
 
    ptr[3] = 1.0;
451
 
  }
452
 
}
453
 
 
454
 
void P3_vertex_get_emissive (PyObject* v, GLfloat* ptr) {
455
 
  PyObject* o;
456
 
  if (PyObject_HasAttrString (v, "emissive")) {
457
 
    o = PyObject_GetAttrString (v, "emissive");
458
 
    if (o != NULL && o != Py_None) {
459
 
      PY_TUPLE_FLOAT_TO_ARRAY_4 (ptr, o);
460
 
      Py_DECREF (o);
461
 
      return;
462
 
    }
463
 
  }
464
 
  ptr[0] = 0.0;
465
 
  ptr[1] = 0.0;
466
 
  ptr[2] = 0.0;
467
 
  ptr[3] = 1.0;
468
 
}
469
 
 
470
 
int P3_vertex_is_morphing (PyObject* v) {
471
 
  PyObject* o;
472
 
  int i;
473
 
  if (PyObject_HasAttrString (v, "morphing") == 1) {
474
 
    o = PyObject_GetAttrString (v, "morphing");
475
 
    i = PyInt_AS_LONG (o);
476
 
    Py_XDECREF (o);
477
 
    return i;
478
 
  }
479
 
  return 0;
480
 
}
481
 
 
482
 
P3_material* P3_vertex_get_material (PyObject* v) {
483
 
  PyObject* m;
484
 
  if (!PyObject_HasAttrString (v, "material")) {
485
 
    return NULL;
486
 
  }
487
 
  m = PyObject_GetAttrString (v, "material");
488
 
  Py_XDECREF (m);
489
 
  if (m == Py_None) {
490
 
    return NULL;
491
 
  } else {
492
 
    return (P3_material*) m;
493
 
  }
494
 
}
495
 
 
496
 
void P3_vertex_set_texcoord (PyObject* v, GLfloat* uv) {
497
 
  PyObject* o;
498
 
  o = PyFloat_FromDouble ((double) uv[0]);
499
 
  PyObject_SetAttrString (v, "tex_x", o);
500
 
  Py_DECREF (o);
501
 
  o = PyFloat_FromDouble ((double) uv[1]);
502
 
  PyObject_SetAttrString (v, "tex_y", o);
503
 
  Py_DECREF (o);
504
 
}