movement|navigation problem
movement|navigation problem
i now updated my movement
(
had the problem that you rotate left --> rotates left
you rotate up 180° and rotate left --> rotates right
)
changed that now -> works fine
one problem still left.
when i move the object out of center it rotates around center instead around model-axis.
download here to test
start = reset
select = screenshot
greets
lumo
(
had the problem that you rotate left --> rotates left
you rotate up 180° and rotate left --> rotates right
)
changed that now -> works fine
one problem still left.
when i move the object out of center it rotates around center instead around model-axis.
download here to test
start = reset
select = screenshot
greets
lumo
The rotate operation works on the centre of the world, you need to:
EDIT: thanks to PlayfulPuppy for pointing out that I had the translate & rotate backwards. (can you tell its been a while since i've actually done any coding 'for fun' ??)
- * push the current matrix
* do the rotation
* translate to the centre of the object you wish to rotate
* draw the object
* pop the matrix back
EDIT: thanks to PlayfulPuppy for pointing out that I had the translate & rotate backwards. (can you tell its been a while since i've actually done any coding 'for fun' ??)
Last edited by cheriff on Fri May 12, 2006 7:48 pm, edited 2 times in total.
Damn, I need a decent signature!
-
- Posts: 22
- Joined: Fri May 05, 2006 12:04 am
Or you could cut out the middle-man and just do the rotation before you do the translation.cheriff wrote:The rotate operation works on the centre of the world, you need to:not sure if psp can push/pop (i assume so) but if not just translate again by the opposite amount
- * push the current matrix
* translate to the centre of the object you wish to rotate
* do the rotation
* pop the matrix back
-
- Posts: 22
- Joined: Fri May 05, 2006 12:04 am
Same problem with you.
Code: Select all
sceGumTranslate(&pos);
sceGumPushMatrix();
sceGumRotateZ(rotationAmount);
// Draw Array
sceGumPopMatrix();
Code: Select all
sceGumRotateZ(rotationAmount);
sceGumTranslate(&pos);
// Draw Array
The reason you were getting problems is because, as mentioned earlier, the rotate functions ONLY rotate around the origin (0, 0, 0). So even when you translated the object away from the origin, it would still be rotating around it, which is why it was moving around in a circle.
-
- Posts: 22
- Joined: Fri May 05, 2006 12:04 am
Ah it's all good, I confuse them myself quite often and I do this stuff for a living! ;)cheriff wrote:ah crap, i got it backwards..
PlayfulPuppy: cheers for catching that one out, original post edited ;)
And LuMo, after you make this change you'll probably discover that your object won't move in the direction he's facing anymore (I don't know if this is what you were trying to do, your site wont load for me).
Anyway, if you are, there's an easy way to get around it.
Matricies are stored in such a fashion that you can extract vectors from them that represent the X, Y and Z axis' even after the object has been rotated. Since it's in 3D, an axis is represented as a 3D point in space (That's exactly 1.0 units away from the origin). Matricies are ordered like this (First row is matrix.f[0][0], last row is matrix.f[4][0]):
Code: Select all
Matrix4x4:
[x.x][y.x][z.x][0]
[x.y][y.y][z.y][0]
[x.z][y.z][z.z][0]
[p.x][p.y][p.z][1]
So to grab a vector that represents the direction your character is facing, do the following after you've set the rotation of the matrix:
Code: Select all
scePspFVector3 dirVec; // Vector to store our direction in
ScePspFMatrix4 mat; // Copy of the matrix that's currently on the stack
sceGumStoreMatrix(&mat); // Get a copy of the current matrix on the stack
// Retrieve the X axis from the matrix
dirVec.x = mat.f[0][0];
dirVec.y = mat.f[1][0];
dirVec.z = mat.f[2][0];
Now you can just add that vector (dirVec) to the position of your object, and it will move forwards one unit in the direction it's facing.
Code: Select all
scePspFVector3 objPos; // Position of the object
objPos.x += dirVec.x;
objPos.y += dirVec.y;
objPos.z += dirVec.z;
// Apply the object position to the current matrix
sceGumTranslate(&objPos);
Code: Select all
float length = 0.5;
dirVec.x *= length;
dirVec.y *= length;
dirVec.z *= length;
Hope this has been useful to someone!
-
- Posts: 22
- Joined: Fri May 05, 2006 12:04 am
You could use Quaternions to do an axis-angle rotation (Which you'd have to implement yourself, and quaternions are bloody difficult to understand), or you could multiply several matricies together.Ess wrote:how would i go about rotating around an arbitrary axis with pspgu?
Start by creating one matrix by rotating around the Y axis:
Code: Select all
ScePspFMatrix4 angleMat;
gumRotateY(&angleMat, angle);
Now, this method isn't perfect. First of all, it doesn't deal well if your Y axis is pointing down positive Z, but we can compensate for that.
Anyway, what we're going to do is create 3 axis' from the one axis you supply. We can do this by using the cross product, which creates a vector that's orthogonal to 2 other vectors. Basically, if means that if you used the cross product on the X and Y vectors, you'd get the Z vector. If you used the cross product on the Y and Z vectors, you'd get the X vector. It's kinda hard to describe without pictures, but have a look around on the 'net and you should be able to find something.
Anyway, I'll start with the code first, then explain it in more detail:
Code: Select all
ScePspFVector3 axis; // This is our axis to rotate around (Set it to whatever you want)
ScePspFVector3 xAxis, yAxis;
ScePspFVector3 zAxis = {0.0f, 0.0f, 1.0f}; // Create a dummy Z axis for reference
yAxis = axis; // We're going to be rotating around the Y axis (Up) with our angle
gumNormalize(&yAxis); // Make sure this vector is normalized (Has a length of 1.0f)
// NOTE: These cross-products are untested, you may have to switch the last 2 values
// if your object/rotation seems to be inverted after applying the matrix
gumCrossProduct(&xAxis, &zAxis, &yAxis); // Create the X axis from the Z and Y axis'
gumCrossProduct(&zAxis, &xAxis, &yAxis); // Fix up the Z axis so it's correct
ScePspMatrix4 axisMat;
gumLoadIdentity((ScePspFMatrix4*)&axisMat);
axisMat.f[0][0] = xAxis.x; // Copy the X axis into our matrix
axisMat.f[1][0] = xAxis.y;
axisMat.f[2][0] = xAxis.z;
axisMat.f[0][1] = yAxis.x; // Copy the Y axis into our matrix
axisMat.f[1][1] = yAxis.y;
axisMat.f[2][1] = yAxis.z;
axisMat.f[0][2] = zAxis.x; // Copy the Z axis into our matrix
axisMat.f[1][2] = zAxis.y;
axisMat.f[2][2] = zAxis.z;
Then, we create the X axis by doing a cross product between our dummy Z axis and our supplied Y axis. This axis will be correct, even though we're using a 'fake' Z axis. HOWEVER, if your supplied axis (Y) is equal to (0, 0, 1), or facing directly down the Z axis, the X axis will equal 0. This is a problem using this technique. There is a way around it, however. Insert this code before doing the cross products:
Code: Select all
if(yAxis.z == 1.0f)
{
zAxis.x = 0.0f;
zAxis.y = -1.0f;
zAxis.z = 0.0f;
}
else if(yAxis.z == -1.0f)
{
zAxis.x = 0.0f;
zAxis.y = 1.0f;
zAxis.z = 0.0f;
}
There's still one last problem, being that if the Y axis is below the horizon (Its Y component is < 0), the Z axis will be pointing in the wrong direction and our X axis will invert, due to the way the cross-product works. Yet again, we can account for this by doing the following before the above code:
Code: Select all
if(yAxis.y < 0.0f)
{
zAxis.x = 0.0f;
zAxis.y = 0.0f;
zAxis.z = -1.0f;
}
Due to the fact our Z axis is an approximation, we just need to be sure that it's facing the right way. This code should take care of that (Although may require tweaking).
Anyways, after we've got the X axis, we need to fix up the Z axis. If we just left it the way it was at this point, your model would skew because the Z axis is not correct, we were only using the previously set values as an approximation. However, since we now have the X and Y axis', we can do a cross product on them and get the correct Z axis! The cross product is a very useful little function like that. (Yet again, I may have got these values the wrong way around, even if the one above it was correct. If your model seems to be facing the wrong way down the Z axis, swap these values).
And that's basically it! Now we just copy the values into our matrix, and we've successfully created a whole matrix out of a single vector.
Now all that's left to do is to apply our rotation matrix (angleMat) to this matrix. We can do this by multiplying them together:
Code: Select all
ScePspFMatrix4 finalMat;
gumMultMatrix(&finalMat, &angleMat, (ScePspFMatrix4*)&axisMat);
Code: Select all
ScePspFVector3 objPos; // The position of our object
gumTranslate(&finalMat, &objPos);
Man, that's a long-arse post. I should write an FAQ on this or something. :P
-
- Posts: 22
- Joined: Fri May 05, 2006 12:04 am
Oh, you mean rotating around an arbitrary point! Rotating around an arbitrary axis is quite a different thing.Ess wrote:Thank you PlayfulPuppy for your response.
How about doing the rotation on a new matrix, and then doing the translation on another new matrix and then multiplying them?
I don't know if that would be easier, but I would understand it easier.
Yes, to do that you need a point of rotation, a point in space (Relative to the object) that determines where the rotation will take place.
1) Translate using the negative point of rotation. (0 minus Point of rotation)
2) Rotate the object
3) Translate back to the origin using the point of rotation
4) Translate to where you want the object to be in the world.
The problem I am having is with a game I am trying to develop. It is (to be) a 2D overhead shooter. The player stays static on the screen and the "world" rotates and moves around him.
This means the world will always rotate around 0,0,0.
I tried rotating --> translating, but then when i tell the player to move forward, the player moves diagonally according to the angle I have rotated. And the "world" just keeps rotating on the same point. I want the point to move wherever the player is.
Does that make sense?
This means the world will always rotate around 0,0,0.
I tried rotating --> translating, but then when i tell the player to move forward, the player moves diagonally according to the angle I have rotated. And the "world" just keeps rotating on the same point. I want the point to move wherever the player is.
Does that make sense?
-
- Posts: 22
- Joined: Fri May 05, 2006 12:04 am
What you actually want to be doing here is not moving the world, but moving the camera and your character.
In the graphics pipeline, there are several matricies that are combined together to get the final 3D result of the verticies. The one's we're interested in here are:
- The World/Model matrix: This determines where in the object is in relation to the origin, or [0, 0, 0].
- The View matrix: This is the one we're interested in. This is like a camera looking into the world.
- The Projection matrix: This is a little more complex. It basically warps the scene so that, with a perspective view, objects that are further from the view appear smaller while objects that are closer to the view are larger (Foreshortening).
When you move your character around the world, the world itself shouldn't really be moving. What you should be doing is moving both the view and the character.
While the results are technically the same, it means that you only have to move 2 objects (The view and the character) rather than moving what could be potentially thousands or millions of objects in the world.
You should have a section in your code where you call sceGumMatrixMode(GU_VIEW). In here, do all your translations and rotations before you call sceGumMatrixMode(GU_MODEL). This should move and rotate the view around the world.
As for making your character move in the correct direction, look earlier in the thread where I described retrieving the directional vector from a matrix. Note that it's not really possible to move a character around by constructing matricies each time, and you should at least store the characters position and a rotation angle.
All you need to do is rotate the character using the standard Gum matrix functions, extract and store the directional vector (As described in my earlier post), and translate the character to his pre-stored position. Any time you want to move the character forwards, just add the stored directional vector to the stored position.
I use ScePspFVector3's to do this. Adding vectors is easy, and you do it like so:
Then you translate the model matrix using the characterPosition vector when you go to render it.
Let me know if any of this doesn't make sense.
In the graphics pipeline, there are several matricies that are combined together to get the final 3D result of the verticies. The one's we're interested in here are:
- The World/Model matrix: This determines where in the object is in relation to the origin, or [0, 0, 0].
- The View matrix: This is the one we're interested in. This is like a camera looking into the world.
- The Projection matrix: This is a little more complex. It basically warps the scene so that, with a perspective view, objects that are further from the view appear smaller while objects that are closer to the view are larger (Foreshortening).
When you move your character around the world, the world itself shouldn't really be moving. What you should be doing is moving both the view and the character.
While the results are technically the same, it means that you only have to move 2 objects (The view and the character) rather than moving what could be potentially thousands or millions of objects in the world.
You should have a section in your code where you call sceGumMatrixMode(GU_VIEW). In here, do all your translations and rotations before you call sceGumMatrixMode(GU_MODEL). This should move and rotate the view around the world.
As for making your character move in the correct direction, look earlier in the thread where I described retrieving the directional vector from a matrix. Note that it's not really possible to move a character around by constructing matricies each time, and you should at least store the characters position and a rotation angle.
All you need to do is rotate the character using the standard Gum matrix functions, extract and store the directional vector (As described in my earlier post), and translate the character to his pre-stored position. Any time you want to move the character forwards, just add the stored directional vector to the stored position.
I use ScePspFVector3's to do this. Adding vectors is easy, and you do it like so:
Code: Select all
// Somewhere in your class definition or as a global variable
ScePspFVector3 characterPosition, characterDirection;
// ... later in the code...
// When the forwards button is pressed
characterPosition.x += characterDirection.x;
characterPosition.y += characterDirection.y;
characterPosition.z += characterDirection.z;
Let me know if any of this doesn't make sense.
It makes sense, but I can't seem to apply it to my game.
I translate, then rotate the view matrix, load my world, rotate back and translate back my model matrix, then load my player.
Now I am back to where I was, when i was moving the world instead. I don't think I am grasping how to do this.
I'm thinking I could do some trigonometry to calculate how much to translate on the X and Y to simulate a strafe relative to the player.
I translate, then rotate the view matrix, load my world, rotate back and translate back my model matrix, then load my player.
Now I am back to where I was, when i was moving the world instead. I don't think I am grasping how to do this.
Code: Select all
sceGumMatrixMode(GU_VIEW);
sceGumLoadIdentity();
ScePspFVector3 pos = { xAmount, yAmount, 0.0f };
ScePspFVector3 pos2 = { 0.0f - xAmount, 0.0f - yAmount, 0.0f };
sceGumTranslate(&pos);
sceGumRotateZ(rotationAmount);
sceGumMatrixMode(GU_MODEL);
sceGumLoadIdentity();
sceGumDrawArray(GU_TRIANGLES, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D, 18*3, 0, vertices);
sceGumRotateZ(0.0f - rotationAmount);
sceGumTranslate(&pos2);
sceGumDrawArray(GU_TRIANGLES, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D, 2*3, 0, guy);
-
- Posts: 22
- Joined: Fri May 05, 2006 12:04 am
-
- Posts: 22
- Joined: Fri May 05, 2006 12:04 am
-
- Posts: 22
- Joined: Fri May 05, 2006 12:04 am
I got it working...
Code: Select all
while( running() )
{
sceCtrlReadBufferPositive(&pad, 1);
if (pad.Lx > 160 || pad.Lx < 100)
{
rotationRate = (float) (pad.Lx - 128) / (127 * 20);
rotationAmount -= rotationRate;
}
if (pad.Ly > 160 || pad.Ly < 100)
{
yAmount -= (float)cos(0.0f - rotationAmount) * ( (pad.Ly - 128.0f) / (127.0f * 10.0f) );
xAmount -= (float)sin(0.0f - rotationAmount) * ( (pad.Ly - 128.0f) / (127.0f * 10.0f) );
}
if (pad.Buttons != 0)
{
if (pad.Buttons & PSP_CTRL_LTRIGGER)
{
yAmount -= (float)sin(rotationAmount) * 0.1f;
xAmount -= (float)cos(rotationAmount) * 0.1f;
}
if (pad.Buttons & PSP_CTRL_RTRIGGER)
{
yAmount += (float)sin(rotationAmount) * 0.1f;
xAmount += (float)cos(rotationAmount) * 0.1f;
}
}
sceGuStart(GU_DIRECT, list);
sceGuClearColor(0);
sceGuClear(GU_COLOR_BUFFER_BIT);
sceGumMatrixMode(GU_PROJECTION);
sceGumLoadIdentity();
sceGumOrtho(-12.0f, 12.0f, -1.0f, 12.6f, 0.0f, 1000.0f);
sceGumMatrixMode(GU_VIEW);
sceGumLoadIdentity();
ScePspFVector3 pos = { 0.0f - xAmount, 0.0f - yAmount, 0.0f };
sceGumRotateZ(0.0f - rotationAmount);
sceGumTranslate(&pos);
sceGumMatrixMode(GU_MODEL);
sceGumLoadIdentity();
sceGumDrawArray(GU_TRIANGLES, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D, 18*3, 0, vertices);
pos.x = xAmount;
pos.y = yAmount;
sceGumTranslate(&pos);
sceGumRotateZ(rotationAmount);
sceGumDrawArray(GU_TRIANGLES, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_3D, 2*3, 0, guy);
sceGuFinish();
sceGuSync(0, 0);
sceDisplayWaitVblankStart();
sceGuSwapBuffers();
}