root/trunk/RBRapier/RBRapier/Renderer/Geometry/NumericVertexArray.c

Revision 658, 12.9 kB (checked in by sholloway, 5 years ago)

*** empty log message ***

Line 
1 /**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2  * ~ License
3  * ~
4  * - The RuneBlade Foundation library is intended to ease some
5  * - aspects of writing intricate Jabber, XML, and User Interface (wxPython, etc.)
6  * - applications, while providing the flexibility to modularly change the
7  * - architecture. Enjoy.
8  * ~
9  * ~ Copyright (C) 2002  TechGame Networks, LLC.
10  * ~
11  * ~ This library is free software; you can redistribute it and/or
12  * ~ modify it under the terms of the BSD style License as found in the
13  * ~ LICENSE file included with this distribution.
14  * ~
15  * ~ TechGame Networks, LLC can be reached at:
16  * ~ 3578 E. Hartsel Drive #211
17  * ~ Colorado Springs, Colorado, USA, 80920
18  * ~
19  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20  *
21  *  Derived from work done by:
22  *          Tom Schwaller     <tom.schwaller@linux-magazin.de>
23  *          Jim Hugunin       <hugunin@python.org>
24  *          David Ascher      <da@skivs.ski.org>
25  *          Michel Sanner     <sanner@scripps.edu>
26  *
27 ***/
28
29 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
30 /*~ Includes                                          */
31 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
32
33 #include "Python.h"
34 #include "arrayobject.h"
35
36 #ifdef MS_WIN32
37 #include <windows.h>
38 #endif
39 #include <math.h>
40 #include <GL/gl.h>
41 #include <GL/glu.h>
42
43 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
44 /*~ Constants and Variables                           */
45 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
46
47 static GLenum GLTypeFromNumericType[] = {
48     GL_UNSIGNED_BYTE,   /* 0 -- Numerc.Character */
49     GL_UNSIGNED_BYTE,   /* 1 -- Numerc.UnsignedInt8 */
50     GL_BYTE,            /* 2 -- Numerc.Int8 */
51     GL_SHORT,           /* 3 -- Numerc.Int16 */
52     GL_UNSIGNED_SHORT,  /* 4 -- Numerc.UnsignedInt16 */
53     GL_INT,             /* 5 -- Numerc.Int32  */
54     GL_UNSIGNED_INT,    /* 6 -- Numerc.UnsignedInt32 */
55     GL_FALSE,           /* 7 -- unknown */
56     GL_FLOAT,           /* 8 -- Numerc.Float32 */
57     GL_DOUBLE,          /* 9 -- Numerc.Float64 */
58     GL_FALSE,           /* 10 -- Numerc.Complex32 */
59     GL_FALSE,           /* 11 -- Numerc.Complex64 */
60
61     GL_FALSE,           /* 12 -- unknown */
62     GL_FALSE,           /* 13 -- unknown */
63     GL_FALSE,           /* 14 -- unknown */
64     GL_FALSE,           /* 15 -- unknown */
65     };
66
67 static PyObject *nvaError = NULL;
68 static PyObject *nvaGLError = NULL;
69
70 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
71 /*~ Macros                                            */
72 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
73
74 #define ASSURE(E,M) if(!(E)) return ErrorReturn(&nvaError, M)
75 #define GLASSURE(E,M) if(!(E)) return ErrorReturn(&nvaGLError, M)
76
77 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
78 /*~ Definitions                                       */
79 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
80
81 static PyObject *ErrorReturn(PyObject** Error, const char *message)
82 {
83     PyErr_SetString(*Error, message);
84     return NULL;
85 }
86
87 static PyObject *nvaVertexArray(PyObject * self, PyObject * args)
88 {
89     GLint size = 0;
90     GLenum type = GL_FLOAT;
91     GLenum _glerr = GL_NO_ERROR;
92     PyObject *objptr = NULL;
93     PyArrayObject *arrayptr = NULL;
94
95     if (!PyArg_ParseTuple(args, "O", &objptr)) return NULL;
96
97     if (objptr == Py_None) {
98         glVertexPointer(0, 0, 0, NULL);
99     } else {
100         ASSURE(PyArray_Check(objptr), "NumericVertexArray assumes a Numeric array object");
101         arrayptr = (PyArrayObject*) objptr;
102         ASSURE(PyArray_ISCONTIGUOUS(arrayptr), "NumericVertexArray assumes contigious Numeric arrays");
103         type = GLTypeFromNumericType[arrayptr->descr->type_num];
104         ASSURE(type!=GL_FALSE, "Numeric type incompatible with OpenGL types");
105         ASSURE(arrayptr->nd > 0, "Numeric scalars are not supported by NumericVertexArray");
106         size = arrayptr->dimensions[arrayptr->nd-1];
107         ASSURE((2 <= size) && (size <= 4), "Invalid size for last dimension of Array.  Expected dimension of 2, 3, or 4.");
108
109         glVertexPointer(size, type, 0, arrayptr->data);
110     }
111
112     GLASSURE((_glerr = glGetError()) == GL_NO_ERROR, gluErrorString(_glerr));
113
114     Py_INCREF(Py_None);
115     return Py_None;
116 }
117
118 static PyObject *nvaColorArray(PyObject * self, PyObject * args)
119 {
120     GLint size = 0;
121     GLenum type = GL_FLOAT;
122     GLenum _glerr = GL_NO_ERROR;
123     PyObject *objptr = NULL;
124     PyArrayObject *arrayptr = NULL;
125
126     if (!PyArg_ParseTuple(args, "O", &objptr)) return NULL;
127
128     if (objptr == Py_None) {
129         glColorPointer(0, 0, 0, NULL);
130     } else {
131         ASSURE(PyArray_Check(objptr), "NumericVertexArray assumes a Numeric array object");
132         arrayptr = (PyArrayObject*) objptr;
133         ASSURE(PyArray_ISCONTIGUOUS(arrayptr), "NumericVertexArray assumes contigious Numeric arrays");
134         type = GLTypeFromNumericType[arrayptr->descr->type_num];
135         ASSURE(type!=GL_FALSE, "Numeric type incompatible with OpenGL types");
136         ASSURE(arrayptr->nd > 0, "Numeric scalars are not supported by NumericVertexArray");
137         size = arrayptr->dimensions[arrayptr->nd-1];
138         ASSURE((3 <= size) && (size <= 4), "Invalid size for last dimension of Array.  Expected dimension of 3 or 4.");
139
140         glColorPointer(size, type, 0, arrayptr->data);
141     }
142
143     GLASSURE((_glerr = glGetError()) == GL_NO_ERROR, gluErrorString(_glerr));
144
145     Py_INCREF(Py_None);
146     return Py_None;
147 }
148
149 static PyObject *nvaNormalArray(PyObject * self, PyObject * args)
150 {
151     GLint size = 0;
152     GLenum type = GL_FLOAT;
153     GLenum _glerr = GL_NO_ERROR;
154     PyObject *objptr = NULL;
155     PyArrayObject *arrayptr = NULL;
156
157     if (!PyArg_ParseTuple(args, "O", &objptr)) return NULL;
158
159     if (objptr == Py_None) {
160         glNormalPointer(0, 0, NULL);
161     } else {
162         ASSURE(PyArray_Check(objptr), "NumericVertexArray assumes a Numeric array object");
163         arrayptr = (PyArrayObject*) objptr;
164         ASSURE(PyArray_ISCONTIGUOUS(arrayptr), "NumericVertexArray assumes contigious Numeric arrays");
165         type = GLTypeFromNumericType[arrayptr->descr->type_num];
166         ASSURE(type!=GL_FALSE, "Numeric type incompatible with OpenGL types");
167         ASSURE(arrayptr->nd > 0, "Numeric scalars are not supported by NumericVertexArray");
168         size = arrayptr->dimensions[arrayptr->nd-1];
169         ASSURE(3 == size, "Invalid size for last dimension of Array.  Expected dimension of 3.");
170
171         glNormalPointer(type, 0, arrayptr->data);
172     }
173
174     GLASSURE((_glerr = glGetError()) == GL_NO_ERROR, gluErrorString(_glerr));
175
176     Py_INCREF(Py_None);
177     return Py_None;
178 }
179
180 static PyObject *nvaTexCoordArray(PyObject * self, PyObject * args)
181 {
182     GLint size = 0;
183     GLenum type = GL_FLOAT;
184     GLenum _glerr = GL_NO_ERROR;
185     PyObject *objptr = NULL;
186     PyArrayObject *arrayptr = NULL;
187
188     if (!PyArg_ParseTuple(args, "O", &objptr)) return NULL;
189
190     if (objptr == Py_None) {
191         glTexCoordPointer(0, 0, 0, NULL);
192     } else {
193         ASSURE(PyArray_Check(objptr), "NumericVertexArray assumes a Numeric array object");
194         arrayptr = (PyArrayObject*) objptr;
195         ASSURE(PyArray_ISCONTIGUOUS(arrayptr), "NumericVertexArray assumes contigious Numeric arrays");
196         type = GLTypeFromNumericType[arrayptr->descr->type_num];
197         ASSURE(type!=GL_FALSE, "Numeric type incompatible with OpenGL types");
198         ASSURE(arrayptr->nd > 0, "Numeric scalars are not supported by NumericVertexArray");
199         size = arrayptr->dimensions[arrayptr->nd-1];
200         ASSURE((1 <= size) && (size <= 4), "Invalid size for last dimension of Array.  Expected dimension of 1, 2, 3, or 4.");
201
202         glTexCoordPointer(size, type, 0, arrayptr->data);
203     }
204
205     GLASSURE((_glerr = glGetError()) == GL_NO_ERROR, gluErrorString(_glerr));
206
207     Py_INCREF(Py_None);
208     return Py_None;
209 }
210
211 static PyObject *nvaDrawElementsArray(PyObject * self, PyObject * args)
212 {
213     GLenum mode = GL_POINTS;
214     GLint count = 0;
215     GLenum type = GL_UNSIGNED_INT;
216     GLenum _glerr = GL_NO_ERROR;
217     PyObject *objptr = NULL;
218     PyArrayObject *arrayptr = NULL;
219
220     if (!PyArg_ParseTuple(args, "iO", &mode, &objptr)) return NULL;
221
222     ASSURE(PyArray_Check(objptr), "NumericVertexArray assumes a Numeric array object");
223     arrayptr = (PyArrayObject*) objptr;
224     ASSURE(PyArray_ISCONTIGUOUS(arrayptr), "NumericVertexArray assumes contigious Numeric arrays");
225     type = GLTypeFromNumericType[arrayptr->descr->type_num];
226     ASSURE(type!=GL_FALSE, "Numeric type incompatible with OpenGL types");
227     count = PyArray_SIZE(arrayptr);
228
229     glDrawElements(mode, count, type, arrayptr->data);
230
231     GLASSURE((_glerr = glGetError()) == GL_NO_ERROR, gluErrorString(_glerr));
232
233     Py_INCREF(Py_None);
234     return Py_None;
235 }
236
237 static const char* nvaversion = "0.1.0";
238 static const char* nvadocstring = "NumericVertexArray bridge between Numeric and PyOpenGL\n\n" \
239     "PyOpenGL is a wonderful extension to python, allowing nearly direct interfacing with OpenGL in a cross-platform way.\n" \
240     "However, myself and others have encountered a few quirks with VertexArrays and Numeric support, leading to copies (gasp!)\n" \
241     "of large memory blocks.  As you can imagine (or may have experienced) this behavior rapidly degrades performance of\n" \
242     "python applications using large vertex arrays.  Many have tried to correct the problem in the library, myself included,\n" \
243     "yet it remains unsolved.  For me, it was far to difficult to try and patch the existing system in such a way as to insure\n" \
244     "existing code would function, while expunging the data copying code.\n" \
245     "\n" \
246     "So, the approach taken with NumericVertexArray is to reduce the complexity.  Therefore, Numeric extensions are *required*,\n" \
247     "arrays are assumed to be contigious, and data is *never* copied.  The philiosophy is that if a copy is required, an exception\n" \
248     "should be raised instead.  Hopefully, this extension will assist you in your pursuits.  And if not, use the source and make\n" \
249     "something new; or send me a patch.  ;)\n" \
250     "\nEnjoy!\n";
251
252 static PyMethodDef nvamethods[] = {
253     {"VertexArray", nvaVertexArray, METH_VARARGS, "glVertexArray(data) -> None\n\nCalls glVertexPointer(size, type, stride, pointer) where:\n    size = data.shape[-1]\n    type = GLtype corresponding to the Numeric code\n    stride = 0\n    pointer = Numeric array's data pointer\n\nNOTE: Be very careful not to pull the rug out from under the module by changing or deleting the array."},
254     {"ColorArray", nvaColorArray, METH_VARARGS, "glColorArray(data) -> None\n\nCalls glColorPointer(size, type, stride, pointer) where:\n    size = data.shape[-1]\n    type = GLtype corresponding to the Numeric code\n    stride = 0\n    pointer = Numeric array's data pointer\n\nNOTE: Be very careful not to pull the rug out from under the module by changing or deleting the array."},
255     {"NormalArray", nvaNormalArray, METH_VARARGS, "glNormalArray(data) -> None\n\nCalls glNormalPointer(size, type, stride, pointer) where:\n    size = data.shape[-1]\n    type = GLtype corresponding to the Numeric code\n    stride = 0\n    pointer = Numeric array's data pointer\n\nNOTE: Be very careful not to pull the rug out from under the module by changing or deleting the array."},
256     {"TexCoordArray", nvaTexCoordArray, METH_VARARGS, "glTexCoordArray(data) -> None\n\nCalls glTexCoordPointer(size, type, stride, pointer) where:\n    size = data.shape[-1]\n    type = GLtype corresponding to the Numeric code\n    stride = 0\n    pointer = Numeric array's data pointer\n\nNOTE: Be very careful not to pull the rug out from under the module by changing or deleting the array."},
257     {"DrawElementsArray", nvaDrawElementsArray, METH_VARARGS, "DrawElementsArray(mode, data) -> None\n\nCalls glDrawElements(mode, size, type, pointer) where:\n    size = total number of elements in data\n    type = GLtype corresponding to the Numeric code\n    pointer = Numeric array's data pointer."},
258     {NULL, NULL, 0, NULL}
259 };
260
261 #ifdef WIN32
262 __declspec(dllexport)
263 #endif
264 void initNumericVertexArray(void)
265 {
266     PyObject *module = NULL;
267     PyObject *dict = NULL;
268     PyObject *__doc__ = NULL;
269     PyObject *__version__ = NULL;
270
271     /* Initialize our new module */
272     module = Py_InitModule("NumericVertexArray", nvamethods);
273
274     /* Initialize Numeric, because we're going to need it */
275     import_array();
276
277     /* Need to set some variables in the module */
278     dict = PyModule_GetDict(module);
279
280     /* Set error to empty, and allow access from python */
281     nvaError = PyErr_NewException("NumericVertexArray.UsageError", PyExc_EnvironmentError, NULL);
282         nvaGLError = PyErr_NewException("NumericVertexArray.GLerror", PyExc_EnvironmentError, NULL);
283
284     PyDict_SetItemString(dict, "UsageError", nvaError);
285     PyDict_SetItemString(dict, "GLerror", nvaGLError);
286
287     /* Set the docstring */
288     __doc__ = Py_BuildValue("s", nvadocstring);
289     PyDict_SetItemString(dict, "__doc__", __doc__);
290
291     /* Set the version */
292     __version__ = Py_BuildValue("s", nvaversion);
293     PyDict_SetItemString(dict, "__version__", __version__);
294
295     if (PyErr_Occurred())
296        Py_FatalError("can not initialize module NumericVertexArray");
297 }
298
Note: See TracBrowser for help on using the browser.