Thread: [PyOpenGL-Users] best way to set up matrices and vertex arrays?
Brought to you by:
mcfletch
From: Kolja K. <kol...@av...> - 2010-03-09 11:10:35
|
Hi all, I've recently discovered PyOpenGL and am quite happy with this package (kudos to the authors!). It's just great for prototyping on different platforms. I keep struggling with how I should best represent vertex data and matrices, though. Here are some of my favorite problems: - Row-major vs. column-major matrices. With the default row-major layout used by numpy, I always have to pass in matrices as the transpose of what I expect. I found out I can create numpy arrays with 'F' order, but I still have to transpose matrices I get back from PyOpenGL, it seems. - What's a good way to build a dynamically growing vertex array? Sort of the equivalent of a std::vector<Vec3f> in C++, with struct Vec3f { float p[3]; }. Currently, I am setting up an array with shape(n,3) and concatenate another array of length 3 to it. It looks horrible in code (sorry, I can't remember the syntax right now), and I believe it's always making a copy. - My hope was to avoid having to do my own 3D-vector- and matrix-classes for doing linear algebra, and just use numpy's abilities. It turns out that this is not always so effortless - e.g. to multiply a matrix with a vector from the right, I have to make sure it's a column vector. To transform a 3D vector with a 4x4 matrix, I have to append an extra 1.0 element, do the multiplication, and then slice off the 4th element again. Looks like it would be cleaner to write out the whole matrix/vector multiplication by hand. Does anyone here have some advice for me on these matters? Maybe I am just missing "the obvious way" to organize these things. Thanks, -Kolja |
From: Dan H. <Dan...@no...> - 2010-03-09 18:14:08
|
Kolja Kaehler wrote: > Does anyone here have some advice for me on these matters? Maybe I am > just missing “the obvious way” to organize these things. Hi Kolja, I haven't had any problems using NumPy's row-major arrays with PyOpenGL. For instance if you have a row-major NumPy array of dtype [ ( "x", np.float32 ), ( "y", np.float32 ) ], you can pass the array directly to PyOpenGL by putting it in a vertex buffer object and then using glVertexPointer( 2, gl.GL_FLOAT, 0, None ) to tell GL to expect 2 floats for each vertex. The same principle works for 3D as well. And if you'd like to store several pieces of NumPy array data together, then you can just use a recarray, and then pass an individual "member" array to PyOpenGL at any point you want. Perhaps you can give an example of what you're trying to do where the row-major/column-major distinction gets in the way? There really isn't a good way to dynamically grow a vertex array with NumPy. Some options are: * Use numpy.resize(), which just returns a new, larger array copy. * Use numpy.ndarray.resize(), which can only resize if there are no other references to the array. * Accumulate and grow with a data structure other than a NumPy array, and then convert to a NumPy array when you're done growing. Some candidates are a Python list (slow), or if you're willing to use Cython or C, then accumulate in a C array with realloc() for growing. I haven't really used NumPy matrices, so I'll let someone else comment on that one. Dan |
From: Ian M. <geo...@gm...> - 2010-03-09 20:45:59
|
On Tue, Mar 9, 2010 at 2:58 AM, Kolja Kaehler <kol...@av...>wrote: > - My hope was to avoid having to do my own 3D-vector- and > matrix-classes for doing linear algebra, and just use numpy’s abilities. It > turns out that this is not always so effortless – e.g. to multiply a matrix > with a vector from the right, I have to make sure it’s a column vector. To > transform a 3D vector with a 4x4 matrix, I have to append an extra 1.0 > element, do the multiplication, and then slice off the 4th element again. > Looks like it would be cleaner to write out the whole matrix/vector > multiplication by hand. > Scale and rotate matrices need only be 3x3 matrices. Translation matrices, which must be 4x4, can instead be expressed as simple addition: e.g., vertex_array += array([1,2,6]) You might also want to consider keeping your vertices as vec4s--that's how OpenGL stores vertices interally, even if you only define the x and y, or the x,y, and z coordinates. You may also consider using OpenGL's own matrix system. It's technically deprecated--but it's still an awes Ian |
From: Greg E. <gre...@ca...> - 2010-03-09 23:36:58
|
Kolja Kaehler wrote: > - Row-major vs. column-major matrices. With the default > row-major layout used by numpy, I always have to pass in matrices as the > transpose of what I expect. I found out I can create numpy arrays with > ‘F’ order, but I still have to transpose matrices I get back from > PyOpenGL, it seems. You might like to consider just working with the transposed arrays as they are. Thinking about this recently, I realised that the OpenGL order may actually be more convenient for some things, such as transforming an array of vertices. With a transposed matrix, you can do A*M, where A is an n-by-4 array. With a non-transposed matrix, you would have to do M*A and transpose A into a 4-by-n array. > - What’s a good way to build a dynamically growing vertex > array? ... Currently, I am setting up an array with > shape(n,3) and concatenate another array of length 3 to it. ... I > believe it’s always making a copy. Yes, that will be horribly inefficient. I would build up a list of vertices first, and then convert the whole list to an array in one go. > To transform a 3D vector with a 4x4 matrix, I have to append an > extra 1.0 element, do the multiplication, and then slice off the 4^th > element again. Another way is to work with 4-element vectors throughout. -- Greg |