0

我正在从这个链接Loading An MD5 Model移植一个动画代码,它是线性代码,所以我变成了定向的。

问题是,当我读取整个模型(已成功完成)时,调试器会在我的代码的另一部分(我加载另一个模型文件 - 静态模型)中指示错误。

原因是,当我尝试将数字写入 int 或 float 变量时会导致堆损坏,如果我写入 char 或 string 则不会导致任何错误。

在几次测试中我发现只有在执行这两个代码时才会出现这个错误,因为当只有一个发生时,程序运行正常。

这是代码:

加载 MD5 文件:(很大)

bool AnimationModelClass::LoadMD5Model(ID3D10Device* device, wstring filename)
{
    ifstream fin;
    char input=' ';
    string temp, temp2;
    int i;

    // Crear temp2

    temp2.clear();

    // Open the model file.
    fin.open(filename);

    // If it could not open the file then exit.
    if(fin.fail())
    {
        return false;
    }

    // Look for MD5 Version
    temp.clear();

    continue_after_string(fin, "MD5Version");

    // Store MD5 Version
    fin >> MD5Model.version;



    // Look for Command Line
    temp.clear();

    continue_after_string(fin, "commandline");

    // Skip line
    skip_lines(fin, 1);



    // Look for the number of joints
    temp.clear();

    continue_after_string(fin, "numJoints");

    // Store the number of meshes (subsets)
    fin >> MD5Model.numJoints;



    // Look for the number of joints
    temp.clear();

    continue_after_string(fin, "numMeshes");

    // Store the number of joints
    fin >> MD5Model.numSubsets;



    // Look for the joints
    temp.clear();

    continue_after_string(fin, "joints");

    continue_after_char(fin, '{');

    // Skip the rest of this line
    skip_lines(fin, 1);

    // - JOINTS - //

    // Fill each joint information
    Joint tempJoint;

    for(i=0; i < MD5Model.numJoints; i++){

        // Jump to name
        skip_chars(fin, 3, input);

        temp.clear();

        // Find closing brackets
        while(input!='"')
        {
        temp+=input;
        fin.get(input);

        }

        // Store tempJoint name
        tempJoint.name = temp;

        // Storte parent ID
        fin >> tempJoint.parentID;

        // Find the positions of this joint
        continue_after_char(fin, '(');

        // Store the positions
        fin >> tempJoint.pos.x >> tempJoint.pos.z >> tempJoint.pos.y;

        // Find the orientation of this joint
        continue_after_char(fin, ')');
        continue_after_char(fin, '(');

        // Store orientation
        fin >> tempJoint.orientation.x >> tempJoint.orientation.z >> tempJoint.orientation.y;

        // Compute the w axis of the quaternion (The MD5 model uses a 3D vector to describe the
        // direction the bone is facing. However, we need to turn this into a quaternion, and the way
        // quaternions work, is the xyz values describe the axis of rotation, while the w is a value
        // between 0 and 1 which describes the angle of rotation)
        float t = 1.0f - ( tempJoint.orientation.x * tempJoint.orientation.x ) - ( tempJoint.orientation.y * tempJoint.orientation.y ) - ( tempJoint.orientation.z * tempJoint.orientation.z );
        if ( t < 0.0f )
        {
            tempJoint.orientation.w = 0.0f;
        }
        else
        {
            tempJoint.orientation.w = -sqrtf(t);
        }

        // Skip the rest of this line
        skip_lines(fin, 1);

        // Store the joint into this models joint vector
        MD5Model.joints.push_back(tempJoint);

    }

    // Skip "}"
    continue_after_char(fin, '}');

    // Find meshes
    continue_after_string(fin, "mesh");

    // Skip "{"
    continue_after_char(fin, '{');

    temp.clear();

    // Variables to fill model subsets
    ModelSubset subset;
    int numVerts, numTris, numWeights;

    // End of file controller
    bool eof = false;
    int gg=0;

    // Read until EOF
    while(!eof){


        // Clear the temp string
        temp.clear();

        // Read until "}"

        while(temp!= "}"){

        if(!get_string(fin, temp)){

            // Break if we cant read anymore
            eof = true;
            break;
        }

            // Case we found shader
            if(temp == "shader"){

            // Store it
            get_string(fin, subset.fileNamePath);

            // Skip the rest of this line
            skip_lines(fin, 1);

            // CHECAR SE A TEXTURA FOI CARREGADA E CARREGA-LA SE NECESSÁRIO
            }

            // Case we found tex vertices
            else if(temp == "numverts"){

            // Store the number of tex vertices
            fin >> numVerts;    

            // Skip the rest of this line
            skip_lines(fin, 1);

            // Store stuff for each tex vertice
            for(int i = 0; i < numVerts; i++)
                {

                    Vertex tempVert;

                    // Skip "vert # ("
                    continue_after_char(fin, '(');

                    fin >> tempVert.texCoord.x;
                    fin >> tempVert.texCoord.y;

                    // Skip ")"
                    continue_after_char(fin, ')');

                    fin >> tempVert.StartWeight;
                    fin >> tempVert.WeightCount;

                    // Skip the rest of this line
                    skip_lines(fin, 1);

                    // Push back this vertex into subsets vertex vector
                    subset.vertices.push_back(tempVert);        
                }


            }

            // Case we found the triangles
            else if(temp == "numtris"){

            // Store the number of triangles
            fin >> numTris;
            subset.numTriangles = numTris;

            // Skip the rest of this line
            skip_lines(fin, 1);

            // Save stuff for each triangle
            for(int i = 0; i < numTris; i++)
                {
                    DWORD tempIndex;

                    // Skip "tri"
                    get_string(fin, temp);

                    // Skip tri counter
                    get_string(fin, temp);

                    // Store the 3 indices
                    for(int k = 0; k < 3; k++)                  
                        {
                            fin >> tempIndex;
                            subset.indices.push_back(tempIndex);
                        }

                    // Skip the rest of this line
                    skip_lines(fin, 1);
                }


            }

            // Case we found the weights
            else if(temp == "numweights"){

            // Store the number of weights
            fin >> numWeights;

            // Skip the rest of this line
            skip_lines(fin, 1);

            // Save stuff for each weight
            for(int i = 0; i < numWeights; i++)
                {
                    Weight tempWeight;

                    // Skip "weight"
                    get_string(fin, temp);

                    // Skip "#"
                    get_string(fin, temp);

                    // Store weight's joint ID
                    fin >> tempWeight.jointID;      

                    // Store weight's influence over a vertex
                    fin >> tempWeight.bias;

                    // Skip "("
                    continue_after_char(fin, '(');

                    // Store weight's pos in joint's local space
                    fin >> tempWeight.pos.x >> tempWeight.pos.z >> tempWeight.pos.y;

                    // Skip the rest of this line
                    skip_lines(fin, 1);

                    // Push back tempWeight into subsets Weight array
                    subset.weights.push_back(tempWeight);
                }


            }
        }

                //*** find each vertex's position using the joints and weights 
                for ( int i = 0; i < subset.vertices.size(); ++i )
                {
                    Vertex tempVert = subset.vertices[i];
                    tempVert.pos = D3DXVECTOR3(0, 0, 0);    // Make sure the vertex's pos is cleared first

                    // Sum up the joints and weights information to get vertex's position
                    for ( int j = 0; j < tempVert.WeightCount; ++j )
                    {
                        Weight tempWeight = subset.weights[tempVert.StartWeight + j];
                        Joint tempJoint = MD5Model.joints[tempWeight.jointID];

                        // Convert joint orientation and weight pos to vectors for easier computation
                        // When converting a 3d vector to a quaternion, you should put 0 for "w", and
                        // When converting a quaternion to a 3d vector, you can just ignore the "w"
                        D3DXQUATERNION tempJointOrientation = D3DXQUATERNION(tempJoint.orientation.x, tempJoint.orientation.y, tempJoint.orientation.z, tempJoint.orientation.w);
                        D3DXQUATERNION tempWeightPos = D3DXQUATERNION(tempWeight.pos.x, tempWeight.pos.y, tempWeight.pos.z, 0.0f);

                        // We will need to use the conjugate of the joint orientation quaternion
                        // To get the conjugate of a quaternion, all you have to do is inverse the x, y, and z
                        D3DXQUATERNION tempJointOrientationConjugate = D3DXQUATERNION(-tempJoint.orientation.x, -tempJoint.orientation.y, -tempJoint.orientation.z, tempJoint.orientation.w);

                        // Calculate vertex position (in joint space, eg. rotate the point around (0,0,0)) for this weight using the joint orientation quaternion and its conjugate
                        // We can rotate a point using a quaternion with the equation "rotatedPoint = quaternion * point * quaternionConjugate"
                        D3DXVECTOR3 rotatedPoint;
                        D3DXQUATERNION temp;

                        D3DXQuaternionMultiply(&temp, &tempJointOrientation, &tempWeightPos);
                        D3DXQuaternionMultiply(&temp, &temp, &tempJointOrientationConjugate);

                        rotatedPoint.x = temp.x;
                        rotatedPoint.y = temp.y;
                        rotatedPoint.z = temp.z;

                        // Now move the verices position from joint space (0,0,0) to the joints position in world space, taking the weights bias into account
                        // The weight bias is used because multiple weights might have an effect on the vertices final position. Each weight is attached to one joint.
                        tempVert.pos.x += ( tempJoint.pos.x + rotatedPoint.x ) * tempWeight.bias;
                        tempVert.pos.y += ( tempJoint.pos.y + rotatedPoint.y ) * tempWeight.bias;
                        tempVert.pos.z += ( tempJoint.pos.z + rotatedPoint.z ) * tempWeight.bias;

                        // Basically what has happened above, is we have taken the weights position relative to the joints position
                        // we then rotate the weights position (so that the weight is actually being rotated around (0, 0, 0) in world space) using
                        // the quaternion describing the joints rotation. We have stored this rotated point in rotatedPoint, which we then add to
                        // the joints position (because we rotated the weight's position around (0,0,0) in world space, and now need to translate it
                        // so that it appears to have been rotated around the joints position). Finally we multiply the answer with the weights bias,
                        // or how much control the weight has over the final vertices position. All weight's bias effecting a single vertex's position
                        // must add up to 1.
                    }

                    subset.positions.push_back(tempVert.pos);           // Store the vertices position in the position vector instead of straight into the vertex vector
                    // since we can use the positions vector for certain things like collision detection or picking
                    // without having to work with the entire vertex structure.
                }

                // Put the positions into the vertices for this subset
                for(int i = 0; i < subset.vertices.size(); i++)
                {
                    subset.vertices[i].pos = subset.positions[i];
                }

                //*** Calculate vertex normals using normal averaging 
                vector<D3DXVECTOR3> tempNormal;

                //normalized and unnormalized normals
                D3DXVECTOR3 unnormalized = D3DXVECTOR3(0.0f, 0.0f, 0.0f);

                //Used to get vectors (sides) from the position of the verts
                float vecX, vecY, vecZ;

                //Two edges of our triangle
                D3DXQUATERNION edge1 = D3DXQUATERNION(0.0f, 0.0f, 0.0f, 0.0f);
                D3DXQUATERNION edge2 = D3DXQUATERNION(0.0f, 0.0f, 0.0f, 0.0f);

                //Compute face normals
                for(int i = 0; i < subset.numTriangles; ++i)
                {
                    //Get the vector describing one edge of our triangle (edge 0,2)
                    vecX = subset.vertices[subset.indices[(i*3)]].pos.x - subset.vertices[subset.indices[(i*3)+2]].pos.x;
                    vecY = subset.vertices[subset.indices[(i*3)]].pos.y - subset.vertices[subset.indices[(i*3)+2]].pos.y;
                    vecZ = subset.vertices[subset.indices[(i*3)]].pos.z - subset.vertices[subset.indices[(i*3)+2]].pos.z;       
                    edge1 = D3DXQUATERNION(vecX, vecY, vecZ, 0.0f); //Create our first edge

                    //Get the vector describing another edge of our triangle (edge 2,1)
                    vecX = subset.vertices[subset.indices[(i*3)+2]].pos.x - subset.vertices[subset.indices[(i*3)+1]].pos.x;
                    vecY = subset.vertices[subset.indices[(i*3)+2]].pos.y - subset.vertices[subset.indices[(i*3)+1]].pos.y;
                    vecZ = subset.vertices[subset.indices[(i*3)+2]].pos.z - subset.vertices[subset.indices[(i*3)+1]].pos.z;     
                    edge2 = D3DXQUATERNION(vecX, vecY, vecZ, 0.0f); //Create our second edge

                    //Cross multiply the two edge vectors to get the un-normalized face normal
                    unnormalized.x = (edge1.y * edge2.z) - (edge1.z * edge2.y);
                    unnormalized.y = (edge1.z * edge2.x) - (edge1.x * edge2.z);
                    unnormalized.z = (edge1.x * edge2.y) - (edge1.y * edge2.x);

                    tempNormal.push_back(unnormalized);
                }

                //Compute vertex normals (normal Averaging)
                D3DXQUATERNION normalSum = D3DXQUATERNION(0.0f, 0.0f, 0.0f, 0.0f);
                int facesUsing = 0;
                float tX, tY, tZ;   //temp axis variables

                //Go through each vertex
                for(int i = 0; i < subset.vertices.size(); ++i)
                {
                    //Check which triangles use this vertex
                    for(int j = 0; j < subset.numTriangles; ++j)
                    {
                        if(subset.indices[j*3] == i ||
                            subset.indices[(j*3)+1] == i ||
                            subset.indices[(j*3)+2] == i)
                        {
                            tX = normalSum.x + tempNormal[j].x;
                            tY = normalSum.y + tempNormal[j].y;
                            tZ = normalSum.z + tempNormal[j].z;

                            normalSum = D3DXQUATERNION(tX, tY, tZ, 0.0f);   //If a face is using the vertex, add the unormalized face normal to the normalSum

                            facesUsing++;
                        }
                    }

                    //Get the actual normal by dividing the normalSum by the number of faces sharing the vertex
                    normalSum = normalSum / facesUsing;

                    //Normalize the normalSum vector
                    D3DXVECTOR3 temp;
                    temp.x = normalSum.x;
                    temp.y = normalSum.y;
                    temp.z = normalSum.z;

                    D3DXVec3Normalize(&temp, &temp);

                    //Store the normal and tangent in our current vertex
                    subset.vertices[i].normal.x = -temp.x;
                    subset.vertices[i].normal.y = -temp.y;
                    subset.vertices[i].normal.z = -temp.z;

                    //Clear normalSum, facesUsing for next vertex
                    normalSum = D3DXQUATERNION(0.0f, 0.0f, 0.0f, 0.0f);
                    facesUsing = 0;
                }

                // Create index buffer
                D3D10_BUFFER_DESC indexBufferDesc;
                ZeroMemory( &indexBufferDesc, sizeof(indexBufferDesc) );

                indexBufferDesc.Usage = D3D10_USAGE_DEFAULT;
                indexBufferDesc.ByteWidth = sizeof(DWORD) * subset.numTriangles * 3;
                indexBufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER;
                indexBufferDesc.CPUAccessFlags = 0;
                indexBufferDesc.MiscFlags = 0;

                D3D10_SUBRESOURCE_DATA iinitData;

                iinitData.pSysMem = &subset.indices[0];
                device->CreateBuffer(&indexBufferDesc, &iinitData, &subset.indexBuff);

                //Create Vertex Buffer
                D3D10_BUFFER_DESC vertexBufferDesc;
                ZeroMemory( &vertexBufferDesc, sizeof(vertexBufferDesc) );

                vertexBufferDesc.Usage = D3D10_USAGE_DYNAMIC;                           // We will be updating this buffer, so we must set as dynamic
                vertexBufferDesc.ByteWidth = sizeof( Vertex ) * subset.vertices.size();
                vertexBufferDesc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
                vertexBufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;               // Give CPU power to write to buffer
                vertexBufferDesc.MiscFlags = 0;

                D3D10_SUBRESOURCE_DATA vertexBufferData; 

                ZeroMemory( &vertexBufferData, sizeof(vertexBufferData) );
                vertexBufferData.pSysMem = &subset.vertices[0];

                HRESULT hr;

                hr = device->CreateBuffer( &vertexBufferDesc, &vertexBufferData, &subset.vertBuff);

                // Push back the temp subset into the models subset vector
                MD5Model.subsets.push_back(subset);

        if(eof == true){
            break;
        }


    i=i;

        }

    fin.clear();
    fin.close();


    return true;
}

