Rotating images with the GU?

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
gotmilk065
Posts: 21
Joined: Sat Nov 28, 2009 10:56 am

Rotating images with the GU?

Post by gotmilk065 »

I wanted to enhance my particle engine a bit, and the next step is to rotate the smoke particles for a better effect.

Problem is, everything I see on rotating images is done on the CPU and involves essentially resampling the image! Isn't there a simple command to change the rotation of vertices and textures about to be rendered, and then switch it back when it's done?
jsharrad
Posts: 100
Joined: Thu Oct 20, 2005 3:06 am

Post by jsharrad »

use the sceGuRotate functions
gotmilk065
Posts: 21
Joined: Sat Nov 28, 2009 10:56 am

Post by gotmilk065 »

I tried that but it flips the entire screen.. And at high speeds, is it radians or degrees?
Criptych
Posts: 64
Joined: Sat Sep 12, 2009 5:18 am

Post by Criptych »

Try using the sceGum* functions.

Code: Select all

sceGumMatrixMode(GU_MODEL); // EDIT

sceGumPushMatrix();
sceGumLoadIdentity();

sceGumRotateZ(angle);
sceGumDrawArray(...);

sceGumPopMatrix();
I don't think it'll work with GU_SPRITES, though; use GU_TRIANGLE_FAN or the like.
gotmilk065 wrote:And at high speeds, is it radians or degrees?
Yes. :) (Just make sure GUM gets it as radians.)
"You hungry? I haven't eaten since later this afternoon."
gotmilk065
Posts: 21
Joined: Sat Nov 28, 2009 10:56 am

Post by gotmilk065 »

Well here's what's going on in the function, doesn't work :(

Code: Select all

int D_DrawParticleBuffered (psp_particle* vertices, particle_t *pparticle, vec3_t up, vec3_t right, float scale, float alpha, float rot) {

	sceGumMatrixMode(GU_MODEL); // EDIT
	
	sceGumPushMatrix();
	sceGumLoadIdentity();

	sceGumRotateZ(rot);

	unsigned int color = d_8to24table&#91;static_cast<int>&#40;pparticle->color&#41;&#93;;
	int i = BufIdx;

	vertices&#91;i&#93;.first.x = pparticle->org&#91;0&#93; - scale*&#40;up&#91;0&#93; + right&#91;0&#93;&#41;;
	vertices&#91;i&#93;.first.y = pparticle->org&#91;1&#93; - scale*&#40;up&#91;1&#93; + right&#91;1&#93;&#41;;
	vertices&#91;i&#93;.first.z = pparticle->org&#91;2&#93; - scale*&#40;up&#91;2&#93; + right&#91;2&#93;&#41;;
	vertices&#91;i&#93;.first.s = 0.0;
	vertices&#91;i&#93;.first.t = 0.0;
	
	if &#40;pparticle->alpha&#41;
		vertices&#91;i&#93;.first.color = GU_RGBA&#40;128, 128, 128, int&#40;alpha&#41;&#41;;
	else
		vertices&#91;i&#93;.first.color = color;
	
	vertices&#91;i&#93;.second.x = pparticle->org&#91;0&#93; + scale*&#40;up&#91;0&#93; + right&#91;0&#93;&#41;;
	vertices&#91;i&#93;.second.y = pparticle->org&#91;1&#93; + scale*&#40;up&#91;1&#93; + right&#91;1&#93;&#41;;
	vertices&#91;i&#93;.second.z = pparticle->org&#91;2&#93; + scale*&#40;up&#91;2&#93; + right&#91;2&#93;&#41;;
	vertices&#91;i&#93;.second.s = 1.0;
	vertices&#91;i&#93;.second.t = 1.0;

	if &#40;pparticle->alpha&#41;
		vertices&#91;i&#93;.second.color = GU_RGBA&#40;128, 128, 128, int&#40;alpha&#41;&#41;;
	else
		vertices&#91;i&#93;.second.color = color;

    BufIdx++;

    if &#40;BufIdx >= BufSize&#41; &#123;
    	sceGuDrawArray&#40;GU_TRIANGLE_STRIP, GU_VERTEX_32BITF|GU_TEXTURE_32BITF|GU_COLOR_8888, BufSize, 0, vertices&#41;;
    	BufIdx = 0;
    	BufSize = -1;

		sceGumPopMatrix&#40;&#41;;
    	return -1;
    &#125;
	sceGumPopMatrix&#40;&#41;;
    return BufIdx;
&#125;
I'm sad that it doesn't work :<
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Post by Raphael »

1.) you seem to try to save some vertices for your particles, to build them all as one large triangle-strip and only adding the bottom-left and top-right vertex. This won't work. You need to render each particle as a seperate triangle-strip or triangle-fan with four vertices. The only option is to use GU_SPRITE with two vertices and apply the rotation on the texture coordinates, rather than the vertex coordinates, but you have to make sure that the rotated texture corners won't get clipped inside the sprite.

