Esempio n. 1
0
//--------------------------------------------------------------------------
Helper::Ptr HelperManager::CreateTangentSpace(	VertexBuffer3F& _pvbo,
        VertexBuffer3F& _nvbo,
        VertexBuffer4F& _tvbo,
        IndexBuffer& _ibo,
        int _startIndex,
        int _countIndex,
        float _vectorSize)
{
    Helper::Ptr ref = Helper::Create();
    ref->vbuffer.Allocate(6*_countIndex,GL_STATIC_DRAW);
    ref->cbuffer.Allocate(6*_countIndex,GL_STATIC_DRAW);
    ref->type  = GL_LINES;
    ref->transform = glm::mat4(1.f);

    glm::vec3* hvertices = ref->vbuffer.Lock();
    glm::vec3* hcolors   = ref->cbuffer.Lock();

    glm::vec3* vertices = _pvbo.Lock();
    glm::vec4* tangents = _tvbo.Lock();
    glm::vec3* normals  = _nvbo.Lock();
    unsigned int* indices= _ibo.Lock();
    int current = 0;
    for(int i=_startIndex; i<_startIndex+_countIndex; ++i)
    {
        int index = indices[i];

        // Tangent
        hvertices[current+0] = vertices[index];
        hvertices[current+1] = vertices[index] + glm::vec3(tangents[index]) * _vectorSize;

        // Bitangent
        glm::vec3 bitangent = glm::cross(glm::vec3(tangents[index]),normals[index]) * glm::sign(tangents[index].w);
        hvertices[current+2] = vertices[index];
        hvertices[current+3] = vertices[index] + bitangent * _vectorSize;

        // Normal
        hvertices[current+4] = vertices[index];
        hvertices[current+5] = vertices[index] + normals[index] * _vectorSize;

        hcolors[current+0] = glm::vec3(1.f,0.f,0.f);
        hcolors[current+1] = glm::vec3(1.f,0.f,0.f);
        hcolors[current+2] = glm::vec3(0.f,1.f,0.f);
        hcolors[current+3] = glm::vec3(0.f,1.f,0.f);
        hcolors[current+4] = glm::vec3(0.f,0.f,1.f);
        hcolors[current+5] = glm::vec3(0.f,0.f,1.f);

        current += 6;
    }
    _ibo.Unlock();
    _nvbo.Unlock();
    _tvbo.Unlock();
    _pvbo.Unlock();

    ref->cbuffer.Unlock();
    ref->vbuffer.Unlock();

    helpers.push_back(ref);
    return ref;
}
void InitIndexBuffer(IndexBuffer & pIB, LPVOID indices, UINT idxCnt, UINT stride)
{
	D3DFORMAT format;
	if (stride == sizeof(WORD)) 
		format = D3DFMT_INDEX16;
	else if (stride == sizeof(DWORD))
		format = D3DFMT_INDEX32;

	GetD3D9Device()->CreateIndexBuffer(idxCnt * stride, NULL, format, D3DPOOL_MANAGED, &pIB, NULL);
	LPVOID pIndex;
	pIB->Lock(0, 0, (LPVOID*)&pIndex, 0);
	memcpy(pIndex, indices, idxCnt * stride);
	pIB->Unlock();
}
Esempio n. 3
0
SharedPtr<Model> Model::Clone(const String& cloneName) const
{
    SharedPtr<Model> ret(new Model(context_));

    ret->SetName(cloneName);
    ret->boundingBox_ = boundingBox_;
    ret->skeleton_ = skeleton_;
    ret->geometryBoneMappings_ = geometryBoneMappings_;
    ret->geometryCenters_ = geometryCenters_;
    ret->morphs_ = morphs_;
    ret->morphRangeStarts_ = morphRangeStarts_;
    ret->morphRangeCounts_ = morphRangeCounts_;

    // Deep copy vertex/index buffers
    HashMap<VertexBuffer*, VertexBuffer*> vbMapping;
    for (Vector<SharedPtr<VertexBuffer> >::ConstIterator i = vertexBuffers_.Begin(); i != vertexBuffers_.End(); ++i)
    {
        VertexBuffer* origBuffer = *i;
        SharedPtr<VertexBuffer> cloneBuffer;

        if (origBuffer)
        {
            cloneBuffer = new VertexBuffer(context_);
            cloneBuffer->SetSize(origBuffer->GetVertexCount(), origBuffer->GetElementMask(), origBuffer->IsDynamic());
            cloneBuffer->SetShadowed(origBuffer->IsShadowed());
            if (origBuffer->IsShadowed())
                cloneBuffer->SetData(origBuffer->GetShadowData());
            else
            {
                void* origData = origBuffer->Lock(0, origBuffer->GetVertexCount());
                if (origData)
                    cloneBuffer->SetData(origData);
                else
                    URHO3D_LOGERROR("Failed to lock original vertex buffer for copying");
            }
            vbMapping[origBuffer] = cloneBuffer;
        }

        ret->vertexBuffers_.Push(cloneBuffer);
    }

    HashMap<IndexBuffer*, IndexBuffer*> ibMapping;
    for (Vector<SharedPtr<IndexBuffer> >::ConstIterator i = indexBuffers_.Begin(); i != indexBuffers_.End(); ++i)
    {
        IndexBuffer* origBuffer = *i;
        SharedPtr<IndexBuffer> cloneBuffer;

        if (origBuffer)
        {
            cloneBuffer = new IndexBuffer(context_);
            cloneBuffer->SetSize(origBuffer->GetIndexCount(), origBuffer->GetIndexSize() == sizeof(unsigned),
                origBuffer->IsDynamic());
            cloneBuffer->SetShadowed(origBuffer->IsShadowed());
            if (origBuffer->IsShadowed())
                cloneBuffer->SetData(origBuffer->GetShadowData());
            else
            {
                void* origData = origBuffer->Lock(0, origBuffer->GetIndexCount());
                if (origData)
                    cloneBuffer->SetData(origData);
                else
                    URHO3D_LOGERROR("Failed to lock original index buffer for copying");
            }
            ibMapping[origBuffer] = cloneBuffer;
        }

        ret->indexBuffers_.Push(cloneBuffer);
    }

    // Deep copy all the geometry LOD levels and refer to the copied vertex/index buffers
    ret->geometries_.Resize(geometries_.Size());
    for (unsigned i = 0; i < geometries_.Size(); ++i)
    {
        ret->geometries_[i].Resize(geometries_[i].Size());
        for (unsigned j = 0; j < geometries_[i].Size(); ++j)
        {
            SharedPtr<Geometry> cloneGeometry;
            Geometry* origGeometry = geometries_[i][j];

            if (origGeometry)
            {
                cloneGeometry = new Geometry(context_);
                cloneGeometry->SetIndexBuffer(ibMapping[origGeometry->GetIndexBuffer()]);
                unsigned numVbs = origGeometry->GetNumVertexBuffers();
                for (unsigned k = 0; k < numVbs; ++k)
                {
                    cloneGeometry->SetVertexBuffer(k, vbMapping[origGeometry->GetVertexBuffer(k)]);
                }
                cloneGeometry->SetDrawRange(origGeometry->GetPrimitiveType(), origGeometry->GetIndexStart(),
                    origGeometry->GetIndexCount(), origGeometry->GetVertexStart(), origGeometry->GetVertexCount(), false);
                cloneGeometry->SetLodDistance(origGeometry->GetLodDistance());
            }

            ret->geometries_[i][j] = cloneGeometry;
        }
    }


    // Deep copy the morph data (if any) to allow modifying it
    for (Vector<ModelMorph>::Iterator i = ret->morphs_.Begin(); i != ret->morphs_.End(); ++i)
    {
        ModelMorph& morph = *i;
        for (HashMap<unsigned, VertexBufferMorph>::Iterator j = morph.buffers_.Begin(); j != morph.buffers_.End(); ++j)
        {
            VertexBufferMorph& vbMorph = j->second_;
            if (vbMorph.dataSize_)
            {
                SharedArrayPtr<unsigned char> cloneData(new unsigned char[vbMorph.dataSize_]);
                memcpy(cloneData.Get(), vbMorph.morphData_.Get(), vbMorph.dataSize_);
                vbMorph.morphData_ = cloneData;
            }
        }
    }

    ret->SetMemoryUse(GetMemoryUse());

    return ret;
}
//=============================================================================
//=============================================================================
void StaticModelPoolMgr::AddStaticModelData(Node *pNode, StaticModel *pStaticModel)
{
    NvMeshData nvMeshData;
    StaticModelData staticModelData;
    Model *pModel = pStaticModel->GetModel();

    // only one geom currently supprted
    assert( pModel && pModel->GetNumGeometries() == 1 && "multiple gemoetries currently NOT supported" );

    Matrix3x4 objMatrix = pNode->GetTransform();
    Quaternion objRotation = pNode->GetRotation();
    Geometry *pGeometry = pModel->GetGeometry(0, 0);
    VertexBuffer *pVbuffer = pGeometry->GetVertexBuffer(0);

    unsigned uElementMask = pVbuffer->GetElementMask();
    unsigned vertexSize = pVbuffer->GetVertexSize();
    const unsigned char *pVertexData = (const unsigned char*)pVbuffer->Lock(0, pVbuffer->GetVertexCount());

    // get verts, normals, uv, etc.
    if ( pVertexData )
    {
        unsigned numVertices = pVbuffer->GetVertexCount();

        for ( unsigned i = 0; i < numVertices; ++i )
        {
            unsigned char *pDataAlign = (unsigned char *)(pVertexData + i * vertexSize);

            if ( uElementMask & MASK_POSITION )
            {
                const Vector3 vPos = *reinterpret_cast<Vector3*>( pDataAlign );
                pDataAlign += sizeof( Vector3 );

                Vector3 vxformPos = objMatrix * vPos; // xform

                // verts list
                staticModelData.listVerts.Push( vxformPos );
                nvMeshData.listVerts.push_back( Vec3f( vxformPos.x_, vxformPos.y_, vxformPos.z_ ) );
            }
            if ( uElementMask & MASK_NORMAL )
            {
                const Vector3 vNorm = *reinterpret_cast<Vector3*>( pDataAlign );
                pDataAlign += sizeof( Vector3 );

                // normal list
                Vector3 vxformNorm = objRotation * vNorm; // xform

                staticModelData.listNormals.Push( vxformNorm );
                nvMeshData.listNormals.push_back( Vec3f( vxformNorm.x_, vxformNorm.y_, vxformNorm.z_ ) );
            }
            if ( uElementMask & MASK_COLOR )
            {
                const unsigned uColor = *reinterpret_cast<unsigned*>( pDataAlign );
                pDataAlign += sizeof( unsigned );
            }
            if ( uElementMask & MASK_TEXCOORD1 )
            {
                const Vector2 vUV = *reinterpret_cast<Vector2*>( pDataAlign );
                pDataAlign += sizeof( Vector2 );

                // uv list
                staticModelData.listUVs.Push( vUV );
            }

            // skip other mask elements - we got what we wanted
        }

        //unlock
        pVbuffer->Unlock();
    }
    else
    {
        // error
        assert( false && "failed to unlock vertex buffer" );
    }

    // get indeces
    IndexBuffer *pIbuffer = pGeometry->GetIndexBuffer();
    const unsigned *pIndexData = (const unsigned *)pIbuffer->Lock( 0, pIbuffer->GetIndexCount() );
    const unsigned short *pUShortData = (const unsigned short *)pIndexData;

    if ( pUShortData )
    {
        unsigned numIndeces = pIbuffer->GetIndexCount();
        unsigned indexSize = pIbuffer->GetIndexSize();
        assert( indexSize == sizeof(unsigned short) );

        for( unsigned i = 0; i < numIndeces; i += 3 )
        {
            int idx0 = (int)pUShortData[i  ];
            int idx1 = (int)pUShortData[i+1];
            int idx2 = (int)pUShortData[i+2];

            staticModelData.listTris.Push( IntVector3( idx0, idx1, idx2 ) );
            nvMeshData.listTris.push_back( Vec3i( idx0, idx1, idx2 ) );
        }

        //unlock
        pIbuffer->Unlock();
    }
    else
    {
        // error
        assert( false && "failed to unlock index buffer" );
    }

    // rest of the static model data
    staticModelData.node       = pNode;
    staticModelData.drawable   = pStaticModel;
    staticModelData.begVertex  = m_pNvScene->getNumVertices();
    staticModelData.begTriList = m_pNvScene->getNumTriangles();

    // resize coeff lists
    staticModelData.listVertexUnshadoweCoeff.Resize( staticModelData.listVerts.Size() );
    staticModelData.listVertexShadowCoeff.Resize( staticModelData.listVerts.Size() );
    staticModelData.listVertexDiffuseColor.Resize( staticModelData.listVerts.Size() );
    staticModelData.listVertexSampleOcclude.resize( staticModelData.listVerts.Size() );

    // find material matcolor
    VertexUtil *pVertexUtil = GetScene()->GetComponent<VertexUtil>();
    staticModelData.materialColor = pVertexUtil->GetModelMaterialColor( pStaticModel );

    // save model
    m_vStaticModelPool.Push( staticModelData );

    // push it to nv Scene
    m_pNvScene->AddTriangleMesh( nvMeshData );
}
Esempio n. 5
0
/**
*  @brief
*    Builds the octree
*/
bool MeshOctree::Build(MeshLODLevel &cMeshLODLevel, uint32 nNumOfGeometries, const uint32 nGeometries[],
                       Array<Array<uint32>*> *plstOctreeIDList)
{
    // Check parameters
    if (!cMeshLODLevel.GetMesh() || !cMeshLODLevel.GetMesh()->GetMorphTarget() ||
            !cMeshLODLevel.GetMesh()->GetMorphTarget()->GetVertexBuffer() || !cMeshLODLevel.GetIndexBuffer())
        return false; // Error!

    // Store geometries
    m_pOwnerMeshLODLevel = &cMeshLODLevel;
    m_bBuild			 = true;
    m_nNumOfGeometries	 = nNumOfGeometries;
    m_pnGeometries		 = new uint32[m_nNumOfGeometries];
    MemoryManager::Copy(m_pnGeometries, nGeometries, sizeof(uint32)*m_nNumOfGeometries);

    // Get vertex and index buffer pointers
    // [TODO] Get right morph target and LOD level!
    VertexBuffer *pVertexBuffer = cMeshLODLevel.GetMesh()->GetMorphTarget()->GetVertexBuffer();
    IndexBuffer  *pIndexBuffer  = cMeshLODLevel.GetIndexBuffer();

    // Lock buffers
    if (!m_pParent) {
        if (!pIndexBuffer->Lock(Lock::ReadOnly))
            return false; // Error!
        if (!pVertexBuffer->Lock(Lock::ReadOnly)) {
            // Unlock the index buffer
            pIndexBuffer->Unlock();

            // Error!
            return false;
        }
    }

    // Init bounding box with the first vertex of the geometry
    Vector3 vBoundingBox[2];
    {
        const Geometry &cGeometry = cMeshLODLevel.GetGeometries()->Get(m_pnGeometries[0]);
        for (int i=0; i<3; i++) {
            vBoundingBox[0][i] =
                vBoundingBox[1][i] = static_cast<float*>(pVertexBuffer->GetData(pIndexBuffer->GetData(cGeometry.GetStartIndex()), VertexBuffer::Position))[i];
        }
    }

    // Get octree bounding box
    for (uint32 nGeometry=0; nGeometry<m_nNumOfGeometries; nGeometry++) {
        // Get geometry
        const Geometry &cGeometry = cMeshLODLevel.GetGeometries()->Get(m_pnGeometries[nGeometry]);

        // Add octree ID to the geometry octree list
        if (plstOctreeIDList)
            plstOctreeIDList->Get(m_pnGeometries[nGeometry])->Add(m_nID);

        // Loop through geometry vertices
        uint32 nIndex = cGeometry.GetStartIndex();
        for (uint32 i=0; i<cGeometry.GetIndexSize(); i++) {
            const float *pfVertex = static_cast<const float*>(pVertexBuffer->GetData(pIndexBuffer->GetData(nIndex++), VertexBuffer::Position));
            if (vBoundingBox[0].x > pfVertex[Vector3::X])
                vBoundingBox[0].x = pfVertex[Vector3::X];
            if (vBoundingBox[1].x < pfVertex[Vector3::X])
                vBoundingBox[1].x = pfVertex[Vector3::X];
            if (vBoundingBox[0].y > pfVertex[Vector3::Y])
                vBoundingBox[0].y = pfVertex[Vector3::Y];
            if (vBoundingBox[1].y < pfVertex[Vector3::Y])
                vBoundingBox[1].y = pfVertex[Vector3::Y];
            if (vBoundingBox[0].z > pfVertex[Vector3::Z])
                vBoundingBox[0].z = pfVertex[Vector3::Z];
            if (vBoundingBox[1].z < pfVertex[Vector3::Z])
                vBoundingBox[1].z = pfVertex[Vector3::Z];
        }
    }
    if (m_pParent) { // Adjust bounding box
        // Get parent center position
        const Vector3 &vPCenter = static_cast<MeshOctree*>(m_pParent)->m_vBBCenter;
        const Vector3  vPBBMin  = static_cast<MeshOctree*>(m_pParent)->m_cBoundingBox.GetCorner1();
        const Vector3  vPBBMax  = static_cast<MeshOctree*>(m_pParent)->m_cBoundingBox.GetCorner2();

        // Check octree sector
        switch (m_nIDOffset) {
        // 0.  left     top		 back
        case 0:
            if (vBoundingBox[0].x <  vPBBMin.x)
                vBoundingBox[0].x =  vPBBMin.x;
            if (vBoundingBox[1].x > vPCenter.x)
                vBoundingBox[1].x = vPCenter.x;
            if (vBoundingBox[0].y < vPCenter.y)
                vBoundingBox[0].y = vPCenter.y;
            if (vBoundingBox[1].y >  vPBBMax.y)
                vBoundingBox[1].y =  vPBBMax.y;
            if (vBoundingBox[0].z <  vPBBMin.z)
                vBoundingBox[0].z =  vPBBMin.z;
            if (vBoundingBox[1].z > vPCenter.z)
                vBoundingBox[1].z = vPCenter.z;
            break;

        // 1.  right    top		 back
        case 1:
            if (vBoundingBox[0].x < vPCenter.x)
                vBoundingBox[0].x = vPCenter.x;
            if (vBoundingBox[1].x >  vPBBMax.x)
                vBoundingBox[1].x =  vPBBMax.x;
            if (vBoundingBox[0].y < vPCenter.y)
                vBoundingBox[0].y = vPCenter.y;
            if (vBoundingBox[1].y >  vPBBMax.y)
                vBoundingBox[1].y =  vPBBMax.y;
            if (vBoundingBox[0].z <  vPBBMin.z)
                vBoundingBox[0].z =  vPBBMin.z;
            if (vBoundingBox[1].z > vPCenter.z)
                vBoundingBox[1].z = vPCenter.z;
            break;

        // 2.  right    top		 front
        case 2:
            if (vBoundingBox[0].x < vPCenter.x)
                vBoundingBox[0].x = vPCenter.x;
            if (vBoundingBox[1].x >  vPBBMax.x)
                vBoundingBox[1].x =  vPBBMax.x;
            if (vBoundingBox[0].y < vPCenter.y)
                vBoundingBox[0].y = vPCenter.y;
            if (vBoundingBox[1].y >  vPBBMax.y)
                vBoundingBox[1].y =  vPBBMax.y;
            if (vBoundingBox[0].z < vPCenter.z)
                vBoundingBox[0].z = vPCenter.z;
            if (vBoundingBox[1].z >  vPBBMax.z)
                vBoundingBox[1].z =  vPBBMax.z;
            break;

        // 3.  left     top		 front
        case 3:
            if (vBoundingBox[0].x <  vPBBMin.x)
                vBoundingBox[0].x =  vPBBMin.x;
            if (vBoundingBox[1].x > vPCenter.x)
                vBoundingBox[1].x = vPCenter.x;
            if (vBoundingBox[0].y < vPCenter.y)
                vBoundingBox[0].y = vPCenter.y;
            if (vBoundingBox[1].y >  vPBBMax.y)
                vBoundingBox[1].y =  vPBBMax.y;
            if (vBoundingBox[0].z < vPCenter.z)
                vBoundingBox[0].z = vPCenter.z;
            if (vBoundingBox[1].z >  vPBBMax.z)
                vBoundingBox[1].z =  vPBBMax.z;
            break;

        // 4.  left     bottom	 back
        case 4:
            if (vBoundingBox[0].x <  vPBBMin.x)
                vBoundingBox[0].x =  vPBBMin.x;
            if (vBoundingBox[1].x > vPCenter.x)
                vBoundingBox[1].x = vPCenter.x;
            if (vBoundingBox[0].y <  vPBBMin.y)
                vBoundingBox[0].y =  vPBBMin.y;
            if (vBoundingBox[1].y > vPCenter.y)
                vBoundingBox[1].y = vPCenter.y;
            if (vBoundingBox[0].z <  vPBBMin.z)
                vBoundingBox[0].z =  vPBBMin.z;
            if (vBoundingBox[1].z > vPCenter.z)
                vBoundingBox[1].z = vPCenter.z;
            break;

        // 5.  right    bottom	 back
        case 5:
            if (vBoundingBox[0].x < vPCenter.x)
                vBoundingBox[0].x = vPCenter.x;
            if (vBoundingBox[1].x >  vPBBMax.x)
                vBoundingBox[1].x =  vPBBMax.x;
            if (vBoundingBox[0].y <  vPBBMin.y)
                vBoundingBox[0].y =  vPBBMin.y;
            if (vBoundingBox[1].y > vPCenter.y)
                vBoundingBox[1].y = vPCenter.y;
            if (vBoundingBox[0].z <  vPBBMin.z)
                vBoundingBox[0].z =  vPBBMin.z;
            if (vBoundingBox[1].z > vPCenter.z)
                vBoundingBox[1].z = vPCenter.z;
            break;

        // 6.  right    bottom	 front
        case 6:
            if (vBoundingBox[0].x < vPCenter.x)
                vBoundingBox[0].x = vPCenter.x;
            if (vBoundingBox[1].x >  vPBBMax.x)
                vBoundingBox[1].x =  vPBBMax.x;
            if (vBoundingBox[0].y <  vPBBMin.y)
                vBoundingBox[0].y =  vPBBMin.y;
            if (vBoundingBox[1].y > vPCenter.y)
                vBoundingBox[1].y = vPCenter.y;
            if (vBoundingBox[0].z < vPCenter.z)
                vBoundingBox[0].z = vPCenter.z;
            if (vBoundingBox[1].z >  vPBBMax.z)
                vBoundingBox[1].z =  vPBBMax.z;
            break;

        // 7.  left     bottom	 front
        case 7:
            if (vBoundingBox[0].x <  vPBBMin.x)
                vBoundingBox[0].x =  vPBBMin.x;
            if (vBoundingBox[1].x > vPCenter.x)
                vBoundingBox[1].x = vPCenter.x;
            if (vBoundingBox[0].y <  vPBBMin.y)
                vBoundingBox[0].y =  vPBBMin.y;
            if (vBoundingBox[1].y > vPCenter.y)
                vBoundingBox[1].y = vPCenter.y;
            if (vBoundingBox[0].z < vPCenter.z)
                vBoundingBox[0].z = vPCenter.z;
            if (vBoundingBox[1].z >  vPBBMax.z)
                vBoundingBox[1].z =  vPBBMax.z;
            break;
        }
    }

    // Get octree center
    m_vBBCenter		 = (vBoundingBox[0]+vBoundingBox[1])/2;
    vBoundingBox[0] -= m_vBBCenter;
    vBoundingBox[1] -= m_vBBCenter;

    // Set octree bounding box
    m_cBoundingBox.SetPos(m_vBBCenter.x, m_vBBCenter.y, m_vBBCenter.z);
    m_cBoundingBox.SetSize(vBoundingBox[0].x, vBoundingBox[0].y, vBoundingBox[0].z,
                           vBoundingBox[1].x, vBoundingBox[1].y, vBoundingBox[1].z);

    // [TODO] Clean this up
    // Check if the octree should be divided
    if (static_cast<signed>(m_nLevel) >= m_nSubdivide) {
//	if (m_nLevel >= m_nSubdivide || m_nNumOfGeometries < m_nMinGeometries) {
        // Unlock the buffers
        if (!m_pParent) {
            pIndexBuffer->Unlock();
            pVertexBuffer->Unlock();
        }

        // Done
        return true;
    }

    // Children
    uint32 nGeometriesT[8];
    uint32 *pGeometriesT[8];

    // Get the geometries in which are in the children
    for (int i=0; i<8; i++) {
        pGeometriesT[i] = new uint32[m_nNumOfGeometries];
        MemoryManager::Set(pGeometriesT[i], -1, sizeof(uint32)*m_nNumOfGeometries);
        nGeometriesT[i] = 0;
    }
    for (uint32 nGeometry=0; nGeometry<m_nNumOfGeometries; nGeometry++) {
        // Get data
        uint32			nGeoID	  = m_pnGeometries[nGeometry];
        const Geometry &cGeometry = cMeshLODLevel.GetGeometries()->Get(nGeoID);
        if (&cGeometry != &Array<Geometry>::Null) {
            // Loop through geometry vertices
            uint32 nIndex = cGeometry.GetStartIndex();
            for (uint32 i=0; i<cGeometry.GetIndexSize(); i++) {
                // Get vertex
                float *pfVertex = static_cast<float*>(pVertexBuffer->GetData(pIndexBuffer->GetData(nIndex++), VertexBuffer::Position));

                // Check in which octree sector the vertex is in
                // 0.  left     top		 back
                if ((!nGeometriesT[0] || pGeometriesT[0][nGeometriesT[0]-1] != nGeoID) &&
                        pfVertex[Vector3::X] <= m_vBBCenter.x && pfVertex[Vector3::Y] >= m_vBBCenter.y && pfVertex[Vector3::Z] <= m_vBBCenter.z) {
                    pGeometriesT[0][nGeometriesT[0]] = nGeoID;
                    nGeometriesT[0]++;
                }

                // 1.  right    top		 back
                if ((!nGeometriesT[1] || pGeometriesT[1][nGeometriesT[1]-1] != nGeoID) &&
                        pfVertex[Vector3::X] >= m_vBBCenter.x && pfVertex[Vector3::Y] >= m_vBBCenter.y && pfVertex[Vector3::Z] <= m_vBBCenter.z) {
                    pGeometriesT[1][nGeometriesT[1]] = nGeoID;
                    nGeometriesT[1]++;
                }

                // 2.  right    top		 front
                if ((!nGeometriesT[2] || pGeometriesT[2][nGeometriesT[2]-1] != nGeoID) &&
                        pfVertex[Vector3::X] >= m_vBBCenter.x && pfVertex[Vector3::Y] >= m_vBBCenter.y && pfVertex[Vector3::Z] >= m_vBBCenter.z) {
                    pGeometriesT[2][nGeometriesT[2]] = nGeoID;
                    nGeometriesT[2]++;
                }

                // 3.  left     top		 front
                if ((!nGeometriesT[3] || pGeometriesT[3][nGeometriesT[3]-1] != nGeoID) &&
                        pfVertex[Vector3::X] <= m_vBBCenter.x && pfVertex[Vector3::Y] >= m_vBBCenter.y && pfVertex[Vector3::Z] >= m_vBBCenter.z) {
                    pGeometriesT[3][nGeometriesT[3]] = nGeoID;
                    nGeometriesT[3]++;
                }

                // 4.  left     bottom	 back
                if ((!nGeometriesT[4] || pGeometriesT[4][nGeometriesT[4]-1] != nGeoID) &&
                        pfVertex[Vector3::X] <= m_vBBCenter.x && pfVertex[Vector3::Y] <= m_vBBCenter.y && pfVertex[Vector3::Z] <= m_vBBCenter.z) {
                    pGeometriesT[4][nGeometriesT[4]] = nGeoID;
                    nGeometriesT[4]++;
                }

                // 5.  right    bottom	 back
                if ((!nGeometriesT[5] || pGeometriesT[5][nGeometriesT[5]-1] != nGeoID) &&
                        pfVertex[Vector3::X] >= m_vBBCenter.x && pfVertex[Vector3::Y] <= m_vBBCenter.y && pfVertex[Vector3::Z] <= m_vBBCenter.z) {
                    pGeometriesT[5][nGeometriesT[5]] = nGeoID;
                    nGeometriesT[5]++;
                }

                // 6.  right    bottom	 front
                if ((!nGeometriesT[6] || pGeometriesT[6][nGeometriesT[6]-1] != nGeoID) &&
                        pfVertex[Vector3::X] >= m_vBBCenter.x && pfVertex[Vector3::Y] <= m_vBBCenter.y && pfVertex[Vector3::Z] >= m_vBBCenter.z) {
                    pGeometriesT[6][nGeometriesT[6]] = nGeoID;
                    nGeometriesT[6]++;
                }

                // 7.  left     bottom	 front
                if ((!nGeometriesT[7] || pGeometriesT[7][nGeometriesT[7]-1] != nGeoID) &&
                        pfVertex[Vector3::X] <= m_vBBCenter.x && pfVertex[Vector3::Y] <= m_vBBCenter.y && pfVertex[Vector3::Z] >= m_vBBCenter.z) {
                    pGeometriesT[7][nGeometriesT[7]] = nGeoID;
                    nGeometriesT[7]++;
                }
            }
        }
    }

    // Get number of children
    m_nNumOfChildren = 0;
    for (int i=0; i<8; i++) {
        if (nGeometriesT[i])
//		if (nGeometriesT[i] >= m_nMinGeometries)
            m_nNumOfChildren++;
    }
    if (m_nNumOfChildren) { // Create children
        uint32 nChild = 0;

        m_ppChild = new Octree*[m_nNumOfChildren];
        for (int i=0; i<8; i++) {
            if (nGeometriesT[i]) {
//			if (nGeometriesT[i] >= m_nMinGeometries) {
                // Build child
                m_ppChild[nChild] = new MeshOctree();
                m_ppChild[nChild]->Init(this, m_nSubdivide, m_nMinGeometries, i);
                static_cast<MeshOctree*>(m_ppChild[nChild])->Build(cMeshLODLevel, nGeometriesT[i], pGeometriesT[i], plstOctreeIDList);
                nChild++;
            }
        }
    }

    // Delete temp child data
    for (int i=0; i<8; i++)
        delete [] pGeometriesT[i];

    // Unlock the buffers
    if (!m_pParent) {
        pIndexBuffer->Unlock();
        pVertexBuffer->Unlock();
    }

    // Done
    return true;
}
Esempio n. 6
0
//[-------------------------------------------------------]
//[ Public virtual SPK::BufferHandler functions           ]
//[-------------------------------------------------------]
void SPK_PLQuadRenderer::createBuffers(const SPK::Group &group)
{
	// Create the SPK_PLBuffer instance
	m_pSPK_PLBuffer = static_cast<SPK_PLBuffer*>(group.createBuffer(PLBufferName, PLBufferCreator(GetPLRenderer(), NumOfVerticesPerParticle, NumOfIndicesPerParticle, texturingMode), 0U, false));

	// Is there a valid m_pSPK_PLBuffer instance?
	if (m_pSPK_PLBuffer && m_pSPK_PLBuffer->GetVertexBuffer()) {
		switch (texturingMode) {
			case SPK::TEXTURE_2D:
				if (!group.getModel()->isEnabled(SPK::PARAM_TEXTURE_INDEX)) {
					// Get the vertex buffer instance from m_pSPK_PLBuffer and lock it
					VertexBuffer *pVertexBuffer = m_pSPK_PLBuffer->GetVertexBuffer();
					if (pVertexBuffer->Lock(Lock::WriteOnly)) {
						// Set correct data
						const uint32 nVertexSize = pVertexBuffer->GetVertexSize();
						float *pfTexCoord = static_cast<float*>(pVertexBuffer->GetData(0, VertexBuffer::TexCoord));
						for (size_t i=0; i<group.getParticles().getNbReserved(); i++) {
							// Top right vertex
							pfTexCoord[0] = 1.0f;
							pfTexCoord[1] = 0.0f;
							pfTexCoord = reinterpret_cast<float*>(reinterpret_cast<char*>(pfTexCoord) + nVertexSize);	// Next, please!

							// Top left vertex
							pfTexCoord[0] = 0.0f;
							pfTexCoord[1] = 0.0f;
							pfTexCoord = reinterpret_cast<float*>(reinterpret_cast<char*>(pfTexCoord) + nVertexSize);	// Next, please!

							// Bottom left
							pfTexCoord[0] = 0.0f;
							pfTexCoord[1] = 1.0f;
							pfTexCoord = reinterpret_cast<float*>(reinterpret_cast<char*>(pfTexCoord) + nVertexSize);	// Next, please!

							// Bottom right
							pfTexCoord[0] = 1.0f;
							pfTexCoord[1] = 1.0f;
							pfTexCoord = reinterpret_cast<float*>(reinterpret_cast<char*>(pfTexCoord) + nVertexSize);	// Next, please!
						}

						// Unlock the vertex buffer
						pVertexBuffer->Unlock();
					}
				}
				break;

			case SPK::TEXTURE_3D:
			{
				// Get the vertex buffer instance from m_pSPK_PLBuffer and lock it
				VertexBuffer *pVertexBuffer = m_pSPK_PLBuffer->GetVertexBuffer();
				if (pVertexBuffer->Lock(Lock::WriteOnly)) {
					// Set correct data
					const uint32 nVertexSize = pVertexBuffer->GetVertexSize();
					float *pfTexCoord = static_cast<float*>(pVertexBuffer->GetData(0, VertexBuffer::TexCoord));
					for (size_t i=0; i<group.getParticles().getNbReserved(); i++) {
						// Top right vertex
						pfTexCoord[0] = 1.0f;
						pfTexCoord[1] = 0.0f;
						pfTexCoord[2] = 0.0f;
						pfTexCoord = reinterpret_cast<float*>(reinterpret_cast<char*>(pfTexCoord) + nVertexSize);	// Next, please!

						// Top left vertex
						pfTexCoord[0] = 0.0f;
						pfTexCoord[1] = 0.0f;
						pfTexCoord[2] = 0.0f;
						pfTexCoord = reinterpret_cast<float*>(reinterpret_cast<char*>(pfTexCoord) + nVertexSize);	// Next, please!

						// Bottom left
						pfTexCoord[0] = 0.0f;
						pfTexCoord[1] = 1.0f;
						pfTexCoord[2] = 0.0f;
						pfTexCoord = reinterpret_cast<float*>(reinterpret_cast<char*>(pfTexCoord) + nVertexSize);	// Next, please!

						// Bottom right
						pfTexCoord[0] = 1.0f;
						pfTexCoord[1] = 1.0f;
						pfTexCoord[2] = 0.0f;
						pfTexCoord = reinterpret_cast<float*>(reinterpret_cast<char*>(pfTexCoord) + nVertexSize);	// Next, please!
					}

					// Unlock the vertex buffer
					pVertexBuffer->Unlock();
				}
				break;
			}
		}
	}

	// Is there a valid m_pSPK_PLBuffer instance?
	if (m_pSPK_PLBuffer && m_pSPK_PLBuffer->GetIndexBuffer()) {
		// Get the index buffer instance from m_pSPK_PLBuffer and lock it
		IndexBuffer *pIndexBuffer = m_pSPK_PLBuffer->GetIndexBuffer();
		if (pIndexBuffer && pIndexBuffer->Lock(Lock::WriteOnly)) {
			// Fill the index buffer with valid data
			for (uint32 i=0, nVertices=4, nIndex=0; i<group.getParticles().getNbReserved(); i++, nVertices+=4) {
				// Triangle 1
				pIndexBuffer->SetData(nIndex++, nVertices-4);
				pIndexBuffer->SetData(nIndex++, nVertices-3);
				pIndexBuffer->SetData(nIndex++, nVertices-2);

				// Triangle 2
				pIndexBuffer->SetData(nIndex++, nVertices-4);
				pIndexBuffer->SetData(nIndex++, nVertices-2);
				pIndexBuffer->SetData(nIndex++, nVertices-1);
			}

			// Unlock the index buffer
			pIndexBuffer->Unlock();
		}
	}
}
Esempio n. 7
0
void RenderManager::DrawTextPrivate()
{
	if(enqueuedTextData.size() == 0)
		return;

	gRenderAPI->BeginPerfEvent("RenderText");

	for(int fnt=0; fnt<FONT_MaxSupported; fnt++)
	{
		// Calculate number of quads to render
		int numQuads = 0;
		for(vector<TextRenderData>::const_iterator it=enqueuedTextData.begin(); it != enqueuedTextData.end(); it++)
		{
			if(it->useFont == fnt)
				numQuads += it->text.length();
		}

		if(numQuads == 0)
			continue;

		// Create vertex buffer
		VertexBuffer* textVB = gRenderAPI->CreateVertexBuffer(VFMT_P3C3U2, numQuads*4, NULL, true);
		VertexContainer_P3C3U2* pData = (VertexContainer_P3C3U2*)textVB->Lock();

		float fontHeightNDC, fontWidthNDC;
		for(vector<TextRenderData>::const_iterator it=enqueuedTextData.begin(); it != enqueuedTextData.end(); it++)
		{
			const TextRenderData& data = *it;

			if(data.useFont == fnt)
			{
				// Convert font height from pixel units to NDC units
				fontHeightNDC = 2*data.size/fullScreenBufferSizeY;

				// The current position of the render cursor
				float renderCursorX = data.posX;

				// Font used
				BitmapFont* font = engineFonts[data.useFont];

				// Font color
				ColorVector color = data.color;

				// Text to render
				const string& renderText = data.text;

				for(unsigned int i=0; i<renderText.length(); i++)
				{
					BitmapFont::CharDescriptor charData = font->GetData(renderText.at(i), data.bBold);

					fontWidthNDC = charData.aspectRatio * fontHeightNDC; 

					pData->px = renderCursorX;
					pData->py = data.posY;
					pData->pz = 0.f;
					pData->cx = color.r;
					pData->cy = color.g;
					pData->cz = color.b;
					pData->u = charData.u1;
					pData->v = charData.v1;

					pData++;

					pData->px = renderCursorX + fontWidthNDC;
					pData->py = data.posY;
					pData->pz = 0.f;
					pData->cx = color.r;
					pData->cy = color.g;
					pData->cz = color.b;
					pData->u = charData.u2;
					pData->v = charData.v1;

					pData++;

					pData->px = renderCursorX + fontWidthNDC;
					pData->py = data.posY - fontHeightNDC;
					pData->pz = 0.f;
					pData->cx = color.r;
					pData->cy = color.g;
					pData->cz = color.b;
					pData->u = charData.u2;
					pData->v = charData.v2;

					pData++;

					pData->px = renderCursorX;
					pData->py = data.posY - fontHeightNDC;
					pData->pz = 0.f;
					pData->cx = color.r;
					pData->cy = color.g;
					pData->cz = color.b;
					pData->u = charData.u1;
					pData->v = charData.v2;

					pData++;

					renderCursorX += fontWidthNDC;
				}
			}
		}

		textVB->Unlock();

		// Create index buffer
		IndexBuffer* textIB = gRenderAPI->CreateIndexBuffer(IFMT_16Bit, numQuads*6, NULL, true);
		short* iData = (short*)textIB->Lock();

		int offset = 0;
		for(unsigned int i=0; i<enqueuedTextData.size(); i++)
		{
			if(enqueuedTextData.at(i).useFont == fnt)
			{
				for(unsigned int j=0; j<enqueuedTextData.at(i).text.length(); j++)
				{
					*iData = offset + 4*j + 0; iData++;
					*iData = offset + 4*j + 1; iData++;
					*iData = offset + 4*j + 3; iData++;

					*iData = offset + 4*j + 2; iData++;
					*iData = offset + 4*j + 3; iData++;
					*iData = offset + 4*j + 1; iData++;
				}

				offset += 4*enqueuedTextData.at(i).text.length();
			}
		}

		textIB->Unlock();

		// Vertex shader
		VertexShader* vShader = gRenderManager.GetPassthroughShader(VFMT_P3C3U2, INTERPOLANT_MeshUV | INTERPOLANT_MeshColor);
		vShader->Bind();

		// Pixel shader
		simpleFontPixelShader->SetValues(engineFonts[fnt]->GetTexture(), SamplerState::TrilinearWrap);
		simpleFontPixelShader->Bind();

		gRenderAPI->SetVertexBuffer(0, textVB);
		gRenderAPI->SetIndexBuffer(textIB);
		gRenderAPI->DrawIndexed(TOPOLOGY_TriangleList, numQuads*2);

		// Clean up the buffers
		gRenderAPI->DestroyVertexBuffer(textVB);
		gRenderAPI->DestroyIndexBuffer(textIB);
	}

	gRenderAPI->EndPerfEvent();
}
Esempio n. 8
0
//[-------------------------------------------------------]
//[ Private virtual MeshCreator functions                 ]
//[-------------------------------------------------------]
Mesh *MeshCreatorCube::Create(Mesh &cMesh, uint32 nLODLevel, bool bStatic) const
{
	// Call base implementation
	MeshCreator::Create(cMesh, nLODLevel, bStatic);

	// Get dimension and offset
	const Vector3 &vDimension = Dimension.Get();
	const Vector3 &vOffset    = Offset.Get();

	// Get morph target
	MeshMorphTarget *pMorphTarget = cMesh.GetMorphTarget(0);
	if (pMorphTarget && pMorphTarget->GetVertexBuffer()) {
		VertexBuffer *pVertexBuffer = pMorphTarget->GetVertexBuffer();
		if (TexCoords || Normals) {
			// Allocate data
			pVertexBuffer->AddVertexAttribute(VertexBuffer::Position, 0, VertexBuffer::Float3);
			if (TexCoords)
				pVertexBuffer->AddVertexAttribute(VertexBuffer::TexCoord, 0, VertexBuffer::Float2);
			if (Normals)
				pVertexBuffer->AddVertexAttribute(VertexBuffer::Normal, 0, VertexBuffer::Float3);
			pVertexBuffer->Allocate(24, bStatic ? Usage::Static : Usage::Dynamic);
			if (pVertexBuffer->Lock(Lock::WriteOnly)) { // Setup vertices
			// x-positive (0)
				// 0
				float *pfVertices = static_cast<float*>(pVertexBuffer->GetData(0, VertexBuffer::Position));
				pfVertices[Vector3::X] =  vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] =  vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] = -vDimension.z + vOffset.z;

				// 1
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(1, VertexBuffer::Position));
				pfVertices[Vector3::X] = vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] = vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] = vDimension.z + vOffset.z;

				// 2
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(2, VertexBuffer::Position));
				pfVertices[Vector3::X] =  vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] = -vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] =  vDimension.z + vOffset.z;

				// 3
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(3, VertexBuffer::Position));
				pfVertices[Vector3::X] =  vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] = -vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] = -vDimension.z + vOffset.z;

			// x-negative (1)
				// 4
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(4, VertexBuffer::Position));
				pfVertices[Vector3::X] = -vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] =  vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] =  vDimension.z + vOffset.z;

				// 5
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(5, VertexBuffer::Position));
				pfVertices[Vector3::X] = -vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] =  vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] = -vDimension.z + vOffset.z;

				// 6
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(6, VertexBuffer::Position));
				pfVertices[Vector3::X] = -vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] = -vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] = -vDimension.z + vOffset.z;

				// 7
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(7, VertexBuffer::Position));
				pfVertices[Vector3::X] = -vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] = -vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] =  vDimension.z + vOffset.z;

			// y-positive (2)
				// 8
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(8, VertexBuffer::Position));
				pfVertices[Vector3::X] =  vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] =  vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] = -vDimension.z + vOffset.z;

				// 9
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(9, VertexBuffer::Position));
				pfVertices[Vector3::X] = -vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] =  vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] = -vDimension.z + vOffset.z;

				// 10
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(10, VertexBuffer::Position));
				pfVertices[Vector3::X] = -vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] =  vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] =  vDimension.z + vOffset.z;

				// 11
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(11, VertexBuffer::Position));
				pfVertices[Vector3::X] = vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] = vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] = vDimension.z + vOffset.z;

			// y-negative (3)
				// 12
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(12, VertexBuffer::Position));
				pfVertices[Vector3::X] =  vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] = -vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] =  vDimension.z + vOffset.z;

				// 13
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(13, VertexBuffer::Position));
				pfVertices[Vector3::X] = -vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] = -vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] =  vDimension.z + vOffset.z;

				// 14
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(14, VertexBuffer::Position));
				pfVertices[Vector3::X] = -vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] = -vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] = -vDimension.z + vOffset.z;

				// 15
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(15, VertexBuffer::Position));
				pfVertices[Vector3::X] =  vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] = -vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] = -vDimension.z + vOffset.z;

			// z-positive (4)
				// 16
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(16, VertexBuffer::Position));
				pfVertices[Vector3::X] =  vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] =  vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] =  vDimension.z + vOffset.z;

				// 17
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(17, VertexBuffer::Position));
				pfVertices[Vector3::X] = -vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] =  vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] =  vDimension.z + vOffset.z;

				// 18
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(18, VertexBuffer::Position));
				pfVertices[Vector3::X] = -vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] = -vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] =  vDimension.z + vOffset.z;

				// 19
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(19, VertexBuffer::Position));
				pfVertices[Vector3::X] =  vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] = -vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] =  vDimension.z + vOffset.z;

			// z-negative (5)
				// 20
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(20, VertexBuffer::Position));
				pfVertices[Vector3::X] = -vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] =  vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] = -vDimension.z + vOffset.z;

				// 21
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(21, VertexBuffer::Position));
				pfVertices[Vector3::X] =  vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] =  vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] = -vDimension.z + vOffset.z;

				// 22
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(22, VertexBuffer::Position));
				pfVertices[Vector3::X] =  vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] = -vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] = -vDimension.z + vOffset.z;

				// 23
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(23, VertexBuffer::Position));
				pfVertices[Vector3::X] = -vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] = -vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] = -vDimension.z + vOffset.z;

				// Setup texture coordinates
				if (TexCoords) {
					for (int nSide=0; nSide<6; nSide++) {
						// 0
						pfVertices = static_cast<float*>(pVertexBuffer->GetData(0+nSide*4, VertexBuffer::TexCoord));
						pfVertices[Vector2::X] = 1.0f;
						pfVertices[Vector2::Y] = 0.0f;

						// 1
						pfVertices = static_cast<float*>(pVertexBuffer->GetData(1+nSide*4, VertexBuffer::TexCoord));
						pfVertices[Vector2::X] = 0.0f;
						pfVertices[Vector2::Y] = 0.0f;

						// 2
						pfVertices = static_cast<float*>(pVertexBuffer->GetData(2+nSide*4, VertexBuffer::TexCoord));
						pfVertices[Vector2::X] = 0.0f;
						pfVertices[Vector2::Y] = 1.0f;

						// 3
						pfVertices = static_cast<float*>(pVertexBuffer->GetData(3+nSide*4, VertexBuffer::TexCoord));
						pfVertices[Vector2::X] = 1.0f;
						pfVertices[Vector2::Y] = 1.0f;
					}
				}

				// Setup normal vectors
				if (Normals) {
					// x-positive (0)
					SetNormals(*pVertexBuffer, 0, 1.0f, 0.0f, 0.0f);

					// x-negative (1)
					SetNormals(*pVertexBuffer, 1, -1.0f, 0.0f, 0.0f);

					// y-positive (2)
					SetNormals(*pVertexBuffer, 2, 0.0f, 1.0f, 0.0f);

					// y-negative (3)
					SetNormals(*pVertexBuffer, 3, 0.0f, -1.0f, 0.0f);

					// z-positive (4)
					SetNormals(*pVertexBuffer, 4, 0.0f, 0.0f, 1.0f);

					// z-negative (5)
					SetNormals(*pVertexBuffer, 5, 0.0f, 0.0f, -1.0f);
				}

				// Unlock the vertex buffer
				pVertexBuffer->Unlock();
			}

			// Get LOD level
			MeshLODLevel *pLODLevel = cMesh.GetLODLevel(nLODLevel);
			if (pLODLevel && pLODLevel->GetIndexBuffer()) {
				// Allocate and setup index buffer
				IndexBuffer *pIndexBuffer = pLODLevel->GetIndexBuffer();
				pIndexBuffer->SetElementTypeByMaximumIndex(pVertexBuffer->GetNumOfElements()-1);
				pIndexBuffer->Allocate(24, bStatic ? Usage::Static : Usage::Dynamic);
				if (pIndexBuffer->Lock(Lock::WriteOnly)) {
					for (int nSide=0; nSide<6; nSide++) {
						if (Order) {
							pIndexBuffer->SetData(nSide*4+0, nSide*4+3-2);
							pIndexBuffer->SetData(nSide*4+1, nSide*4+3-3);
							pIndexBuffer->SetData(nSide*4+2, nSide*4+3-1);
							pIndexBuffer->SetData(nSide*4+3, nSide*4+3-0);
						} else {
							pIndexBuffer->SetData(nSide*4+0, nSide*4+3-1);
							pIndexBuffer->SetData(nSide*4+1, nSide*4+3-0);
							pIndexBuffer->SetData(nSide*4+2, nSide*4+3-2);
							pIndexBuffer->SetData(nSide*4+3, nSide*4+3-3);
						}
					}

					// Unlock the index buffer
					pIndexBuffer->Unlock();
				}

				// Create the geometries
				Array<Geometry> &lstGeometries = *pLODLevel->GetGeometries();
				for (int i=0; i<6; i++) {
					Geometry &cGeometry = lstGeometries.Add();
					cGeometry.SetPrimitiveType(Primitive::TriangleStrip);
					cGeometry.SetStartIndex(i*4);
					cGeometry.SetIndexSize(4);
					if (MultiMaterials && i) {
						cMesh.AddMaterial(cMesh.GetRenderer()->GetRendererContext().GetMaterialManager().Create());
						cGeometry.SetMaterial(i);
					}
				}
			}
		} else { // No texture coordinates
			// Allocate and setup data
			pVertexBuffer->AddVertexAttribute(VertexBuffer::Position, 0, VertexBuffer::Float3);
			pVertexBuffer->Allocate(8, bStatic ? Usage::Static : Usage::Dynamic);
			if (pVertexBuffer->Lock(Lock::WriteOnly)) { // Setup vertices
				// 0
				float *pfVertices = static_cast<float*>(pVertexBuffer->GetData(0, VertexBuffer::Position));
				pfVertices[Vector3::X] = -vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] =  vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] = -vDimension.z + vOffset.z;

				// 1
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(1, VertexBuffer::Position));
				pfVertices[Vector3::X] =  vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] =  vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] = -vDimension.z + vOffset.z;

				// 2
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(2, VertexBuffer::Position));
				pfVertices[Vector3::X] =  vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] =  vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] =  vDimension.z + vOffset.z;

				// 3
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(3, VertexBuffer::Position));
				pfVertices[Vector3::X] = -vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] =  vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] =  vDimension.z + vOffset.z;

				// 4
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(4, VertexBuffer::Position));
				pfVertices[Vector3::X] = -vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] = -vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] = -vDimension.z + vOffset.z;

				// 5
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(5, VertexBuffer::Position));
				pfVertices[Vector3::X] =  vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] = -vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] = -vDimension.z + vOffset.z;

				// 6
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(6, VertexBuffer::Position));
				pfVertices[Vector3::X] =  vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] = -vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] =  vDimension.z + vOffset.z;

				// 7
				pfVertices = static_cast<float*>(pVertexBuffer->GetData(7, VertexBuffer::Position));
				pfVertices[Vector3::X] = -vDimension.x + vOffset.x;
				pfVertices[Vector3::Y] = -vDimension.y + vOffset.y;
				pfVertices[Vector3::Z] =  vDimension.z + vOffset.z;

				// Unlock the vertex buffer
				pVertexBuffer->Unlock();
			}

			// Get LOD level
			MeshLODLevel *pLODLevel = cMesh.GetLODLevel(nLODLevel);
			if (pLODLevel) {
				// Allocate and setup index buffer
				IndexBuffer *pIndexBuffer = pLODLevel->GetIndexBuffer();
				pIndexBuffer->SetElementTypeByMaximumIndex(pVertexBuffer->GetNumOfElements()-1);
				pIndexBuffer->Allocate(24, bStatic ? Usage::Static : Usage::Dynamic);
				if (pIndexBuffer->Lock(Lock::WriteOnly)) {
					if (Order) {
						// Left
						pIndexBuffer->SetData(0,  7);
						pIndexBuffer->SetData(1,  4);
						pIndexBuffer->SetData(2,  3);
						pIndexBuffer->SetData(3,  0);
						// Front
						pIndexBuffer->SetData(4,  1);
						pIndexBuffer->SetData(5,  0);
						pIndexBuffer->SetData(6,  5);
						pIndexBuffer->SetData(7,  4);
						// Right
						pIndexBuffer->SetData(8,  5);
						pIndexBuffer->SetData(9,  6);
						pIndexBuffer->SetData(10, 1);
						pIndexBuffer->SetData(11, 2);
						// Back
						pIndexBuffer->SetData(12, 6);
						pIndexBuffer->SetData(13, 7);
						pIndexBuffer->SetData(14, 2);
						pIndexBuffer->SetData(15, 3);
						// Top
						pIndexBuffer->SetData(16, 2);
						pIndexBuffer->SetData(17, 3);
						pIndexBuffer->SetData(18, 1);
						pIndexBuffer->SetData(19, 0);
						// Bottom
						pIndexBuffer->SetData(20, 5);
						pIndexBuffer->SetData(21, 4);
						pIndexBuffer->SetData(22, 6);
						pIndexBuffer->SetData(23, 7);
					} else {
						// Left
						pIndexBuffer->SetData(0,  3);
						pIndexBuffer->SetData(1,  0);
						pIndexBuffer->SetData(2,  7);
						pIndexBuffer->SetData(3,  4);
						// Front
						pIndexBuffer->SetData(4,  5);
						pIndexBuffer->SetData(5,  4);
						pIndexBuffer->SetData(6,  1);
						pIndexBuffer->SetData(7,  0);
						// Right
						pIndexBuffer->SetData(8,  1);
						pIndexBuffer->SetData(9,  2);
						pIndexBuffer->SetData(10, 5);
						pIndexBuffer->SetData(11, 6);
						// Back 
						pIndexBuffer->SetData(12, 2);
						pIndexBuffer->SetData(13, 3);
						pIndexBuffer->SetData(14, 6);
						pIndexBuffer->SetData(15, 7);
						// Top
						pIndexBuffer->SetData(16, 1);
						pIndexBuffer->SetData(17, 0);
						pIndexBuffer->SetData(18, 2);
						pIndexBuffer->SetData(19, 3);
						// Bottom
						pIndexBuffer->SetData(20, 6);
						pIndexBuffer->SetData(21, 7);
						pIndexBuffer->SetData(22, 5);
						pIndexBuffer->SetData(23, 4);
					}

					// Unlock the index buffer
					pIndexBuffer->Unlock();
				}

				// Create the geometries
				Array<Geometry> &lstGeometries = *pLODLevel->GetGeometries();
				for (int i=0; i<6; i++) {
					Geometry &cGeometry = lstGeometries.Add();
					cGeometry.SetPrimitiveType(Primitive::TriangleStrip);
					cGeometry.SetStartIndex(i*4);
					cGeometry.SetIndexSize(4);
				}
			}
		}
	}

	// Return the created mesh
	return &cMesh;
}