Author Topic: Decent FF7 Model Viewer  (Read 105163 times)

mirex

  • *
  • Posts: 1645
    • View Profile
    • http://mirex.mypage.sk
Decent FF7 Model Viewer
« Reply #225 on: 2004-10-05 05:49:14 »
Try looking into this thread FF7 models to 3ds Max for some hints.

Kislinskiy

  • Guest
Decent FF7 Model Viewer
« Reply #226 on: 2004-10-06 08:23:54 »


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

L. Spiro

  • *
  • Posts: 797
    • View Profile
    • http://www.memoryhacking.com/index.php
Decent FF7 Model Viewer
« Reply #227 on: 2004-10-06 10:59:34 »
Your setup is completely different from mine so my code will not help much, but I will post it anyway.



Code: [Select]
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

L. Spiro

  • *
  • Posts: 797
    • View Profile
    • http://www.memoryhacking.com/index.php
Something Something VII Online.
« Reply #228 on: 2004-10-07 08:13:08 »
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

Micky

  • *
  • Posts: 300
    • View Profile
Re: Something Something VII Online.
« Reply #229 on: 2004-10-07 17:39:08 »
Quote from: 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?

mirex

  • *
  • Posts: 1645
    • View Profile
    • http://mirex.mypage.sk
Decent FF7 Model Viewer
« Reply #230 on: 2004-10-10 13:09:41 »
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]

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

}

phaeron

  • *
  • Posts: 30
    • View Profile
Decent FF7 Model Viewer
« Reply #231 on: 2004-10-16 06:19:18 »
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.