Re: Surface batch methods... Re: [pygame] API draft for vector type
On Apr 28, 2009, at 11:09 PM, René Dudfield wrote: [..] fill_multi might look like this: Surface.fill_multi(color, rects, special_flags=0) Basically the same as the fill() except the first two arguments accept buffer objects that are arrays of colors and rects respectively. I think it would be best if color accepted both a single color value or an array of RGBA values. I think supporting only RGBA (as 4-byte words) is good enough and the alpha would just be ignored if the surface did not support it. Though this would preclude indexed color surfaces. I'm open to opinion on this. If color is an array, it would need to be the same length as rects to keep things simple. Otherwise it would raise an exception (ValueError?). blit_multi would be: Surface.blit_multi(source, dests, area=None, special_flags=0) source is a single surface, dests is an buffer array of x, y coordinate ints, or maybe a RectArray, see below. Area is a single rect, for now, but I could imagine supporting an array of rects for advanced use (sprite- sheet, etc). Seems like we would want a RectArray object to allow creation and some manipulation and passing of rectangles en-masse from python, though maybe that's overkill for a first rev. I'm going to check out 1.9 now and see how it looks. I remember looking at doing something similar in pygame from the lepton side and deciding it was not too practical from an outside library. But, given these apis it would be easy. I suspect the fill_multi() implementation will be more complex, we'll see. -Casey Sounds pretty good. A common use case for blit_multi would be when you are blitting a whole group of sprites to the screen. But you don't necessarily have to complete each use case to start with... as long as the interface raises exceptions when people try, and mention it in the docs. I think it would be relatively easy to let source be a sequence of surfaces whose length must equal dests. OTOH, I'm not exactly sure if this is more or less convenient then just batching your sprites by surface and calling blit_multi for each batch. OTOOH, it would be very useful for mass blitting many animated sprites, a feature I just added to the OpenGL Lepton renders that would be very cool to also be able to do efficiently in pygame. So, I think it would be worth it. One issue might be... Surface.fill_multi(color, rects, special_flags=0) With color it can be a single int, or (0,0,0) or (0,0,0,0). So I think the sequences would have to be len(rects) == len(color) Except if you have 3-4 colors + rects... ([1,2,3], [r1,r2,r3]) then the color argument has an ambiguity of either 3 colors, or 1 color. So perhaps explicit length of arguments? Or a separate color and colors argument? I was thinking this would be determined by if the color value passed supported the buffer protocol, but that may be too magical and ambiguous. I think the one color for all rects use-case is worth supporting for convenience. perhaps changing the signature to all keywords would suffice: Surface.fill_multi(color=None, rect_array=None, color_array=None, special_flags=0) The crummy part being that rect_array is not really optional and one of color or color_array must be specified. This would of course be enforced by the api, but is a bit unintuitive. Then again calling it with positional args would work more or less as expected and it would only get slightly more verbose when you used a color_array. We would basically have the same problem with the blit_multi, if it accepted both a single source surface and a sequence. So it would be good to make them consistent. Also, I was assuming that color_array (aka colors) and rect_array (aka rects) would only accept array buffers and not arbitrary sequences of Color, Rect or tuple, but you seem to be implying support for the latter. Is that right? -Casey
Re: [pygame] API draft for vector type
On, Tue Apr 28, 2009, Jake b wrote: On Tue, Apr 28, 2009 at 2:48 PM, Marcus von Appen m...@sysfault.org wrote: On, Tue Apr 28, 2009, Lorenz Quack wrote: Casey Duncan ca...@pandora.com: Degrees, I'd say. The api should be easy to use and letting users calculate the rad values before is not that intuitive. I just checked: unfortunately pygame seems to be inconsistent: transform.rotate use degrees and draw.arc uses radians. Which is a problem to get solved. Thus we should stick to degrees. I thought the standard was to use radians since trig. functions use radians. ( And opengl? ) OpenGL uses degrees - which brings me (personally) to use degrees, too. Additionally it's easier to read and debug, if you work with degrees, in my opinion, bceause you do not have to fire up your calculator and convert the angular values the whole time. What do you find easier to understand for angles? 1.5707963267948966 or ~90.0? ;-) I'm Curious: if pygame uses degrees, does it end up being faster than if pygame used radians, and the user has to manually convert to degrees? Or is the difference insignificant? It is mostly insignificant, though the user would save one call to a python function (and python's math module). Converting degrees to radians is described as rad = degrees * pi / 180.0 So it's a single multiplication and division. You can narrow that down to a single multiplication, which python does and we can do as well. The only difference thus would be the user's math.radians() call overhead. Regards Marcus pgpMJ3hjTklIv.pgp Description: PGP signature
Re: Surface batch methods... Re: [pygame] API draft for vector type
Quoting Casey Duncan ca...@pandora.com: Also, I was assuming that color_array (aka colors) and rect_array (aka rects) would only accept array buffers and not arbitrary sequences of Color, Rect or tuple, but you seem to be implying support for the latter. Is that right? Hi Casey, See _arraysurfarray.c for an example of using the array interface. Unlike a simple buffer it gives information on shape and item type. So object testing is much more thorough and safe. Both Numeric and Numpy support the array interface. And the Python 3 buffer interface is also supposed to provide similar information. -- Lenard Lindstrom le...@telus.net
Re: [pygame] API draft for vector type
On, Mon Apr 27, 2009, Lorenz Quack wrote: [...] Some general notes in short, which the other thread repliers already pointed out: Vector2d is needed Vector3d is needed, too (at least for me), to have 2d/3d transformations. Vector4d can be realised using the 'w' property easily in your Vector3d class. Vector2d is basically Vector3d without considering a z component. Daniel Jo ost...@gmail.com: Vector classes work well for convenience and code readability, but from a performance standpoint they aren't very useful. Right, that's what batch operations are suitable for. Lorenz' proposal mentions e.g. creating vectors from sequence types. If we add a set of helper functions to the module (pygame.math.do_stuff (many_vectors)), we can easily get around that issue. This only requires us to keep the internally optimised methods separated well enough. Casey Duncan ca...@pandora.com: array of C structs, but you can iterate them and access the individual vectors for position, velocity, etc. from python. The proposed math helper functions thus should be suitable to operate on array() objects or buffers, where the type and object size has to be explicitily stated. We then can get equal results easily. Brian Fisher: One aspect of vector class design that I've become more and more a fan of over time is vector immutability. Seconded. Casey Duncan ca...@pandora.com: PEP-8 for method and property naming! Seconded. Rene Dudfield ren...@gmail.com What number types are used? eg, can you have a float vector, a long vector, an int vector? Any python number? A uint8 ? I'd vote for two major types here: long/int and float. Depending on what the passed values are. If we argue to use 'any python number', we'll have to refer to the number protocol anytime an arithmetic function occurs. This makes anything painfully slow. If the passed values are all int or long, the vector might be handled as long/int vector with matching optimised functions. if the numbers are all float, other matching optimised functions might be used. However, those considerations should be handled later on. To implement such hooks is a bit complex due to the behaviour specification. For now I'd vote for using either float (double) as internal representation (for being exact enough) and/or two vector types: FVector (floating point) LVector (long/int) 1.5.4.1 v.isNormalized() - bool 1.5.4.2 v.normalize() - None# normalizes inplace 1.5.4.3 v1.normalized() - v2# returns normalized vector In my opinion normalize() and normalized() are far too ambiguous. We might should use something like ip_XXX() for inplace operations: v.ip_normalize () - None v.normalize () - v2 We do that naming already for Rect objects and should take care of doing that anywhere where inplace operations happen. The same then applies to the rest of your inplace methods. 1.6 properties == 1.6.1.1 v.length - a # gets the magnitude/length of the vector 1.6.1.2 v.length = a # sets the length of the vector while preserving its direction The setter might be risky due to rounding issues. 1.6.2.1 a) v.lengthSquared - a b) v.length2 - a # gets the squared length of the vector. same as v.dot(v) or v * v 1.6.2.1 a) v.lengthSquared = a b) v.length2 = a # sets the squared length of the vector. preserving its direction Same as above. 1.7 comparison operations = 1.7.0the == and != and bool operater compare the differences against the attribute v._epsilon. this way the user can adjust the accuracy. 1.7.1.1 v == s - bool # true if all component differ at most by v._epsilon How am I as user supposed to manipulate _epsilon? It should be made public. 1.8 misc == 1.8.1 support iter protocol 1.8.2 str(v) - [x, y, z] 1.8.3 repr(v) - Vecx, y, z Most objects have the same output for str() and repr(). Why do you differ here? 1.10 open questions (in no particular order) 1.10.1 a) use radians for all angles b) use degrees for all angles Degrees, I'd say. The api should be easy to use and letting users calculate the rad values before is not that intuitive. 1.10.2 what about slicing? Slicing in a fixed 1-column matrix sounds useless to me. 1.10.4 do we need int or complex vectors? A specialised int vector class would be nice for even more optimised code, but (in my opinion) that can be considered in a later stage. Most of the time it's just about replacing C floating point functions with the matching integer functions. 1.10.5 what about negative indices in the sequence protocol? Required as supported by the Python standard. The sequence protocol is pretty easy to implement and usually you receive a nicely converted positive Py_ssize_t, if it is within the range. Take a look at the PixelArray and Color classes, which implement sequence
Re: [pygame] API draft for vector type
Hi, thanks for the feedback and suggestions. That said, I just realized that I never really introduced myself. So here it goes: I'm a physics student from germany. I took some programming classes of questionable quality in school. I really started of with C++ in 2003 and maybe a year and a half later with python and once I got over the fact that whitespaces matter it blew my mind! Now I'm working on my final thesis (german: Diplomarbeit) and teach a beginners course on C++. That and a few other activities take quite some of my time but everything else is dedicated to bringing vector types to pygame =) But don't think I jumped ship if I don't respond instantly. I'm just occupied with other affairs. so enough of that. let's get down to business. René Dudfield wrote: On Tue, Apr 28, 2009 at 2:52 PM, Casey Duncan ca...@pandora.com mailto:ca...@pandora.com wrote: On Apr 27, 2009, at 6:16 PM, René Dudfield wrote: Would be nice if the vectors storage of things could be anything underneath. This would be useful to allow them to use pygame.Rect or numpy.array underneath. This means they can refer to a batch of vectors, but also operate only on a single vector at a time. +1, though there are performance vs. generality tradeoffs to be made. On the general side, a vector class could assume the underlying storage supports __getitem__, but the performance of this would suffer, I think too greatly. On the performance side, it could just have a pointer to an array of floats that it wraps with the vector api. I used this strategy with Lepton and the performance is great, but it is inflexible for the storage, and probably not very practical for totally general use across different storages. ah, that's an interesting point. We could have a few special cases for giving a buffer to use. Then as it's written in C, there will only be one pointer indirection. I'm not sure I understand what you#re discussing here. Are you suggesting, that one should be able to store any python object in the vector components? For now I only considered numbers either double or int/long. If I understood you correctly, what would be a use case of a vector class holding arbitrary objects? Are you thinking in the lines of something like this: # create in this case a 5-dimensional vector with obj positions positions = Vector([(1,2,3), (2,3,4), (3,4,5), (4,5,6), (7,8,9)]) # create velocities for each object velocities = Vector([(2,0,0), (0,3,1), (0,1,0), (-5,0,.5), (1,1,1)]) for timeslice in game.tick(): positions += timeslice * velocities ...this is interesting. As I said, until now I only considered normal math vectors. But as you already pointed out there would definitely be a speed penalty. Wondering about why only 3 element vectors? 2,3, and 4 element ones are common? Yea, 2 and 4 dimensions shouldn't be a problem. I only proposed a API for 3 dimensions because it's usually the richest. for example you don't have a cross-product in 4 dimensions. and I figured that if I wrote the whole thing for 2 and 4 dims as well it would have become a bit confusing. but fear not 2 and 4 dimensions are on the list :) Is there a way to make a combined 2,3,4 type? Most operations can assume the higher dimensions are always zero, or the length could just be variable. But in either case the code would be slower than it would strictly need to be, since many operations would do more work than needed or would require loops where they would not be required for single purpose 2D, 3D or better vectors. Exactly what Casey wrote. What number types are used? eg, can you have a float vector, a long vector, an int vector? Any python number? A uint8 ? Seems to me like the most general number type would be a double, as it could comfortably support a wide range, does not generally have resolution issues like a 32-bit float can and performs well on modern hardware. It would also give consistent results compared to a python float, which is nice. I'm not sure what the use-case is for ints or (python) longs, the latter would probably gain little by being coded in C compared to pure python. Even in sprite-based 2D games, I find integers to be far too coarse for vector math, and operations like normalize become basically impossible. If you support multiple vector numeric types, than you have to confront a combinatorial explosion of type conversions and either duplicate, templatize or generalize the code in such a way that you trade either performance or maintainability or both. -Casey Yeah, indeed. Old numeric used to auto-generate most of its code for different types. Also there is vectypes written in python that generates it's code for all of the different types ( http://code.google.com/p/vectypes/ ).
Re: [pygame] API draft for vector type
Hi, as I already wrote in my other mail. thanks for the feedback! Marcus von Appen wrote: On, Mon Apr 27, 2009, Lorenz Quack wrote: [...] Some general notes in short, which the other thread repliers already pointed out: Vector2d is needed Vector3d is needed, too (at least for me), to have 2d/3d transformations. Vector4d can be realised using the 'w' property easily in your Vector3d class. Vector2d is basically Vector3d without considering a z component. I believe 3d is the most work and 2d is a trivial dumbing down and 4d is a trivial expansion while leaving out some special methods like v.cross(). Daniel Jo ost...@gmail.com: Vector classes work well for convenience and code readability, but from a performance standpoint they aren't very useful. Right, that's what batch operations are suitable for. Lorenz' proposal mentions e.g. creating vectors from sequence types. If we add a set of helper functions to the module (pygame.math.do_stuff (many_vectors)), we can easily get around that issue. This only requires us to keep the internally optimised methods separated well enough. seems like you already have this worked out in your head. but module-level batch functions sound like a good idea (even though I don't know how to actually implement that, yet). Casey Duncan ca...@pandora.com: array of C structs, but you can iterate them and access the individual vectors for position, velocity, etc. from python. The proposed math helper functions thus should be suitable to operate on array() objects or buffers, where the type and object size has to be explicitily stated. We then can get equal results easily. just for clarity: do you mean that the helper functions should operate on arrays (numpy arrays?) of vectors of regular numbers. something like this: v1 = Vector3d((1, 2, 3)) v2 = Vector3d((-4, 5.6, 7)) a = array(v1, v2) axis = Vector3d((1,0,0)) angle = 90 #degrees pygame.math.rotateBatch(axis, angle, a) ? Brian Fisher: One aspect of vector class design that I've become more and more a fan of over time is vector immutability. Seconded. interesting. I need to see more code using immutable vectors to be totally convinced. Casey Duncan ca...@pandora.com: PEP-8 for method and property naming! Seconded. +1. I'm for standard compliance. I just used my own style while writing the draft without thinking. but you're totally right. Rene Dudfield ren...@gmail.com What number types are used? eg, can you have a float vector, a long vector, an int vector? Any python number? A uint8 ? I'd vote for two major types here: long/int and float. Depending on what the passed values are. If we argue to use 'any python number', we'll have to refer to the number protocol anytime an arithmetic function occurs. This makes anything painfully slow. If the passed values are all int or long, the vector might be handled as long/int vector with matching optimised functions. if the numbers are all float, other matching optimised functions might be used. However, those considerations should be handled later on. To implement such hooks is a bit complex due to the behaviour specification. For now I'd vote for using either float (double) as internal representation (for being exact enough) and/or two vector types: FVector (floating point) LVector (long/int) +1 on floating point vectors (though using double precision). +0 on int/long. I would like to see some use cases of int vectors. -1 on the names. I think floating point is the thing users normally want so I would call that Vector, Vector3d or whatever. The int vector is a special case and therefore wait in second line with a name like IVector (in python3 we only have int so I would go for the I instead of the L) 1.5.4.1 v.isNormalized() - bool 1.5.4.2 v.normalize() - None# normalizes inplace 1.5.4.3 v1.normalized() - v2# returns normalized vector In my opinion normalize() and normalized() are far too ambiguous. We might should use something like ip_XXX() for inplace operations: v.ip_normalize () - None v.normalize () - v2 We do that naming already for Rect objects and should take care of doing that anywhere where inplace operations happen. The same then applies to the rest of your inplace methods. hm. ok. but the ip is after the name: v.normalize_ip() 1.6 properties == 1.6.1.1 v.length - a # gets the magnitude/length of the vector 1.6.1.2 v.length = a # sets the length of the vector while preserving its direction The setter might be risky due to rounding issues. true, but I think this can be very usefull. and I can live with the fact that v.length = 1. v.length == 1. # - false when dealing with floating point variables you have to expect weird behavior like this. 1.6.2.1 a) v.lengthSquared - a b) v.length2 - a # gets the squared length of the vector. same as v.dot(v) or v * v 1.6.2.1 a) v.lengthSquared = a b) v.length2 = a #
Re: [pygame] API draft for vector type
Surface.fill_multi and Surface.blit_multi would be awesome for particle effects, in fact I could take good advantage of them in Lepton right now to make the pygame renderers mucho-faster. Would that be something that would be considered in pgreloaded (or even pygame 1.9)? If so I would be interested in helping to implement them as I would be an early adopter ;^) -Casey On Apr 27, 2009, at 11:38 PM, René Dudfield wrote: hi again, a slightly related point... consider that pygame already works with big multidimensional vectors of a limited amount of types - this is Surface. However it is limited to 1, 2, 3, and 4 uint8 multi dimensional vectors. For these limited cases it is fairly fast. It should be possible to make some sorts of really basic particle systems with Surface I guess. Having one image for positions, one for direction vectors, one for lifetime etc. To update the movement each frame, you'd use: position_surf.blit(directions_surf, (0,0), special_flags=BLEND_ADD) Would still need a fast way to draw each particle based on the pixels in each surface. If pygames functions/methods took more arrays it could be possible... eg. a Surface.blit_multi which took a buffer of destination rects. On Tue, Apr 28, 2009 at 3:06 PM, Casey Duncan ca...@pandora.com wrote: I have found this to be generally true as well, and storing a large number of individual vector objects to be operated on in a batch performs poorly regardless of implementation language. As an example, for Lepton I coded a controller object which looped over a large number of particles to update their velocities. Under the covers the particles are stored as a simple array of C structs, but you can iterate them and access the individual vectors for position, velocity, etc. from python. To make a long story short, the python version of the code that iterated and updated the velocities by manipulating vector objects was about 1600x slower than the equivalent C code that did the same using inline vector functions. psyco sped up the python code almost 5x, but it still was no contest. This is definitely an extreme case, but one relevant to game coding at least 8^) -Casey On Apr 27, 2009, at 7:24 PM, Daniel Jo wrote: I've pretty much abandoned the idea of vector classes in Python. I've tested various implementations: pure python classes (with and without __slots__), C++ exposed through Pyrex/Cython, tuples manipulated through add/mul/div/etc functions. . . Of these, C++ turned out to be the fastest, but faster by far than that was simply not using any structure at all. Store the components in tuples for convenience, but extract them and manipulated them individually for complex equations. Vector classes work well for convenience and code readability, but from a performance standpoint they aren't very useful. On Mon, Apr 27, 2009 at 4:28 PM, Brian Fisher br...@hamsterrepublic.com wrote: I don't see a 3 element vector type being useful from a pygame perspective. What pygame api anywhere even takes 3 element lists aside from colors? (which already have a special struct type thing) I'm not saying 3 element vectors don't have their uses - just that the seem to me to be a pretty random thing to have added to pygame, which is exclusively 2d in every interesting respect. It seems like the sort of thing to add that would add much more to the maintenance and testing cost of the pygame library than it would bring to the users as a whole. To put another way, there is no synergy between a 3 element vector class and pygame. Why would a 3 element vector class be better as part of pygame than not? what existing element of pygame is better or easier to use with a 3 element vector also being part of pygame? ...now a 2 element vector being part of pygame... rect could be better by making use of it, it could be used as an argument to the various functions that take 2 element lists, etc. etc ... and a 3 element vector (and quaternions and matrices) being part of pyOpenGL, that sounds great too... On Mon, Apr 27, 2009 at 2:59 PM, Lorenz Quack d...@amberfisharts.com wrote: Hello, I am interested in the inclusion of a vector and matrix types into pygame as suggested here [4]. In this email I want to propose a API for a vector module. I will for brevity only present the API for the types in three dimensions. The APIs for two or four dimensions should look analog. Also I enumerated every API for easier reference in discussions. Alternatives are denoted by lexical items (e.g. a) or b)) At the end I put together a small comparison to existing implementations. This is only a suggestion to spark discussion and provoke feedback. So throw in your 2 cents. sincerely yours //Lorenz PS: If this turns out to be of any value I will put something similar together for matrix types and quaternions. ** * API draft v1.0 *
Re: [pygame] API draft for vector type
On, Tue Apr 28, 2009, Lorenz Quack wrote: [...] Marcus von Appen wrote: On, Mon Apr 27, 2009, Lorenz Quack wrote: [...] Daniel Jo ost...@gmail.com: Vector classes work well for convenience and code readability, but from a performance standpoint they aren't very useful. Right, that's what batch operations are suitable for. Lorenz' proposal mentions e.g. creating vectors from sequence types. If we add a set of helper functions to the module (pygame.math.do_stuff (many_vectors)), we can easily get around that issue. This only requires us to keep the internally optimised methods separated well enough. seems like you already have this worked out in your head. but module-level batch functions sound like a good idea (even though I don't know how to actually implement that, yet). Here's a short snippet: static PyMethodDef _audio_methods[] = { { init, (PyCFunction) _sdl_audioinit, METH_NOARGS, DOC_AUDIO_INIT }, }; static PyObject* _sdl_audioinit (PyObject *self) { /* self resolves to the module, usually */ ... } PyMODINIT_FUNC initaudio (void) { PyObject *mod = Py_InitModule3 (audio, _audio_methods, DOC_AUDIO); ... } It's fairly easy as you see. Instead of binding methods to the object, you bind them to the module. Casey Duncan ca...@pandora.com: array of C structs, but you can iterate them and access the individual vectors for position, velocity, etc. from python. The proposed math helper functions thus should be suitable to operate on array() objects or buffers, where the type and object size has to be explicitily stated. We then can get equal results easily. just for clarity: do you mean that the helper functions should operate on arrays (numpy arrays?) of vectors of regular numbers. something like this: v1 = Vector3d((1, 2, 3)) v2 = Vector3d((-4, 5.6, 7)) a = array(v1, v2) axis = Vector3d((1,0,0)) angle = 90 #degrees pygame.math.rotateBatch(axis, angle, a) ? Arbitrary arrays, sequences or buffers, to be more exact. Let's say, I've got a sequence of numbers, which denote 3d vectors to be rotated: a = [(1,2,3), (-1, 0, 0), ...] v = Vector3d (1, 0, 0) # rotateBatch performs a PySequence_Check() and acts accordingly. pygame.math.rotateBatch (v, 90, a) Now the same for a buffer: # Read 30 elements from some file. buf = myfile.doread_binary (30) v = Vector3d (1, 0, 0) # # rotateBatch checks for the buffer, reads the element size hint (2 # bytes for each element) and acts accordingly in the following way: # # for i 0 to = len (buf) # elem = get [size] bytes element from buf as [type] value # result = rotate (elem v, 90) # set result back into buf # pygame.math.rotateBatch (v, 90, buf, size=2, type=float) and so forth. It might sound complex right now, but in fact it's quite easy to realise it - we do it the whole time with surfaces :-). [...] Rene Dudfield ren...@gmail.com What number types are used? eg, can you have a float vector, a long vector, an int vector? Any python number? A uint8 ? I'd vote for two major types here: long/int and float. Depending on what the passed values are. If we argue to use 'any python number', we'll have to refer to the number protocol anytime an arithmetic function occurs. This makes anything painfully slow. If the passed values are all int or long, the vector might be handled as long/int vector with matching optimised functions. if the numbers are all float, other matching optimised functions might be used. However, those considerations should be handled later on. To implement such hooks is a bit complex due to the behaviour specification. For now I'd vote for using either float (double) as internal representation (for being exact enough) and/or two vector types: FVector (floating point) LVector (long/int) +1 on floating point vectors (though using double precision). +0 on int/long. I would like to see some use cases of int vectors. -1 on the names. I think floating point is the thing users normally want so I would call that Vector, Vector3d or whatever. The int vector is a special case and therefore wait in second line with a name like IVector (in python3 we only have int so I would go for the I instead of the L) Those were just examples. Personally I'd favour Vector and IntVector (IVector sounds like an interface to me). IntVector however is something to be considered later on. 1.5.4.1 v.isNormalized() - bool 1.5.4.2 v.normalize() - None# normalizes inplace 1.5.4.3 v1.normalized() - v2# returns normalized vector In my opinion normalize() and normalized() are far too ambiguous. We might should use something like ip_XXX() for inplace operations: v.ip_normalize () - None v.normalize () - v2 We do that naming already for Rect objects and should take care of doing that anywhere where inplace operations happen. The same
Re: [pygame] API draft for vector type
On Apr 28, 2009, at 1:48 PM, Marcus von Appen wrote: 1.6 properties == 1.6.1.1 v.length - a # gets the magnitude/length of the vector 1.6.1.2 v.length = a # sets the length of the vector while preserving its direction The setter might be risky due to rounding issues. true, but I think this can be very usefull. and I can live with the fact that v.length = 1. v.length == 1. # - false when dealing with floating point variables you have to expect weird behavior like this. As I said, it's risky. If I set v.length = 1, I expect v.length == 1 to work. Any other behaviour is wrong for both, readability and behaviour expectations, in my opinion. How would you propose to make that true? I imagine you could store the length as a vector attribute, but then it's either a lie or it means the values must be scaled to it for every operation (i.e., x,y,z are always stored in unit-form and the length is stored separately). Also, if length is settable, what happens when I do this: v.length = 0 v.length = 1 That would work with the unit-form approach, but would result in some inconsistencies, i.e.: v1 = Vector3(1,1,0) v2 = Vector3(0,1,1) v1 == v2 False v1.length = v2.length = 0 v1 == v2 True? (I dunno, they are both null vectors) v1.length = v2.length = 1 v1 == v2 False Another option is to make length comparison epsilon-based to compensate for rounding, however that implies length returns some new number type that does that. Feels like a lot of effort for little gain, though it might be able to be done by a relatively simple float subclass, I dunno. I kinda feel like a settable length is too magical. How about a scale_to_length() or somesuch method that lets you scale the vector to a given length (and raises an error for null vectors). I think that would be more explicit less surprising in corner cases. And it would be easy to document that scaling a vector to a given length does not guarantee the resulting length will be precisely that value due to rounding errors. -Casey
Re: [pygame] API draft for vector type
On Tue, Apr 28, 2009 at 2:48 PM, Marcus von Appen m...@sysfault.org wrote: On, Tue Apr 28, 2009, Lorenz Quack wrote: Casey Duncan ca...@pandora.com: Degrees, I'd say. The api should be easy to use and letting users calculate the rad values before is not that intuitive. I just checked: unfortunately pygame seems to be inconsistent: transform.rotate use degrees and draw.arc uses radians. Which is a problem to get solved. Thus we should stick to degrees. I thought the standard was to use radians since trig. functions use radians. ( And opengl? ) I'm Curious: if pygame uses degrees, does it end up being faster than if pygame used radians, and the user has to manually convert to degrees? Or is the difference insignificant? foo(d) vs foo(radians(d)) -- Jake
Re: [pygame] API draft for vector type
On Tue, Apr 28, 2009 at 06:32:12PM +0200, Lorenz Quack wrote: 1.5.4.1 v.isNormalized() - bool 1.5.4.2 v.normalize() - None# normalizes inplace 1.5.4.3 v1.normalized() - v2# returns normalized vector In my opinion normalize() and normalized() are far too ambiguous. We might should use something like ip_XXX() for inplace operations: v.ip_normalize () - None v.normalize () - v2 We do that naming already for Rect objects and should take care of doing that anywhere where inplace operations happen. The same then applies to the rest of your inplace methods. hm. ok. but the ip is after the name: v.normalize_ip() When I see 'ip', I cannot stop thinking about IP addresses. I think .normalize() vs .normalized() is clear enough, and also follows the convention set by Python builtins (list.sort() vs sorted()). And if vectors are immutable, this question becomes moot. 1.6 properties == 1.6.1.1 v.length - a # gets the magnitude/length of the vector 1.6.1.2 v.length = a # sets the length of the vector while preserving its direction The setter might be risky due to rounding issues. true, but I think this can be very usefull. and I can live with the fact that v.length = 1. v.length == 1. # - false when dealing with floating point variables you have to expect weird behavior like this. I used to think that way. Then I read _What Every Computer Scientist Should Know About Floating Point Arithmetic_ and understood that floats are very predictable if you understand them. (I still don't understand them. *wink*) 1.7 comparison operations = 1.7.0the == and != and bool operater compare the differences against the attribute v._epsilon. this way the user can adjust the accuracy. 1.7.1.1 v == s - bool # true if all component differ at most by v._epsilon How am I as user supposed to manipulate _epsilon? It should be made public. well. I thought you rarely want to twiddle with this so I marked it private. I thought the normal user doesn't want to be bothered with this and the pro can access it. I'm kind of expecting some expert to pop in and explain how this breaks mathematical properties of equality (v1 == v2 and v2 == v3 no longer implies v1 == v3) and how this could result in bugs and pain in real life code. 1.8 misc == 1.8.1 support iter protocol 1.8.2 str(v) - [x, y, z] 1.8.3 repr(v) - Vecx, y, z Most objects have the same output for str() and repr(). Why do you differ here? with repr I wanted to make explicitly clear that this is not a list but I thought that the normal str() would look nicer that way. what would you suggest? [x, y, z] for both (or (x, y, z) if we choose to make vectors immutable) or Vector3dx, y, z? I'm +0.95 for distinct __str__ and __repr__. str is what you show your users and should be short and clear, while repr is what you give the programmers who're debugging and therefore exact types matter. 1.10 open questions (in no particular order) 1.10.1 a) use radians for all angles b) use degrees for all angles Degrees, I'd say. The api should be easy to use and letting users calculate the rad values before is not that intuitive. math.radians(180) is not intuitive? Well, maybe. You have to know it's there. (Can I mention math.hypot? Nobody knows about math.hypot. It's a modest little function that deserves more fame than it gets.) I just checked: unfortunately pygame seems to be inconsistent: transform.rotate use degrees and draw.arc uses radians. Does transform.rotate rotate clockwise or counter-clockwise? Pydoc doesn't say. * __abs__ pyeuclid returns the magnitude. 3DVectorType returns vec3d(abs(x), abs(y), abs(z)) vectypes and this proposal don't implement __abs__ to avoid confusion I'd expect abs() to get the magnitude/length, too. I don't so to avoid confusion I wouldn't implement it at all. how do other people feel about this? I'd expect len(v) to return its length, but (1) that would be a horrible abuse of the sequence protocol, and (2) Python doesn't allow __len__ to return a non-integer value, thankfully. I didn't even know/had forgotten all about __abs__. thanks again for the quite thorough feedback. Thanks for the comprehensive proposal. Marius Gedminas -- User n.: A programmer who will believe anything you tell him. signature.asc Description: Digital signature
Re: [pygame] API draft for vector type
On Wed, Apr 29, 2009 at 2:29 AM, Casey Duncan ca...@pandora.com wrote: Surface.fill_multi and Surface.blit_multi would be awesome for particle effects, in fact I could take good advantage of them in Lepton right now to make the pygame renderers mucho-faster. Would that be something that would be considered in pgreloaded (or even pygame 1.9)? If so I would be interested in helping to implement them as I would be an early adopter ;^) -Casey Definitely! That would be cool. For pygame 1.9 it'd need to be ready within 4 weeks, with tests and docs. For 1.9.1 there's at least 4-5 months to go. Would _multi methods work with different multiple arguments? eg multiple surfaces, multiple dst rects, multiple source rects? Or you could just do one method for each multiple... or detect the case based on the input arguments. Probably best to just do your use case... (which is multiple src rects?)... then raise NotImplementedError for other combinations. I don't think that'd take long to make. cu,
Re: [pygame] API draft for vector type
On Apr 28, 2009, at 8:41 PM, René Dudfield wrote: On Wed, Apr 29, 2009 at 2:29 AM, Casey Duncan ca...@pandora.com wrote: Surface.fill_multi and Surface.blit_multi would be awesome for particle effects, in fact I could take good advantage of them in Lepton right now to make the pygame renderers mucho-faster. Would that be something that would be considered in pgreloaded (or even pygame 1.9)? If so I would be interested in helping to implement them as I would be an early adopter ;^) -Casey Definitely! That would be cool. For pygame 1.9 it'd need to be ready within 4 weeks, with tests and docs. For 1.9.1 there's at least 4-5 months to go. Would _multi methods work with different multiple arguments? eg multiple surfaces, multiple dst rects, multiple source rects? Or you could just do one method for each multiple... or detect the case based on the input arguments. Probably best to just do your use case... (which is multiple src rects?)... then raise NotImplementedError for other combinations. fill_multi might look like this: Surface.fill_multi(color, rects, special_flags=0) Basically the same as the fill() except the first two arguments accept buffer objects that are arrays of colors and rects respectively. I think it would be best if color accepted both a single color value or an array of RGBA values. I think supporting only RGBA (as 4-byte words) is good enough and the alpha would just be ignored if the surface did not support it. Though this would preclude indexed color surfaces. I'm open to opinion on this. If color is an array, it would need to be the same length as rects to keep things simple. Otherwise it would raise an exception (ValueError?). blit_multi would be: Surface.blit_multi(source, dests, area=None, special_flags=0) source is a single surface, dests is an buffer array of x, y coordinate ints, or maybe a RectArray, see below. Area is a single rect, for now, but I could imagine supporting an array of rects for advanced use (sprite-sheet, etc). Seems like we would want a RectArray object to allow creation and some manipulation and passing of rectangles en-masse from python, though maybe that's overkill for a first rev. I'm going to check out 1.9 now and see how it looks. I remember looking at doing something similar in pygame from the lepton side and deciding it was not too practical from an outside library. But, given these apis it would be easy. I suspect the fill_multi() implementation will be more complex, we'll see. -Casey
Surface batch methods... Re: [pygame] API draft for vector type
On Wed, Apr 29, 2009 at 2:35 PM, Casey Duncan ca...@pandora.com wrote: On Apr 28, 2009, at 8:41 PM, René Dudfield wrote: On Wed, Apr 29, 2009 at 2:29 AM, Casey Duncan ca...@pandora.com wrote: Surface.fill_multi and Surface.blit_multi would be awesome for particle effects, in fact I could take good advantage of them in Lepton right now to make the pygame renderers mucho-faster. Would that be something that would be considered in pgreloaded (or even pygame 1.9)? If so I would be interested in helping to implement them as I would be an early adopter ;^) -Casey Definitely! That would be cool. For pygame 1.9 it'd need to be ready within 4 weeks, with tests and docs. For 1.9.1 there's at least 4-5 months to go. Would _multi methods work with different multiple arguments? eg multiple surfaces, multiple dst rects, multiple source rects? Or you could just do one method for each multiple... or detect the case based on the input arguments. Probably best to just do your use case... (which is multiple src rects?)... then raise NotImplementedError for other combinations. fill_multi might look like this: Surface.fill_multi(color, rects, special_flags=0) Basically the same as the fill() except the first two arguments accept buffer objects that are arrays of colors and rects respectively. I think it would be best if color accepted both a single color value or an array of RGBA values. I think supporting only RGBA (as 4-byte words) is good enough and the alpha would just be ignored if the surface did not support it. Though this would preclude indexed color surfaces. I'm open to opinion on this. If color is an array, it would need to be the same length as rects to keep things simple. Otherwise it would raise an exception (ValueError?). blit_multi would be: Surface.blit_multi(source, dests, area=None, special_flags=0) source is a single surface, dests is an buffer array of x, y coordinate ints, or maybe a RectArray, see below. Area is a single rect, for now, but I could imagine supporting an array of rects for advanced use (sprite-sheet, etc). Seems like we would want a RectArray object to allow creation and some manipulation and passing of rectangles en-masse from python, though maybe that's overkill for a first rev. I'm going to check out 1.9 now and see how it looks. I remember looking at doing something similar in pygame from the lepton side and deciding it was not too practical from an outside library. But, given these apis it would be easy. I suspect the fill_multi() implementation will be more complex, we'll see. -Casey Sounds pretty good. A common use case for blit_multi would be when you are blitting a whole group of sprites to the screen. But you don't necessarily have to complete each use case to start with... as long as the interface raises exceptions when people try, and mention it in the docs. One issue might be... Surface.fill_multi(color, rects, special_flags=0) With color it can be a single int, or (0,0,0) or (0,0,0,0). So I think the sequences would have to be len(rects) == len(color) Except if you have 3-4 colors + rects... ([1,2,3], [r1,r2,r3]) then the color argument has an ambiguity of either 3 colors, or 1 color. So perhaps explicit length of arguments? Or a separate color and colors argument?
Re: [pygame] API draft for vector type
One aspect of vector class design that I've become more and more a fan of over time is vector immutability. So you can't say stuff like: vector.x += 2 vector.x = 5 but instead would have to say stuff like: vector += (2, 0) vector = vector2d(5, vector.y) their are a couple reasons to design them that way - first is no one can ever change your attributes underneath you - which is a bug I've run into every now and then with mutable vectors, and have had to work around by having stuff contruct and return new vectors instead of returning the internal one. what I mean is code like this is pretty bad (but moderately easy to write) --- class Angel(object) def __init__(self, offset): self.offset = offset t = new Angel() halo_pos = t.offset halo_pos.y -= 5 DrawHalo(halo_pos) - and immutability of vectors makes that bug impossible. the second reason for immutability of vectors is that they can because keys in dicts (something I've found useful, but have had to use 2 element tuples instead to make it work) On Mon, Apr 27, 2009 at 2:59 PM, Lorenz Quack d...@amberfisharts.com wrote: Hello, I am interested in the inclusion of a vector and matrix types into pygame as suggested here [4]. In this email I want to propose a API for a vector module. I will for brevity only present the API for the types in three dimensions. The APIs for two or four dimensions should look analog. Also I enumerated every API for easier reference in discussions. Alternatives are denoted by lexical items (e.g. a) or b)) At the end I put together a small comparison to existing implementations. This is only a suggestion to spark discussion and provoke feedback. So throw in your 2 cents. sincerely yours //Lorenz PS: If this turns out to be of any value I will put something similar together for matrix types and quaternions. ** * API draft v1.0 * ** In the following I will use the notation: v, v1, v2, ... are vectors s, s1, s2, ... are objects implementing the sequences protocol (list, tuple, the proposed vector) a, a1, a2, ... are scalars (int, float) § 1 Vector type 1.1 Class name and constructor == 1.1.1 a) Vector3 b) Vector3d 1.1.2 V(a1, a2, a3)# initialize x, y and z with a1, a2 and a3 respectivly 1.1.3 V(s) # initialize x, y and z with s[0], s[1] and s[2] respectivly 1.1.4 V() # initialize x, y and z with zeros 1.2 numerical behavior == 1.2.1.1 v1 + s - v3 1.2.1.2 s + v1 - v3 1.2.1.3 v += s 1.2.2.1 v1 - s - v3 1.2.2.2 s - v1 - v3 1.2.2.3 v -= s 1.2.3.1 v1 * a - v3 1.2.3.2 a * v1 - v3 1.2.3.3 v *= a 1.2.4.1 v1 / a - v3 1.2.4.2 v /= a 1.2.5.1 v1 // a - v3 1.2.5.2 v //= a 1.2.6.1 v1 % a - v3 1.2.6.2 v %= a 1.2.7.1 v * s - a # dot/scalar/inner product 1.2.7.2 s * v - a # dot/scalar/inner product 1.2.8.1 +v1 - v2 # returns a new vector 1.2.8.2 -v1 - v2 1.3 sequence behavior = 1.3.1len(v) - 3 # fixed length 1.3.2.1 v[0] - a # 0-based indexing 1.3.2.2 v[0] = a 1.4 attributes == 1.4.0x, y, z (and w for 4th dimension) _epsilon for comparison operations 1.4.1.1 v.x - a 1.4.1.2 v.x = a 1.5 methods === 1.5.1v.dot(s) - a # dot/scalar/inner product 1.5.2v.cross(s) - v # cross/vector product # in 2 dimensions this returns v.x * s[1] - v.y * s[0] # this is not defined in 4 dimensions 1.5.3v.outer(s) - m # outer product yielding a matrix 1.5.4.1 v.isNormalized() - bool 1.5.4.2 v.normalize() - None# normalizes inplace 1.5.4.3 v1.normalized() - v2# returns normalized vector 1.5.5.1 v1.rotate(s1[, a]) - None # rotates around s1 by angle a. if a isn't given it # rotates around s1 by the magnitude of s1 # this is an inplace operation 1.5.5.2 v1.rotated(s1[, a]) - v2 # same as 1.5.6 but returns a new vector and leaves v1 untouched 1.5.6.1 v1.rotateX(a) - None # rotates v1 around the x-axis by the angle a 1.5.6.2 v1.rotatedX(a) - v2 # same as 1.5.6.1 but returns a new vector and leaves v1 untouched 1.5.6.3 # implement 1.5.6.1 and 2 also for Y and Z 1.5.7v1.reflect(s) - v2 # reflects the vector of a surface with surface normal s 1.5.8a) v1.interpolate(s, a) - generator of vectors b) v1.slerp(s, a) - generator of vectors # the distance between v1 and s divided in a steps 1.5.9v.getAngleTo(s) - a # returns the angle between v and s 1.5.10.1 v.getDistanceTo(s) - a # returns the distance between v and s 1.5.10.2 v.getDistance2To(s) - a # returns the squared distance between v and s 1.6 properties == 1.6.1.1 v.length - a # gets the magnitude/length of the vector 1.6.1.2
Re: [pygame] API draft for vector type
Any reason to not follow the pep-8 naming convention for methods, i.e.: v.get_distance_to() instead of: v.getDistanceTo() or maybe even (the get seems a little superfluous): v.distanceto() Other pygame modules seem to use the pep-8 convention, would be a shame to break the nice consistency. -Casey On Apr 27, 2009, at 3:59 PM, Lorenz Quack wrote: Hello, I am interested in the inclusion of a vector and matrix types into pygame as suggested here [4]. In this email I want to propose a API for a vector module. I will for brevity only present the API for the types in three dimensions. The APIs for two or four dimensions should look analog. Also I enumerated every API for easier reference in discussions. Alternatives are denoted by lexical items (e.g. a) or b)) At the end I put together a small comparison to existing implementations. This is only a suggestion to spark discussion and provoke feedback. So throw in your 2 cents. sincerely yours //Lorenz PS: If this turns out to be of any value I will put something similar together for matrix types and quaternions. ** * API draft v1.0 * ** In the following I will use the notation: v, v1, v2, ... are vectors s, s1, s2, ... are objects implementing the sequences protocol (list, tuple, the proposed vector) a, a1, a2, ... are scalars (int, float) § 1 Vector type 1.1 Class name and constructor == 1.1.1 a) Vector3 b) Vector3d 1.1.2 V(a1, a2, a3)# initialize x, y and z with a1, a2 and a3 respectivly 1.1.3 V(s) # initialize x, y and z with s[0], s[1] and s[2] respectivly 1.1.4 V() # initialize x, y and z with zeros 1.2 numerical behavior == 1.2.1.1 v1 + s - v3 1.2.1.2 s + v1 - v3 1.2.1.3 v += s 1.2.2.1 v1 - s - v3 1.2.2.2 s - v1 - v3 1.2.2.3 v -= s 1.2.3.1 v1 * a - v3 1.2.3.2 a * v1 - v3 1.2.3.3 v *= a 1.2.4.1 v1 / a - v3 1.2.4.2 v /= a 1.2.5.1 v1 // a - v3 1.2.5.2 v //= a 1.2.6.1 v1 % a - v3 1.2.6.2 v %= a 1.2.7.1 v * s - a # dot/scalar/inner product 1.2.7.2 s * v - a # dot/scalar/inner product 1.2.8.1 +v1 - v2 # returns a new vector 1.2.8.2 -v1 - v2 1.3 sequence behavior = 1.3.1len(v) - 3 # fixed length 1.3.2.1 v[0] - a # 0-based indexing 1.3.2.2 v[0] = a 1.4 attributes == 1.4.0x, y, z (and w for 4th dimension) _epsilon for comparison operations 1.4.1.1 v.x - a 1.4.1.2 v.x = a 1.5 methods === 1.5.1v.dot(s) - a # dot/scalar/inner product 1.5.2v.cross(s) - v # cross/vector product # in 2 dimensions this returns v.x * s[1] - v.y * s[0] # this is not defined in 4 dimensions 1.5.3v.outer(s) - m # outer product yielding a matrix 1.5.4.1 v.isNormalized() - bool 1.5.4.2 v.normalize() - None# normalizes inplace 1.5.4.3 v1.normalized() - v2# returns normalized vector 1.5.5.1 v1.rotate(s1[, a]) - None # rotates around s1 by angle a. if a isn't given it # rotates around s1 by the magnitude of s1 # this is an inplace operation 1.5.5.2 v1.rotated(s1[, a]) - v2 # same as 1.5.6 but returns a new vector and leaves v1 untouched 1.5.6.1 v1.rotateX(a) - None # rotates v1 around the x-axis by the angle a 1.5.6.2 v1.rotatedX(a) - v2 # same as 1.5.6.1 but returns a new vector and leaves v1 untouched 1.5.6.3 # implement 1.5.6.1 and 2 also for Y and Z 1.5.7v1.reflect(s) - v2 # reflects the vector of a surface with surface normal s 1.5.8a) v1.interpolate(s, a) - generator of vectors b) v1.slerp(s, a) - generator of vectors # the distance between v1 and s divided in a steps 1.5.9v.getAngleTo(s) - a # returns the angle between v and s 1.5.10.1 v.getDistanceTo(s) - a # returns the distance between v and s 1.5.10.2 v.getDistance2To(s) - a # returns the squared distance between v and s 1.6 properties == 1.6.1.1 v.length - a # gets the magnitude/length of the vector 1.6.1.2 v.length = a # sets the length of the vector while preserving its direction 1.6.2.1 a) v.lengthSquared - a b) v.length2 - a # gets the squared length of the vector. same as v.dot(v) or v * v 1.6.2.1 a) v.lengthSquared = a b) v.length2 = a # sets the squared length of the vector. preserving its direction # the following only have meaning in 3 dimensions 1.6.3.1 v.r - a # returns the r coordiante of sherical coordinates # this is the same as the length property 1.6.3.2 v.r = a 1.6.4.1 v.phi - a # returns the phi coordiante of spherical coordiantes 1.6.4.2 v.phi = a 1.6.5.1 v.theta - a # returns the theta coordiante of spherical coordiantes 1.6.5.2 v.theta = a 1.7 comparison operations = 1.7.0the == and != and bool operater compare the
Re: [pygame] API draft for vector type
On Apr 27, 2009, at 4:28 PM, Brian Fisher wrote: I don't see a 3 element vector type being useful from a pygame perspective. What pygame api anywhere even takes 3 element lists aside from colors? (which already have a special struct type thing) I'd have to disagree with this myself, since pygame+pyOpenGL is a fairly popular combo, it seems like omitting 3d vectors on the grounds that most pygames are 2D is too minimalist. OTOH, I don't think it needs 4D vectors. 1D vectors, however, would be awesome ;^) ... and a 3 element vector (and quaternions and matrices) being part of pyOpenGL, that sounds great too... I could be wrong, but I don't think pyOpenGL strives to provide such tools, which are not strictly part of the OpenGL api. Whereas pygame does try to provide such lower-level abstractions. Of course you could make a slippery slope argument here, where there is soon demand for more 3D tools given 3D vectors, like rectangular prisms, etc. -Casey
Re: [pygame] API draft for vector type
very good work. +1 to the pep8 naming like someone else mentioned. Would be nice if the vectors storage of things could be anything underneath. This would be useful to allow them to use pygame.Rect or numpy.array underneath. This means they can refer to a batch of vectors, but also operate only on a single vector at a time. Wondering about why only 3 element vectors? 2,3, and 4 element ones are common? Is there a way to make a combined 2,3,4 type? What number types are used? eg, can you have a float vector, a long vector, an int vector? Any python number? A uint8 ? cu, On Tue, Apr 28, 2009 at 7:59 AM, Lorenz Quack d...@amberfisharts.com wrote: Hello, I am interested in the inclusion of a vector and matrix types into pygame as suggested here [4]. In this email I want to propose a API for a vector module. I will for brevity only present the API for the types in three dimensions. The APIs for two or four dimensions should look analog. Also I enumerated every API for easier reference in discussions. Alternatives are denoted by lexical items (e.g. a) or b)) At the end I put together a small comparison to existing implementations. This is only a suggestion to spark discussion and provoke feedback. So throw in your 2 cents. sincerely yours //Lorenz PS: If this turns out to be of any value I will put something similar together for matrix types and quaternions. ** * API draft v1.0 * ** In the following I will use the notation: v, v1, v2, ... are vectors s, s1, s2, ... are objects implementing the sequences protocol (list, tuple, the proposed vector) a, a1, a2, ... are scalars (int, float) § 1 Vector type 1.1 Class name and constructor == 1.1.1 a) Vector3 b) Vector3d 1.1.2 V(a1, a2, a3)# initialize x, y and z with a1, a2 and a3 respectivly 1.1.3 V(s) # initialize x, y and z with s[0], s[1] and s[2] respectivly 1.1.4 V() # initialize x, y and z with zeros 1.2 numerical behavior == 1.2.1.1 v1 + s - v3 1.2.1.2 s + v1 - v3 1.2.1.3 v += s 1.2.2.1 v1 - s - v3 1.2.2.2 s - v1 - v3 1.2.2.3 v -= s 1.2.3.1 v1 * a - v3 1.2.3.2 a * v1 - v3 1.2.3.3 v *= a 1.2.4.1 v1 / a - v3 1.2.4.2 v /= a 1.2.5.1 v1 // a - v3 1.2.5.2 v //= a 1.2.6.1 v1 % a - v3 1.2.6.2 v %= a 1.2.7.1 v * s - a # dot/scalar/inner product 1.2.7.2 s * v - a # dot/scalar/inner product 1.2.8.1 +v1 - v2 # returns a new vector 1.2.8.2 -v1 - v2 1.3 sequence behavior = 1.3.1len(v) - 3 # fixed length 1.3.2.1 v[0] - a # 0-based indexing 1.3.2.2 v[0] = a 1.4 attributes == 1.4.0x, y, z (and w for 4th dimension) _epsilon for comparison operations 1.4.1.1 v.x - a 1.4.1.2 v.x = a 1.5 methods === 1.5.1v.dot(s) - a # dot/scalar/inner product 1.5.2v.cross(s) - v # cross/vector product # in 2 dimensions this returns v.x * s[1] - v.y * s[0] # this is not defined in 4 dimensions 1.5.3v.outer(s) - m # outer product yielding a matrix 1.5.4.1 v.isNormalized() - bool 1.5.4.2 v.normalize() - None# normalizes inplace 1.5.4.3 v1.normalized() - v2# returns normalized vector 1.5.5.1 v1.rotate(s1[, a]) - None # rotates around s1 by angle a. if a isn't given it # rotates around s1 by the magnitude of s1 # this is an inplace operation 1.5.5.2 v1.rotated(s1[, a]) - v2 # same as 1.5.6 but returns a new vector and leaves v1 untouched 1.5.6.1 v1.rotateX(a) - None # rotates v1 around the x-axis by the angle a 1.5.6.2 v1.rotatedX(a) - v2 # same as 1.5.6.1 but returns a new vector and leaves v1 untouched 1.5.6.3 # implement 1.5.6.1 and 2 also for Y and Z 1.5.7v1.reflect(s) - v2 # reflects the vector of a surface with surface normal s 1.5.8a) v1.interpolate(s, a) - generator of vectors b) v1.slerp(s, a) - generator of vectors # the distance between v1 and s divided in a steps 1.5.9v.getAngleTo(s) - a # returns the angle between v and s 1.5.10.1 v.getDistanceTo(s) - a # returns the distance between v and s 1.5.10.2 v.getDistance2To(s) - a # returns the squared distance between v and s 1.6 properties == 1.6.1.1 v.length - a # gets the magnitude/length of the vector 1.6.1.2 v.length = a # sets the length of the vector while preserving its direction 1.6.2.1 a) v.lengthSquared - a b) v.length2 - a # gets the squared length of the vector. same as v.dot(v) or v * v 1.6.2.1 a) v.lengthSquared = a b) v.length2 = a # sets the squared length of the vector. preserving its direction # the following only have meaning in 3 dimensions 1.6.3.1 v.r - a # returns the r coordiante of sherical coordinates
Re: [pygame] API draft for vector type
I've pretty much abandoned the idea of vector classes in Python. I've tested various implementations: pure python classes (with and without __slots__), C++ exposed through Pyrex/Cython, tuples manipulated through add/mul/div/etc functions. . . Of these, C++ turned out to be the fastest, but faster by far than that was simply not using any structure at all. Store the components in tuples for convenience, but extract them and manipulated them individually for complex equations. Vector classes work well for convenience and code readability, but from a performance standpoint they aren't very useful. On Mon, Apr 27, 2009 at 4:28 PM, Brian Fisher br...@hamsterrepublic.com wrote: I don't see a 3 element vector type being useful from a pygame perspective. What pygame api anywhere even takes 3 element lists aside from colors? (which already have a special struct type thing) I'm not saying 3 element vectors don't have their uses - just that the seem to me to be a pretty random thing to have added to pygame, which is exclusively 2d in every interesting respect. It seems like the sort of thing to add that would add much more to the maintenance and testing cost of the pygame library than it would bring to the users as a whole. To put another way, there is no synergy between a 3 element vector class and pygame. Why would a 3 element vector class be better as part of pygame than not? what existing element of pygame is better or easier to use with a 3 element vector also being part of pygame? ...now a 2 element vector being part of pygame... rect could be better by making use of it, it could be used as an argument to the various functions that take 2 element lists, etc. etc ... and a 3 element vector (and quaternions and matrices) being part of pyOpenGL, that sounds great too... On Mon, Apr 27, 2009 at 2:59 PM, Lorenz Quack d...@amberfisharts.com wrote: Hello, I am interested in the inclusion of a vector and matrix types into pygame as suggested here [4]. In this email I want to propose a API for a vector module. I will for brevity only present the API for the types in three dimensions. The APIs for two or four dimensions should look analog. Also I enumerated every API for easier reference in discussions. Alternatives are denoted by lexical items (e.g. a) or b)) At the end I put together a small comparison to existing implementations. This is only a suggestion to spark discussion and provoke feedback. So throw in your 2 cents. sincerely yours //Lorenz PS: If this turns out to be of any value I will put something similar together for matrix types and quaternions. ** * API draft v1.0 * ** In the following I will use the notation: v, v1, v2, ... are vectors s, s1, s2, ... are objects implementing the sequences protocol (list, tuple, the proposed vector) a, a1, a2, ... are scalars (int, float) § 1 Vector type 1.1 Class name and constructor == 1.1.1 a) Vector3 b) Vector3d 1.1.2 V(a1, a2, a3)# initialize x, y and z with a1, a2 and a3 respectivly 1.1.3 V(s) # initialize x, y and z with s[0], s[1] and s[2] respectivly 1.1.4 V() # initialize x, y and z with zeros 1.2 numerical behavior == 1.2.1.1 v1 + s - v3 1.2.1.2 s + v1 - v3 1.2.1.3 v += s 1.2.2.1 v1 - s - v3 1.2.2.2 s - v1 - v3 1.2.2.3 v -= s 1.2.3.1 v1 * a - v3 1.2.3.2 a * v1 - v3 1.2.3.3 v *= a 1.2.4.1 v1 / a - v3 1.2.4.2 v /= a 1.2.5.1 v1 // a - v3 1.2.5.2 v //= a 1.2.6.1 v1 % a - v3 1.2.6.2 v %= a 1.2.7.1 v * s - a # dot/scalar/inner product 1.2.7.2 s * v - a # dot/scalar/inner product 1.2.8.1 +v1 - v2 # returns a new vector 1.2.8.2 -v1 - v2 1.3 sequence behavior = 1.3.1 len(v) - 3 # fixed length 1.3.2.1 v[0] - a # 0-based indexing 1.3.2.2 v[0] = a 1.4 attributes == 1.4.0 x, y, z (and w for 4th dimension) _epsilon for comparison operations 1.4.1.1 v.x - a 1.4.1.2 v.x = a 1.5 methods === 1.5.1 v.dot(s) - a # dot/scalar/inner product 1.5.2 v.cross(s) - v # cross/vector product # in 2 dimensions this returns v.x * s[1] - v.y * s[0] # this is not defined in 4 dimensions 1.5.3 v.outer(s) - m # outer product yielding a matrix 1.5.4.1 v.isNormalized() - bool 1.5.4.2 v.normalize() - None # normalizes inplace 1.5.4.3 v1.normalized() - v2 # returns normalized vector 1.5.5.1 v1.rotate(s1[, a]) - None # rotates around s1 by angle a. if a isn't given it # rotates around s1 by the magnitude of s1 # this is an inplace operation 1.5.5.2 v1.rotated(s1[, a]) - v2 # same as 1.5.6 but returns a new vector and leaves v1 untouched 1.5.6.1 v1.rotateX(a) - None # rotates v1 around the x-axis by the angle a 1.5.6.2
Re: [pygame] API draft for vector type
On Apr 27, 2009, at 6:16 PM, René Dudfield wrote: Would be nice if the vectors storage of things could be anything underneath. This would be useful to allow them to use pygame.Rect or numpy.array underneath. This means they can refer to a batch of vectors, but also operate only on a single vector at a time. +1, though there are performance vs. generality tradeoffs to be made. On the general side, a vector class could assume the underlying storage supports __getitem__, but the performance of this would suffer, I think too greatly. On the performance side, it could just have a pointer to an array of floats that it wraps with the vector api. I used this strategy with Lepton and the performance is great, but it is inflexible for the storage, and probably not very practical for totally general use across different storages. Wondering about why only 3 element vectors? 2,3, and 4 element ones are common? Is there a way to make a combined 2,3,4 type? Most operations can assume the higher dimensions are always zero, or the length could just be variable. But in either case the code would be slower than it would strictly need to be, since many operations would do more work than needed or would require loops where they would not be required for single purpose 2D, 3D or better vectors. What number types are used? eg, can you have a float vector, a long vector, an int vector? Any python number? A uint8 ? Seems to me like the most general number type would be a double, as it could comfortably support a wide range, does not generally have resolution issues like a 32-bit float can and performs well on modern hardware. It would also give consistent results compared to a python float, which is nice. I'm not sure what the use-case is for ints or (python) longs, the latter would probably gain little by being coded in C compared to pure python. Even in sprite-based 2D games, I find integers to be far too coarse for vector math, and operations like normalize become basically impossible. If you support multiple vector numeric types, than you have to confront a combinatorial explosion of type conversions and either duplicate, templatize or generalize the code in such a way that you trade either performance or maintainability or both. -Casey
Re: [pygame] API draft for vector type
I have found this to be generally true as well, and storing a large number of individual vector objects to be operated on in a batch performs poorly regardless of implementation language. As an example, for Lepton I coded a controller object which looped over a large number of particles to update their velocities. Under the covers the particles are stored as a simple array of C structs, but you can iterate them and access the individual vectors for position, velocity, etc. from python. To make a long story short, the python version of the code that iterated and updated the velocities by manipulating vector objects was about 1600x slower than the equivalent C code that did the same using inline vector functions. psyco sped up the python code almost 5x, but it still was no contest. This is definitely an extreme case, but one relevant to game coding at least 8^) -Casey On Apr 27, 2009, at 7:24 PM, Daniel Jo wrote: I've pretty much abandoned the idea of vector classes in Python. I've tested various implementations: pure python classes (with and without __slots__), C++ exposed through Pyrex/Cython, tuples manipulated through add/mul/div/etc functions. . . Of these, C++ turned out to be the fastest, but faster by far than that was simply not using any structure at all. Store the components in tuples for convenience, but extract them and manipulated them individually for complex equations. Vector classes work well for convenience and code readability, but from a performance standpoint they aren't very useful. On Mon, Apr 27, 2009 at 4:28 PM, Brian Fisher br...@hamsterrepublic.com wrote: I don't see a 3 element vector type being useful from a pygame perspective. What pygame api anywhere even takes 3 element lists aside from colors? (which already have a special struct type thing) I'm not saying 3 element vectors don't have their uses - just that the seem to me to be a pretty random thing to have added to pygame, which is exclusively 2d in every interesting respect. It seems like the sort of thing to add that would add much more to the maintenance and testing cost of the pygame library than it would bring to the users as a whole. To put another way, there is no synergy between a 3 element vector class and pygame. Why would a 3 element vector class be better as part of pygame than not? what existing element of pygame is better or easier to use with a 3 element vector also being part of pygame? ...now a 2 element vector being part of pygame... rect could be better by making use of it, it could be used as an argument to the various functions that take 2 element lists, etc. etc ... and a 3 element vector (and quaternions and matrices) being part of pyOpenGL, that sounds great too... On Mon, Apr 27, 2009 at 2:59 PM, Lorenz Quack d...@amberfisharts.com wrote: Hello, I am interested in the inclusion of a vector and matrix types into pygame as suggested here [4]. In this email I want to propose a API for a vector module. I will for brevity only present the API for the types in three dimensions. The APIs for two or four dimensions should look analog. Also I enumerated every API for easier reference in discussions. Alternatives are denoted by lexical items (e.g. a) or b)) At the end I put together a small comparison to existing implementations. This is only a suggestion to spark discussion and provoke feedback. So throw in your 2 cents. sincerely yours //Lorenz PS: If this turns out to be of any value I will put something similar together for matrix types and quaternions. ** * API draft v1.0 * ** In the following I will use the notation: v, v1, v2, ... are vectors s, s1, s2, ... are objects implementing the sequences protocol (list, tuple, the proposed vector) a, a1, a2, ... are scalars (int, float) § 1 Vector type 1.1 Class name and constructor == 1.1.1 a) Vector3 b) Vector3d 1.1.2 V(a1, a2, a3)# initialize x, y and z with a1, a2 and a3 respectivly 1.1.3 V(s) # initialize x, y and z with s[0], s[1] and s[2] respectivly 1.1.4 V() # initialize x, y and z with zeros 1.2 numerical behavior == 1.2.1.1 v1 + s - v3 1.2.1.2 s + v1 - v3 1.2.1.3 v += s 1.2.2.1 v1 - s - v3 1.2.2.2 s - v1 - v3 1.2.2.3 v -= s 1.2.3.1 v1 * a - v3 1.2.3.2 a * v1 - v3 1.2.3.3 v *= a 1.2.4.1 v1 / a - v3 1.2.4.2 v /= a 1.2.5.1 v1 // a - v3 1.2.5.2 v //= a 1.2.6.1 v1 % a - v3 1.2.6.2 v %= a 1.2.7.1 v * s - a # dot/scalar/inner product 1.2.7.2 s * v - a # dot/scalar/inner product 1.2.8.1 +v1 - v2 # returns a new vector 1.2.8.2 -v1 - v2 1.3 sequence behavior = 1.3.1len(v) - 3 # fixed length 1.3.2.1 v[0] - a # 0-based indexing 1.3.2.2 v[0] = a 1.4 attributes == 1.4.0x, y, z (and w for 4th dimension)
Re: [pygame] API draft for vector type
On Tue, Apr 28, 2009 at 2:52 PM, Casey Duncan ca...@pandora.com wrote: On Apr 27, 2009, at 6:16 PM, René Dudfield wrote: Would be nice if the vectors storage of things could be anything underneath. This would be useful to allow them to use pygame.Rect or numpy.array underneath. This means they can refer to a batch of vectors, but also operate only on a single vector at a time. +1, though there are performance vs. generality tradeoffs to be made. On the general side, a vector class could assume the underlying storage supports __getitem__, but the performance of this would suffer, I think too greatly. On the performance side, it could just have a pointer to an array of floats that it wraps with the vector api. I used this strategy with Lepton and the performance is great, but it is inflexible for the storage, and probably not very practical for totally general use across different storages. ah, that's an interesting point. We could have a few special cases for giving a buffer to use. Then as it's written in C, there will only be one pointer indirection. Wondering about why only 3 element vectors? 2,3, and 4 element ones are common? Is there a way to make a combined 2,3,4 type? Most operations can assume the higher dimensions are always zero, or the length could just be variable. But in either case the code would be slower than it would strictly need to be, since many operations would do more work than needed or would require loops where they would not be required for single purpose 2D, 3D or better vectors. What number types are used? eg, can you have a float vector, a long vector, an int vector? Any python number? A uint8 ? Seems to me like the most general number type would be a double, as it could comfortably support a wide range, does not generally have resolution issues like a 32-bit float can and performs well on modern hardware. It would also give consistent results compared to a python float, which is nice. I'm not sure what the use-case is for ints or (python) longs, the latter would probably gain little by being coded in C compared to pure python. Even in sprite-based 2D games, I find integers to be far too coarse for vector math, and operations like normalize become basically impossible. If you support multiple vector numeric types, than you have to confront a combinatorial explosion of type conversions and either duplicate, templatize or generalize the code in such a way that you trade either performance or maintainability or both. -Casey Yeah, indeed. Old numeric used to auto-generate most of its code for different types. Also there is vectypes written in python that generates it's code for all of the different types ( http://code.google.com/p/vectypes/ ). You want to use ints for precision I guess... and other use cases too. eg, using 8bit uints can mean massive memory savings (a vector can fit in one word)... and you can also use less instructions to process a vector.
Re: [pygame] API draft for vector type
hi again, a slightly related point... consider that pygame already works with big multidimensional vectors of a limited amount of types - this is Surface. However it is limited to 1, 2, 3, and 4 uint8 multi dimensional vectors. For these limited cases it is fairly fast. It should be possible to make some sorts of really basic particle systems with Surface I guess. Having one image for positions, one for direction vectors, one for lifetime etc. To update the movement each frame, you'd use: position_surf.blit(directions_surf, (0,0), special_flags=BLEND_ADD) Would still need a fast way to draw each particle based on the pixels in each surface. If pygames functions/methods took more arrays it could be possible... eg. a Surface.blit_multi which took a buffer of destination rects. On Tue, Apr 28, 2009 at 3:06 PM, Casey Duncan ca...@pandora.com wrote: I have found this to be generally true as well, and storing a large number of individual vector objects to be operated on in a batch performs poorly regardless of implementation language. As an example, for Lepton I coded a controller object which looped over a large number of particles to update their velocities. Under the covers the particles are stored as a simple array of C structs, but you can iterate them and access the individual vectors for position, velocity, etc. from python. To make a long story short, the python version of the code that iterated and updated the velocities by manipulating vector objects was about 1600x slower than the equivalent C code that did the same using inline vector functions. psyco sped up the python code almost 5x, but it still was no contest. This is definitely an extreme case, but one relevant to game coding at least 8^) -Casey On Apr 27, 2009, at 7:24 PM, Daniel Jo wrote: I've pretty much abandoned the idea of vector classes in Python. I've tested various implementations: pure python classes (with and without __slots__), C++ exposed through Pyrex/Cython, tuples manipulated through add/mul/div/etc functions. . . Of these, C++ turned out to be the fastest, but faster by far than that was simply not using any structure at all. Store the components in tuples for convenience, but extract them and manipulated them individually for complex equations. Vector classes work well for convenience and code readability, but from a performance standpoint they aren't very useful. On Mon, Apr 27, 2009 at 4:28 PM, Brian Fisher br...@hamsterrepublic.com wrote: I don't see a 3 element vector type being useful from a pygame perspective. What pygame api anywhere even takes 3 element lists aside from colors? (which already have a special struct type thing) I'm not saying 3 element vectors don't have their uses - just that the seem to me to be a pretty random thing to have added to pygame, which is exclusively 2d in every interesting respect. It seems like the sort of thing to add that would add much more to the maintenance and testing cost of the pygame library than it would bring to the users as a whole. To put another way, there is no synergy between a 3 element vector class and pygame. Why would a 3 element vector class be better as part of pygame than not? what existing element of pygame is better or easier to use with a 3 element vector also being part of pygame? ...now a 2 element vector being part of pygame... rect could be better by making use of it, it could be used as an argument to the various functions that take 2 element lists, etc. etc ... and a 3 element vector (and quaternions and matrices) being part of pyOpenGL, that sounds great too... On Mon, Apr 27, 2009 at 2:59 PM, Lorenz Quack d...@amberfisharts.com wrote: Hello, I am interested in the inclusion of a vector and matrix types into pygame as suggested here [4]. In this email I want to propose a API for a vector module. I will for brevity only present the API for the types in three dimensions. The APIs for two or four dimensions should look analog. Also I enumerated every API for easier reference in discussions. Alternatives are denoted by lexical items (e.g. a) or b)) At the end I put together a small comparison to existing implementations. This is only a suggestion to spark discussion and provoke feedback. So throw in your 2 cents. sincerely yours //Lorenz PS: If this turns out to be of any value I will put something similar together for matrix types and quaternions. ** * API draft v1.0 * ** In the following I will use the notation: v, v1, v2, ... are vectors s, s1, s2, ... are objects implementing the sequences protocol (list, tuple, the proposed vector) a, a1, a2, ... are scalars (int, float) § 1 Vector type 1.1 Class name and constructor == 1.1.1 a) Vector3 b) Vector3d 1.1.2 V(a1, a2, a3)# initialize x, y and z with a1, a2 and a3