Computer Webmaster Gaming Console Graphics Forum

Welcome to the Computer Webmaster Gaming Console Graphics Forum forums.

You are currently viewing our boards as a guest which gives you limited access to view most discussions and access our other features. By joining our free community you will have access to post topics, communicate privately with other members (PM), respond to polls, upload content and access many other special features. Registration is fast, simple and absolutely free so please, join our community today!

If you have any problems with the registration process or your account login, please contact contact us.

MK PitStop Main Earn $25 Earn Money Posting Extras Members Blogs Image Hosting User Pages
Go Back   Computer Webmaster Gaming Console Graphics Forum > Computer Forums > Software Programming
Register FAQ/Rules Become A V.I.P. Member Search Today's Posts Mark Forums Read

Software Programming Software programming talk, ask questions about computer software programming or help others

Google
Closed Thread
 
LinkBack Thread Tools Display Modes
Old 06-12-2007, 9:40 PM   #1
Scott Campbell
 
Scott Campbell's Avatar
 
Posts: n/a
My Photos: (0)

Banked:
MK Cash: $

I am Worth:
MK Cash: $
Donate

Recent Blog: None

Default Camera Rotation Problem

I had the same problem... The camera would roll when I started looking left
and right, but looking up an down was fine...
In C++ with DirectX 8, this is what I did...
This code isn't the neatest around, but it works...

D3DXMATRIX matView;

float AngleX = testrotX * CONVERT_TO_RADIANS;
float AngleY = testrotY * CONVERT_TO_RADIANS;
float PositionX = STARTX - testposoffsetX;
float PositionY = STARTY - testposoffsetY;
float PositionZ = STARTZ - testposoffsetZ;

D3DXMATRIX LookAtRotX;
D3DXMATRIX LookAtRotY;
D3DXMATRIX LookAtRot;
D3DXVECTOR3 LookAt;
D3DXVECTOR3 CameraPos(PositionX,PositionY,PositionZ);

D3DXMatrixRotationX(&LookAtRotX,AngleY);
D3DXMatrixRotationZ(&LookAtRotY,AngleX);
D3DXMatrixMultiply(&LookAtRot,&LookAtRotX,&LookAtR otY);
D3DXVec3TransformCoord(&LookAt,&D3DXVECTOR3(0,40,0 ),&LookAtRot);
LookAt += CameraPos;

D3DXMatrixLookAtRH( &matView, &CameraPos,
&LookAt,
&D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) );

g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );


I am not going to attempt to convert this to C#, maybe someone else can do
that for you...

There is still one problem with this code... When I look up 90 degrees, the
camera will flip over. This has something to do with my lookup vector which
I haven't worked out yet. I will either limit my lookup for a FPS because
no-one can look behind them by looking up. Or if I decide to do something
decent style, I will have to work out how to use the lookup vector. Anyone
got any ideas...



"Stephan Rose" <kermos@no.bestnetpc.spam.com> wrote in message
news:rlehev4nf6jermugb7ppbo0d6108phsrp6@4ax.com...
> Working on my camera code, uses Yaw pitch roll as input (amount of new
> rotation only), calculates a quaternion based on that, multiplies this
> with my original rotation to yield the new rotation that the camera
> should be facing.
>
> This works great when I only rotate in 1 axis. The second I rotate in
> both yaw and pitch a roll gets introduced over time, even though I
> never touch roll.
>
> Anyone have any idea why?
>
> Code is writtin in C#
>
> Here's the code that creates my new rotation quaternion:
>
> public void YawPitchRoll(float yaw, float pitch, float roll)
> {
> yaw = (yaw/180.0f)*(float)System.Math.PI;
> pitch = (pitch/180.0f)*(float)System.Math.PI;
> roll = (roll/180.0f)*(float)System.Math.PI;
>
> Quaternion rotate =
> Quaternion.RotationYawPitchRoll(yaw,pitch,roll);
>
> rotate.Normalize(); // normalizes the rotation quaternion
> rotation.Multiply(rotate); // Multiplies the prior rotation
> quaternion by the new one resulting in the new final rotation.
> }
>
> public void Update(Device dev)
> {
> Matrix trans;
> Matrix rotation;
>
>
> rotation = Matrix.RotationQuaternion(this.rotation);
> trans = Matrix.Translation(position);
> trans.Invert();
> trans.Multiply(rotation);
> dev.Transform.View = trans;
> }
>
> If anyone sees any error here..please let me know. It's driving me
> nuts!!!
>
> Thanks,
>
> Stephan Rose
> kermos@bestnetpc.com
>



 
Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!Spurl this Post!Reddit!
Advertisements
Old 06-12-2007, 9:40 PM   #2
John R. Strohm
 