这里还有另一个代码:(这里有问题!)

bool ModelClass::LoadModel(char* filename)
{
    ifstream fin;
    char input;
    int i;


    // Open the model file.
    fin.open(filename);

    // If it could not open the file then exit.
    if(fin.fail())
    {
        return false;
    }

    // Read up to the value of vertex count.
    fin.get(input);
    while(input != ':')
    {
        fin.get(input);
    }

    // Read in the vertex count.
    fin >> m_vertexCount;

    // Set the number of indices to be the same as the vertex count.
    m_indexCount = m_vertexCount;

    // Create the model using the vertex count that was read in.
    m_model = new ModelType[m_vertexCount];
    if(!m_model)
    {
        return false;
    }

    // Read up to the beginning of the data.
    fin.get(input);
    while(input != ':')
    {
        fin.get(input);
    }
    fin.get(input);
    fin.get(input);

    // Read in the vertex data.
    for(i=0; i<m_vertexCount; i++)
    {

            ///////////// HERE IS THE PROBLEM!! //////////////

        fin >> m_model[i].x >> m_model[i].y >> m_model[i].z;
        fin >> m_model[i].tu >> m_model[i].tv;
        fin >> m_model[i].nx >> m_model[i].ny >> m_model[i].nz;
    }

    // Close the model file.
    fin.close();

    return true;
}

