|
|
@@ -78,18 +78,19 @@ HL1MDLLoader::HL1MDLLoader(
|
|
|
aiScene *scene,
|
|
|
IOSystem *io,
|
|
|
const unsigned char *buffer,
|
|
|
+ size_t buffer_length,
|
|
|
const std::string &file_path,
|
|
|
const HL1ImportSettings &import_settings) :
|
|
|
scene_(scene),
|
|
|
io_(io),
|
|
|
- buffer_(buffer),
|
|
|
+ buffer_(HL1DataBuffer::view(buffer, buffer_length)),
|
|
|
file_path_(file_path),
|
|
|
import_settings_(import_settings),
|
|
|
header_(nullptr),
|
|
|
texture_header_(nullptr),
|
|
|
- anim_headers_(nullptr),
|
|
|
- texture_buffer_(nullptr),
|
|
|
- anim_buffers_(nullptr),
|
|
|
+ anim_headers_(),
|
|
|
+ texture_buffer_(),
|
|
|
+ anim_buffers_(),
|
|
|
num_sequence_groups_(0),
|
|
|
rootnode_children_(),
|
|
|
unique_name_generator_(),
|
|
|
@@ -108,28 +109,6 @@ HL1MDLLoader::~HL1MDLLoader() {
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
void HL1MDLLoader::release_resources() {
|
|
|
- if (buffer_ != texture_buffer_) {
|
|
|
- delete[] texture_buffer_;
|
|
|
- texture_buffer_ = nullptr;
|
|
|
- }
|
|
|
-
|
|
|
- if (num_sequence_groups_ && anim_buffers_) {
|
|
|
- for (int i = 1; i < num_sequence_groups_; ++i) {
|
|
|
- if (anim_buffers_[i]) {
|
|
|
- delete[] anim_buffers_[i];
|
|
|
- anim_buffers_[i] = nullptr;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- delete[] anim_buffers_;
|
|
|
- anim_buffers_ = nullptr;
|
|
|
- }
|
|
|
-
|
|
|
- if (anim_headers_) {
|
|
|
- delete[] anim_headers_;
|
|
|
- anim_headers_ = nullptr;
|
|
|
- }
|
|
|
-
|
|
|
// Root has some children nodes. so let's proceed them
|
|
|
if (!rootnode_children_.empty()) {
|
|
|
// Here, it means that the nodes were not added to the
|
|
|
@@ -147,7 +126,7 @@ void HL1MDLLoader::release_resources() {
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
void HL1MDLLoader::load_file() {
|
|
|
try {
|
|
|
- header_ = (const Header_HL1 *)buffer_;
|
|
|
+ header_ = get_buffer_data<Header_HL1>(0, 1);
|
|
|
validate_header(header_, false);
|
|
|
|
|
|
// Create the root scene node.
|
|
|
@@ -286,10 +265,10 @@ void HL1MDLLoader::load_texture_file() {
|
|
|
load_file_into_buffer<Header_HL1>(texture_file_path, texture_buffer_);
|
|
|
} else {
|
|
|
// Model has no external texture file. This means the texture is stored inside the main MDL file.
|
|
|
- texture_buffer_ = const_cast<unsigned char *>(buffer_);
|
|
|
+ texture_buffer_ = HL1DataBuffer::view(buffer_);
|
|
|
}
|
|
|
|
|
|
- texture_header_ = (const Header_HL1 *)texture_buffer_;
|
|
|
+ texture_header_ = get_texture_buffer_data<Header_HL1>(0, 1);
|
|
|
|
|
|
// Validate texture header.
|
|
|
validate_header(texture_header_, true);
|
|
|
@@ -318,12 +297,8 @@ void HL1MDLLoader::load_sequence_groups_files() {
|
|
|
|
|
|
num_sequence_groups_ = header_->numseqgroups;
|
|
|
|
|
|
- anim_buffers_ = new unsigned char *[num_sequence_groups_];
|
|
|
- anim_headers_ = new SequenceHeader_HL1 *[num_sequence_groups_];
|
|
|
- for (int i = 0; i < num_sequence_groups_; ++i) {
|
|
|
- anim_buffers_[i] = nullptr;
|
|
|
- anim_headers_[i] = nullptr;
|
|
|
- }
|
|
|
+ anim_buffers_.resize(num_sequence_groups_);
|
|
|
+ anim_headers_.resize(num_sequence_groups_, nullptr);
|
|
|
|
|
|
std::string file_path_without_extension =
|
|
|
DefaultIOSystem::absolutePath(file_path_) +
|
|
|
@@ -340,14 +315,14 @@ void HL1MDLLoader::load_sequence_groups_files() {
|
|
|
|
|
|
load_file_into_buffer<SequenceHeader_HL1>(sequence_file_path, anim_buffers_[i]);
|
|
|
|
|
|
- anim_headers_[i] = (SequenceHeader_HL1 *)anim_buffers_[i];
|
|
|
+ anim_headers_[i] = get_anim_buffer_data<SequenceHeader_HL1>(i, 0, 1);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
// Read an MDL texture.
|
|
|
void HL1MDLLoader::read_texture(const Texture_HL1 *ptexture,
|
|
|
- uint8_t *data, uint8_t *pal, aiTexture *pResult,
|
|
|
+ const uint8_t *data, const uint8_t *pal, aiTexture *pResult,
|
|
|
aiColor3D &last_palette_color) {
|
|
|
pResult->mFilename = ptexture->name;
|
|
|
pResult->mWidth = static_cast<unsigned int>(ptexture->width);
|
|
|
@@ -381,24 +356,24 @@ void HL1MDLLoader::read_texture(const Texture_HL1 *ptexture,
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
void HL1MDLLoader::read_textures() {
|
|
|
- const Texture_HL1 *ptexture = (const Texture_HL1 *)((uint8_t *)texture_header_ + texture_header_->textureindex);
|
|
|
- unsigned char *pin = texture_buffer_;
|
|
|
+ scene_->mTextures = new aiTexture *[texture_header_->numtextures];
|
|
|
+ scene_->mMaterials = new aiMaterial *[texture_header_->numtextures];
|
|
|
|
|
|
- scene_->mNumTextures = scene_->mNumMaterials = texture_header_->numtextures;
|
|
|
- scene_->mTextures = new aiTexture *[scene_->mNumTextures];
|
|
|
- scene_->mMaterials = new aiMaterial *[scene_->mNumMaterials];
|
|
|
+ const Texture_HL1 *ptexture = get_texture_buffer_data<Texture_HL1>(texture_header_->textureindex, texture_header_->numtextures);
|
|
|
|
|
|
for (int i = 0; i < texture_header_->numtextures; ++i) {
|
|
|
scene_->mTextures[i] = new aiTexture();
|
|
|
+ ++scene_->mNumTextures;
|
|
|
+
|
|
|
+ const uint8_t *data = get_texture_buffer_data<uint8_t>(ptexture[i].index, ptexture[i].width * ptexture[i].height);
|
|
|
+ const uint8_t *pal = get_texture_buffer_data<uint8_t>(ptexture[i].index + ptexture[i].width * ptexture[i].height, 256 * 3);
|
|
|
|
|
|
aiColor3D last_palette_color;
|
|
|
- read_texture(&ptexture[i],
|
|
|
- pin + ptexture[i].index,
|
|
|
- pin + ptexture[i].width * ptexture[i].height + ptexture[i].index,
|
|
|
- scene_->mTextures[i],
|
|
|
- last_palette_color);
|
|
|
+ read_texture(&ptexture[i], data, pal, scene_->mTextures[i], last_palette_color);
|
|
|
|
|
|
- aiMaterial *scene_material = scene_->mMaterials[i] = new aiMaterial();
|
|
|
+ aiMaterial *scene_material = new aiMaterial();
|
|
|
+ scene_->mMaterials[i] = scene_material;
|
|
|
+ ++scene_->mNumMaterials;
|
|
|
|
|
|
const aiTextureType texture_type = aiTextureType_DIFFUSE;
|
|
|
aiString texture_name(ptexture[i].name);
|
|
|
@@ -435,10 +410,14 @@ void HL1MDLLoader::read_skins() {
|
|
|
}
|
|
|
|
|
|
// Pointer to base texture index.
|
|
|
- short *default_skin_ptr = (short *)((uint8_t *)texture_header_ + texture_header_->skinindex);
|
|
|
+ const short *default_skin_ptr = get_texture_buffer_data<short>(
|
|
|
+ texture_header_->skinindex,
|
|
|
+ texture_header_->numskinref);
|
|
|
|
|
|
// Start at first replacement skin.
|
|
|
- short *replacement_skin_ptr = default_skin_ptr + texture_header_->numskinref;
|
|
|
+ const short *replacement_skin_ptr = get_texture_buffer_data<short>(
|
|
|
+ texture_header_->skinindex + texture_header_->numskinref * sizeof(short),
|
|
|
+ (texture_header_->numskinfamilies - 1) * texture_header_->numskinref);
|
|
|
|
|
|
for (int i = 1; i < texture_header_->numskinfamilies; ++i, replacement_skin_ptr += texture_header_->numskinref) {
|
|
|
for (int j = 0; j < texture_header_->numskinref; ++j) {
|
|
|
@@ -457,7 +436,7 @@ void HL1MDLLoader::read_bones() {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- const Bone_HL1 *pbone = (const Bone_HL1 *)((uint8_t *)header_ + header_->boneindex);
|
|
|
+ const Bone_HL1 *pbone = get_buffer_data<Bone_HL1>(header_->boneindex, header_->numbones);
|
|
|
|
|
|
std::vector<std::string> unique_bones_names(header_->numbones);
|
|
|
for (int i = 0; i < header_->numbones; ++i) {
|
|
|
@@ -589,12 +568,12 @@ void HL1MDLLoader::read_meshes() {
|
|
|
int total_triangles = 0;
|
|
|
total_models_ = 0;
|
|
|
|
|
|
- const Bodypart_HL1 *pbodypart = (const Bodypart_HL1 *)((uint8_t *)header_ + header_->bodypartindex);
|
|
|
+ const Bodypart_HL1 *pbodypart = get_buffer_data<Bodypart_HL1>(header_->bodypartindex, header_->numbodyparts);
|
|
|
const Model_HL1 *pmodel = nullptr;
|
|
|
const Mesh_HL1 *pmesh = nullptr;
|
|
|
|
|
|
- const Texture_HL1 *ptexture = (const Texture_HL1 *)((uint8_t *)texture_header_ + texture_header_->textureindex);
|
|
|
- short *pskinref = (short *)((uint8_t *)texture_header_ + texture_header_->skinindex);
|
|
|
+ const Texture_HL1 *ptexture = get_texture_buffer_data<Texture_HL1>(texture_header_->textureindex, texture_header_->numtextures);
|
|
|
+ const short *pskinref = get_texture_buffer_data<short>(texture_header_->skinindex, texture_header_->numskinref);
|
|
|
|
|
|
scene_->mNumMeshes = 0;
|
|
|
|
|
|
@@ -606,7 +585,7 @@ void HL1MDLLoader::read_meshes() {
|
|
|
for (int i = 0; i < header_->numbodyparts; ++i, ++pbodypart) {
|
|
|
unique_bodyparts_names[i] = pbodypart->name;
|
|
|
|
|
|
- pmodel = (Model_HL1 *)((uint8_t *)header_ + pbodypart->modelindex);
|
|
|
+ pmodel = get_buffer_data<Model_HL1>(pbodypart->modelindex, pbodypart->nummodels);
|
|
|
for (int j = 0; j < pbodypart->nummodels; ++j, ++pmodel) {
|
|
|
scene_->mNumMeshes += pmodel->nummesh;
|
|
|
total_verts += pmodel->numverts;
|
|
|
@@ -633,7 +612,7 @@ void HL1MDLLoader::read_meshes() {
|
|
|
unique_name_generator_.make_unique(unique_bodyparts_names);
|
|
|
|
|
|
// Now do the same for each model.
|
|
|
- pbodypart = (const Bodypart_HL1 *)((uint8_t *)header_ + header_->bodypartindex);
|
|
|
+ pbodypart = get_buffer_data<Bodypart_HL1>(header_->bodypartindex, header_->numbodyparts);
|
|
|
|
|
|
// Prepare template name for bodypart models.
|
|
|
std::vector<std::string> unique_models_names;
|
|
|
@@ -642,7 +621,7 @@ void HL1MDLLoader::read_meshes() {
|
|
|
unsigned int model_index = 0;
|
|
|
|
|
|
for (int i = 0; i < header_->numbodyparts; ++i, ++pbodypart) {
|
|
|
- pmodel = (Model_HL1 *)((uint8_t *)header_ + pbodypart->modelindex);
|
|
|
+ pmodel = get_buffer_data<Model_HL1>(pbodypart->modelindex, pbodypart->nummodels);
|
|
|
for (int j = 0; j < pbodypart->nummodels; ++j, ++pmodel, ++model_index)
|
|
|
unique_models_names[model_index] = pmodel->name;
|
|
|
}
|
|
|
@@ -654,7 +633,7 @@ void HL1MDLLoader::read_meshes() {
|
|
|
|
|
|
scene_->mMeshes = new aiMesh *[scene_->mNumMeshes];
|
|
|
|
|
|
- pbodypart = (const Bodypart_HL1 *)((uint8_t *)header_ + header_->bodypartindex);
|
|
|
+ pbodypart = get_buffer_data<Bodypart_HL1>(header_->bodypartindex, header_->numbodyparts);
|
|
|
|
|
|
/* Create a node that will represent the mesh hierarchy.
|
|
|
|
|
|
@@ -738,7 +717,7 @@ void HL1MDLLoader::read_meshes() {
|
|
|
model_index = 0;
|
|
|
|
|
|
for (int i = 0; i < header_->numbodyparts; ++i, ++pbodypart, ++bodyparts_node_ptr) {
|
|
|
- pmodel = (const Model_HL1 *)((uint8_t *)header_ + pbodypart->modelindex);
|
|
|
+ pmodel = get_buffer_data<Model_HL1>(pbodypart->modelindex, pbodypart->nummodels);
|
|
|
|
|
|
// Create bodypart node for the mesh tree hierarchy.
|
|
|
aiNode *bodypart_node = (*bodyparts_node_ptr) = new aiNode(unique_bodyparts_names[i]);
|
|
|
@@ -753,12 +732,12 @@ void HL1MDLLoader::read_meshes() {
|
|
|
for (int j = 0; j < pbodypart->nummodels;
|
|
|
++j, ++pmodel, ++bodypart_models_ptr, ++model_index) {
|
|
|
|
|
|
- pmesh = (const Mesh_HL1 *)((uint8_t *)header_ + pmodel->meshindex);
|
|
|
+ pmesh = get_buffer_data<Mesh_HL1>(pmodel->meshindex, pmodel->nummesh);
|
|
|
|
|
|
- uint8_t *pvertbone = ((uint8_t *)header_ + pmodel->vertinfoindex);
|
|
|
- uint8_t *pnormbone = ((uint8_t *)header_ + pmodel->norminfoindex);
|
|
|
- vec3_t *pstudioverts = (vec3_t *)((uint8_t *)header_ + pmodel->vertindex);
|
|
|
- vec3_t *pstudionorms = (vec3_t *)((uint8_t *)header_ + pmodel->normindex);
|
|
|
+ const uint8_t *pvertbone = get_buffer_data<uint8_t>(pmodel->vertinfoindex, pmodel->numverts);
|
|
|
+ const uint8_t *pnormbone = get_buffer_data<uint8_t>(pmodel->norminfoindex, pmodel->numnorms);
|
|
|
+ const vec3_t *pstudioverts = get_buffer_data<vec3_t>(pmodel->vertindex, pmodel->numverts);
|
|
|
+ const vec3_t *pstudionorms = get_buffer_data<vec3_t>(pmodel->normindex, pmodel->numnorms);
|
|
|
|
|
|
// Each vertex and normal is in local space, so transform
|
|
|
// each of them to bring them in bind pose.
|
|
|
@@ -964,7 +943,7 @@ void HL1MDLLoader::read_animations() {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- const SequenceDesc_HL1 *pseqdesc = (const SequenceDesc_HL1 *)((uint8_t *)header_ + header_->seqindex);
|
|
|
+ const SequenceDesc_HL1 *pseqdesc = get_buffer_data<SequenceDesc_HL1>(header_->seqindex, header_->numseq);
|
|
|
const SequenceGroup_HL1 *pseqgroup = nullptr;
|
|
|
const AnimValueOffset_HL1 *panim = nullptr;
|
|
|
const AnimValue_HL1 *panimvalue = nullptr;
|
|
|
@@ -990,22 +969,22 @@ void HL1MDLLoader::read_animations() {
|
|
|
// Get the number of available blend controllers for global info.
|
|
|
get_num_blend_controllers(highest_num_blend_animations, num_blend_controllers_);
|
|
|
|
|
|
- pseqdesc = (const SequenceDesc_HL1 *)((uint8_t *)header_ + header_->seqindex);
|
|
|
+ pseqdesc = get_buffer_data<SequenceDesc_HL1>(header_->seqindex, header_->numseq);
|
|
|
|
|
|
aiAnimation **scene_animations_ptr = scene_->mAnimations = new aiAnimation *[scene_->mNumAnimations];
|
|
|
|
|
|
for (int sequence = 0; sequence < header_->numseq; ++sequence, ++pseqdesc) {
|
|
|
- pseqgroup = (const SequenceGroup_HL1 *)((uint8_t *)header_ + header_->seqgroupindex) + pseqdesc->seqgroup;
|
|
|
+ pseqgroup = get_buffer_data<SequenceGroup_HL1>(header_->seqgroupindex + pseqdesc->seqgroup * sizeof(SequenceGroup_HL1), 1);
|
|
|
|
|
|
if (pseqdesc->seqgroup == 0) {
|
|
|
- panim = (const AnimValueOffset_HL1 *)((uint8_t *)header_ + pseqgroup->unused2 + pseqdesc->animindex);
|
|
|
+ panim = get_buffer_data<AnimValueOffset_HL1>(pseqgroup->unused2 + pseqdesc->animindex, pseqdesc->numblends * header_->numbones);
|
|
|
} else {
|
|
|
- panim = (const AnimValueOffset_HL1 *)((uint8_t *)anim_headers_[pseqdesc->seqgroup] + pseqdesc->animindex);
|
|
|
+ panim = get_anim_buffer_data<AnimValueOffset_HL1>(pseqdesc->seqgroup, pseqdesc->animindex, pseqdesc->numblends * header_->numbones);
|
|
|
}
|
|
|
|
|
|
for (int blend = 0; blend < pseqdesc->numblends; ++blend, ++scene_animations_ptr) {
|
|
|
|
|
|
- const Bone_HL1 *pbone = (const Bone_HL1 *)((uint8_t *)header_ + header_->boneindex);
|
|
|
+ const Bone_HL1 *pbone = get_buffer_data<Bone_HL1>(header_->boneindex, header_->numbones);
|
|
|
|
|
|
aiAnimation *scene_animation = (*scene_animations_ptr) = new aiAnimation();
|
|
|
|
|
|
@@ -1074,7 +1053,7 @@ void HL1MDLLoader::read_sequence_groups_info() {
|
|
|
sequence_groups_node->mNumChildren = static_cast<unsigned int>(header_->numseqgroups);
|
|
|
sequence_groups_node->mChildren = new aiNode *[sequence_groups_node->mNumChildren];
|
|
|
|
|
|
- const SequenceGroup_HL1 *pseqgroup = (const SequenceGroup_HL1 *)((uint8_t *)header_ + header_->seqgroupindex);
|
|
|
+ const SequenceGroup_HL1 *pseqgroup = get_buffer_data<SequenceGroup_HL1>(header_->seqgroupindex, header_->numseqgroups);
|
|
|
|
|
|
unique_sequence_groups_names_.resize(header_->numseqgroups);
|
|
|
for (int i = 0; i < header_->numseqgroups; ++i) {
|
|
|
@@ -1106,7 +1085,7 @@ void HL1MDLLoader::read_sequence_infos() {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- const SequenceDesc_HL1 *pseqdesc = (const SequenceDesc_HL1 *)((uint8_t *)header_ + header_->seqindex);
|
|
|
+ const SequenceDesc_HL1 *pseqdesc = get_buffer_data<SequenceDesc_HL1>(header_->seqindex, header_->numseq);
|
|
|
|
|
|
aiNode *sequence_infos_node = new aiNode(AI_MDL_HL1_NODE_SEQUENCE_INFOS);
|
|
|
rootnode_children_.push_back(sequence_infos_node);
|
|
|
@@ -1178,7 +1157,7 @@ void HL1MDLLoader::read_sequence_infos() {
|
|
|
pseqdesc->numevents, "animation events");
|
|
|
}
|
|
|
|
|
|
- const AnimEvent_HL1 *pevent = (const AnimEvent_HL1 *)((uint8_t *)header_ + pseqdesc->eventindex);
|
|
|
+ const AnimEvent_HL1 *pevent = get_buffer_data<AnimEvent_HL1>(pseqdesc->eventindex, pseqdesc->numevents);
|
|
|
|
|
|
aiNode *pEventsNode = new aiNode(AI_MDL_HL1_NODE_ANIMATION_EVENTS);
|
|
|
sequence_info_node_children.push_back(pEventsNode);
|
|
|
@@ -1215,7 +1194,7 @@ void HL1MDLLoader::read_sequence_transitions() {
|
|
|
aiNode *transition_graph_node = new aiNode(AI_MDL_HL1_NODE_SEQUENCE_TRANSITION_GRAPH);
|
|
|
rootnode_children_.push_back(transition_graph_node);
|
|
|
|
|
|
- uint8_t *ptransitions = ((uint8_t *)header_ + header_->transitionindex);
|
|
|
+ const uint8_t *ptransitions = get_buffer_data<uint8_t>(header_->transitionindex, header_->numtransitions * header_->numtransitions);
|
|
|
aiMetadata *md = transition_graph_node->mMetaData = aiMetadata::Alloc(header_->numtransitions * header_->numtransitions);
|
|
|
for (unsigned int i = 0; i < md->mNumProperties; ++i)
|
|
|
md->Set(i, std::to_string(i), static_cast<int>(ptransitions[i]));
|
|
|
@@ -1226,7 +1205,7 @@ void HL1MDLLoader::read_attachments() {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- const Attachment_HL1 *pattach = (const Attachment_HL1 *)((uint8_t *)header_ + header_->attachmentindex);
|
|
|
+ const Attachment_HL1 *pattach = get_buffer_data<Attachment_HL1>(header_->attachmentindex, header_->numattachments);
|
|
|
|
|
|
aiNode *attachments_node = new aiNode(AI_MDL_HL1_NODE_ATTACHMENTS);
|
|
|
rootnode_children_.push_back(attachments_node);
|
|
|
@@ -1250,7 +1229,7 @@ void HL1MDLLoader::read_hitboxes() {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- const Hitbox_HL1 *phitbox = (const Hitbox_HL1 *)((uint8_t *)header_ + header_->hitboxindex);
|
|
|
+ const Hitbox_HL1 *phitbox = get_buffer_data<Hitbox_HL1>(header_->hitboxindex, header_->numhitboxes);
|
|
|
|
|
|
aiNode *hitboxes_node = new aiNode(AI_MDL_HL1_NODE_HITBOXES);
|
|
|
rootnode_children_.push_back(hitboxes_node);
|
|
|
@@ -1277,7 +1256,9 @@ void HL1MDLLoader::read_bone_controllers() {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- const BoneController_HL1 *pbonecontroller = (const BoneController_HL1 *)((uint8_t *)header_ + header_->bonecontrollerindex);
|
|
|
+ const BoneController_HL1 *pbonecontroller = get_buffer_data<BoneController_HL1>(
|
|
|
+ header_->bonecontrollerindex,
|
|
|
+ header_->numbonecontrollers);
|
|
|
|
|
|
aiNode *bones_controller_node = new aiNode(AI_MDL_HL1_NODE_BONE_CONTROLLERS);
|
|
|
rootnode_children_.push_back(bones_controller_node);
|