John R. Strohm's Avatar
 
Posts: n/a
My Photos: (0)

Banked:
MK Cash: $

I am Worth:
MK Cash: $
Donate

Recent Blog: None

Default Camera Rotation Problem


"Scott Campbell" <nospam@spiffysoftware.com> wrote in message
news:beil1d$5eh08$1@ID-180785.news.dfncis.de...
> I had the same problem... The camera would roll when I started looking

left
> and right, but looking up an down was fine...
> In C++ with DirectX 8, this is what I did...
> This code isn't the neatest around, but it works...
>
> D3DXMATRIX matView;
>
> float AngleX = testrotX * CONVERT_TO_RADIANS;
> float AngleY = testrotY * CONVERT_TO_RADIANS;
> float PositionX = STARTX - testposoffsetX;
> float PositionY = STARTY - testposoffsetY;
> float PositionZ = STARTZ - testposoffsetZ;
>
> D3DXMATRIX LookAtRotX;
> D3DXMATRIX LookAtRotY;
> D3DXMATRIX LookAtRot;
> D3DXVECTOR3 LookAt;
> D3DXVECTOR3 CameraPos(PositionX,PositionY,PositionZ);
>
> D3DXMatrixRotationX(&LookAtRotX,AngleY);
> D3DXMatrixRotationZ(&LookAtRotY,AngleX);
> D3DXMatrixMultiply(&LookAtRot,&LookAtRotX,&LookAtR otY);
> D3DXVec3TransformCoord(&LookAt,&D3DXVECTOR3(0,40,0 ),&LookAtRot);
> LookAt += CameraPos;
>
> D3DXMatrixLookAtRH( &matView, &CameraPos,
> &LookAt,
> &D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) );
>
> g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
>
>
> I am not going to attempt to convert this to C#, maybe someone else can do
> that for you...
>
> There is still one problem with this code... When I look up 90 degrees,

the
> camera will flip over. This has something to do with my lookup vector

which
> I haven't worked out yet. I will either limit my lookup for a FPS because
> no-one can look behind them by looking up. Or if I decide to do something
> decent style, I will have to work out how to use the lookup vector. Anyone
> got any ideas...


First, your life will be a LOT easier if you learn to write your code with
MEANINGFUL VARIABLE NAMES.

Without knowing YOUR particular XYZ coordinate system, I have NO idea what
you are actually trying to do.

For line-of-sight stuff, azimuth and elevation are the traditional names.
Azimuth usually ranges over -PI to +PI, or -180 to +180 degrees. Elevation
usually ranges over -PI/2 to PI/2, or -90 to +90 degrees.

There's probably a technical term for what is eating you alive, but, not
being a graphics meisterprogrammer, I don't know the magic word. I did all
my coordinate transformations in sightline control and target tracking
stuff, with a little bit of simulation thrown in for seasoning. BUT: What
is eating your lunch is that you are pitching FIRST, and THEN you are yawing
to the look-at point, and this is inducing roll into your image. The fix is
to yaw first and THEN pitch.

Try changing this line:
> D3DXMatrixMultiply(&LookAtRot,&LookAtRotX,&LookAtR otY);


