[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

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 <casey@xxxxxxxxxxx> 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 <brian@xxxxxxxxxxxxxxxxxxx > 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 <don@xxxxxxxxxxxxxxxxx> 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  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.7    v1.reflect(s) -> v2
       # reflects the vector of a surface with surface normal s
1.5.8    a) 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.9    v.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.0    the "==" 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
1.7.1.2  s == v -> bool
1.7.2.1  v != s -> bool
       # true unless all component differ at most by v._epsilon
1.7.2.2  s != v -> bool
1.7.3    bool(v) -> bool
       # returns true if any component is larger than v._epsilon
       # formerly known as v.__nonzero__


1.8 misc
======================
1.8.1  support iter protocol
1.8.2  str(v) -> "[x, y, z]"
1.8.3  repr(v) -> "Vec<x, y, z>"
1.8.4  support pickle protocol


1.10 open questions (in no particular order)
============================================
1.10.1  a) use radians for all angles
      b) use degrees for all angles
1.10.2  what about slicing?
1.10.3  what about swizzling?
1.10.4  do we need int or complex vectors?
1.10.5  what about negative indices in the sequence protocol?
1.10.6  is there need for explicit row- and column-vectors?





Contrast to existing implementations
####################################

There are of course already existing implementations of vector types. In
particular I want to take a look at pyeuclid [1], vectypes [2] and
3DVectorClass [3]. In this chapter I want to compare them and point out their similarities and differences. This isn't a full review but I tried
to
find out and describe the most important differences. If your favorite
implementation is missing from this comparison feel free to contribute
your
own analysis.  Disclaimer: I never used any of these.

numerical behaviour:
 * __add__ and __sub__:
 vectypes doesn't interact with other sequence types.
   e.g. "vec2() + [3, 4]" would not work.
 * __mul__ with other vectors
 pyeuclid doesn't support multiplication with anything but numbers
   e.g. "Vector2() * Vector2()" would not work
 vectypes and 3DVectorClass do elementwise multiplication
   e.g. "vec2(1,2) * vec2(3,4) == vec(1*3, 2*4)"
 this proposal preforms a dot product
   e.g. "V(1,2) * V(3,4) == 1*3 + 2*4"
 * __div__
pyeuclid and this proposal only support division by (int, long, float)
 vectypes and 3DVectorClass also do implicit elementwise division
 same for __floordiv__ and __mod__
 * __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

other differences:
 * from the mentioned packages only pyeuclid optionally supports
swizzleing
 * pyeuclid has a method "magnitude" instead of "length"
* vectypes uses functions at a module level rather than instance methods.
 * vectypes has a method refract
* pyeuclid has seperate geometry classes like "point", "line", "ray" and
 "lineSegment"
 * only 3DVectorClass and this proposal have built-in methods of
 the "rotate"-family


#################################################
[1] http://partiallydisassembled.net/euclid.html
[2] http://code.google.com/p/vectypes/
[3] http://pygame.org/wiki/3DVectorClass
[4]
http://pygame.org/wiki/gsoc2009ideas#Math%20for%20pygame%20(vectors,%20matrix,%20etc.)



<div><br></div>