我测试了放置断点,问题就在那里(上图)。

如果我这样做:

// Read in the vertex data.
for(i=0; i<m_vertexCount; i++)
{
            char a;

    fin >> a;
}

它有效......但我不知道为什么我这样做:

// Read in the vertex data.
for(i=0; i<m_vertexCount; i++)
{
            float f;  // or int, but float is what I want

    fin >> f;
}

砰,堆腐败!

如上所述,两个代码都可以正常工作。

对不起,我的英语不好。

如果有人可以提供帮助,因为这让我很烦......:D


Obs:如果我切换顺序都可以工作(那些代码)并且不会发生堆损坏

4

1 回答 1

0

我在“AnimationModelClass”的声明中找到了问题的原因:

class AnimationModelClass
{
private:

    struct Vertex   //Overloaded Vertex Structure
    {
    Vertex(){}
    Vertex(float x, float y, float z,
    float u, float v,
    float nx, float ny, float nz,
    float tx, float ty, float tz)
    : pos(x,y,z), texCoord(u, v), normal(nx, ny, nz),
    tangent(tx, ty, tz){}

    D3DXVECTOR3 pos;
    D3DXVECTOR2 texCoord;
    D3DXVECTOR3 normal;
    D3DXVECTOR3 tangent;
    D3DXVECTOR3 biTangent;