to
D3DXMatrixMultiply(&LookAtRot,&LookAtRotY,&LookAtR otX);


 
Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!Spurl this Post!Reddit!
Old 06-12-2007, 9:40 PM   #3
Scott Campbell
 
Scott Campbell's Avatar
 
Posts: n/a
My Photos: (0)

Banked:
MK Cash: $

I am Worth:
MK Cash: $
Donate

Recent Blog: None

Default Camera Rotation Problem

"John R. Strohm" <strohm@airmail.net> wrote in message
news:beis09$mps@library1.airnews.net...
>
> "Scott Campbell" <nospam@spiffysoftware.com> wrote in message
> news:beil1d$5eh08$1@ID-180785.news.dfncis.de...
> > I had the same problem... The camera would roll when I started looking

> left
> > and right, but looking up an down was fine...
> > In C++ with DirectX 8, this is what I did...
> > This code isn't the neatest around, but it works...
> >
> > D3DXMATRIX matView;
> >
> > float AngleX = testrotX * CONVERT_TO_RADIANS;
> > float AngleY = testrotY * CONVERT_TO_RADIANS;
> > float PositionX = STARTX - testposoffsetX;
> > float PositionY = STARTY - testposoffsetY;
> > float PositionZ = STARTZ - testposoffsetZ;
> >
> > D3DXMATRIX LookAtRotX;
> > D3DXMATRIX LookAtRotY;
> > D3DXMATRIX LookAtRot;
> > D3DXVECTOR3 LookAt;
> > D3DXVECTOR3 CameraPos(PositionX,PositionY,PositionZ);
> >
> > D3DXMatrixRotationX(&LookAtRotX,AngleY);
> > D3DXMatrixRotationZ(&LookAtRotY,AngleX);
> > D3DXMatrixMultiply(&LookAtRot,&LookAtRotX,&LookAtR otY);
> > D3DXVec3TransformCoord(&LookAt,&D3DXVECTOR3(0,40,0 ),&LookAtRot);
> > LookAt += CameraPos;
> >
> > D3DXMatrixLookAtRH( &matView, &CameraPos,
> > &LookAt,
> > &D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) );
> >
> > g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
> >
> >
> > I am not going to attempt to convert this to C#, maybe someone else can

do
> > that for you...
> >
> > There is still one problem with this code... When I look up 90 degrees,

> the
> > camera will flip over. This has something to do with my lookup vector

> which
> > I haven't worked out yet. I will either limit my lookup for a FPS

because
> > no-one can look behind them by looking up. Or if I decide to do

something
> > decent style, I will have to work out how to use the lookup vector.

Anyone
> > got any ideas...

>
> First, your life will be a LOT easier if you learn to write your code with
> MEANINGFUL VARIABLE NAMES.
>
> Without knowing YOUR particular XYZ coordinate system, I have NO idea what
> you are actually trying to do.
>
> For line-of-sight stuff, azimuth and elevation are the traditional names.
> Azimuth usually ranges over -PI to +PI, or -180 to +180 degrees.

Elevation
> usually ranges over -PI/2 to PI/2, or -90 to +90 degrees.
>
> There's probably a technical term for what is eating you alive, but, not
> being a graphics meisterprogrammer, I don't know the magic word. I did

all
> my coordinate transformations in sightline control and target tracking
> stuff, with a little bit of simulation thrown in for seasoning. BUT: What
> is eating your lunch is that you are pitching FIRST, and THEN you are

yawing
> to the look-at point, and this is inducing roll into your image. The fix

is
> to yaw first and THEN pitch.
>
> Try changing this line:
> > D3DXMatrixMultiply(&LookAtRot,&LookAtRotX,&LookAtR otY);

>
> to
> D3DXMatrixMultiply(&LookAtRot,&LookAtRotY,&LookAtR otX);
>
>


