如何在不使用任何第三方库的情况下从.obj文件加载对象?我正在使用Visual Studio 2013 Windows8!
答案 0 :(得分:1)
我正在使用自己的std :: vector类,因为std :: vector有点慢,但你可以改变以下代码使用std :: vector
所以这是一个CGrowableArray类:
注意:#include< assert.h>和< Windows.h>
template<typename TYPE> class CGrowableArray
{
public:
CGrowableArray() { m_pData = NULL; m_nSize = 0; m_nMaxSize = 0; }
CGrowableArray(const CGrowableArray<TYPE>& a) { for (int i = 0; i < a.m_nSize; i++) Add(a.m_pData[i]); }
~CGrowableArray() { RemoveAll(); }
const TYPE& operator[](int nIndex) const { return GetAt(nIndex); }
TYPE& operator[](int nIndex) { return GetAt(nIndex); }
CGrowableArray& operator=(const CGrowableArray<TYPE>& a) { if (this == &a) return *this; RemoveAll(); for (int i = 0; i < a.m_nSize; i++) Add(a.m_pData[i]); return *this; }
HRESULT SetSize(int nNewMaxSize);
HRESULT Add(const TYPE& value);
HRESULT Insert(int nIndex, const TYPE& value);
HRESULT SetAt(int nIndex, const TYPE& value);
TYPE& GetAt(int nIndex) const { assert(nIndex >= 0 && nIndex < m_nSize); return m_pData[nIndex]; }
int GetSize() const { return m_nSize; }
TYPE* GetData() { return m_pData; }
bool Contains(const TYPE& value){ return (-1 != IndexOf(value)); }
int IndexOf(const TYPE& value) { return (m_nSize > 0) ? IndexOf(value, 0, m_nSize) : -1; }
int IndexOf(const TYPE& value, int iStart) { return IndexOf(value, iStart, m_nSize - iStart); }
int IndexOf(const TYPE& value, int nIndex, int nNumElements);
int LastIndexOf(const TYPE& value) { return (m_nSize > 0) ? LastIndexOf(value, m_nSize - 1, m_nSize) : -1; }
int LastIndexOf(const TYPE& value, int nIndex) { return LastIndexOf(value, nIndex, nIndex + 1); }
int LastIndexOf(const TYPE& value, int nIndex, int nNumElements);
HRESULT Remove(int nIndex);
void RemoveAll() { SetSize(0); }
void Reset() { m_nSize = 0; }
protected:
TYPE* m_pData; // the actual array of data
int m_nSize; // # of elements (upperBound - 1)
int m_nMaxSize; // max allocated
HRESULT SetSizeInternal(int nNewMaxSize); // This version doesn't call ctor or dtor.
};
//----Implementations----
// This version doesn't call ctor or dtor.
template<typename TYPE> HRESULT CGrowableArray <TYPE>::SetSizeInternal(int nNewMaxSize)
{
if (nNewMaxSize < 0 || (nNewMaxSize > INT_MAX / sizeof(TYPE)))
{
assert(false);
return E_INVALIDARG;
}
if (nNewMaxSize == 0)
{
// Shrink to 0 size & cleanup
if (m_pData)
{
free(m_pData);
m_pData = NULL;
}
m_nMaxSize = 0;
m_nSize = 0;
}
else if (m_pData == NULL || nNewMaxSize > m_nMaxSize)
{
// Grow array
int nGrowBy = (m_nMaxSize == 0) ? 16 : m_nMaxSize;
// Limit nGrowBy to keep m_nMaxSize less than INT_MAX
if ((UINT)m_nMaxSize + (UINT)nGrowBy > (UINT)INT_MAX)
nGrowBy = INT_MAX - m_nMaxSize;
nNewMaxSize = __max(nNewMaxSize, m_nMaxSize + nGrowBy);
// Verify that (nNewMaxSize * sizeof(TYPE)) is not greater than UINT_MAX or the realloc will overrun
if (sizeof(TYPE) > UINT_MAX / (UINT)nNewMaxSize)
return E_INVALIDARG;
TYPE* pDataNew = (TYPE*)realloc(m_pData, nNewMaxSize * sizeof(TYPE));
if (pDataNew == NULL)
return E_OUTOFMEMORY;
m_pData = pDataNew;
m_nMaxSize = nNewMaxSize;
}
return S_OK;
}
//--------------------------------------------------------------------------------------
template<typename TYPE> HRESULT CGrowableArray <TYPE>::SetSize(int nNewMaxSize)
{
int nOldSize = m_nSize;
if (nOldSize > nNewMaxSize)
{
assert(m_pData);
if (m_pData)
{
// Removing elements. Call dtor.
for (int i = nNewMaxSize; i < nOldSize; ++i)
m_pData[i].~TYPE();
}
}
// Adjust buffer. Note that there's no need to check for error
// since if it happens, nOldSize == nNewMaxSize will be true.)
HRESULT hr = SetSizeInternal(nNewMaxSize);
if (nOldSize < nNewMaxSize)
{
assert(m_pData);
if (m_pData)
{
// Adding elements. Call ctor.
for (int i = nOldSize; i < nNewMaxSize; ++i)
::new (&m_pData[i]) TYPE;
}
}
return hr;
}
//--------------------------------------------------------------------------------------
template<typename TYPE> HRESULT CGrowableArray <TYPE>::Add(const TYPE& value)
{
HRESULT hr;
if (FAILED(hr = SetSizeInternal(m_nSize + 1)))
return hr;
assert(m_pData != NULL);
// Construct the new element
::new (&m_pData[m_nSize]) TYPE;
// Assign
m_pData[m_nSize] = value;
++m_nSize;
return S_OK;
}
//--------------------------------------------------------------------------------------
template<typename TYPE> HRESULT CGrowableArray <TYPE>::Insert(int nIndex, const TYPE& value)
{
HRESULT hr;
// Validate index
if (nIndex < 0 ||
nIndex > m_nSize)
{
assert(false);
return E_INVALIDARG;
}
// Prepare the buffer
if (FAILED(hr = SetSizeInternal(m_nSize + 1)))
return hr;
// Shift the array
MoveMemory(&m_pData[nIndex + 1], &m_pData[nIndex], sizeof(TYPE)* (m_nSize - nIndex));
// Construct the new element
::new (&m_pData[nIndex]) TYPE;
// Set the value and increase the size
m_pData[nIndex] = value;
++m_nSize;
return S_OK;
}
//--------------------------------------------------------------------------------------
template<typename TYPE> HRESULT CGrowableArray <TYPE>::SetAt(int nIndex, const TYPE& value)
{
// Validate arguments
if (nIndex < 0 ||
nIndex >= m_nSize)
{
assert(false);
return E_INVALIDARG;
}
m_pData[nIndex] = value;
return S_OK;
}
//--------------------------------------------------------------------------------------
// Searches for the specified value and returns the index of the first occurrence
// within the section of the data array that extends from iStart and contains the
// specified number of elements. Returns -1 if value is not found within the given
// section.
//--------------------------------------------------------------------------------------
template<typename TYPE> int CGrowableArray <TYPE>::IndexOf(const TYPE& value, int iStart, int nNumElements)
{
// Validate arguments
if (iStart < 0 ||
iStart >= m_nSize ||
nNumElements < 0 ||
iStart + nNumElements > m_nSize)
{
assert(false);
return -1;
}
// Search
for (int i = iStart; i < (iStart + nNumElements); i++)
{
if (value == m_pData[i])
return i;
}
// Not found
return -1;
}
//--------------------------------------------------------------------------------------
// Searches for the specified value and returns the index of the last occurrence
// within the section of the data array that contains the specified number of elements
// and ends at iEnd. Returns -1 if value is not found within the given section.
//--------------------------------------------------------------------------------------
template<typename TYPE> int CGrowableArray <TYPE>::LastIndexOf(const TYPE& value, int iEnd, int nNumElements)
{
// Validate arguments
if (iEnd < 0 ||
iEnd >= m_nSize ||
nNumElements < 0 ||
iEnd - nNumElements < 0)
{
assert(false);
return -1;
}
// Search
for (int i = iEnd; i >(iEnd - nNumElements); i--)
{
if (value == m_pData[i])
return i;
}
// Not found
return -1;
}
//--------------------------------------------------------------------------------------
template<typename TYPE> HRESULT CGrowableArray <TYPE>::Remove(int nIndex)
{
if (nIndex < 0 ||
nIndex >= m_nSize)
{
assert(false);
return E_INVALIDARG;
}
// Destruct the element to be removed
m_pData[nIndex].~TYPE();
// Compact the array and decrease the size
MoveMemory(&m_pData[nIndex], &m_pData[nIndex + 1], sizeof(TYPE)* (m_nSize - (nIndex + 1)));
--m_nSize;
return S_OK;
}
以下结构将保存所有顶点数据
typedef struct _VERTEX{
XMFLOAT3 Position;
XMFLOAT2 TexCoord;
}VERTEX;
此功能加载所有数据
std::ifstream ss(YOURFILENAME);
CGrowableArray<VERTEX> m_Vertex;
CGrowableArray<UINT> m_Index;
CGrowableArray <XMFLOAT3> Position;
CGrowableArray <XMFLOAT2> TexCoord;
CGrowableArray <XMFLOAT3> Normal;
char cmd[256] = { 0 };
while (TRUE)
{
ss >> cmd;
if (!ss)
break;
if (0 == strcmp(cmd, "#"))
{
}
else if (0 == strcmp(cmd, "v"))
{
float x, y, z;
ss >> x >> y >> z;
Position.Add(XMFLOAT3(x, y, z));
}
else if (0 == strcmp(cmd, "vt"))
{
float u, v, w;
ss >> u >> v >> w;
TexCoord.Add(XMFLOAT2(u, v));
}
else if (0 == strcmp(cmd, "vn"))
{
float x, y, z;
ss >> x >> y >> z;
Normal.Add(XMFLOAT3(x, y, z));
}
else if (0 == strcmp(cmd, "f"))
{
UINT Value; VERTEX vertex;
for (int iFace = 0; iFace < 3; iFace++)
{
ss >> Value;
vertex.Position = Position[Value - 1];
ss.ignore();
ss >> Value;
vertex.TexCoord = TexCoord[Value - 1];
ss.ignore();
ss >> Value;
m_Index.Add(AddVertex(vertex));
}
}
}
现在m_Index包含当前对象的索引和m_Vertex顶点 注意:以下代码仅加载具有一个网格的对象!!
最后一个代码:代码中使用的AddVertex函数!
UINT AddVertex(VERTEX vertex)
{
for (int a = 0; a < m_Vertex.GetSize(); a++)
{
if (VertexEqual(m_Vertex[a], vertex))
return a;
}
m_Vertex.Add(vertex);
return m_Vertex.GetSize() - 1;
}
我希望这段代码可以帮到你。如果您有任何问题,请写评论!
任务
答案 1 :(得分:0)
在DirectX SDK中有一个样本 MeshFromOBJ10 是用DirectX10编写的,看看它,我认为很容易将它转换为DX11,因为DX10和DX11的API几乎是相同。