Jump to content

View more

Image of the Day

Working on an auto spawn system. #gamedev #indiedev #screenshotsaturday https://t.co/Mm2kfekz7b
IOTD | Top Screenshots

The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

Sign up now

vector subscript out of bounds

4: Adsense

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
2 replies to this topic

#1 proanim   Members   


Posted 04 October 2012 - 01:03 PM

I am having really hard time with this i want to implement md5 model format in my 'engine' but when i try to render a simple cube model i get standard 'line: 932 exception: vector subscript out of bounds'. This is quite annoying because it is imposible to debug (at least for me). I checked my code many times and it appears that something isn't right with vertex and index buffers. Can someone look into this and tell me what should be fixed?

This is my code
[source lang="cpp"]#ifndef _MD5_MODEL_H_#define _MD5_MODEL_H_#include <d3d11.h>#include <d3dx10math.h>#include <fstream>#include <istream>#include <sstream>#include <xnamath.h>#include <vector>using namespace std;#include "textureclass.h"class MD5Class{public: MD5Class(); MD5Class(const MD5Class&); ~MD5Class(); bool Initialize(ID3D11Device*, WCHAR*, WCHAR*); void Shutdown(); void Render(ID3D11DeviceContext*); int GetIndexCount(); ID3D11ShaderResourceView* GetTexture();private: struct VertexType { VertexType(){} VertexType(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){} XMFLOAT3 pos; XMFLOAT2 texCoord; XMFLOAT3 normal; XMFLOAT3 tangent; int StartWeight; int WeightCount; }; struct ModelType { float x, y, z; float tu, tv; float nx, ny, nz; }; struct Joint { wstring name; int parentID; XMFLOAT3 pos; XMFLOAT4 orientation; }; struct BoundingBox { XMFLOAT3 min; XMFLOAT3 max; }; struct FrameData { int frameID; vector<float> frameData; }; struct AnimJointInfo { wstring name; int parentID; int flags; int startIndex; }; struct ModelAnimation { int numFrames; int numJoints; int frameRate; int numAnimatedComponents; float frameTime; float totalAnimTime; float currAnimTime; vector<AnimJointInfo> jointInfo; vector<BoundingBox> frameBounds; vector<Joint> baseFrameJoints; vector<FrameData> frameData; vector<std::vector<Joint>> frameSkeleton; }; struct Weight { int jointID; float bias; XMFLOAT3 pos; XMFLOAT3 normal; }; struct ModelSubset { int texArrayIndex; int numTriangles; vector<VertexType> vertices; vector<XMFLOAT3> jointSpaceNormals; vector<DWORD> indices; vector<Weight> weights; vector<XMFLOAT3> positions; ID3D11Buffer* vertBuff; ID3D11Buffer* indexBuff; }; struct Model3D { int numSubsets; int numJoints; vector<Joint> joints; vector<ModelSubset> subsets; vector<ModelAnimation> animations; }; bool InitializeBuffers(ID3D11Device*); void ShutdownBuffers(); void RenderBuffers(ID3D11DeviceContext*); bool LoadTexture(ID3D11Device*, WCHAR*); void ReleaseTexture(); bool LoadModel(ID3D11Device* device, wstring); void ReleaseModel(); ID3D11Buffer *m_vertexBuffer, *m_indexBuffer; D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc; D3D11_SUBRESOURCE_DATA vertexData, indexData; int m_vertexCount, m_indexCount; TextureClass* m_Texture; VertexType* vertices; unsigned long* indices; ModelType* m_model; wifstream fin; std::wstring checkString; wchar_t checkChar; bool jointNameFound; wstring filePath; bool fileNameFound; DWORD tempIndex; HRESULT result; int i; unsigned int stride; unsigned int offset; Joint tempJoint; Joint joint0; Joint joint1; XMVECTOR jointOrientation; XMVECTOR joint0Orient; XMVECTOR joint1Orient; VertexType tempVert; Weight tempWeight; XMVECTOR tempJointOrientation; XMVECTOR tempWeightPos; XMVECTOR tempJointOrientationConjugate; XMFLOAT3 rotatedPoint; XMVECTOR tempWeightNormal; float currentFrame; int frame0; int frame1; float interpolation; vector<Joint> interpolatedSkeleton; ModelSubset subset; int numVerts; int numTris; int numWeights; Model3D MD5Model; vector<XMFLOAT3> tempNormal; XMFLOAT3 unnormalized; float vecX, vecY, vecZ; XMVECTOR edge1; XMVECTOR edge2; XMVECTOR normalSum; int facesUsing; float tX, tY, tZ; XMVECTOR normal; D3D11_SUBRESOURCE_DATA iinitData; D3D11_SUBRESOURCE_DATA vertexBufferData;};#endif[/source]