Firstly, meaningful variable names are in the eye of the beholder. The names
I gave my variables are meaningful to me even if they are not to you... I
have not been a 3D programmer for very long and it is hard to give a
variable the name it deserves until I have a more in-depth knowledge of what
I am doing...


Now onto the actual problem.

I don't see how changing the line:
D3DXMatrixMultiply(&LookAtRot,&LookAtRotX,&LookAtR otY);
to
D3DXMatrixMultiply(&LookAtRot,&LookAtRotY,&LookAtR otX);
is going to change anything...

Will it not come out with the same value. Like multiplying 2 and 3... No
matter which way you put it, it still makes 6... I had all my year 9 maths
books thrown out so I have to find something on the internet about matrix
math...

The roll I am getting is at 90 deg and -90 deg pitch, and then it is just a
direct 180 deg roll... So everything is always right way up, where things
should be coming out upsidedown.


 
Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!Spurl this Post!Reddit!
Old 06-12-2007, 9:40 PM   #4
John R. Strohm
 
John R. Strohm's Avatar
 
Posts: n/a
My Photos: (0)

Banked:
MK Cash: $

I am Worth:
MK Cash: $
Donate

Recent Blog: None

Default Camera Rotation Problem

"Scott Campbell" <nospam@spiffysoftware.com> wrote in message
news:beivoj$5h5i6$1@ID-180785.news.dfncis.de...
> I don't see how changing the line:
> D3DXMatrixMultiply(&LookAtRot,&LookAtRotX,&LookAtR otY);
> to
> D3DXMatrixMultiply(&LookAtRot,&LookAtRotY,&LookAtR otX);
> is going to change anything...
>
> Will it not come out with the same value. Like multiplying 2 and 3... No
> matter which way you put it, it still makes 6... I had all my year 9 maths
> books thrown out so I have to find something on the internet about matrix
> math...


No, it won't come out with the same value.

Matrix multiplication is not commutative. For two arbitrary square matrices
A and B, the product A*B is not the same as the product B*A.

Friendly hint: Your life in 3D programming and computer graphics will be
MUCH easier if you have a SOLID grounding in vector and matrix algebra, as
well as trigonometry. There are no shortcuts.



 
Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!Spurl this Post!Reddit!
Old 06-12-2007, 9:40 PM   #5
John R. Strohm
 
John R. Strohm's Avatar
 
Posts: n/a
My Photos: (0)

Banked:
MK Cash: $

I am Worth:
MK Cash: $
Donate

Recent Blog: None

Default Camera Rotation Problem


"Scott Campbell" <nospam@spiffysoftware.com> wrote in message
news:5a66573d.0307111827.317e29d7@posting.google.c om...
> "John R. Strohm" <strohm@airmail.net> wrote in message

news:<bek3mt$4ql@library2.airnews.net>...
> > "Scott Campbell" <nospam@spiffysoftware.com> wrote in message
> > news:beivoj$5h5i6$1@ID-180785.news.dfncis.de...
> > > I don't see how changing the line:
> > > D3DXMatrixMultiply(&LookAtRot,&LookAtRotX,&LookAtR otY);
> > > to
> > > D3DXMatrixMultiply(&LookAtRot,&LookAtRotY,&LookAtR otX);
> > > is going to change anything...
> > >
> > > Will it not come out with the same value. Like multiplying 2 and 3...

No
> > > matter which way you put it, it still makes 6... I had all my year 9

maths
> > > books thrown out so I have to find something on the internet about

matrix
> > > math...

> >
> > No, it won't come out with the same value.
> >
> > Matrix multiplication is not commutative. For two arbitrary square

matrices
> > A and B, the product A*B is not the same as the product B*A.
> >
> > Friendly hint: Your life in 3D programming and computer graphics will be
> > MUCH easier if you have a SOLID grounding in vector and matrix algebra,

as
> > well as trigonometry. There are no shortcuts.

