#pragma once #include "ace_common.h" #include "p3d/parser.hpp" #include "p3d/model.hpp" #include #include namespace ace { namespace p3d { parser::parser() {} parser::~parser() {} model * parser::load(const std::string filepath) { std::ifstream ifstream; model *_model = new model(); size_t index = 4; _model->filepath = filepath; ifstream.open(filepath, std::ios::binary); if (!ifstream.good()) { printf("! File not found\n"); return false; } // get length of file: ifstream.seekg(0, std::ios::end); _model->size = ifstream.tellg(); ifstream.seekg(0, std::ios::beg); // Read the whole file into memory real fast _model->raw = new unsigned char[_model->size]; ifstream.read((char *)_model->raw, _model->size); // use the ifstream to read the data ifstream.seekg(0, std::ios::beg); ifstream.read((char *)&_model->header.filetype, 4); ifstream.read((char *)&_model->header.version, sizeof(uint64_t)); // If version > 48, it may have a path or a empty null byte. if (_model->header.version >= 48) { for (int x = 0; x < sizeof(_model->header.prefix); x++) { char byte; ifstream.read(&byte, 1); _model->header.prefix[x] = byte; if (byte == 0x00) break; } } ifstream.read((char *)&_model->header.lod_count, sizeof(uint32_t)); printf("Version: %d\n", _model->header.version); printf("%s\n", _model->header.prefix); printf("\tLODs:\t%d\n", (long long)_model->header.lod_count); #ifdef _DEBUG #define READ_DATA(stream, output, size) stream.read((char *)&output, size); #else #define READ_DATA(stream, output, size) stream.read((char *)&output, size); #endif #define PRINT_INDEX { std::streamoff pos = ifstream.tellg(); printf("Current Index: %08x\n", pos); } // Begin model info READ_DATA(ifstream, _model->info.LodResolutions, sizeof(float)*_model->header.lod_count); READ_DATA(ifstream, _model->info.Index, sizeof(uint32_t)); READ_DATA(ifstream, _model->info.MemLodSphere, sizeof(float)); READ_DATA(ifstream, _model->info.GeoLodSphere, sizeof(float)); READ_DATA(ifstream, _model->info.PointFlags, sizeof(uint32_t)*3); READ_DATA(ifstream, _model->info.Offset1, sizeof(XYZTriplet)); READ_DATA(ifstream, _model->info.mapIconColor, sizeof(uint32_t)); READ_DATA(ifstream, _model->info.mapSelectedColor, sizeof(uint32_t)); READ_DATA(ifstream, _model->info.ViewDensity, sizeof(float)); READ_DATA(ifstream, _model->info.bboxMinPosition, sizeof(XYZTriplet)); READ_DATA(ifstream, _model->info.bboxMaxPosition, sizeof(XYZTriplet)); READ_DATA(ifstream, _model->info.CentreOfGravity, sizeof(XYZTriplet)); READ_DATA(ifstream, _model->info.Offset2, sizeof(XYZTriplet)); READ_DATA(ifstream, _model->info.CogOffset, sizeof(XYZTriplet)); READ_DATA(ifstream, _model->info.ModelMassVectors, sizeof(XYZTriplet)*3); READ_DATA(ifstream, _model->info.ThermalProfile2, sizeof(uint8_t)*24); READ_DATA(ifstream, _model->info.AutoCenter, sizeof(uint8_t)); READ_DATA(ifstream, _model->info.lockAutoCenter, sizeof(uint8_t)); READ_DATA(ifstream, _model->info.canOcclude, sizeof(uint8_t)); READ_DATA(ifstream, _model->info.canBeOccluded, sizeof(uint8_t)); READ_DATA(ifstream, _model->info.allowAnimation, sizeof(uint8_t)); READ_DATA(ifstream, _model->info.UnknownARMAFlags, sizeof(uint8_t) * 6); READ_DATA(ifstream, _model->info.ThermalProfile, sizeof(uint8_t) * 24); READ_DATA(ifstream, _model->info.UnknownLong, sizeof(uint32_t)); // Skeleton! for (int x = 0; x < sizeof(_model->info.Skeleton); x++) { char byte; ifstream.read(&byte, 1); _model->info.Skeleton.name[x] = byte; if (byte == 0x00) break; } if (_model->info.Skeleton.name[0] != 0x00) { READ_DATA(ifstream, _model->info.Skeleton.isInherited, sizeof(uint8_t)); READ_DATA(ifstream, _model->info.Skeleton.bone_count, sizeof(uint32_t)); for (int x = 0; x < 256 && x < _model->info.Skeleton.bone_count; x++) { for (int y = 0; y < sizeof(_model->info.Skeleton.bone_names[x].BoneName); y++) { char byte; ifstream.read(&byte, 1); _model->info.Skeleton.bone_names[x].BoneName[y] = byte; if (byte == 0x00) break; } for (int y = 0; y < sizeof(_model->info.Skeleton.bone_names[x].ParentBoneName); y++) { char byte; ifstream.read(&byte, 1); _model->info.Skeleton.bone_names[x].ParentBoneName[y] = byte; if (byte == 0x00) break; } printf("Read bone entry: %s -> Parent:%s\n", _model->info.Skeleton.bone_names[x].BoneName, _model->info.Skeleton.bone_names[x].ParentBoneName); } } READ_DATA(ifstream, _model->info.UnknownByte, sizeof(uint8_t)); READ_DATA(ifstream, _model->info.nFloats, sizeof(uint32_t)); printf("Floats: %d\n", _model->info.nFloats); if (_model->info.nFloats * sizeof(float) > 1024) { // TODO!: Read compressed segment } else { ifstream.seekg(_model->info.nFloats*sizeof(float), ifstream.cur); //READ_DATA(ifstream, _model->info.UnknownFloats, ); } READ_DATA(ifstream, _model->info.Mass, sizeof(float)); READ_DATA(ifstream, _model->info.MassReciprocal, sizeof(float)); READ_DATA(ifstream, _model->info.AltMass, sizeof(float)); READ_DATA(ifstream, _model->info.AltMassReciprocal, sizeof(float)); READ_DATA(ifstream, _model->info.UnknownByteIndices, sizeof(uint8_t) * 14); READ_DATA(ifstream, _model->info.UnknownShort, sizeof(uint16_t)); READ_DATA(ifstream, _model->info.UnknownLodCount, sizeof(uint32_t)); READ_DATA(ifstream, _model->info.UnknownBool, sizeof(uint8_t)); /* for (int x = 0; x < sizeof(_model->info.ClassType); x++) { char byte; ifstream.read(&byte, 1); _model->info.ClassType[x] = byte; if (byte == 0x00 || byte == 0xff) break; } for (int x = 0; x < sizeof(_model->info.DestructType); x++) { char byte; ifstream.read(&byte, 1); _model->info.DestructType[x] = byte; if (byte == 0x00 || byte == 0xff) break; }*/ READ_DATA(ifstream, _model->info.UnknownBool2, sizeof(uint8_t)); READ_DATA(ifstream, _model->info.Always0, sizeof(uint8_t)); for (int x = 0; x < sizeof(_model->header.lod_count); x++) { READ_DATA(ifstream, _model->info.DefaultIndicators[x], sizeof(uint8_t)*12); } // Read ahead because i dont understand whats going on for (int x = 0; x < _model->size; x++) { char byte; ifstream.read(&byte, 1); if (byte != -1) { ifstream.seekg(-1, ifstream.cur); break; }; } READ_DATA(ifstream, _model->animations.AnimsExist, sizeof(uint8_t)); if (_model->animations.AnimsExist) { READ_DATA(ifstream, _model->animations.nAnimationClasses, sizeof(uint32_t)); printf("Animations: %d", _model->animations.nAnimationClasses); for (int n = 0; n < _model->animations.nAnimationClasses; n++) { READ_DATA(ifstream, _model->animations.AnimationClasses[n].AnimTransformType, sizeof(uint32_t)); for (int x = 0; x < sizeof(_model->animations.AnimationClasses[n].AnimClassName); x++) { char byte; ifstream.read(&byte, 1); _model->animations.AnimationClasses[n].AnimClassName[x] = byte; if (byte == 0x00) break; } for (int x = 0; x < sizeof(_model->animations.AnimationClasses[n].AnimSource); x++) { char byte; ifstream.read(&byte, 1); _model->animations.AnimationClasses[n].AnimSource[x] = byte; if (byte == 0x00) break; } printf("Reading animation: [%08x]-[%s]-%s\n", _model->animations.AnimationClasses[n].AnimTransformType, _model->animations.AnimationClasses[n].AnimClassName, _model->animations.AnimationClasses[n].AnimSource); READ_DATA(ifstream, _model->animations.AnimationClasses[n].MinMaxValue, sizeof(float) * 2); READ_DATA(ifstream, _model->animations.AnimationClasses[n].MinMaxPhase, sizeof(float) * 2); READ_DATA(ifstream, _model->animations.AnimationClasses[n].sourceAddress, sizeof(uint32_t)); READ_DATA(ifstream, _model->animations.AnimationClasses[n].Always0, sizeof(uint32_t)); READ_DATA(ifstream, _model->animations.AnimationClasses[n].nFloats, sizeof(uint32_t)); for (int x = 0; x < _model->animations.AnimationClasses[n].nFloats; x++) { READ_DATA(ifstream, _model->animations.AnimationClasses[n].floats, sizeof(float)); } READ_DATA(ifstream, _model->animations.AnimationClasses[n].value, sizeof(float)); switch (_model->animations.AnimationClasses[n].AnimTransformType) { case 0:READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float)); break;//rotaton case 1:READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float)); break;//rotationX case 2:READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float)); break;//rotationY case 3:READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float)); break;//rotationZ READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float) * 2); break; case 4:READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float)); break;//translation case 5:READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float)); break;//translationX case 6:READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float)); break;//translationY case 7:READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float)); break; //translationZ READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float)*2); break; case 8: //"direct" READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float) * 8); break; case 9: //"hide" READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float)); break; default: READ_DATA(ifstream, _model->animations.AnimationClasses[n].value, sizeof(float)); } PRINT_INDEX; } } // Animations done, WEEE! READ_DATA(ifstream, _model->animations.NoOfResolutions, sizeof(uint32_t)); for (int x = 0; x < _model->animations.NoOfResolutions; x++) { // Read a Bones2Anims entry READ_DATA(ifstream, _model->animations.Bones2Anims[x].NoOfBones, sizeof(uint32_t)); for (int y = 0; y < _model->animations.Bones2Anims[x].NoOfBones; y++) { READ_DATA(ifstream, _model->animations.Bones2Anims[x].Bone2AnimClassLists[y].NoOfAnimClasses, sizeof(uint32_t)); for (int z = 0; z < _model->animations.Bones2Anims[x].Bone2AnimClassLists[y].NoOfAnimClasses; z++) { READ_DATA(ifstream, _model->animations.Bones2Anims[x].Bone2AnimClassLists[y].AnimationClassIndex[z], sizeof(uint32_t)); } } } for (int x = 0; x < _model->animations.NoOfResolutions; x++) { // Read Anims2Bones for (int y = 0; y < _model->animations.nAnimationClasses; y++) { READ_DATA(ifstream, _model->animations.Anims2Bones[x].AnimBones[y].SkeletonBoneNameIndex, sizeof(uint32_t)); if (_model->animations.Anims2Bones[x].AnimBones[y].SkeletonBoneNameIndex != -1 && _model->animations.AnimationClasses[y].AnimTransformType != 8 && _model->animations.AnimationClasses[y].AnimTransformType != 9) { READ_DATA(ifstream, _model->animations.Anims2Bones[x].AnimBones[y].axisPos, sizeof(float) * 3); READ_DATA(ifstream, _model->animations.Anims2Bones[x].AnimBones[y].axisDir, sizeof(float) * 3); } PRINT_INDEX; printf("Read bone index: %d\n", _model->animations.Anims2Bones[x].AnimBones[y].SkeletonBoneNameIndex); } } READ_DATA(ifstream, _model->StartAddressOfLods, sizeof(uint32_t)*_model->header.lod_count); READ_DATA(ifstream, _model->EndAddressOfLods, sizeof(uint32_t)*_model->header.lod_count); printf("Beginning LOD Read: Start[%d] End[%d]\n", _model->StartAddressOfLods, _model->EndAddressOfLods); return _model; } }; };