Decent FF7 Model Viewer

  • Thread starter Thread starter Sephiroth2000
  • Start date Start date
Status
Not open for further replies.
In OpenGL®, the code is as follows:

Code: [Select]
Code:
 glRotatef( -fY, 0, 1, 0 ); glRotatef( fX, 1, 0, 0 );  glRotatef( -fZ, 0, 0, 1 );
This is for rotations/bones.
Rotated first by -Y, then X, then -Z.


As for the 3-D models, reversing only the Z does not work.
Aside from changing the cull order (a minor problem), the objects become backwards.  Cloud’s head, for example, points back.
But I am sure if you manipulate the bones correctly, you can make the joints go the right directions to make everything dandy.

If you did that, the obect wouldn’t be mirrored horizontally (though it may be mirrored vertically).

I will personally pursue this matter to see if there is a winning combination for the bone rotations to counter the affects of only inverting the Z.


As for 90-degree fractures, I have never had that.


L. Spiro
 
I sware, Mirex
If you put an option to export models in Leviathon...
Its not needed, Unmass & Biturn can export everything you see in Leviathan. Check them out.
 
Yeah well i spent about 4 hours just trying to export cloud 2 a 3ds max file :x  Yeah not so easy for me... Maybe someone could upload a few of the famous characters?
 
earith.jpg


There is still an error in my recursive rotation algorithm. How do you exactly rotate the bones?

I store a matrix in every bone class containing the rotation of the bone.

Matrix = Matrix.RotationAxis(0, 1, 0, -y)
Matrix *= Matrix.RotationAxis(1, 0, 0, x)
Matrix *= Matrix.RotationAxis(0, 0, 1, -z)

My recursive RenderBone Method looks like this Pseudo Code:

Code: [Select]
Code:
RenderBone(Bone bone, Rotation rotation, Position position){ rotation *= bone.Rotation World  = rotation World  *= Matrix.Translation(position) Render() Matrix matrix = Matrix.Translation(0, 0, bone.NegativeLength) matrix   *= rotation; position.Add(matrix.Tx, matrix.Ty, matrix.Tz) if(!bone.IsLeaf)  foreach(Bone child in bone.Children)   RenderBone(child, rotation, position);}

RenderBone(rootBone, Matrix.Identity, Vector3.Origin)

Rotations, coordinates etc. in this post are in OpenGL format. Bone length is -z.
 
Your setup is completely different from mine so my code will not help much, but I will post it anyway.


Code: [Select]
Code:
VOID FF7Model::AttachBones( LPDIRECT3DDEVICE9 pd3dDevice ) { mDXStackPointer = 0; float tempXr, tempYr, tempZr; dxLoadIdentity(); for ( int I = 0; I < m_iBones; I++ ) {  if ( m_pBone[I].GetParentIndex() == -1 ) {   dxPushMatrix();   dxTranslatef( m_fXTrans, m_fYTrans, m_fZTrans );      tempXr = m_pBone[I].GetXRotation();   tempYr = m_pBone[I].GetYRotation();   tempZr = m_pBone[I].GetZRotation();      dxRotatef( -tempYr, 0, 1, 0 );   dxRotatef( tempXr, 1, 0, 0 );   dxRotatef( -tempZr, 0, 0, 1 );          m_pBone[I].SetMatrix( mDXMatrixStack[mDXStackPointer] );   dxTranslatef( 0, 0, -m_pBone[I].GetLength() );   for ( int J = 0; J < m_pBone[I].GetTotalChildren(); J++ ) {    AttachSubBones( m_pBone[I].GetChild( J ), pd3dDevice );   }   dxPopMatrix();  } }}VOID FF7Model::AttachSubBones( int iIndex, LPDIRECT3DDEVICE9 pd3dDevice ) { float fTempXr, fTempYr, fTempZr; fTempXr = m_pBone[iIndex].GetXRotation(); fTempYr = m_pBone[iIndex].GetYRotation(); fTempZr = m_pBone[iIndex].GetZRotation(); dxPushMatrix();  dxRotatef( -fTempYr, 0, 1, 0 ); dxRotatef( fTempXr, 1, 0, 0 );  dxRotatef( -fTempZr, 0, 0, 1 ); m_pBone[iIndex].SetMatrix( mDXMatrixStack[mDXStackPointer] ); dxTranslatef( 0, 0, -m_pBone[iIndex].GetLength() ); for ( int J = 0; J < m_pBone[iIndex].GetTotalChildren(); J++ ) {  AttachSubBones( m_pBone[iIndex].GetChild( J ), pd3dDevice ); } dxPopMatrix();}


Here is what you need to know about this code.

I store temp variables for each XYZ rotation, taken from m_pBone.GetXRotation();.  GetXRotation() returns the animation rotation for that bone and the animation’s current frame (GetXRotation() returns specifically the X, obviously).

That part explains itself.
I have two functions.
AttachBones() is not recursive; it only walks the root bones.
Any time a root bone has children, it calls AttachSubBones(), which in turn calls itself recursively on all children of that bone’s children.

The matrices need to be pushed and popped correctly to get the correct results, and this is also why there are two seperate functions to handle the walking.
The first function sets up the matrices to their default values, which needs to be done only once (instead of once per recursive call).