2.) With your current implementation, you always apply the rotation of the current particle to the model matrix, then undo it (with sceGumPopMatrix). The only time, the rotation will get applied is in the case when your buffer gets filled (BufIdx>=BufSize), in which case only the rotation of the current particle will get applied to the draw (because all others have been undone before the render command got sent).

3.) You rotate all your particle vertices around the world-view Z axis. This is doubtly what you want. You probably want to rotate the particles around their own center, hence you need to translate the vertice positions into object space (or directly set them in object space - ie place vertices relative to the particles center) and translate them back after the rotation. Since sceGum transformation matrix is applied from left to right, you need to do the back-translation *before* the rotation command (ie

Code: Select all

sceGumTranslate&#40;&pos&#41;;
sceGumRotateZ&#40;angle&#41;;
). This may sound contra-intuitive, but is logical from a mathematical point of view.


Sample code from triEngine:

Code: Select all

sceGumPushMatrix&#40;&#41;;
sceGumLoadIdentity&#40;&#41;;
ScePspFVector3 trans;
trans.x = &#40;x + width/2&#41;;
trans.y = &#40;y + height/2&#41;;
trans.z = 0;
sceGumTranslate&#40; &trans &#41;;
sceGumRotateZ&#40; angle*GU_PI/180 &#41;;

triVertUV* vertices = &#40;triVertUV*&#41;sceGuGetMemory&#40;4 * sizeof&#40;triVertUV&#41;&#41;;
vertices&#91;0&#93;.u = u0;
vertices&#91;0&#93;.v = v0;
vertices&#91;0&#93;.x = -&#40;width/2&#41;;
vertices&#91;0&#93;.y = -&#40;height/2&#41;;
vertices&#91;0&#93;.z = 0;

vertices&#91;1&#93;.u = u0;
vertices&#91;1&#93;.v = v1;
vertices&#91;1&#93;.x = -&#40;width/2&#41;;
vertices&#91;1&#93;.y = &#40;height/2&#41;;
vertices&#91;1&#93;.z = 0;
	
vertices&#91;2&#93;.u = u1;
vertices&#91;2&#93;.v = v1;
vertices&#91;2&#93;.x = &#40;width/2&#41;;
vertices&#91;2&#93;.y = &#40;height/2&#41;;
vertices&#91;2&#93;.z = 0;

vertices&#91;3&#93;.u = u1;
vertices&#91;3&#93;.v = v0;
vertices&#91;3&#93;.x = &#40;width/2&#41;;
vertices&#91;3&#93;.y = -&#40;height/2&#41;;
vertices&#91;3&#93;.z = 0;

sceGumDrawArray&#40;GU_TRIANGLE_FAN,GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_3D,4,0,vertices&#41;;

sceGumPopMatrix&#40;&#41;;
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki

Alexander Berl
gotmilk065
Posts: 21
Joined: Sat Nov 28, 2009 10:56 am

Post by gotmilk065 »

I'm simply not getting this o_o

Your first solution seems simplest, rotate the texture instead of the poly itself, but the whole repeating texture deal if it exceeds the bounds kind of ruins it.

I'm totally lost. Here's my new function, but it's not even displaying the particles at all o.o

