forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

movement|navigation problem

 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development
View previous topic :: View next topic  
Author Message
LuMo



Joined: 21 Aug 2005
Posts: 410
Location: Austria

PostPosted: Fri Mar 10, 2006 9:17 pm    Post subject: movement|navigation problem Reply with quote

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
_________________
"Good artists copy, great artists steal."
Pablo Picasso
go2lumo.com
Back to top
View user's profile Send private message Visit poster's website
sg57



Joined: 14 Oct 2005
Posts: 154

PostPosted: Mon Mar 13, 2006 7:44 am    Post subject: Reply with quote

hey how do you rotate an image??? a example that would be perfect for everyone would be rotating an image to the direction of the analog nub. It would show the rotate function, demonstrate its use, and show how to change angles, all in one, think you could make an example or soemthing
Back to top
View user's profile Send private message
LuMo



Joined: 21 Aug 2005
Posts: 410
Location: Austria

PostPosted: Mon Mar 13, 2006 8:03 pm    Post subject: Reply with quote

i am not rotating images;
i am working in 3d --> rotate meshes

greets
lumo
_________________
"Good artists copy, great artists steal."
Pablo Picasso
go2lumo.com
Back to top
View user's profile Send private message Visit poster's website
Ess



Joined: 20 Apr 2006
Posts: 16

PostPosted: Fri May 12, 2006 2:26 pm    Post subject: Reply with quote

yes but a 2d example would be beneficial, for simplicity's sake.
Back to top
View user's profile Send private message MSN Messenger
cheriff
Regular


Joined: 23 Jun 2004
Posts: 262
Location: Sydney.au

PostPosted: Fri May 12, 2006 3:33 pm    Post subject: Reply with quote

The rotate operation works on the centre of the world, you need to:

    * 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
not sure if psp can push/pop (i assume so) but if not just translate again by the opposite amount

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' ??)
_________________
Damn, I need a decent signature!


Last edited by cheriff on Fri May 12, 2006 7:48 pm; edited 2 times in total
Back to top
View user's profile Send private message
Ess



Joined: 20 Apr 2006
Posts: 16

PostPosted: Fri May 12, 2006 4:34 pm    Post subject: Reply with quote

Why doesn't mine work?

http://pastebin.com/713028
Back to top
View user's profile Send private message MSN Messenger
LuMo



Joined: 21 Aug 2005
Posts: 410
Location: Austria

PostPosted: Fri May 12, 2006 5:50 pm    Post subject: Reply with quote

Ess... what does not work? (did not check the whole code)
_________________
"Good artists copy, great artists steal."
Pablo Picasso
go2lumo.com
Back to top
View user's profile Send private message Visit poster's website
PlayfulPuppy



Joined: 05 May 2006
Posts: 22

PostPosted: Fri May 12, 2006 6:51 pm    Post subject: Reply with quote

cheriff wrote:
The rotate operation works on the centre of the world, you need to:

    * push the current matrix
    * translate to the centre of the object you wish to rotate
    * do the rotation
    * pop the matrix back
not sure if psp can push/pop (i assume so) but if not just translate again by the opposite amount


Or you could cut out the middle-man and just do the rotation before you do the translation.
Back to top
View user's profile Send private message
PlayfulPuppy



Joined: 05 May 2006
Posts: 22

PostPosted: Fri May 12, 2006 7:01 pm    Post subject: Reply with quote

Ess wrote:
Why doesn't mine work?

http://pastebin.com/713028


Same problem with you.

Code:

       sceGumTranslate(&pos);
       sceGumPushMatrix();
       sceGumRotateZ(rotationAmount);
       // Draw Array
       sceGumPopMatrix();


Should be:

Code:

       sceGumRotateZ(rotationAmount);
       sceGumTranslate(&pos);
       // Draw Array


Note you shouldn't really have to push or pop the matrix stack unless you want to do something hierachically (Parent/Child objects).

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.
Back to top
View user's profile Send private message
cheriff
Regular


Joined: 23 Jun 2004
Posts: 262
Location: Sydney.au

PostPosted: Fri May 12, 2006 7:46 pm    Post subject: Reply with quote

ah crap, i got it backwards..
PlayfulPuppy: cheers for catching that one out, original post edited ;)
_________________
Damn, I need a decent signature!
Back to top
View user's profile Send private message
PlayfulPuppy



Joined: 05 May 2006
Posts: 22

PostPosted: Fri May 12, 2006 8:24 pm    Post subject: Reply with quote

cheriff wrote:
ah crap, i got it backwards..
PlayfulPuppy: cheers for catching that one out, original post edited ;)


Ah it's all good, I confuse them myself quite often and I do this stuff for a living! ;)

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:

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]


Where P is the position of the object.

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:

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];


(Note: This is assuming your character is facing down the positive X axis, or to the right of the screen)

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:

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);


If you want your object to move faster or slower, you can just multiply the vector to change its length:

Code:

float length = 0.5;

dirVec.x *= length;
dirVec.y *= length;
dirVec.z *= length;


And now the object will only move forwards 0.5 units.

Hope this has been useful to someone!
Back to top
View user's profile Send private message
Ess



Joined: 20 Apr 2006
Posts: 16

PostPosted: Sat May 13, 2006 3:35 am    Post subject: Reply with quote