The bone rotations don’t carry over by multiplication.  They carry over by leaving the world in the same spot as it was when it processes the parent bone (which goes into pushing and popping correctly).  Every subsequent rotation and translation is performed from there.


Each bone uses SetMatrix() to store that matrix into the bone itself, so that when it comes time to draw, the world will be set to the stored matrix and the object drawn there.


L. Spiro
 
Just an update on my own project’s progress.

http://bin.mypage.sk/FILES/Enemies.zip

Looking good so far and I am really happy with the results.

The cyclerate in each of those pictures is over 100 with 1280×1024×32 resolution and 6×anti-aliasing.
Though most monitors don’t update that often, so the framerate you SEE is not 100.


I am almost able to put out a playable demo once we figure out these animation file formats.

My project’s official name is “Something Something VII Online” and as you can guess from the shots and the name, it is a “mod” that allows Final Fantasy® VII to be played online.

But I am keeping it mostly underground for now.  Let’s not talk TOO much about this, okay?
I talk about it here and there, and release some shots sometimes, but that should be fine as long as it stays on a low level.

I have a demo already ready for testing but it seems no one has the game installed AND has DirectX® 9.0c.


But we really need to work on this animation format so I can get an online Battle Square type demo going.  Just battles against people and monsters, enforced and run by the server.

Well I am working on this a lot lately but I will be back on the animation formats soon.
Until then, who else is working on them?


L. Spiro
 
The cyclerate in each of those pictures is over 100 with 1280×1024×32 resolution and 6×anti-aliasing.
Though most monitors don’t update that often, so the framerate you SEE is not 100.
This is really cool. What about burning some of the unused fillrate by adding stencil or depthmap shadows?
 
Hey guys this is code from Leviathan, for displaying the models. Its in OpenGl. Model coordinates & rotations are in default order (i mean not swapped or anything). Hope it helps.

Code: [Select]
Code:
void CF7BwDlg::GlDisplayBoneChildren( int bone_parent ){ int  b; float f; for( b=0; b<skelet.bones; b++ )  if (( skelet.bone[ b ].parent == bone_parent ) &&   ( skelet.bone[ b ].displayed == false )) {   glPushMatrix();   glRotatef( skelet.bone[ b ].roty, 0.0f, 1.0f, 0.0f );   glRotatef( skelet.bone[ b ].rotx, 1.0f, 0.0f, 0.0f );   glRotatef( skelet.bone[ b ].rotz, 0.0f, 0.0f, 1.0f );   if ( ! m_skel ) {    //displaying skeleton    glBegin( GL_TRIANGLES );    f = skelet.bone[ b ].length / 10;    glColor3f( 1.0f, 0.8f, 0.8f );    glVertex3f(  f, 0.0f, 0.0f );    glColor3f( 0.8f, 1.0f, 0.8f );    glVertex3f( -f, 0.0f, 0.0f );    glColor3f( 1.0f, 1.0f, 1.0f );    glVertex3f( 0.0f, 0.0f, skelet.bone[ b ].length );    glColor3f( 0.8f, 1.0f, 0.8f );    glVertex3f( -f, 0.0f, 0.0f );    glColor3f( 0.8f, 0.8f, 1.0f );    glVertex3f( 0.0f, f, 0.0f );    glColor3f( 1.0f, 1.0f, 1.0f );    glVertex3f( 0.0f, 0.0f, skelet.bone[ b ].length );    glColor3f( 0.8f, 0.8f, 1.0f );    glVertex3f( 0.0f, f, 0.0f );    glColor3f( 1.0f, 0.8f, 0.8f );    glVertex3f( f, 0.0f, 0.0f );    glColor3f( 1.0f, 1.0f, 1.0f );    glVertex3f( 0.0f, 0.0f, skelet.bone[ b ].length );    glEnd();   }   if ( ! m_model ) {    //display model    if (( skelet.bone[ b ].model_bound ) &&     ( skelet.bone[ b ].model_data_set ))     glCallList( skelet.bone[ b ].partId );   }   skelet.bone[ b ].displayed = true;   glTranslatef( 0.0f, 0.0f, skelet.bone[ b ].length );   GlDisplayBoneChildren( b );   glPopMatrix();  }}
 
I'm not sure there is anything in this that you guys haven't already replicated in your own viewers, but what the heck....

Here is the binary and source to my own OpenGL-based model viewer for FF7 PSX that I wrote:

http://www.virtualdub.org/other/ff7view.zip
http://www.virtualdub.org/other/ff7viewsrc.zip

As compiled it will expect EARITH.BIN and CLOUD.BIN in the current directory or it will crash (decompress EARITH.LZS and CLOUD.LZS to get these). It will then load and display Aerith, and you can adjust the skeleton. The keys are something like (a)ntialias, (w)ireframe, (t)ranslate, f2/f3 to load and save, (i)k mode, space to switch axes, and [ and ] to change bones. The viewer knows how to load the models as well as the first frame of 12-bit coded anims. There's some really ratty export-to-DXF code in there as well although I don't think it ever worked that well since it couldn't export vertex colors.

Obviously, the viewer isn't polished; I wrote it to make a really high quality image for a T-shirt of Aerith hugging Cloud.
 
Status
Not open for further replies.
Back
Top