【问题标题】:Problem with reading data into structs using a C casting method使用 C 转换方法将数据读入结构的问题
【发布时间】:2009-12-28 13:36:36
【问题描述】:

我正在用 C++ 编写一个 MD3 模型加载器,我了解文件格式以及我需要做什么,但我似乎无法正确使用语法。我有一个模型类,在该类中有一组结构,可以将模型数据读入其中。在类的实现中,有一个构造函数,它在使用 MD3 文件初始化时读取数据。我正在使用 C 风格的转换来做到这一点。第一个结构似乎正在工作并且数据似乎已正确读取,但以下两个似乎所有值都保留为零,这不应该是这种情况。代码编译没有错误,但我对 C++ 相当陌生,所以我可能在这里犯了一个简单的错误!

主文件只是用 MD3 文件设置对象,然后继续设置一些 OpenGL 的东西,但一切正常,不会影响构造函数。

界面:GameObject.h

class GameObject1 {
public:
GameObject1();
GameObject1(const char * filename);
virtual ~GameObject1();

virtual void Draw();

private:
struct md3_header_t
{
    int  IDENT;         //id of file, always "IDP3"
    int  Version;       //version number, always 15
    char Name[64];      //name of character
    int  Flags;         //blank but needed
    int  Num_frames;    //number of Frames
    int  Num_surfaces;  // number of shaders
    int  Num_skins;     //...
    int  Num_triangles; //num triangles - important one
    int  Ofs_triangles; // offset of triangles
    int  Ofs_frames;    // frames offset
    int  Ofs_tags;      // tags offset
    int  Ofs_surfaces;  //offset to surfaces
    int  Ofs_eof;       //offset of end of header

};

typedef float vec3[3];

struct md3_frame_header_t
{
    vec3 Min_bounds;    //first corner of bounding box
    vec3 Max_bounds;    //other corner
    vec3 local_origin;  //usually 0 0 0
    float Radius;       //radius of bounding sphere
    char NAME[16];      // name of frame
};

struct md3_tag_header_t
{
    char NAME[64];      //name of tag
    vec3 origin;        //origin of tag eg head or torso
    vec3 Axis[3];       //axis stuff
};

struct md3_surface_header_t
{
    int IDENT;           //id, must be IDP3
    char Name[64];       //name of mesh
    int Flags;          // blank space
    int Num_frames;     // number of frames
    int Num_shaders;    // no shaders
    int Num_vert;       // number verts
    int Num_triangles;  //number of triangles
    int Ofs_triangles;  //offset of triangle data from surface start
    int Ofs_shaders;    // offset of shaders
    int Ofs_st;         // offset texture data
    int Ofs_xyznormal;  // offset of verts
    int Ofs_end;        // offset of end of surface section from start
};

还有接口GameObect.cpp,注意我这里只包含了构造方法,因为析构方法和draw方法目前都是空的:

#include "GameObject1.h"

GameObject1::GameObject1() {
   //if we have no model...
}

//constructor if a model has been provided
GameObject1::GameObject1(const char * filename) {
ifstream md3file;
md3file.open(filename, ios::in|ios::binary);

// C stuff
md3_header_t * md3header = (struct md3_header_t *)
    malloc(sizeof(struct md3_header_t));
md3file.read((char *) md3header, sizeof (struct md3_header_t));


// Check the file
if (md3header->IDENT != 860898377) {
    // Error!
    cerr << "Error: bad version or identifier" << endl;
}  


// seekg to search through the file to add new data to structs
    // frame struct
md3_frame_header_t * md3frame = (struct md3_frame_header_t *)
            malloc(sizeof(struct md3_frame_header_t));
md3file.seekg(md3header->Ofs_frames);
md3file.read((char *) md3frame, sizeof (struct md3_frame_header_t));

//surface struct
md3_surface_header_t * md3surface = (struct md3_surface_header_t *)
                                 malloc(sizeof( md3_surface_header_t));
md3file.seekg(md3header->Ofs_surfaces);
md3file.read((char *) md3surface, sizeof (struct md3_surface_header_t));

md3file.close();
}

GameObject1::~GameObject1() {
// deconstructor
}

void GameObject1::Draw(){
 // eventually a method to draw the model to screen using OpenGL and SDL
}

我真的迷失了这个,所以任何帮助将不胜感激。

谢谢,

乔恩

【问题讨论】:

  • 你应该测试你对 read() 的调用的返回值——这至少会告诉你哪个失败了。

标签: c++ casting struct


【解决方案1】:

检查md3header-&gt;Ofs_framesmd3header-&gt;Ofs_surfaces 的值,确保它们没有尝试索引超出文件末尾。如果是,则 MD3 文件可能已损坏或读取文件未正确映射到结构。

不确定这是否是一个问题,但如果文件是在 32 位上生成的(反之亦然),您可能会在 64 位系统上遇到问题,因为整数的大小会不同,这会导致映射失败到结构。

可能想要找到一个您知道可以正确读取文件并将这些值与您获得的值进行比较的工具。或者使用十六进制编辑器手动查看文件以验证值。

【讨论】:

    【解决方案2】:

    查看结构的内存布局:打印出 sizeof(float)、sizeof(int)、sizeof(char)、sizeof(md3_frame_header_t) 等,看看它们是否正是您所期望的。如果没有,您可能想要使用#pragma pack,强制将结构的内存布局作为文件布局。另外,文件中字节的字节序是否与内存中的布局相同?

    一般来说,我也建议不要从文件中读取结构。通过这样做节省的几个 CPU 周期在 90 年代很重要,但现在它们不再重要了。您应该实现正确的读写代码,以读取和解析文件格式文档中指定的字段,然后使用 set 方法将它们存储在您自己的内存表示中。这使得内存中的布局独立于文件布局,使代码更容易调试,如果你想切换到不同的架构等,也更容易移植

    【讨论】:

      【解决方案3】:

      你的结构需要正确对齐,看here

      【讨论】:

        【解决方案4】:

        感谢您的帮助。我最终通过检查md3_header_t 结构的大小发现了问题。那里有一个额外的 int (Ofs_triangles),它不应该在那里。它现在可以完美地读取数据,所以我将开始下一部分的工作。

        再次感谢,

        乔恩

        【讨论】:

          【解决方案5】:

          我的建议:

          代码在构造函数中存在内存泄漏,因为您尚未释放在堆上分配的内存。 所以当它没有任何用处时释放内存。

          【讨论】:

            【解决方案6】:

            首先你给出准确的值,然后检查 检查大小是否正确

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2022-01-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2023-03-06
              • 1970-01-01
              相关资源
              最近更新 更多