how would i go about rotating around an arbitrary axis with pspgu?
Back to top
View user's profile Send private message MSN Messenger
PlayfulPuppy



Joined: 05 May 2006
Posts: 22

PostPosted: Sat May 13, 2006 11:58 am    Post subject: Reply with quote

Ess wrote:
how would i go about rotating around an arbitrary axis with pspgu?


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.

Start by creating one matrix by rotating around the Y axis:

Code:

ScePspFMatrix4 angleMat;
gumRotateY(&angleMat, angle);


That's the easy part. Now we need to create a matrix from the axis you've specified. We can do this one of two ways; By retrieving the X, Y and Z rotation angles from the vector and rotating a matrix using them (You can find information about doing that on the 'net), or we can construct a matrix manually which is what I'm going to demonstrate here.

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:

   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;


So what we're doing here is first creating a dummy Z axis that's pointing down the positive Z. This allows us to extract the potential X axis from the Y axis you supplied. The Y axis is then normalized, to make sure our matrix is also normalized (If your Y axis length is greater or less than 1.0f, the scale of your object will be off and could make some wierd results).

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:

   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;
   }


This will avoid the Y and the Z axis' being the same, and will avoid getting a zero-lenth X axis.

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:

   if(yAxis.y < 0.0f)
   {
      zAxis.x = 0.0f;
      zAxis.y = 0.0f;
      zAxis.z = -1.0f;
   }


Basically, depending on the order you do the cross product in, you'll get a vector pointing in one of two directions. Z cross Y will get you a positive X axis, while Y cross Z will get you a negative X axis (Note: I can't actually remember the order correctly, so this has a 50/50 chance of being wrong. If so, and your model seems to be facing the wrong way, just try switching the values).

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:

   ScePspFMatrix4 finalMat;

   gumMultMatrix(&finalMat, &angleMat, (ScePspFMatrix4*)&axisMat);


And finally add our object position:

Code:

   ScePspFVector3 objPos;   // The position of our object

   gumTranslate(&finalMat, &objPos);


And congratulations! You've created an axis/angle rotation matrix. Put this all into a function such as RotateAxisAngle(ScePspFMatrix4 &result, ScePspFVector3 axis, float angle), and it'll be there whenever you need it.

Man, that's a long-arse post. I should write an FAQ on this or something. :P
Back to top
View user's profile Send private message
Ess



Joined: 20 Apr 2006
Posts: 16

PostPosted: Sun May 14, 2006 3:36 pm    Post subject: Reply with quote

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.
Back to top
View user's profile Send private message MSN Messenger
PlayfulPuppy



Joined: 05 May 2006
Posts: 22

PostPosted: Sun May 14, 2006 3:43 pm    Post subject: Reply with quote

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.


Oh, you mean rotating around an arbitrary point! Rotating around an arbitrary axis is quite a different thing.

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.
Back to top
View user's profile Send private message
Ess



Joined: 20 Apr 2006
Posts: 16

PostPosted: Sun May 14, 2006 4:31 pm    Post subject: Reply with quote

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?
Back to top
View user's profile Send private message MSN Messenger
PlayfulPuppy



Joined: 05 May 2006
Posts: 22

PostPosted: Sun May 14, 2006 4:57 pm    Post subject: Reply with quote

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:

Code:

// 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;


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.
Back to top
View user's profile Send private message
Ess



Joined: 20 Apr 2006
Posts: 16

PostPosted: Mon May 15, 2006 2:37 am    Post subject: Reply with quote

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.

Code:
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);


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.
Back to top
View user's profile Send private message MSN Messenger
PlayfulPuppy



Joined: 05 May 2006
Posts: 22

PostPosted: Mon May 15, 2006 9:07 am    Post subject: Reply with quote

You're translating and rotating the view in the wrong order.

Also, if you want your character to be in the center of the screen, your view should be directly above the character (So pos2 should be the same as pos1 except with a Z value > 0, say about 20)
Back to top
View user's profile Send private message
Ess



Joined: 20 Apr 2006
Posts: 16

PostPosted: Mon May 15, 2006 10:43 am    Post subject: Reply with quote

You are right, that code is in the wrong order. When I rotate first, then translate, The strafing is still on a diagonal. I am really starting to lose my mind on this... haha

Thank you for all of your help so far though, I feel like I am getting closer.
Back to top
View user's profile Send private message MSN Messenger
PlayfulPuppy



Joined: 05 May 2006
Posts: 22

PostPosted: Mon May 15, 2006 7:04 pm    Post subject: Reply with quote

How are you getting the strafing coordinates? You should be extracting a vector from the matrix like I did in my earlier post, except grabbing the Y axis instead of the X axis (Or the other way around, depending on what you're doing)
Back to top
View user's profile Send private message
PlayfulPuppy



Joined: 05 May 2006
Posts: 22

PostPosted: Mon May 15, 2006 7:07 pm    Post subject: Reply with quote

How are you getting the strafing coordinates? You should be extracting a vector from the matrix like I did in my earlier post, except grabbing the Y axis instead of the X axis (Or the other way around, depending on what you're doing).
Back to top
View user's profile Send private message
Ess



Joined: 20 Apr 2006
Posts: 16

PostPosted: Tue May 16, 2006 4:22 pm    Post subject: Reply with quote

I got it working...

Code:
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();
   }
Back to top
View user's profile Send private message MSN Messenger
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development All times are GMT + 10 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group