DirectX11如何加载Obj文件

时间:2014-02-22 13:11:28

标签: c++ directx directx-11

如何在不使用任何第三方库的情况下从.obj文件加载对象?我正在使用Visual Studio 2013 Windows8!

2 个答案:

答案 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几乎是相同。