Very fast & dirty rotations?

Started by
15 comments, last by Sander 20 years, 7 months ago
I''m still strugling with the physics of my particle system. This time I want to make the particles rotate around a vector. I read a lot today about rotating points about arbitrary vectors but most explanations are eighter too mathematical for me to comprehend (mathworld, etcetera) or just give the general solution: convert to quaternion -> apply rotation -> convert to matrix3x3 -> apply to vector. That sounds so awefully slow. I need a really quick and dirty way because I can have up to 4096 particles per frame (and loads more when I get myself a real video card instead of a TNT2), each with a unique position and a unique rotation vector. In short: I''m looking for a function that takes a point, a (unit)vector and an angle and returns the rotated point. Accucary isn''t important, speed is. Any idea''s? Sander Maréchal [Lone Wolves Game Development][RoboBlast][Articles][GD Emporium][Webdesign][E-mail]

<hr />
Sander Marechal<small>[Lone Wolves][Hearts for GNOME][E-mail][Forum FAQ]</small>

Advertisement
i know this isnt the answer you want, but if you dont mind losing some accuracy and you want some speed, why don''t you group bunches of particles together at various positions and rotate all of them around an arbitary axis, and have like 32 of these groups, each containing 128 polygons. if you do it this way, you might be able to make up for some of the speed done with the calculations
"a low level aho master like you couldn't kill me even if I let you"
Don''t you need center of rotation too?

Anyhow, one way to do rotations is to calculate the cross product of angular velocity vector and the vector from the center of rotation to the point you''re trying to rotate. Then add the resultant vector to the point being rotated.

Hope that helps..
--bart

// Somewhere Global or in a Class
int *sin_tab = new int[360];
int *cos_tab = new int[360];


// in the Init Function
for (int i = 0; i<360;i++)
sin_tab = (int)sin(i);
for (i = 0; i<360;i++)
cos_tab = (int)cos(i);<br><br><br>Fast & Dirty…<br><br> </i>
J.A.N.K.E.Y.: Journeying Artificial Nocturnal Killing and Exploration Youth
I''m not sure if you''ve already read this, but this has a good explanation of rotation about an aribrary axis using matrices.
Thanks all.

@Tooot: That article should be renamed "rotation around an arbitrary axis that is parallel to one of the main axes.

@Jankey: I knew that trick already. Been using it since my BASIC days some ehhh... 14(?) years ago...

@bpj1138: That sounds more promising. I''ll take a look into angular velocities.

@Uthman: That would be a goodsolution if the stream of particles is pretty steady (and the general velocity somewhat the same). robjem is, I want the particle system attached to the payer (which moves a lot). So almost every particle is going to have a unique axis of rotation. I could group at most 8 or 16 together, but that would mean tracking and clustering 4096 particles in 256 - 512 groups. I think that the increased time of tracking and clustering all of these will offset the speed gain by doing multiple rotations at once.

Sander Maréchal
[Lone Wolves Game Development][RoboBlast][Articles][GD Emporium][Webdesign][E-mail]

<hr />
Sander Marechal<small>[Lone Wolves][Hearts for GNOME][E-mail][Forum FAQ]</small>

@Sander: ok, no newbie.
Had the same problem as you a few months ago:

In short: I''m looking for a function that takes a point, a (unit)vector and an angle and returns the rotated point. Accucary isn''t important, speed is. Any idea''s?

Look for a Advanced Quaterion Lib, to Convert the Vector into a Quation, multyply both and then, Quaterion.RotateGL();

Dont Learn to Understand a Library, just use it
J.A.N.K.E.Y.: Journeying Artificial Nocturnal Killing and Exploration Youth
You should have asked to Dr Maths

OK each particule has a unique axis of rotation.
But in the end how do you want to render such particules ? Quads that may appear flat in front of the viewer ? Or always as impostors ?

In anyway if you want to transform quickly. The problem is matrix rotation. That's slow and this denormalizes the matrices. So you have to use quaternions instead. W (Omega) = rotationnal speed as a quaternion. Now you can transform your quad vertices directly as P'=W*P, it's as fast as a matrix. But beware that precision errors after each rotation may scale your quads. Another slution is to maintain Q (Position) as a quaternion. Make a quat mul each time. then same thing but accelerated since you quad verts are box (+-r,+-r,0) corners. That's the best solution.

BTW it's nearly equivalent to the cross prod trick of bpj. ^ seems more seducing tho but beware that it scales your quads continuously.

            b            I  cross prod added (bpj)o____________a ob>oa necessarilly (Phytagoros). thus you need to rescale ob each time by a constant .... which gives the exact quat*point formula ....   


There can be different solutions depending on if you want to maintain you quad vertices or recompute them on the fly by maintaining a position instead. Both solutions cost nearly the same ( around 16 floats all counted ).

Else maybe it could be worse thinking 2D and impostors, in the z planes of the impostors. Then simple cached trigonometry as someone mentionned here.

Well you know where we can continue this discussion in details.

[edited by - Charles B on September 3, 2003 2:42:08 PM]
"Coding math tricks in asm is more fun than Java"
Woah.. This is getting interesting

@Jankey: Quaternions sound good, especially if I don''t neet to convert them to full matrices before I can apply them to my points. I assume that my "Quaterion.RotateGL();" you mean calling glRotatef() and let the video card handle it. If that is what you mean than it won''t be possible. (If you mean something else, please let me know.

First, it would use up 4096 glPushMatrix(), glRotaef(), glPopMatrix sequences (or 8192 glRotatef()''s if you invert the rotations). That''s going to be a major slowdown on the graphics card, which already suffers from the sheer amount of particles. Second, it would force me back into OpenGL Immediate mode, calling 4096 glBegin/glEnd pairs for every particle (or a 4096 glDrawArrays() call with only 4 elements in it). At the moment, I use regular arrays and only one call to glDrawArrays, which is much faster.

@Charles variation of BPJ: That looks very good. I indeed want to rotate only the particle position (one point), since I split the update function into two parts. One part particle physics update, one part buffer filling (where the position get exploded to 4 vertices). I might go with BPJ''s original though. I actually *want* my particles to scale. Now I build in a separate scaling factor to do this for me using randomized vectors perpendicular to the axis of rotation (which is slow at initialization and marginally fast at update time). Looks like I can actually get an added rotation for the cost of one dotproduct and a vector-to-quaternion per particle.

Things are looking up for me!


Sander Maréchal
[Lone Wolves Game Development][RoboBlast][Articles][GD Emporium][Webdesign][E-mail]

<hr />
Sander Marechal<small>[Lone Wolves][Hearts for GNOME][E-mail][Forum FAQ]</small>

I dont know opengl but in Directx there is a vertex format called
transformed lit vertices (D3DFVF_XYZRHW ). In this format no world , view and projection transformation is applied to vertices. This is very useful to drawing quads to screen without calculating appropriate matrices.

In a partical system I think you can calculate the positions of the
quads using traditional x''=f*x/z, y''=f*y/z projection. Then render the quads.
I think there will be a matrix vector multiply to find x,y,z in camera space and the two projection calculation for each quad.

I did not try this but it seem very logical to me. But I dont know is there exists such a vertex format.
be yourself.

This topic is closed to new replies.

Advertisement