Code: Select all

	sceGumPushMatrix&#40;&#41;;
	sceGumLoadIdentity&#40;&#41;;
	ScePspFVector3 trans;
	trans.x = &#40;pparticle->org&#91;0&#93; + scale/2&#41;;
	trans.y = &#40;pparticle->org&#91;1&#93; + scale/2&#41;;
	trans.z = &#40;pparticle->org&#91;2&#93; + scale/2&#41;;
	sceGumTranslate&#40;&trans&#41;;
	sceGumRotateZ&#40;rot*GU_PI/180&#41;; 

	unsigned int color = d_8to24table&#91;static_cast<int>&#40;pparticle->color&#41;&#93;;
	
	struct part_vertex &#123;
		float s, t;
		unsigned int color;
		float x, y, z;
	&#125;;

	part_vertex* const vertices = static_cast<part_vertex*>&#40;sceGuGetMemory&#40;4*sizeof&#40;part_vertex&#41;&#41;&#41;;

	vertices&#91;0&#93;.x = -&#40;scale/2&#41;;
	vertices&#91;0&#93;.y = -&#40;scale/2&#41;;
	vertices&#91;0&#93;.z = 0;
	vertices&#91;0&#93;.s = 0.0;
	vertices&#91;0&#93;.t = 0.0;

	vertices&#91;1&#93;.x = -&#40;scale/2&#41;;
	vertices&#91;1&#93;.y = &#40;scale/2&#41;;
	vertices&#91;1&#93;.z = 0;
	vertices&#91;1&#93;.s = 1.0;
	vertices&#91;1&#93;.t = 1.0;

	vertices&#91;2&#93;.x = &#40;scale/2&#41;;
	vertices&#91;2&#93;.y = &#40;scale/2&#41;;
	vertices&#91;2&#93;.z = 0;
	vertices&#91;2&#93;.s = 1.0;
	vertices&#91;2&#93;.t = 1.0;
	
	vertices&#91;3&#93;.x = &#40;scale/2&#41;;
	vertices&#91;3&#93;.y = -&#40;scale/2&#41;;
	vertices&#91;3&#93;.z = 0;
	vertices&#91;3&#93;.s = 1.0;
	vertices&#91;3&#93;.t = 1.0;
	
	if &#40;pparticle->alpha&#41; &#123;
		vertices&#91;0&#93;.color = GU_RGBA&#40;128, 128, 128, int&#40;pparticle->alpha&#41;&#41;;
		vertices&#91;1&#93;.color = GU_RGBA&#40;128, 128, 128, int&#40;pparticle->alpha&#41;&#41;;
		vertices&#91;2&#93;.color = GU_RGBA&#40;128, 128, 128, int&#40;pparticle->alpha&#41;&#41;;
		vertices&#91;3&#93;.color = GU_RGBA&#40;128, 128, 128, int&#40;pparticle->alpha&#41;&#41;;
	&#125; else &#123;
		vertices&#91;0&#93;.color = color;
		vertices&#91;1&#93;.color = color;
		vertices&#91;2&#93;.color = color;
		vertices&#91;3&#93;.color = color;
	&#125;

	sceGuDrawArray&#40;GU_TRIANGLE_FAN, GU_VERTEX_32BITF|GU_TEXTURE_32BITF|GU_COLOR_8888|GU_TRANSFORM_3D, 4, 0, vertices&#41;;
	
	sceGumPopMatrix&#40;&#41;;
If I can't get this working, I'll have to say goodbye to rotating particles and just stick with the static ones :(
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Post by Raphael »

The only thing that is still wrong now, is that the vertices texture coordinates aren't set correctly, which *might* cause the particles to not appear, depending on the texture used.
This should be correct:

Code: Select all

   vertices&#91;0&#93;.x = -&#40;scale/2&#41;;
   vertices&#91;0&#93;.y = -&#40;scale/2&#41;;
   vertices&#91;0&#93;.z = 0;
   vertices&#91;0&#93;.s = 0.0;
   vertices&#91;0&#93;.t = 0.0;

   vertices&#91;1&#93;.x = -&#40;scale/2&#41;;
   vertices&#91;1&#93;.y = &#40;scale/2&#41;;
   vertices&#91;1&#93;.z = 0;
   vertices&#91;1&#93;.s = 0.0;
   vertices&#91;1&#93;.t = 1.0;

   vertices&#91;2&#93;.x = &#40;scale/2&#41;;
   vertices&#91;2&#93;.y = &#40;scale/2&#41;;
   vertices&#91;2&#93;.z = 0;
   vertices&#91;2&#93;.s = 1.0;
   vertices&#91;2&#93;.t = 1.0;
   
   vertices&#91;3&#93;.x = &#40;scale/2&#41;;
   vertices&#91;3&#93;.y = -&#40;scale/2&#41;;
   vertices&#91;3&#93;.z = 0;
   vertices&#91;3&#93;.s = 1.0;
   vertices&#91;3&#93;.t = 0.0;
EDIT: I just remembered that it could also be due to your backface culling order, that the particles don't show. If the above still won't show anything and you are sure your view/projection matrices are correct, try switching vertice[1] and vertice[3] values, so the winding order gets inverted.
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki

Alexander Berl
gotmilk065
Posts: 21
Joined: Sat Nov 28, 2009 10:56 am

Post by gotmilk065 »

I'll try that when I get home.

Until then; Merry Christmas!
gotmilk065
Posts: 21
Joined: Sat Nov 28, 2009 10:56 am

Post by gotmilk065 »

:( I even did so much as disabling backfacing; they still don't appear.

Just to let you know, the old function did work, the buffered one, but without rotation, and I had something before that worked withou the buffer or the rotation.
Post Reply