Rotating images with the GU?
-
- Posts: 21
- Joined: Sat Nov 28, 2009 10:56 am
Rotating images with the GU?
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?
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?
-
- Posts: 21
- Joined: Sat Nov 28, 2009 10:56 am
Try using the sceGum* functions.
I don't think it'll work with GU_SPRITES, though; use GU_TRIANGLE_FAN or the like.
Code: Select all
sceGumMatrixMode(GU_MODEL); // EDIT
sceGumPushMatrix();
sceGumLoadIdentity();
sceGumRotateZ(angle);
sceGumDrawArray(...);
sceGumPopMatrix();
Yes. :) (Just make sure GUM gets it as radians.)gotmilk065 wrote:And at high speeds, is it radians or degrees?
"You hungry? I haven't eaten since later this afternoon."
-
- Posts: 21
- Joined: Sat Nov 28, 2009 10:56 am
Well here's what's going on in the function, doesn't work :(
I'm sad that it 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[static_cast<int>(pparticle->color)];
int i = BufIdx;
vertices[i].first.x = pparticle->org[0] - scale*(up[0] + right[0]);
vertices[i].first.y = pparticle->org[1] - scale*(up[1] + right[1]);
vertices[i].first.z = pparticle->org[2] - scale*(up[2] + right[2]);
vertices[i].first.s = 0.0;
vertices[i].first.t = 0.0;
if (pparticle->alpha)
vertices[i].first.color = GU_RGBA(128, 128, 128, int(alpha));
else
vertices[i].first.color = color;
vertices[i].second.x = pparticle->org[0] + scale*(up[0] + right[0]);
vertices[i].second.y = pparticle->org[1] + scale*(up[1] + right[1]);
vertices[i].second.z = pparticle->org[2] + scale*(up[2] + right[2]);
vertices[i].second.s = 1.0;
vertices[i].second.t = 1.0;
if (pparticle->alpha)
vertices[i].second.color = GU_RGBA(128, 128, 128, int(alpha));
else
vertices[i].second.color = color;
BufIdx++;
if (BufIdx >= BufSize) {
sceGuDrawArray(GU_TRIANGLE_STRIP, GU_VERTEX_32BITF|GU_TEXTURE_32BITF|GU_COLOR_8888, BufSize, 0, vertices);
BufIdx = 0;
BufSize = -1;
sceGumPopMatrix();
return -1;
}
sceGumPopMatrix();
return BufIdx;
}
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). This may sound contra-intuitive, but is logical from a mathematical point of view.
Sample code from triEngine:
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(&pos);
sceGumRotateZ(angle);
Sample code from triEngine:
Code: Select all
sceGumPushMatrix();
sceGumLoadIdentity();
ScePspFVector3 trans;
trans.x = (x + width/2);
trans.y = (y + height/2);
trans.z = 0;
sceGumTranslate( &trans );
sceGumRotateZ( angle*GU_PI/180 );
triVertUV* vertices = (triVertUV*)sceGuGetMemory(4 * sizeof(triVertUV));
vertices[0].u = u0;
vertices[0].v = v0;
vertices[0].x = -(width/2);
vertices[0].y = -(height/2);
vertices[0].z = 0;
vertices[1].u = u0;
vertices[1].v = v1;
vertices[1].x = -(width/2);
vertices[1].y = (height/2);
vertices[1].z = 0;
vertices[2].u = u1;
vertices[2].v = v1;
vertices[2].x = (width/2);
vertices[2].y = (height/2);
vertices[2].z = 0;
vertices[3].u = u1;
vertices[3].v = v0;
vertices[3].x = (width/2);
vertices[3].y = -(height/2);
vertices[3].z = 0;
sceGumDrawArray(GU_TRIANGLE_FAN,GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_3D,4,0,vertices);
sceGumPopMatrix();
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki
Alexander Berl
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki
Alexander Berl
-
- Posts: 21
- Joined: Sat Nov 28, 2009 10:56 am
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
If I can't get this working, I'll have to say goodbye to rotating particles and just stick with the static ones :(
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();
sceGumLoadIdentity();
ScePspFVector3 trans;
trans.x = (pparticle->org[0] + scale/2);
trans.y = (pparticle->org[1] + scale/2);
trans.z = (pparticle->org[2] + scale/2);
sceGumTranslate(&trans);
sceGumRotateZ(rot*GU_PI/180);
unsigned int color = d_8to24table[static_cast<int>(pparticle->color)];
struct part_vertex {
float s, t;
unsigned int color;
float x, y, z;
};
part_vertex* const vertices = static_cast<part_vertex*>(sceGuGetMemory(4*sizeof(part_vertex)));
vertices[0].x = -(scale/2);
vertices[0].y = -(scale/2);
vertices[0].z = 0;
vertices[0].s = 0.0;
vertices[0].t = 0.0;
vertices[1].x = -(scale/2);
vertices[1].y = (scale/2);
vertices[1].z = 0;
vertices[1].s = 1.0;
vertices[1].t = 1.0;
vertices[2].x = (scale/2);
vertices[2].y = (scale/2);
vertices[2].z = 0;
vertices[2].s = 1.0;
vertices[2].t = 1.0;
vertices[3].x = (scale/2);
vertices[3].y = -(scale/2);
vertices[3].z = 0;
vertices[3].s = 1.0;
vertices[3].t = 1.0;
if (pparticle->alpha) {
vertices[0].color = GU_RGBA(128, 128, 128, int(pparticle->alpha));
vertices[1].color = GU_RGBA(128, 128, 128, int(pparticle->alpha));
vertices[2].color = GU_RGBA(128, 128, 128, int(pparticle->alpha));
vertices[3].color = GU_RGBA(128, 128, 128, int(pparticle->alpha));
} else {
vertices[0].color = color;
vertices[1].color = color;
vertices[2].color = color;
vertices[3].color = color;
}
sceGuDrawArray(GU_TRIANGLE_FAN, GU_VERTEX_32BITF|GU_TEXTURE_32BITF|GU_COLOR_8888|GU_TRANSFORM_3D, 4, 0, vertices);
sceGumPopMatrix();
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:
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.
This should be correct:
Code: Select all
vertices[0].x = -(scale/2);
vertices[0].y = -(scale/2);
vertices[0].z = 0;
vertices[0].s = 0.0;
vertices[0].t = 0.0;
vertices[1].x = -(scale/2);
vertices[1].y = (scale/2);
vertices[1].z = 0;
vertices[1].s = 0.0;
vertices[1].t = 1.0;
vertices[2].x = (scale/2);
vertices[2].y = (scale/2);
vertices[2].z = 0;
vertices[2].s = 1.0;
vertices[2].t = 1.0;
vertices[3].x = (scale/2);
vertices[3].y = -(scale/2);
vertices[3].z = 0;
vertices[3].s = 1.0;
vertices[3].t = 0.0;
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki
Alexander Berl
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki
Alexander Berl
-
- Posts: 21
- Joined: Sat Nov 28, 2009 10:56 am
-
- Posts: 21
- Joined: Sat Nov 28, 2009 10:56 am