>
>
> I have tried what you suggested, and although the results were
> slightly different but still wrong, the only difference is now I can
> see a roll in the camera.
>
> Before the change, looking up too far would just flip the camera 180
> deg. Now when I look up, it slowly rolls 180 deg. To me this seems
> worse than before.


OK, this tells me that I misinterpreted your original post. You had the
multiplication order correct originally; change it back. (Also note that
you have demonstrated to yourself that the multiplication order IS
significant.)

What did you EXPECT the camera to do when you flipped it upside down, by
pitching it up over 90 degrees from horizontal?

> Friendly reply: Friendly or not, I am not trying to seek out
> shortcuts. I have created very simple 3D projects and I am learning as
> I go along. I have created a Grand Theft Auto model viewer with
> texture mapping and I am now trying the Quake level viewer (which also
> has texture mapping working).
>
> I come here to ask a question about a problem that I am having, and it
> seems people just cannot wait to belittle you. Do you know how hard
> that makes learning anything. You may think it is friendly, but it
> doesn't come off that way.


You asked for help. I made a suggestion. You said you didn't see how that
would change anything, and the WAY you said it suggested strongly that you
didn't understand something very basic, that you NEED to understand.

How do YOU suggest I tell you that "Matrix algebra is fundamental to 3D
computer graphics. You NEED to know how matrices and vectors work, how they
are defined, how they operate. There is no substitute for this knowledge."?


 
Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!Spurl this Post!Reddit!
Old 06-12-2007, 9:41 PM   #6
John R. Strohm
 
John R. Strohm's Avatar
 
Posts: n/a
My Photos: (0)

Banked:
MK Cash: $

I am Worth:
MK Cash: $
Donate

Recent Blog: None

Default Camera Rotation Problem

"Scott Campbell" <nospam@spiffysoftware.com> wrote in message
news:bespml$8i89u$1@ID-180785.news.uni-berlin.de...
> > What did you EXPECT the camera to do when you flipped it upside down, by
> > pitching it up over 90 degrees from horizontal?

>
> When I pitch up over 90 degrees I would like the view flipped upside

down...
> Instead the view is always right way up... The ground is always underneath
> me and the sky is always above... Take your view from being inside a space
> ship (or something like that). If I was to pitch up over 90 deg, the

ground
> would be up, the sky would be down. When I do it with my current code,

this
> does not happen. I believe the problem is my look-up vector.
>
> D3DXMatrixLookAtRH( &matView, &CameraPos,
> &LookAt,
> &D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) );
>
> See in this case, the lookup vector is 0, 0, 1.
>
> Should I have the lookup vector change from 0, 0, 1 to 0, 0, -1 based on

the
> pitch maybe... Or can I have the lookup vector always pointing up from the
> camera?


I don't have the Direct3D documentation, so this is educated guesswork, but
that looks like it may be the problem.

D3DXMatrixMultiply(&LookAtRot,&LookAtRotX,&LookAtR otY); // Multiply
rotations
D3DXVec3TransformCoord(&LookAt,&D3DXVECTOR3(0,40,0 ),&LookAtRot); // What
is (0,40,0) which you rotate through the camera viewing angles?

LookAt += CameraPos; // ???

D3DXMatrixLookAtRH( &matView, &CameraPos,
&LookAt,
&D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) );

// Apparently, (0,0,1) is supposed to give a local vertical orientation.

g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );


You MIGHT try pushing (0,0,1) through the camera rotation matrix LookAtRot,
then feeding that to D3DXMatrixLookAtRH() and see what happens.


 
Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!Spurl this Post!Reddit!
Old 06-12-2007, 9:41 PM   #7
Scott Campbell
 
Scott Campbell's Avatar
 
Posts: n/a
My Photos: (0)

Banked:
MK Cash: $

I am Worth:
MK Cash: $
Donate

Recent Blog: None

Default Camera Rotation Problem

> "Scott Campbell" <nospam@spiffysoftware.com> wrote in message
> news:bespml$8i89u$1@ID-180785.news.uni-berlin.de...
> > > What did you EXPECT the camera to do when you flipped it upside down,

