BsxFile.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. #include <Ogre.h>
  2. #include "../../common/Logger.h"
  3. #include "BsxFile.h"
  4. #include "BcxFile.h"
  5. #include "TdbFile.h"
  6. #include "AnimationFile.h"
  7. #include "MeshFile.h"
  8. #include "SkeletonFile.h"
  9. BsxFile::BsxFile(const Ogre::String& file):
  10. LzsFile(file), m_Vram(Vram::MakeInstance())
  11. {
  12. ReadBSXTextureToVram();
  13. }
  14. BsxFile::BsxFile(File* pFile):
  15. LzsFile(pFile), m_Vram(Vram::MakeInstance())
  16. {
  17. ReadBSXTextureToVram();
  18. }
  19. BsxFile::BsxFile(File* pFile, const u32 offset, const u32 length):
  20. LzsFile(pFile, offset, length), m_Vram(Vram::MakeInstance())
  21. {
  22. ReadBSXTextureToVram();
  23. }
  24. BsxFile::BsxFile(u8* pBuffer, const u32 offset, const u32 length):
  25. LzsFile(pBuffer, offset, length), m_Vram(Vram::MakeInstance())
  26. {
  27. ReadBSXTextureToVram();
  28. }
  29. BsxFile::~BsxFile()
  30. {
  31. }
  32. Ogre::Entity*
  33. BsxFile::GetModel( Ogre::Entity* entity, const s8 character_id, const Unit& unit, const DatModelData dat )
  34. {
  35. int start_animation = ( dat.global_model_id > 0 ) ? 3 : 0;
  36. u32 offset_to_models_description = GetU32LE( 0x04 );
  37. s32 number_of_models_description = GetU32LE( offset_to_models_description + 0x04 );
  38. if( character_id >= number_of_models_description )
  39. {
  40. return NULL;
  41. }
  42. u32 offset_to_field_model_description = offset_to_models_description + 0x10 + character_id * 0x30;
  43. //LOGGER->Log(LOGGER_INFO, "\n\noffset_to_field_model_description: %08x", offset_to_field_model_description);
  44. u8 number_of_bones = GetU8(offset_to_field_model_description + 0x17);
  45. u8 number_of_parts = GetU8(offset_to_field_model_description + 0x23);
  46. u8 number_of_animations = GetU8(offset_to_field_model_description + 0x2f);
  47. //LOGGER->Log(LOGGER_INFO, "number of bones %02x", number_of_bones);
  48. //LOGGER->Log(LOGGER_INFO, "number of parts %02x", number_of_parts);
  49. //LOGGER->Log(LOGGER_INFO, "number of animations %02x", number_of_animations);
  50. VectorTexForGenBsx textures;
  51. std::vector< s16 > skeleton_length;
  52. Ogre::MeshPtr mesh;
  53. Ogre::SkeletonPtr skeleton;
  54. if (entity == NULL)
  55. {
  56. mesh = Ogre::MeshManager::getSingleton().create( "export" + unit.name, "General" );
  57. skeleton = Ogre::SkeletonManager::getSingleton().create( "export" + unit.name, "General" );
  58. switch (dat.global_model_id)
  59. {
  60. case 1:
  61. {
  62. BcxFile file( "data/field/cloud.bcx" );
  63. file.GetModel(skeleton_length, unit, mesh, skeleton, textures);
  64. }
  65. break;
  66. case 3:
  67. {
  68. BcxFile file( "data/field/ballet.bcx" );
  69. file.GetModel(skeleton_length, unit, mesh, skeleton, textures);
  70. }
  71. break;
  72. case 4:
  73. {
  74. BcxFile file( "data/field/tifa.bcx" );
  75. file.GetModel(skeleton_length, unit, mesh, skeleton, textures);
  76. }
  77. break;
  78. case 7:
  79. {
  80. BcxFile file( "data/field/yufi.bcx" );
  81. file.GetModel(skeleton_length, unit, mesh, skeleton, textures);
  82. }
  83. break;
  84. default:
  85. {
  86. // mesh
  87. u32 offset_to_parts = offset_to_field_model_description + GetU32LE(offset_to_field_model_description + 0x4) + number_of_bones * 4;
  88. MeshFile file_m(this);
  89. file_m.GetData(unit.name, offset_to_parts, number_of_parts, mesh, textures);
  90. // skeleton
  91. u32 offset_to_bones = offset_to_field_model_description + GetU16LE(offset_to_field_model_description + 0x4);
  92. SkeletonFile file_s(this);
  93. file_s.GetData(skeleton_length, offset_to_bones, number_of_bones, skeleton);
  94. }
  95. }
  96. }
  97. else
  98. {
  99. skeleton = Ogre::SkeletonManager::getSingleton().getByName(entity->getSkeleton()->getName());
  100. switch( dat.global_model_id )
  101. {
  102. case 1:
  103. {
  104. BcxFile file( "data/field/cloud.bcx" );
  105. file.GetSkeleton( skeleton_length );
  106. }
  107. break;
  108. case 3:
  109. {
  110. BcxFile file( "data/field/ballet.bcx" );
  111. file.GetSkeleton( skeleton_length );
  112. }
  113. break;
  114. case 4:
  115. {
  116. BcxFile file( "data/field/tifa.bcx" );
  117. file.GetSkeleton( skeleton_length );
  118. }
  119. break;
  120. case 7:
  121. {
  122. BcxFile file( "data/field/yufi.bcx" );
  123. file.GetSkeleton( skeleton_length );
  124. }
  125. break;
  126. default:
  127. {
  128. // skeleton
  129. u32 offset_to_bones = offset_to_field_model_description + GetU16LE( offset_to_field_model_description + 0x4 );
  130. SkeletonFile file_s( this );
  131. Ogre::SkeletonPtr null_skeleton;
  132. null_skeleton.setNull();
  133. file_s.GetData( skeleton_length, offset_to_bones, number_of_bones, null_skeleton );
  134. }
  135. }
  136. }
  137. // animations
  138. u32 offset_to_animations = offset_to_field_model_description + GetU16LE(offset_to_field_model_description + 0x4) + number_of_bones * 4 + number_of_parts * 0x20;
  139. AnimationFile file( this );
  140. file.GetData( skeleton_length, unit, offset_to_animations, number_of_animations, start_animation, skeleton );
  141. Ogre::SkeletonSerializer skeleton_serializer;
  142. skeleton_serializer.exportSkeleton( skeleton.getPointer(), "exported/models/ffvii/field/units/" + unit.name + ".skeleton" );
  143. if( entity == NULL )
  144. {
  145. // Update bounds
  146. Ogre::AxisAlignedBox aabb( -999, -999, -999, 999, 999, 999 );
  147. mesh->_setBounds( aabb, false );
  148. mesh->_setBoundingSphereRadius( 999 );
  149. mesh->setSkeletonName( "models/ffvii/field/units/" + unit.name + ".skeleton" );
  150. Ogre::MeshSerializer ser;
  151. ser.exportMesh( mesh.getPointer(), "exported/models/ffvii/field/units/" + unit.name + ".mesh" );
  152. // create and export textures for model
  153. CreateTexture( unit.name, dat.face_id, textures );
  154. Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create( "ffvii/model/field/" + unit.name, "General" );
  155. Ogre::Technique* tech = material->getTechnique( 0 );
  156. Ogre::Pass* pass1 = tech->getPass( 0 );
  157. pass1->setVertexColourTracking( Ogre::TVC_AMBIENT );
  158. pass1->setCullingMode( Ogre::CULL_NONE );
  159. Ogre::Pass* pass2 = tech->createPass();
  160. pass2->setCullingMode( Ogre::CULL_NONE );
  161. pass2->setAlphaRejectFunction( Ogre::CMPF_GREATER );
  162. pass2->setAlphaRejectValue( 0 );
  163. Ogre::TextureUnitState* tex = pass2->createTextureUnitState();
  164. /*
  165. if( dat.face_id != 0x21 )
  166. {
  167. tex->setTextureScroll( 0.0625 * 2, 0 );
  168. }
  169. */
  170. tex->setTextureName( "models/ffvii/field/units/" + unit.name + ".png" );
  171. tex->setNumMipmaps( 0 );
  172. tex->setTextureFiltering( Ogre::TFO_NONE );
  173. Ogre::MaterialSerializer mat;
  174. mat.exportMaterial( material, "exported/models/ffvii/field/units/" + unit.name + ".material" );
  175. Ogre::SceneManager* scene_manager = Ogre::Root::getSingleton().getSceneManager( "Scene" );
  176. Ogre::Entity* thisEntity = scene_manager->createEntity( unit.name, "models/ffvii/field/units/" + unit.name + ".mesh" );
  177. //thisEntity->setDisplaySkeleton(true);
  178. //thisEntity->setDebugDisplayEnabled(true);
  179. thisEntity->setVisible( false );
  180. thisEntity->getAnimationState( "Idle" )->setEnabled( true );
  181. thisEntity->getAnimationState( "Idle" )->setLoop( true );
  182. Ogre::SceneNode* thisSceneNode = scene_manager->getRootSceneNode()->createChildSceneNode();
  183. thisSceneNode->setPosition( 0, 0, 0 );
  184. thisSceneNode->roll( Ogre::Radian( Ogre::Degree( 180.0f ) ) );
  185. thisSceneNode->yaw( Ogre::Radian( Ogre::Degree( 120.0f ) ) );
  186. thisSceneNode->pitch( Ogre::Radian( Ogre::Degree( 90.0f ) ) );
  187. thisSceneNode->attachObject( thisEntity );
  188. return thisEntity;
  189. }
  190. else
  191. {
  192. entity->refreshAvailableAnimationState();
  193. return NULL;
  194. }
  195. }
  196. void
  197. BsxFile::CreateTexture( const Ogre::String& name, const int face_id, const VectorTexForGenBsx& textures )
  198. {
  199. int tex_width = 512;
  200. int tex_height = 256;
  201. Ogre::TexturePtr ptex;
  202. Ogre::HardwarePixelBufferSharedPtr buffer;
  203. ptex = Ogre::TextureManager::getSingleton().createManual( "DynaTex", "General", Ogre::TEX_TYPE_2D, tex_width, tex_height, 0, Ogre::PF_R8G8B8A8, Ogre::TU_STATIC );
  204. buffer = ptex->getBuffer( 0, 0 );
  205. buffer->lock( Ogre::HardwareBuffer::HBL_DISCARD );
  206. const Ogre::PixelBox& pb = buffer->getCurrentLock();
  207. for( unsigned int i = 0; i < textures.size(); ++i )
  208. {
  209. // type 0x0 - eye, type 0x1 - mouth, type 0x2 - normal texture.
  210. if( textures[ i ].type == 0 || textures[ i ].type == 1 )
  211. {
  212. TdbFile face_texture( "data/field/field.tdb" );
  213. face_texture.CreateTexture( pb, face_id, textures[ i ].start_x, textures[ i ].start_y );
  214. }
  215. else if( textures[ i ].type == 2 )
  216. {
  217. CreateTextureFromVram( pb, m_Vram.get(), textures[ i ].start_x, textures[ i ].start_y, textures[ i ].palette_x, textures[ i ].palette_y, textures[ i ].texture_x, textures[ i ].texture_y, textures[ i ].bpp, true );
  218. }
  219. }
  220. Ogre::Image image;
  221. image.loadDynamicImage((Ogre::uchar*)pb.data, tex_width, tex_height, Ogre::PF_R8G8B8A8);
  222. image.save( "exported/models/ffvii/field/units/" + name + ".png" );
  223. buffer->unlock();
  224. return;
  225. }
  226. void
  227. BsxFile::ReadBSXTextureToVram()
  228. {
  229. u32 offset_to_models_description = GetU32LE( 0x04 );
  230. u32 offset_to_texture = offset_to_models_description + GetU32LE( offset_to_models_description + 0x08 );
  231. u32 unknown = GetU32LE( offset_to_texture + 0x04 ) & 0xffffff00;
  232. //LOGGER->Log(LOGGER_INFO, "WARNING WARNING %04x", unknown);
  233. u8 number_of_texture = GetU8( offset_to_texture + 0x04 );
  234. //LOGGER->Log(LOGGER_INFO, "number_of_texture %04x", number_of_texture);
  235. if( number_of_texture == 0 )
  236. {
  237. return;
  238. }
  239. for( int i = 0; i < number_of_texture; ++i )
  240. {
  241. u16 width = GetU16LE( offset_to_texture + 0x08 + i * 0x0c + 0x00 ) * 2;
  242. u16 height = GetU16LE( offset_to_texture + 0x08 + i * 0x0c + 0x02 );
  243. u16 vram_x = GetU16LE( offset_to_texture + 0x08 + i * 0x0c + 0x04 ) * 2;
  244. u16 vram_y = GetU16LE( offset_to_texture + 0x08 + i * 0x0c + 0x06 );
  245. u32 start = offset_to_texture + GetU32LE( offset_to_texture + 0x08 + i * 0x0c + 0x08 );
  246. //LOGGER->Log(LOGGER_INFO, "Store BSX texture to vram %04x %04x", vram_x, vram_y);
  247. for( int y = 0; y < height; ++y )
  248. {
  249. for( int x = 0; x < width; ++x )
  250. {
  251. m_Vram->PutU8( vram_x + x, vram_y + y, GetU8( start + y * width + x ) );
  252. }
  253. }
  254. }
  255. }