    int StartWeight;
    int WeightCount;

    };

    struct Joint
    {
        string name;
        int parentID;

        D3DXVECTOR3 pos;
        D3DXVECTOR4 orientation;
    };

    struct Weight
    {
        int jointID;
        float bias;
        D3DXVECTOR3 pos;
    };

    struct ModelSubset
    {
        int texArrayIndex;
        int numTriangles;
        int numVertices;
        int numWeights;
        string fileNamePath;

        Vertex* m_vertices;
        DWORD* m_indices;
        Weight* m_weights;

        D3DXVECTOR3* m_positions;

        ID3D10Buffer* vertBuff; 
        ID3D10Buffer* indexBuff;
    };

    struct Model3D
    {
        int version;
        int numSubsets;
        int numJoints;

        Joint* m_joints;
        ModelSubset* m_subsets;
    };

private:

    wstring textureNamePath;

public:

    AnimationModelClass();
    AnimationModelClass(const AnimationModelClass&);
    ~AnimationModelClass();

    bool Initialize(ID3D10Device*);
    bool LoadModel(ID3D10Device*, wstring);
    bool render(ID3D10Device*);

private:

    bool LoadMD5Model(ID3D10Device*, wstring);

private:

    D3DXMATRIX* m_smilesWorld;
    Model3D* MD5Model;

    ID3D10Device* m_device;

};

我意识到我没有使用变量“textureNamePath”并决定删除它,然后一切都开始工作了。

我不知道为什么会这样,但是,它已经解决了!

于 2012-12-27T21:16:58.247 回答