by
> > > pitching it up over 90 degrees from horizontal?

> >
> > When I pitch up over 90 degrees I would like the view flipped upside

> down...
> > Instead the view is always right way up... The ground is always

underneath
> > me and the sky is always above... Take your view from being inside a

space
> > ship (or something like that). If I was to pitch up over 90 deg, the

> ground
> > would be up, the sky would be down. When I do it with my current code,

> this
> > does not happen. I believe the problem is my look-up vector.
> >
> > D3DXMatrixLookAtRH( &matView, &CameraPos,
> > &LookAt,
> > &D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) );
> >
> > See in this case, the lookup vector is 0, 0, 1.
> >
> > Should I have the lookup vector change from 0, 0, 1 to 0, 0, -1 based on

> the
> > pitch maybe... Or can I have the lookup vector always pointing up from

the
> > camera?

>
> I don't have the Direct3D documentation, so this is educated guesswork,

but
> that looks like it may be the problem.
>
> D3DXMatrixMultiply(&LookAtRot,&LookAtRotX,&LookAtR otY); // Multiply
> rotations
> D3DXVec3TransformCoord(&LookAt,&D3DXVECTOR3(0,40,0 ),&LookAtRot); // What
> is (0,40,0) which you rotate through the camera viewing angles?
>
> LookAt += CameraPos; // ???
>
> D3DXMatrixLookAtRH( &matView, &CameraPos,
> &LookAt,
> &D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) );
>
> // Apparently, (0,0,1) is supposed to give a local vertical orientation.
>
> g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
>
>
> You MIGHT try pushing (0,0,1) through the camera rotation matrix

LookAtRot,
> then feeding that to D3DXMatrixLookAtRH() and see what happens.



Great. It works now. The funny thing is I thought I had tried this method
before and it had failed... Must have been some other changes I made also.

D3DXMATRIX LookAtRotX;
D3DXMATRIX LookAtRotY;
D3DXMATRIX LookAtRot;
D3DXVECTOR3 LookAt;
D3DXVECTOR3 LookUp; //Added variable for LookUp vector.
D3DXVECTOR3 CameraPos(PositionX,PositionY,PositionZ);

D3DXMatrixRotationX(&LookAtRotX,AngleY);
D3DXMatrixRotationZ(&LookAtRotY,AngleX);
D3DXMatrixMultiply(&LookAtRot,&LookAtRotX,&LookAtR otY);
D3DXVec3TransformCoord(&LookAt,&D3DXVECTOR3(0,1,0) ,&LookAtRot); /*
Changed to 1 from 40. Doesn't really matter, but anyway :o) */
D3DXVec3TransformCoord(&LookUp,&D3DXVECTOR3(0,0,1) ,&LookAtRot); /*
LookUp vector is above your head. So rotate it in relation to camera
roatation */

LookAt += CameraPos;

D3DXMatrixLookAtRH( &matView, &CameraPos,
&LookAt,
&LookUp); // Now use the new lookup vector.

g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );


 
Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!Spurl this Post!Reddit!
Featured Websites
Free Space
Free Space
Free Space Free Space
Closed Thread
Tags: , ,




Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On

Similar Threads
Thread Thread Starter Forum Replies Last Post
which camera? Ridwan Hughes Ebay Technical Questions 0 05-31-2007 12:37 AM
which camera? Lucas Tam Ebay Technical Questions 0 05-31-2007 12:37 AM
which camera? trappeduser Ebay Technical Questions 0 05-31-2007 12:37 AM
which camera? Don Lancaster Ebay Technical Questions 0 05-31-2007 12:37 AM
camera error driver problem solved deep Operating Systems And Software 0 05-28-2007 5:48 PM


Featured Websites




All times are GMT +1. The time now is 12:33 AM.


Powered by: vBulletin Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO 3.0.0
Cheap Computers
MK PitStop Copyright 2005 - 2008

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98