[source lang="cpp"]#include "md5_model.h"MD5Class::MD5Class(){ m_vertexBuffer = 0; m_indexBuffer = 0; m_Texture = 0; m_model = 0; m_vertexCount = 0; m_indexCount = 0; numVerts = 0; numTris = 0; numWeights = 0; facesUsing = 0; vecX = 0.0f; vecY = 0.0f; vecZ = 0.0f; tX = 0.0f; tY = 0.0f; tZ = 0.0f;}MD5Class::MD5Class(const MD5Class& other){}MD5Class::~MD5Class(){}bool MD5Class::Initialize(ID3D11Device* device, WCHAR* modelFilename, WCHAR* textureFilename){ bool result; // Load in the model data, result = LoadModel(device, modelFilename); if(!result) return false; // Load the texture for this model. result = LoadTexture(device, textureFilename); if(!result) return false; return true;}void MD5Class::Shutdown(){ // Release the model texture. ReleaseTexture(); // Shutdown the vertex and index buffers. ShutdownBuffers(); // Release the model data. ReleaseModel(); return;}void MD5Class::Render(ID3D11DeviceContext* deviceContext){ // Put the vertex and index buffers on the graphics pipeline to prepare them for drawing. RenderBuffers(deviceContext); return;}void MD5Class::ShutdownBuffers(){ // Release the index buffer. if(m_indexBuffer) { m_indexBuffer->Release(); m_indexBuffer = 0; } // Release the vertex buffer. if(m_vertexBuffer) { m_vertexBuffer->Release(); m_vertexBuffer = 0; } return;}void MD5Class::RenderBuffers(ID3D11DeviceContext* deviceContext){ // Set vertex buffer stride and offset. stride = sizeof(VertexType); offset = 0; // Set the vertex buffer to active in the input assembler so it can be rendered. deviceContext->IASetVertexBuffers(0, 1, &MD5Model.subsets[i].vertBuff, &stride, &offset); // Set the index buffer to active in the input assembler so it can be rendered. deviceContext->IASetIndexBuffer(MD5Model.subsets[i].indexBuff, DXGI_FORMAT_R32_UINT, 0); // Set the type of primitive that should be rendered from this vertex buffer, in this case triangles. deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); deviceContext->DrawIndexed(MD5Model.subsets[i].indices.size(), 0, 0); return;}bool MD5Class::LoadTexture(ID3D11Device* device, WCHAR* filename){ bool result; // Create the texture object. m_Texture = new TextureClass; if(!m_Texture) { return false; } // Initialize the texture object. result = m_Texture->Initialize(device, filename); if(!result) { return false; } return true;}int MD5Class::GetIndexCount(){ return subset.numTriangles * 3;}ID3D11ShaderResourceView* MD5Class::GetTexture(){ return m_Texture->GetTexture();}void MD5Class::ReleaseTexture(){ // Release the texture object. if(m_Texture) { m_Texture->Shutdown(); delete m_Texture; m_Texture = 0; } return;}bool MD5Class::LoadModel(ID3D11Device* device, wstring filename){ // Open the model file. wifstream fin(filename.c_str()); // If the file was opened if(fin) { // Loop until the end of the file is reached while(fin) { fin >> checkString; // Get next string from file if(checkString == L"MD5Version") // Get MD5 version getline(fin, checkString); // Ignore the rest of this line else if (checkString == L"commandline") getline(fin, checkString); // Ignore the rest of this line else if(checkString == L"numJoints") fin >> MD5Model.numJoints; // Store number of joints else if(checkString == L"numMeshes") fin >> MD5Model.numSubsets; // Store number of meshes else if(checkString == L"joints") { fin >> checkString; // Skip the "{" for(int i = 0; i < MD5Model.numJoints; i++) { fin >> tempJoint.name; // Store joints name // Sometimes the names might contain spaces. If that is the case, we need to continue // to read the name until we get to the closing " (quotation marks) if(tempJoint.name[tempJoint.name.size()-1] != '"') { jointNameFound = false; while(!jointNameFound) { checkChar = fin.get(); if(checkChar == '"') jointNameFound = true; tempJoint.name += checkChar; } } fin >> tempJoint.parentID; // Store Parent joint's ID fin >> checkString; // Skip the "(" // Store position of this joint (swap y and z axis if model was made in RH Coord Sys) fin >> tempJoint.pos.x >> tempJoint.pos.z >> tempJoint.pos.y; fin >> checkString >> checkString; // Skip the ")" and "(" // Store orientation of this joint fin >> tempJoint.orientation.x >> tempJoint.orientation.z >> tempJoint.orientation.y; // Remove the quotation marks from joints name tempJoint.name.erase(0, 1); tempJoint.name.erase(tempJoint.name.size()-1, 1); // 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); getline(fin, checkString); // Skip rest of this line MD5Model.joints.push_back(tempJoint); // Store the joint into this models joint vector } fin >> checkString; // Skip the "}" } else if(checkString == L"mesh") { fin >> checkString; // Skip the "{" fin >> checkString; while(checkString != L"}") // Read until '}' { if(checkString == L"shader") // Load the texture or material { fin >> filePath; // Get texture's filename // Take spaces into account if filename or material name has a space in it if(filePath[filePath.size()-1] != '"') { fileNameFound = false; while(!fileNameFound) { checkChar = fin.get(); if(checkChar == '"') fileNameFound = true; filePath += checkChar; } } // Remove the quotation marks from texture path filePath.erase(0, 1); filePath.erase(filePath.size()-1, 1); //FIXME: check if this texture has already been loaded //FIXME: load the texture getline(fin, checkString); // Skip rest of this line } else if(checkString == L"numverts") { fin >> numVerts; // Store number of vertices getline(fin, checkString); // Skip rest of this line for(int i = 0; i < numVerts; i++) { fin >> checkString // Skip "vert # (" >> checkString >> checkString; fin >> tempVert.texCoord.x // Store tex coords >> tempVert.texCoord.y; fin >> checkString; // Skip ")" fin >> tempVert.StartWeight; // Index of first weight this vert will be weighted to fin >> tempVert.WeightCount; // Number of weights for this vertex getline(fin, checkString); // Skip rest of this line subset.vertices.push_back(tempVert); // Push back this vertex into subsets vertex vector } } else if(checkString == L"numtris") { fin >> numTris; subset.numTriangles = numTris; getline(fin, checkString); // Skip rest of this line for(int i = 0; i < numTris; i++) // Loop through each triangle { fin >> checkString; // Skip "tri" fin >> checkString; // Skip tri counter for(int k = 0; k < 3; k++) // Store the 3 indices { fin >> tempIndex; subset.indices.push_back(tempIndex); } getline(fin, checkString); // Skip rest of this line } } else if(checkString == L"numweights") { fin >> numWeights; getline(fin, checkString); // Skip rest of this line for(int i = 0; i < numWeights; i++) { fin >> checkString >> checkString; // Skip "weight #" fin >> tempWeight.jointID; // Store weight's joint ID fin >> tempWeight.bias; // Store weight's influence over a vertex fin >> checkString; // Skip "(" fin >> tempWeight.pos.x // Store weight's pos in joint's local space >> tempWeight.pos.z >> tempWeight.pos.y; getline(fin, checkString); // Skip rest of this line subset.weights.push_back(tempWeight); // Push back tempWeight into subsets Weight array } } else getline(fin, checkString); // Skip anything else fin >> checkString; // Skip "}" } // Find each vertex's position using the joints and weights for (size_t i = 0; i < subset.vertices.size(); ++i ) { tempVert = subset.vertices[i]; tempVert.pos = XMFLOAT3(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 ) { tempWeight = subset.weights[tempVert.StartWeight + j]; 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" tempJointOrientation = XMVectorSet(tempJoint.orientation.x, tempJoint.orientation.y, tempJoint.orientation.z, tempJoint.orientation.w); tempWeightPos = XMVectorSet(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 tempJointOrientationConjugate = XMVectorSet(-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" XMStoreFloat3(&rotatedPoint, XMQuaternionMultiply(XMQuaternionMultiply(tempJointOrientation, tempWeightPos), tempJointOrientationConjugate)); // 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; } 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(size_t i = 0; i < subset.vertices.size(); i++) { subset.vertices[i].pos = subset.positions[i]; } // Normalized and unnormalized normals unnormalized = XMFLOAT3(0.0f, 0.0f, 0.0f); // Two edges of our triangle edge1 = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f); edge2 = XMVectorSet(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 = XMVectorSet(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 = XMVectorSet(vecX, vecY, vecZ, 0.0f); //Create our second edge // Cross multiply the two edge vectors to get the un-normalized face normal XMStoreFloat3(&unnormalized, XMVector3Cross(edge1, edge2)); tempNormal.push_back(unnormalized); } // Compute vertex normals (normal Averaging) normalSum = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f); facesUsing = 0; // Go through each vertex for(size_t 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 = XMVectorGetX(normalSum) + tempNormal[j].x; tY = XMVectorGetY(normalSum) + tempNormal[j].y; tZ = XMVectorGetZ(normalSum) + tempNormal[j].z; normalSum = XMVectorSet(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 normalSum = XMVector3Normalize(normalSum); // Store the normal and tangent in our current vertex subset.vertices[i].normal.x = -XMVectorGetX(normalSum); subset.vertices[i].normal.y = -XMVectorGetY(normalSum); subset.vertices[i].normal.z = -XMVectorGetZ(normalSum); // Create the joint space normal for easy normal calculations in animation tempVert = subset.vertices[i]; // Get the current vertex subset.jointSpaceNormals.push_back(XMFLOAT3(0,0,0)); // Push back a blank normal normal = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f); // Clear normal for ( int k = 0; k < tempVert.WeightCount; k++) // Loop through each of the vertices weights { tempJoint = MD5Model.joints[subset.weights[tempVert.StartWeight + k].jointID]; // Get the joints orientation jointOrientation = XMVectorSet(tempJoint.orientation.x, tempJoint.orientation.y, tempJoint.orientation.z, tempJoint.orientation.w); // Calculate normal based off joints orientation (turn into joint space) normal = XMQuaternionMultiply(XMQuaternionMultiply(XMQuaternionInverse(jointOrientation), normalSum), jointOrientation); XMStoreFloat3(&subset.weights[tempVert.StartWeight + k].normal, XMVector3Normalize(normal)); // Store the normalized quaternion into our weights normal } // Clear normalSum, facesUsing for next vertex normalSum = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f); facesUsing = 0; } //FIXME: setup vertex and index buffers //Create Vertex Buffer ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc)); vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC; // We will be updating this buffer, so we must set as dynamic vertexBufferDesc.ByteWidth = sizeof(VertexType) * subset.vertices.size(); vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; // Give CPU power to write to buffer vertexBufferDesc.MiscFlags = 0; //D3D11_SUBRESOURCE_DATA vertexBufferData; ZeroMemory(&vertexBufferData, sizeof(vertexBufferData)); vertexBufferData.pSysMem = &subset.vertices[0]; result = device->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &subset.vertBuff); // Create index buffer ZeroMemory(&indexBufferDesc, sizeof(indexBufferDesc)); indexBufferDesc.Usage = D3D11_USAGE_DEFAULT; indexBufferDesc.ByteWidth = sizeof(DWORD) * subset.numTriangles * 3; indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; indexBufferDesc.CPUAccessFlags = 0; indexBufferDesc.MiscFlags = 0; //D3D11_SUBRESOURCE_DATA iinitData; iinitData.pSysMem = &subset.indices[0]; result = device->CreateBuffer(&indexBufferDesc, &iinitData, &subset.indexBuff); // Push back the temp subset into the models subset vector MD5Model.subsets.push_back(subset); } } } return true;}void MD5Class::ReleaseModel(){ if(m_model) { delete [] m_model; m_model = 0; } return;}[/source]

