void BcxFile::GetModel( std::vector< s16 >& skeleton_length, const Unit& unit, Ogre::MeshPtr mesh, Ogre::SkeletonPtr skeleton, VectorTexForGenBsx& textures ) { u32 offset_to_model_info = GetU32LE(0x04); u8 number_of_bones = GetU8(offset_to_model_info + 0x02); u8 number_of_parts = GetU8(offset_to_model_info + 0x03); u8 number_of_animations = GetU8(offset_to_model_info + 0x04); ////////////////////////// // mesh ////////////////////////// u16 offset_to_parts = GetU16LE(offset_to_model_info + 0x1c) + number_of_bones * 4; MeshFile file_m(this); file_m.GetData(unit.name, offset_to_parts, number_of_parts, mesh, textures); ////////////////////////// ////////////////////////// // skeleton ////////////////////////// u16 offset_to_bones = GetU16LE(offset_to_model_info + 0x1C); SkeletonFile file_s(this); file_s.GetData( skeleton_length, offset_to_bones, number_of_bones, skeleton ); ////////////////////////// /////////////////////////////////////////////////// // animations /////////////////////////////////////////////////// u32 offset_to_animations = GetU32LE(offset_to_model_info + 0x1C) - 0x80000000 + number_of_bones * 4 + number_of_parts * 0x20; AnimationFile afile(this); afile.GetData( skeleton_length, unit, offset_to_animations, number_of_animations, 0, skeleton ); }
uint16_t utils::GetU16(char *str,int pos){ #ifndef __EMSCRIPTEN__ uint16_t *addr = (uint16_t*)(str+pos); return (*addr); #else uint16_t r = (GetU8(str,pos)) + (GetU8(str,pos+1) << 8); return r; #endif }
uint32_t utils::GetU24(char *str,int pos){ #ifndef __EMSCRIPTEN__ uint32_t *addr = (uint32_t*)(str+pos); return (*addr)&0xffffff; #else uint32_t r = (GetU8(str,pos) ) + (GetU8(str,pos+1) << 8) + (GetU8(str,pos+2) << 16); return r; #endif }
uint32_t utils::GetU32(char *str,int pos){ #ifndef __EMSCRIPTEN__ uint32_t *addr = (uint32_t*)(str+pos); return *addr; #else uint32_t r = (GetU8(str,pos) ) + (GetU8(str,pos+1) << 8) + (GetU8(str,pos+2) << 16) + (GetU8(str,pos+3) << 24); return r; #endif }
void ScriptFile::GetU8Variable(u32& script_pointer, const RString &name) { u8 data = GetU8(script_pointer); LOGGER->Log("(u8 %s 0x%02x)", name.c_str(), data); script_pointer += 1; }
void ScriptFile::GetFVariable(u32& script_pointer) { u8 data = GetU8(script_pointer); LOGGER->Log("(flags 0x%02x)", data); script_pointer += 1; }
void ScriptFile::GetEVariable(u32& script_pointer) { u8 data = GetU8(script_pointer); LOGGER->Log("(entity_id 0x%02x)", data); script_pointer += 1; }
void BcxFile::GetSkeleton( std::vector< s16 >& skeleton_length ) { u32 offset_to_model_info = GetU32LE(0x04); u8 number_of_bones = GetU8(offset_to_model_info + 0x02); u16 offset_to_bones = GetU16LE(offset_to_model_info + 0x1C); SkeletonFile file_s(this); Ogre::SkeletonPtr skeleton; skeleton.setNull(); file_s.GetData( skeleton_length, offset_to_bones, number_of_bones, skeleton); }
dip_status ImpSymLocation( imp_image_handle *ii, imp_sym_handle *is, location_context *lc, location_list *ll, ji_ptr *obj_handle ) { address a; dip_status ds; location_list var; unsigned acc; unsigned cp_idx; unsigned_32 off; ji_ptr sig; switch( is->kind ) { case JS_METHOD: sig = 0; acc = GetU16( is->u.mb + offsetof( struct methodblock, fb.access ) ); if( acc & ACC_NATIVE ) return( DS_ERR | DS_BAD_LOCATION ); a = DefCodeAddr; a.mach.offset = GetPointer( is->u.mb + offsetof( struct methodblock, code ) ); LocationCreate( ll, LT_ADDR, &a ); break; case JS_FIELD: sig = GetPointer( is->u.fb + offsetof( struct fieldblock, signature ) ); acc = GetU16( is->u.fb + offsetof( struct fieldblock, access ) ); if( acc & ACC_STATIC ) { a = DefDataAddr; switch( GetU8( sig ) ) { case SIGNATURE_LONG: case SIGNATURE_DOUBLE: a.mach.offset = GetPointer( is->u.fb + offsetof( struct fieldblock, u.static_address ) ); break; default: a.mach.offset = is->u.fb + offsetof( struct fieldblock, u.static_value ); break; } LocationCreate( ll, LT_ADDR, &a ); } else {
dip_status DIGENTRY DIPImpSymType( imp_image_handle *ii, imp_sym_handle *is, imp_type_handle *it ) { it->sig = GetSignature( ii, is ); switch( is->kind ) { case JS_TYPE: case JS_PACKAGE: it->kind = JT_RAWNAME; return( DS_OK ); } switch( GetU8( it->sig ) ) { case SIGNATURE_ARRAY: case SIGNATURE_CLASS: it->u.is = *is; it->kind = JT_WANTOBJECT; break; default: it->kind = JT_SIGNATURE; break; } return( DS_OK ); }
Surface* FontFile::GetSurface(void) { int width = 512; int height = 4096; int chars = 0; int char_num = 6165; Surface* ret = CreateSurface(width, height); int x_16 = 0; int y_16 = 0; struct ClutColor { u8 r; /**< @brief red color in CLUT */ u8 g; /**< @brief green color in CLUT */ u8 b; /**< @brief blue color in CLUT */ u8 a; /**< @brief alpha in CLUT */ }; ClutColor color; color.r = 0; color.g = 0; color.b = 0; color.a = 255; u8 data = 0; for (int chars = 0; chars < char_num; ++chars) { Surface* glyth = CreateSurface(16, 16); for (int y = 0; y < 16; ++y) { data = (y < 11) ? GetU8(0xE + chars * 22 + y * 2 + 0) : 0; //LOGGER->Log(LOGGER_INFO, "%x, %02x", y, data); int j = 0; for (int i = 7; i >= 0; --i) { color.r = ((data >> i) & 0x01 == 1) ? 0 : 255; color.g = ((data >> i) & 0x01 == 1) ? 0 : 255; color.b = ((data >> i) & 0x01 == 1) ? 0 : 255; color.a = ((data >> i) & 0x01 == 1) ? 255 : 255; memcpy(glyth->pixels + 64 * y + j, &color, sizeof(ClutColor)); j += 4; } data = (y < 11) ? GetU8(0xE + chars * 22 + y * 2 + 1) : 0; //LOGGER->Log(LOGGER_INFO, "%02x", data); for (int i = 7; i >= 0; --i) { color.r = ((data >> i) & 0x01 == 1) ? 0 : 255; color.g = ((data >> i) & 0x01 == 1) ? 0 : 255; color.b = ((data >> i) & 0x01 == 1) ? 0 : 255; color.a = ((data >> i) & 0x01 == 1) ? 255 : 255; memcpy(glyth->pixels + 64 * y + j, &color, sizeof(ClutColor)); j += 4; } } CopyToSurface(ret, x_16, y_16, glyth); delete glyth; x_16 += 16; if (x_16 == ret->width) { y_16 += 16; x_16 = 0; } } Ogre::TexturePtr ptex; Ogre::HardwarePixelBufferSharedPtr buffer; ptex = Ogre::TextureManager::getSingleton().createManual("DynaTex", "General", Ogre::TEX_TYPE_2D, ret->width, ret->height, 0, Ogre::PF_R8G8B8A8, Ogre::TU_STATIC); buffer = ptex->getBuffer(0, 0); buffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); const Ogre::PixelBox& pb = buffer->getCurrentLock(); for (Uint32 y = 0; y < ret->height; ++y) { Uint32* data = static_cast<Uint32*>(pb.data) + y * pb.rowPitch; for (Uint32 x = 0; x < ret->width; ++x) { Uint32 clut = ret->pixels[y * ret->width * 4 + x * 4 + 3] | (ret->pixels[y * ret->width * 4 + x * 4 + 2] << 8) | (ret->pixels[y * ret->width * 4 + x * 4 + 1] << 16) | (ret->pixels[y * ret->width * 4 + x * 4 + 0] << 24); data[x] = clut; } } Ogre::Image image; image.loadDynamicImage((Ogre::uchar*)pb.data, ret->width, ret->height, Ogre::PF_R8G8B8A8); image.save("font.png"); buffer->unlock(); Ogre::TextureManager::getSingleton().remove("DynaTex"); return ret; }
walk_result DIGENTRY DIPImpWalkSymList( imp_image_handle *ii, symbol_source ss, void *source, IMP_SYM_WKR *wk, imp_sym_handle *is, void *d ) { scope_block *scope; address *a; walk_result wr; unsigned i; ji_ptr clazz; imp_type_handle *it; struct walk_data data; data.wk = wk; data.d = d; switch( ss ) { case SS_BLOCK: scope = source; switch( FindMBIndex( ii, scope->start.mach.offset, &i ) ) { case SR_EXACT: case SR_CLOSEST: break; default: return( WR_CONTINUE ); } if( scope->unique == OBJECT_SCOPE ) { wr = WalkObject( ii, FALSE, ii->cc, WalkSymGlue, is, &data ); } else { wr = WalkAScope( ii, i, scope, WalkSymGlue, is, &data ); } return( wr ); case SS_MODULE: /* no module scope symbols in Java */ break; case SS_SCOPED: a = source; switch( FindMBIndex( ii, a->mach.offset, &i ) ) { case SR_EXACT: case SR_CLOSEST: break; default: return( WR_CONTINUE ); } wr = WalkAllScopes( ii, i, a->mach.offset, WalkSymGlue, is, &data ); break; case SS_TYPE: it = source; switch( it->kind ) { case JT_RAWNAME: clazz = GetClass( it->sig ); break; case JT_WANTOBJECT: case JT_SIGNATURE: if( GetU8( it->sig ) != SIGNATURE_CLASS ) return( WR_CONTINUE ); clazz = GetClass( it->sig + 1 ); break; default: return( WR_CONTINUE ); } if( clazz != 0 ) { return( WalkObject( ii, FALSE, clazz, WalkSymGlue, is, &data ) ); } break; } return( WR_CONTINUE ); }
void ScriptFile::GetScripts() { u32 number_of_entity = GetU8(0x80); u32 offset_to_script = 0x84 + number_of_entity * 0x40; for (u32 i = 0; i < number_of_entity; ++i) { LOGGER->Log("Entity: 0x%02x\n", i); for (int j = 0; j < 0x20; ++j) { u32 offset_in_script = GetU16LE(0x84 + i * 0x40 + j * 2); if (offset_in_script == 0) { break; } LOGGER->Log("Script: 0x%02x\n", j); u32 script_pointer_end = 0; for (u32 l = i; l < number_of_entity; ++l) { u32 offset_in_next_script = 0; for (int script_id = 0; script_id < 0x20; ++script_id) { if (l == i && script_id <= j) { continue; } offset_in_next_script = GetU16LE(0x84 + l * 0x40 + script_id * 2); if (offset_in_next_script == 0) { continue; } else if (offset_in_script == offset_in_next_script) { offset_in_next_script = 0; continue; } break; } if (offset_in_next_script != 0) { script_pointer_end = offset_in_next_script + offset_to_script; break; } } if (script_pointer_end == 0) { script_pointer_end = mBufferSize; } u32 script_pointer = offset_to_script + offset_in_script; for (; script_pointer < script_pointer_end;) { LOGGER->Log("0x%04x ", script_pointer - offset_to_script); u8 opcode = GetU8(script_pointer); script_pointer += 1; if (opcode == 0x00) { LOGGER->Log("0x00_Return();\n"); } else if (opcode == 0x01) { LOGGER->Log("0x01_JumpTo(0x%04x);\n", GetU16LE(script_pointer)); script_pointer += 2; } else if (opcode == 0x02) { LOGGER->Log("0x02_ConditionalJumpTo"); u8 flag = GetU8(script_pointer + 4); switch (flag & 0xF0) { case 0x00: GetVVariable(script_pointer, "value1"); GetVVariable(script_pointer, "value2"); break; case 0x40: GetVVariable(script_pointer, "value1"); GetS16Variable(script_pointer, "value2"); break; case 0x80: GetS16Variable(script_pointer, "value1"); GetVVariable(script_pointer, "value2"); break; case 0xC0: GetS16Variable(script_pointer, "value1"); GetS16Variable(script_pointer, "value2"); break; } script_pointer += 1; // skip flag LOGGER->Log("; // continue if "); switch (flag & 0x0F) { case 0x00: LOGGER->Log("value1 == value2"); break; case 0x01: LOGGER->Log("value1 != value2"); break; case 0x02: LOGGER->Log("value1 > value2"); break; case 0x03: LOGGER->Log("value1 < value2"); break; case 0x04: LOGGER->Log("value1 >= value2"); break; case 0x05: LOGGER->Log("value1 <= value2"); break; case 0x06: LOGGER->Log("value1 & value2"); break; case 0x07: LOGGER->Log("value1 != value2"); break; case 0x08: LOGGER->Log("value1 | value2"); break; case 0x09: LOGGER->Log("value1 & value2"); break; case 0x0A: LOGGER->Log("(0 NOR value1) & value2"); break; } LOGGER->Log(", jump to 0x%04x otherwise;\n", GetU16LE(script_pointer)); script_pointer += 2; } else if (opcode == 0x0B) { LOGGER->Log("0x0B_EntityNPCInit"); GetV80Variable(script_pointer, "model_id"); LOGGER->Log("; // init values for entity with model.\n"); } else if (opcode == 0x16) { LOGGER->Log("0x16_EntityPCInit"); GetV80Variable(script_pointer, "character_id"); LOGGER->Log("; // init values for player character entity with model.\n"); } else if (opcode == 0x19) { LOGGER->Log("0x19_SetPosition"); GetVF80Variable(script_pointer, "x"); GetVF40Variable(script_pointer, "z"); GetFVariable(script_pointer); LOGGER->Log("; // set entity on walkmesh based on given x and y.\n"); } else if (opcode == 0x20) { LOGGER->Log("0x20_SetFlags"); GetV80Variable(script_pointer, "flags"); LOGGER->Log("; // set some flags for movement and collision.\n"); } else if (opcode == 0x23) { LOGGER->Log("0x23(); // add flag 0020 in 80114f2c + 58 of current entity.\n"); } else if (opcode == 0x26) { LOGGER->Log("0x26_Wait"); GetV80Variable(script_pointer, "time"); LOGGER->Log("; // stop script execution till script will be called given number of times.\n"); } else if (opcode == 0x29) { LOGGER->Log("0x29_EntityTurnOff"); GetEVariable(script_pointer); LOGGER->Log("; // turn entity off (script will not be runned, close dialog from this entity and so on).\n"); } else if (opcode == 0x2A) { LOGGER->Log("0x2A(); // add flag 00000002 in 80115cdc + 0 of current entity.\n"); } else if (opcode == 0x69) { LOGGER->Log("0x69_SetRotation"); GetV80Variable(script_pointer, "rotation"); LOGGER->Log(";\n"); } else if (opcode == 0x6B) { LOGGER->Log("0x6B_RotateClockwise"); GetV80Variable(script_pointer, "rotation"); LOGGER->Log(";\n"); } else if (opcode == 0x6C) { LOGGER->Log("0x6C_RotateAntiClockwise"); GetV80Variable(script_pointer, "rotation"); LOGGER->Log(";\n"); } else if (opcode == 0x6F) { LOGGER->Log("0x6F_RotateToEntity"); GetEVariable(script_pointer); LOGGER->Log(";\n"); } else if (opcode == 0x86) { LOGGER->Log("0x86_ProgressNotEqualJumpTo"); GetV80Variable(script_pointer, "value"); LOGGER->Log("; // jump to 0x%04x if progress != value\n", GetU16LE(script_pointer)); script_pointer += 2; } else if (opcode == 0xBC) { LOGGER->Log("0xBC_EntityNoModelInit(); // init values for entity without model.\n"); } else if (opcode == 0xC4) { LOGGER->Log("0xC4_DoorOpen(0x%02x); // 0 - clockwise, 1 - anticlockwise\n", GetU8(script_pointer)); script_pointer += 1; } else if (opcode == 0xC5) { LOGGER->Log("0xC5_DoorClose(0x%02x); // 0 - clockwise, 1 - anticlockwise\n", GetU8(script_pointer)); script_pointer += 1; } else if (opcode == 0xD2) { LOGGER->Log("0xD2_DialogShow"); GetU16Variable(script_pointer, "dialog_id"); GetU8Variable(script_pointer, "flags"); LOGGER->Log(";\n", GetU16LE(script_pointer)); } else if (opcode == 0xFE) { u8 eo_opcode = GetU8(script_pointer); script_pointer += 1; if (eo_opcode == 0x0D) { LOGGER->Log("0xFE0D_SetAvatar"); GetV80Variable(script_pointer, "character_id"); LOGGER->Log("; // assign avatar for current entity.\n"); } else { LOGGER->Log("MISSING OPCODE 0xFE%02x\n", eo_opcode); break; } } /* if (opcode == 0x10) { u8 flag = GetU8(o + 1); if (flag == 0) { size = 9; } else { size = 2; } LOGGER->Log("\t%s", opcodes_names[opcode].c_str()); } else if (opcode == 0x57) { u8 flag = GetU8(o + 1); if ((flag & 3) == 0 || (flag & 3) == 1 || (flag & 3) == 2) { size = 0xB; } else { size = 0x2; } LOGGER->Log("\t%s", opcodes_names[opcode].c_str()); } */ else { LOGGER->Log("MISSING OPCODE %02x\n", opcode); break; } } LOGGER->Log("\n"); } LOGGER->Log("\n\n\n"); } }
uint8_t utils::GetU8c (char *str,int &pos){ uint8_t r = GetU8(str,pos); pos += 1; return r; }
Ogre::Entity* ModelFile::GetModel( const ModelInfo& info ) { VectorTexForGen textures; Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().create( info.data.name + "export", "General" ); Ogre::SkeletonPtr skeleton = Ogre::SkeletonManager::getSingleton().create( info.data.name + "export", "General" ); int number_of_bones = GetU8( 0x02 ); int number_of_parts = GetU8( 0x03 ); int offset_to_bones = GetU32LE( 0x0c ); int offset_to_parts = GetU32LE( 0x10 ); Ogre::Bone* root1 = skeleton->createBone( "0", 0 ); Ogre::Bone* root2 = skeleton->createBone( "1", 1 ); root1->addChild( root2 ); for( int i = 0; i < number_of_bones; ++i ) { Bone bone; bone.parent_id = ( i != 0 ) ? ( s8 )GetU8( offset_to_bones + i * 0x04 + 0x03 ) : -1; bone.length = ( s16 )GetU16LE( offset_to_bones + i * 0x04 + 0x00 ); m_Skeleton.push_back(bone); Ogre::Bone* bone1 = skeleton->createBone( Ogre::StringConverter::toString( i * 2 + 2 ), i * 2 + 2 ); Ogre::Bone* bone2 = skeleton->createBone( Ogre::StringConverter::toString( i * 2 + 3 ), i * 2 + 3 ); LOGGER->Log( "Add skeleton bone: bone_id = " + Ogre::StringConverter::toString( i ) + ", length = " + Ogre::StringConverter::toString( bone.length ) + ", parent = " + Ogre::StringConverter::toString( bone.parent_id ) + ".\n" ); if( bone.parent_id == -1 ) { skeleton->getBone( 1 )->addChild( bone1 ); } else { skeleton->getBone( bone.parent_id * 2 + 3 )->addChild( bone1 ); } bone1->addChild( bone2 ); } AnimationExtractor( skeleton, info, m_Skeleton ); // draw skeleton { //DrawSkeleton( m_Skeleton, mesh ); } for( int i = 0; i < number_of_parts; ++i ) { MeshExtractor( info.data, "ffix/field_model/" + info.data.name, this, offset_to_parts + i * 0x28, textures, mesh ); } // <OGRE> /////////////////////////////// skeleton->optimiseAllAnimations(); Ogre::SkeletonSerializer skeleton_serializer; skeleton_serializer.exportSkeleton( skeleton.getPointer(), "exported/models/field/units/" + info.data.name + ".skeleton" ); // Update bounds Ogre::AxisAlignedBox aabb( -999, -999, -999, 999, 999, 999 ); mesh->_setBounds( aabb, false ); mesh->_setBoundingSphereRadius( 999 ); mesh->setSkeletonName( "models/field/units/" + info.data.name + ".skeleton" ); Ogre::MeshSerializer ser; ser.exportMesh( mesh.getPointer(), "exported/models/field/units/" + info.data.name + ".mesh" ); // create and export textures for model //if (textures.size() > 0) { Vram* vram = new Vram(); File* tex = new File( "./data/field/5/1b/2/4/1.tim" ); LoadTimFileToVram( tex, 0, vram ); delete tex; tex = new File( "./data/field/5/1b/2/4/2.tim" ); LoadTimFileToVram( tex, 0, vram ); delete tex; vram->Save( "1.jpg" ); CreateTexture( vram, info.data, "exported/models/field/units/" + info.data.name + ".png", textures ); delete vram; } CreateMaterial( "ffix/field_model/" + info.data.name, "exported/models/field/units/" + info.data.name + ".material", ( textures.size() > 0 ) ? "models/field/units/" + info.data.name + ".png" : "", "", "" ); Ogre::SceneManager* scene_manager = Ogre::Root::getSingleton().getSceneManager( "Scene" ); Ogre::Entity* thisEntity = scene_manager->createEntity( info.data.name, "models/field/units/" + info.data.name + ".mesh" ); //thisEntity->setDisplaySkeleton(true); //thisEntity->setDebugDisplayEnabled(true); thisEntity->setVisible( false ); thisEntity->getAnimationState( info.animations_name[ 0 ] )->setEnabled(true); thisEntity->getAnimationState( info.animations_name[ 0 ] )->setLoop(true); Ogre::SceneNode* thisSceneNode = scene_manager->getRootSceneNode()->createChildSceneNode(); thisSceneNode->setPosition( 0, 0, 0 ); thisSceneNode->roll( Ogre::Radian( Ogre::Degree( 180.0f ) ) ); thisSceneNode->yaw( Ogre::Radian( Ogre::Degree( 120.0f ) ) ); thisSceneNode->pitch( Ogre::Radian( Ogre::Degree(90.0f ) ) ); thisSceneNode->attachObject( thisEntity ); return thisEntity; }
_U8 CConstObject::GetU8(const char* name, _U32 index) const { return GetU8(Zion::StringFormat("%s[%d]", name, index).c_str()); }
void AnimationFile::GetData( std::vector< s16 >& skeleton_length, const Unit& unit, const int offset_to_animations, const int number_of_animation, const int start_animation, Ogre::SkeletonPtr skeleton) { for (int i = 0; i < number_of_animation; ++i) { /*LOGGER->Log(LOGGER_INFO, "Animation Header %02x%02x %02x %02x %02x %02x %02x%02x %02x%02x %02x%02x %02x%02x%02x%02x", GetU8(offset_to_animations + i * 0x10 + 0x00), GetU8(offset_to_animations + i * 0x10 + 0x01), GetU8(offset_to_animations + i * 0x10 + 0x02), GetU8(offset_to_animations + i * 0x10 + 0x03), GetU8(offset_to_animations + i * 0x10 + 0x04), GetU8(offset_to_animations + i * 0x10 + 0x05), GetU8(offset_to_animations + i * 0x10 + 0x06), GetU8(offset_to_animations + i * 0x10 + 0x07), GetU8(offset_to_animations + i * 0x10 + 0x08), GetU8(offset_to_animations + i * 0x10 + 0x09), GetU8(offset_to_animations + i * 0x10 + 0x0A), GetU8(offset_to_animations + i * 0x10 + 0x0B), GetU8(offset_to_animations + i * 0x10 + 0x0C), GetU8(offset_to_animations + i * 0x10 + 0x0D), GetU8(offset_to_animations + i * 0x10 + 0x0E), GetU8(offset_to_animations + i * 0x10 + 0x0F)); */ AnimationHeader header; header.number_of_frames = GetU16LE(offset_to_animations + i * 0x10 + 0x00); header.number_of_bones = GetU8(offset_to_animations + i * 0x10 + 0x02); header.number_of_frames_translation = GetU8(offset_to_animations + i * 0x10 + 0x03); header.number_of_static_translation = GetU8(offset_to_animations + i * 0x10 + 0x04); header.number_of_frames_rotation = GetU8(offset_to_animations + i * 0x10 + 0x05); header.offset_to_frames_translation_data = GetU16LE(offset_to_animations + i * 0x10 + 0x06); header.offset_to_static_translation_data = GetU16LE(offset_to_animations + i * 0x10 + 0x08); header.offset_to_frames_rotation_data = GetU16LE(offset_to_animations + i * 0x10 + 0x0A); header.offset_to_animation_data = GetU32LE(offset_to_animations + i * 0x10 + 0x0C) - 0x80000000; m_AnimationHeaders.push_back(header); } for (size_t i = 0; (i < static_cast<size_t>(number_of_animation)) && (start_animation + i < unit.animations.size()); ++i) { if (unit.animations[start_animation + i] == "" || unit.animations[start_animation + i] == " ") { continue; } /* File file(mpBuffer, m_AnimationHeaders[i].offset_to_animation_data, 0x04 + m_AnimationHeaders[i].number_of_bones * 0x08 + m_AnimationHeaders[i].number_of_frames_translation * m_AnimationHeaders[i].number_of_frames * 0x02 + m_AnimationHeaders[i].number_of_static_translation * 0x02 + m_AnimationHeaders[i].number_of_frames_rotation * m_AnimationHeaders[i].number_of_frames); file.WriteFile(RString((Ogre::String("dump/") + Ogre::String("animation_") + Ogre::StringConverter::toString(i) + Ogre::String("_data")).c_str())); */ Ogre::Animation* anim = skeleton->createAnimation(unit.animations[start_animation + i], (float)(m_AnimationHeaders[i].number_of_frames - 1) / 30.0f); for (u32 j = 0; j < m_AnimationHeaders[i].number_of_frames; ++j) { Frame frame; // root bone Ogre::Bone* root = skeleton->getBone(0); Ogre::NodeAnimationTrack* track; if (j == 0) { track = anim->createNodeTrack(0, root); track->removeAllKeyFrames(); } else { track = anim->getNodeTrack(0); } Ogre::TransformKeyFrame* frame_root = track->createNodeKeyFrame((float)j / 30.0f); Ogre::Quaternion rot; Ogre::Matrix3 mat; mat.FromEulerAnglesZXY(Ogre::Radian(Ogre::Degree(180)), Ogre::Radian(Ogre::Degree(0)), Ogre::Radian(Ogre::Degree(0))); rot.FromRotationMatrix(mat); frame_root->setRotation(rot); for (u32 k = 0; k < m_AnimationHeaders[i].number_of_bones; ++k) { BonePosition position; u8 flag = GetU8(m_AnimationHeaders[i].offset_to_animation_data + 0x04 + k * 0x08 + 0x00); u8 rx = GetU8(m_AnimationHeaders[i].offset_to_animation_data + 0x04 + k * 0x08 + 0x01); u8 ry = GetU8(m_AnimationHeaders[i].offset_to_animation_data + 0x04 + k * 0x08 + 0x02); u8 rz = GetU8(m_AnimationHeaders[i].offset_to_animation_data + 0x04 + k * 0x08 + 0x03); u8 tx = GetU8(m_AnimationHeaders[i].offset_to_animation_data + 0x04 + k * 0x08 + 0x04); u8 ty = GetU8(m_AnimationHeaders[i].offset_to_animation_data + 0x04 + k * 0x08 + 0x05); u8 tz = GetU8(m_AnimationHeaders[i].offset_to_animation_data + 0x04 + k * 0x08 + 0x06); // rotation if (flag & 0x01) { position.rotation_x = 360.0f * GetU8(m_AnimationHeaders[i].offset_to_animation_data + m_AnimationHeaders[i].offset_to_frames_rotation_data + rx * m_AnimationHeaders[i].number_of_frames + j) / 255.0f; } else { position.rotation_x = 360.0f * rx / 255.0f; } if (flag & 0x02) { position.rotation_y = 360.0f * GetU8(m_AnimationHeaders[i].offset_to_animation_data + m_AnimationHeaders[i].offset_to_frames_rotation_data + ry * m_AnimationHeaders[i].number_of_frames + j) / 255.0f; } else { position.rotation_y = 360.0f * ry / 255.0f; } if (flag & 0x04) { position.rotation_z = 360.0f * GetU8(m_AnimationHeaders[i].offset_to_animation_data + m_AnimationHeaders[i].offset_to_frames_rotation_data + rz * m_AnimationHeaders[i].number_of_frames + j) / 255.0f; } else { position.rotation_z = 360.0f * rz / 255.0f; } // translation position.translation_x = 0; position.translation_y = 0; position.translation_z = 0; if (flag & 0x10) { position.translation_x = static_cast<float>( -(s16)GetU16LE(m_AnimationHeaders[i].offset_to_animation_data + m_AnimationHeaders[i].offset_to_frames_translation_data + tx * m_AnimationHeaders[i].number_of_frames * 2 + j * 2)); } else if (tx != 0xFF) { position.translation_x = static_cast<float>(-(s16)GetU16LE(m_AnimationHeaders[i].offset_to_animation_data + m_AnimationHeaders[i].offset_to_static_translation_data + tx * 2)); } if (flag & 0x20) { position.translation_y = static_cast<float>(-(s16)GetU16LE(m_AnimationHeaders[i].offset_to_animation_data + m_AnimationHeaders[i].offset_to_frames_translation_data + ty * m_AnimationHeaders[i].number_of_frames * 2 + j * 2)); } else if (ty != 0xFF) { position.translation_y = static_cast<float>(-(s16)GetU16LE(m_AnimationHeaders[i].offset_to_animation_data + m_AnimationHeaders[i].offset_to_static_translation_data + ty * 2)); } if (flag & 0x40) { position.translation_z = static_cast<float>(-(s16)GetU16LE(m_AnimationHeaders[i].offset_to_animation_data + m_AnimationHeaders[i].offset_to_frames_translation_data + tz * m_AnimationHeaders[i].number_of_frames * 2 + j * 2)); } else if (tz != 0xFF) { position.translation_z = static_cast<float>(-(s16)GetU16LE(m_AnimationHeaders[i].offset_to_animation_data + m_AnimationHeaders[i].offset_to_static_translation_data + tz * 2)); } //LOGGER->Log(LOGGER_INFO, "%d %d", m_AnimationHeaders[i].number_of_frames, j); //LOGGER->Log(LOGGER_INFO, "animation (%f %f %f) (%f %f %f)", position.rotation_x, position.rotation_y, position.rotation_z, position.translation_x, position.translation_y, position.translation_z); frame.bone.push_back(position); Ogre::Bone* bone1 = skeleton->getBone(k * 2 + 1); Ogre::Bone* bone2 = skeleton->getBone(k * 2 + 2); Ogre::NodeAnimationTrack* track1; Ogre::NodeAnimationTrack* track2; if (j == 0) { track1 = anim->createNodeTrack(k * 2 + 1, bone1); track1->removeAllKeyFrames(); track2 = anim->createNodeTrack(k * 2 + 2, bone2); track2->removeAllKeyFrames(); } else { track1 = anim->getNodeTrack(k * 2 + 1); track2 = anim->getNodeTrack(k * 2 + 2); } Ogre::TransformKeyFrame* frame1 = track1->createNodeKeyFrame((float)j / 30.0f); Ogre::TransformKeyFrame* frame2 = track2->createNodeKeyFrame((float)j / 30.0f); float length = skeleton_length[ k ]; frame1->setTranslate(Ogre::Vector3(position.translation_x, position.translation_z - length, position.translation_y) / 1024); Ogre::Quaternion rot; Ogre::Matrix3 mat; mat.FromEulerAnglesZXY(Ogre::Radian(Ogre::Degree(-position.rotation_y)), Ogre::Radian(Ogre::Degree(-position.rotation_x)), Ogre::Radian(Ogre::Degree(-position.rotation_z))); rot.FromRotationMatrix(mat); frame2->setRotation(rot); } } } }