my rendering function is this
[source lang="cpp"]bool GraphicsClass::Render(float rotation){ D3DXMATRIX worldMatrix, viewMatrix, projectionMatrix; bool result; // Clear the buffers to begin the scene. m_D3D->BeginScene(0.0f, 0.0f, 0.0f, 1.0f); // Generate the view matrix based on the camera's position. m_Camera->Render(); // Get the world, view, and projection matrices from the camera and d3d objects. m_Camera->GetViewMatrix(viewMatrix); m_D3D->GetWorldMatrix(worldMatrix); m_D3D->GetProjectionMatrix(projectionMatrix); // Rotate the world matrix by the rotation value so that the triangle will spin. //D3DXMatrixRotationY(&worldMatrix, rotation); // Put the model vertex and index buffers on the graphics pipeline to prepare them for drawing. m_md5->Render(m_D3D->GetDeviceContext()); // Render the model using the light shader. result = m_LightShader->Render(m_D3D->GetDeviceContext(), m_md5->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_md5->GetTexture(), m_Light->GetDirection(), m_Light->GetDiffuseColor()); if(!result) { return false; } // Present the rendered scene to the screen. m_D3D->EndScene(); return true;}[/source]
I can't debbug this code whenever i put break points on function that loads the model it eather goes without error or crashes at creation of index buffer.

#2 InvalidPointer   Members   


Posted 05 October 2012 - 09:46 PM

For starters you never appear to set the (extremely poorly named-- what does it do/control?) member variable 'i' to anything, so it's going to be 0xCDCDCDCD on MSVC/heap memory debugging enabled and random garbage in release mode. That's pretty big in decimal, and is very likely to be out of range when you do
void MD5Class::RenderBuffers(ID3D11DeviceContext* deviceContext)
    // Set vertex buffer stride and offset.
    stride = sizeof(VertexType);
    offset = 0;
    // Set the vertex buffer to active in the input assembler so it can be rendered.
    deviceContext->IASetVertexBuffers(0, 1, &MD5Model.subsets[i].vertBuff, &stride, &offset);
    // Set the index buffer to active in the input assembler so it can be rendered.
    deviceContext->IASetIndexBuffer(MD5Model.subsets[i].indexBuff, DXGI_FORMAT_R32_UINT, 0);

    // Set the type of primitive that should be rendered from this vertex buffer, in this case triangles.

    deviceContext->DrawIndexed(MD5Model.subsets[i].indices.size(), 0, 0);


EDIT: I also apologize if this comes off as snarky, but I'm not sure why you jumped to index buffer creation as being problem when the debugger explicitly tells you that you're feeding a vector an index larger than what it has room for. Slow down a bit and take the time to learn the debugger, as it's designed to make this process really straightforward. You need to walk before you can run.
clb: At the end of 2012, the positions of jupiter, saturn, mercury, and deimos are aligned so as to cause a denormalized flush-to-zero bug when computing earth's gravitational force, slinging it to the sun.

#3 proanim   Members   


Posted 06 October 2012 - 10:42 AM

Thank you, that fixed the problem.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.