Пример #1
0
bool HasDynamicBuffers(Model* model, unsigned lodLevel)
{
    unsigned numGeometries = model->GetNumGeometries();

    for (unsigned i = 0; i < numGeometries; ++i)
    {
        Geometry* geometry = model->GetGeometry(i, lodLevel);
        if (!geometry)
            continue;
        unsigned numVertexBuffers = geometry->GetNumVertexBuffers();
        for (unsigned j = 0; j < numVertexBuffers; ++j)
        {
            VertexBuffer* buffer = geometry->GetVertexBuffer(j);
            if (!buffer)
                continue;
            if (buffer->IsDynamic())
                return true;
        }
        IndexBuffer* buffer = geometry->GetIndexBuffer();
        if (buffer && buffer->IsDynamic())
            return true;
    }

    return false;
}
Пример #2
0
void Renderer::Draw(Renderable* pRenderable)
{
	DLOG();

	assert(pRenderable);
	if (pRenderable)
	{
		Geometry* pGeometry = pRenderable->GetGeometry();
		ShaderProgram* pShader = pRenderable->GetShader();
		assert(pShader && pGeometry);
		if (pShader && pGeometry)
		{
			pShader->Setup(*pRenderable);

			glDrawElements(GL_TRIANGLES, pGeometry->GetNumIndices(), GL_UNSIGNED_SHORT, pGeometry->GetIndexBuffer());
		}
	}
}
Пример #3
0
void CollisionShape::SetMesh(Mesh *mesh, SkeletonNode &skeletonNode, mat4 transformation)
{
	mat4 modelTransformation = transformation * skeletonNode.transformation;
	for (auto meshIndex : skeletonNode.meshes)
	{				
		Geometry *geometry = mesh->GetGeometries()[meshIndex];
		VertexBuffer *vertexBuffer = geometry->GetVertexBuffer();
		IndexBuffer *indexBuffer = geometry->GetIndexBuffer();
		auto &vertexData = vertexBuffer->GetShadowData();
		auto &indexData = indexBuffer->GetShadowData();
		if (indexData.empty() == false && vertexData.empty() == false)
		{
			unsigned int positionOffset = vertexBuffer->GetVertexAttributeOffset(VertexAttributeType::POSITION);
			for (unsigned int i = 0; i < indexData.size() / sizeof(unsigned int); i += 3)
			{
				unsigned int i0 = *((unsigned int *)&indexData[(i + 0) * sizeof(unsigned int)]);
				unsigned int i1 = *((unsigned int *)&indexData[(i + 1) * sizeof(unsigned int)]);
				unsigned int i2 = *((unsigned int *)&indexData[(i + 2) * sizeof(unsigned int)]);

				vec3 pos0 = modelTransformation * *((vec3 *)&vertexData[i0 * vertexBuffer->GetVertexSize() + positionOffset]);
				vec3 pos1 = modelTransformation * *((vec3 *)&vertexData[i1 * vertexBuffer->GetVertexSize() + positionOffset]);
				vec3 pos2 = modelTransformation * *((vec3 *)&vertexData[i2 * vertexBuffer->GetVertexSize() + positionOffset]);

				collisionMesh->triangles.push_back(CollisionTriangle(pos0, pos1, pos2));
				collisionMesh->boundingBox.Expand(pos0);
				collisionMesh->boundingBox.Expand(pos1);
				collisionMesh->boundingBox.Expand(pos2);
			}
		}
	}

	for (auto &c : skeletonNode.children)
	{
		SetMesh(mesh, c, modelTransformation);
	}
}
Пример #4
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;
}
Пример #5
0
bool Model::Save(Serializer& dest) const
{
    // Write ID
    if (!dest.WriteFileID("UMD2"))
        return false;

    // Write vertex buffers
    dest.WriteUInt(vertexBuffers_.Size());
    for (unsigned i = 0; i < vertexBuffers_.Size(); ++i)
    {
        VertexBuffer* buffer = vertexBuffers_[i];
        dest.WriteUInt(buffer->GetVertexCount());
        const PODVector<VertexElement>& elements = buffer->GetElements();
        dest.WriteUInt(elements.Size());
        for (unsigned j = 0; j < elements.Size(); ++j)
        {
            unsigned elementDesc = ((unsigned)elements[j].type_) |
                (((unsigned)elements[j].semantic_) << 8) |
                (((unsigned)elements[j].index_) << 16);
            dest.WriteUInt(elementDesc);
        }
        dest.WriteUInt(morphRangeStarts_[i]);
        dest.WriteUInt(morphRangeCounts_[i]);
        dest.Write(buffer->GetShadowData(), buffer->GetVertexCount() * buffer->GetVertexSize());
    }
    // Write index buffers
    dest.WriteUInt(indexBuffers_.Size());
    for (unsigned i = 0; i < indexBuffers_.Size(); ++i)
    {
        IndexBuffer* buffer = indexBuffers_[i];
        dest.WriteUInt(buffer->GetIndexCount());
        dest.WriteUInt(buffer->GetIndexSize());
        dest.Write(buffer->GetShadowData(), buffer->GetIndexCount() * buffer->GetIndexSize());
    }
    // Write geometries
    dest.WriteUInt(geometries_.Size());
    for (unsigned i = 0; i < geometries_.Size(); ++i)
    {
        // Write bone mappings
        dest.WriteUInt(geometryBoneMappings_[i].Size());
        for (unsigned j = 0; j < geometryBoneMappings_[i].Size(); ++j)
            dest.WriteUInt(geometryBoneMappings_[i][j]);

        // Write the LOD levels
        dest.WriteUInt(geometries_[i].Size());
        for (unsigned j = 0; j < geometries_[i].Size(); ++j)
        {
            Geometry* geometry = geometries_[i][j];
            dest.WriteFloat(geometry->GetLodDistance());
            dest.WriteUInt(geometry->GetPrimitiveType());
            dest.WriteUInt(LookupVertexBuffer(geometry->GetVertexBuffer(0), vertexBuffers_));
            dest.WriteUInt(LookupIndexBuffer(geometry->GetIndexBuffer(), indexBuffers_));
            dest.WriteUInt(geometry->GetIndexStart());
            dest.WriteUInt(geometry->GetIndexCount());
        }
    }

    // Write morphs
    dest.WriteUInt(morphs_.Size());
    for (unsigned i = 0; i < morphs_.Size(); ++i)
    {
        dest.WriteString(morphs_[i].name_);
        dest.WriteUInt(morphs_[i].buffers_.Size());

        // Write morph vertex buffers
        for (HashMap<unsigned, VertexBufferMorph>::ConstIterator j = morphs_[i].buffers_.Begin();
             j != morphs_[i].buffers_.End(); ++j)
        {
            dest.WriteUInt(j->first_);
            dest.WriteUInt(j->second_.elementMask_);
            dest.WriteUInt(j->second_.vertexCount_);

            // Base size: size of each vertex index
            unsigned vertexSize = sizeof(unsigned);
            // Add size of individual elements
            if (j->second_.elementMask_ & MASK_POSITION)
                vertexSize += sizeof(Vector3);
            if (j->second_.elementMask_ & MASK_NORMAL)
                vertexSize += sizeof(Vector3);
            if (j->second_.elementMask_ & MASK_TANGENT)
                vertexSize += sizeof(Vector3);

            dest.Write(j->second_.morphData_.Get(), vertexSize * j->second_.vertexCount_);
        }
    }

    // Write skeleton
    skeleton_.Save(dest);

    // Write bounding box
    dest.WriteBoundingBox(boundingBox_);

    // Write geometry centers
    for (unsigned i = 0; i < geometryCenters_.Size(); ++i)
        dest.WriteVector3(geometryCenters_[i]);

    // Write metadata
    if (HasMetadata())
    {
        File* destFile = dynamic_cast<File*>(&dest);
        if (destFile)
        {
            String xmlName = ReplaceExtension(destFile->GetName(), ".xml");

            SharedPtr<XMLFile> xml(new XMLFile(context_));
            XMLElement rootElem = xml->CreateRoot("model");
            SaveMetadataToXML(rootElem);

            File xmlFile(context_, xmlName, FILE_WRITE);
            xml->Save(xmlFile);
        }
        else
            URHO3D_LOGWARNING("Can not save model metadata when not saving into a file");
    }

    return true;
}
Пример #6
0
void DecalSet::GetFaces(Vector<PODVector<DecalVertex> >& faces, Drawable* target, unsigned batchIndex, const Frustum& frustum,
    const Vector3& decalNormal, float normalCutoff)
{
    // Try to use the most accurate LOD level if possible
    Geometry* geometry = target->GetLodGeometry(batchIndex, 0);
    if (!geometry || geometry->GetPrimitiveType() != TRIANGLE_LIST)
        return;

    const unsigned char* positionData = 0;
    const unsigned char* normalData = 0;
    const unsigned char* skinningData = 0;
    const unsigned char* indexData = 0;
    unsigned positionStride = 0;
    unsigned normalStride = 0;
    unsigned skinningStride = 0;
    unsigned indexStride = 0;

    IndexBuffer* ib = geometry->GetIndexBuffer();
    if (ib)
    {
        indexData = ib->GetShadowData();
        indexStride = ib->GetIndexSize();
    }

    // For morphed models positions, normals and skinning may be in different buffers
    for (unsigned i = 0; i < geometry->GetNumVertexBuffers(); ++i)
    {
        VertexBuffer* vb = geometry->GetVertexBuffer(i);
        if (!vb)
            continue;

        unsigned elementMask = vb->GetElementMask();
        unsigned char* data = vb->GetShadowData();
        if (!data)
            continue;

        if (elementMask & MASK_POSITION)
        {
            positionData = data;
            positionStride = vb->GetVertexSize();
        }
        if (elementMask & MASK_NORMAL)
        {
            normalData = data + vb->GetElementOffset(SEM_NORMAL);
            normalStride = vb->GetVertexSize();
        }
        if (elementMask & MASK_BLENDWEIGHTS)
        {
            skinningData = data + vb->GetElementOffset(SEM_BLENDWEIGHTS);
            skinningStride = vb->GetVertexSize();
        }
    }

    // Positions and indices are needed
    if (!positionData)
    {
        // As a fallback, try to get the geometry's raw vertex/index data
        const PODVector<VertexElement>* elements;
        geometry->GetRawData(positionData, positionStride, indexData, indexStride, elements);
        if (!positionData)
        {
            URHO3D_LOGWARNING("Can not add decal, target drawable has no CPU-side geometry data");
            return;
        }
    }

    if (indexData)
    {
        unsigned indexStart = geometry->GetIndexStart();
        unsigned indexCount = geometry->GetIndexCount();

        // 16-bit indices
        if (indexStride == sizeof(unsigned short))
        {
            const unsigned short* indices = ((const unsigned short*)indexData) + indexStart;
            const unsigned short* indicesEnd = indices + indexCount;

            while (indices < indicesEnd)
            {
                GetFace(faces, target, batchIndex, indices[0], indices[1], indices[2], positionData, normalData, skinningData,
                    positionStride, normalStride, skinningStride, frustum, decalNormal, normalCutoff);
                indices += 3;
            }
        }
        else
        // 32-bit indices
        {
            const unsigned* indices = ((const unsigned*)indexData) + indexStart;
            const unsigned* indicesEnd = indices + indexCount;

            while (indices < indicesEnd)
            {
                GetFace(faces, target, batchIndex, indices[0], indices[1], indices[2], positionData, normalData, skinningData,
                    positionStride, normalStride, skinningStride, frustum, decalNormal, normalCutoff);
                indices += 3;
            }
        }
    }
    else
    {
        // Non-indexed geometry
        unsigned indices = geometry->GetVertexStart();
        unsigned indicesEnd = indices + geometry->GetVertexCount();

        while (indices + 2 < indicesEnd)
        {
            GetFace(faces, target, batchIndex, indices, indices + 1, indices + 2, positionData, normalData, skinningData,
                positionStride, normalStride, skinningStride, frustum, decalNormal, normalCutoff);
            indices += 3;
        }
    }
}
Пример #7
0
bool Model::Save(Serializer& dest) const
{
    // Write ID
    if (!dest.WriteFileID("AMDL")) // atomic model specifier
        return false;

    // Write vertex buffers
    dest.WriteUInt(vertexBuffers_.Size());
    for (unsigned i = 0; i < vertexBuffers_.Size(); ++i)
    {
        VertexBuffer* buffer = vertexBuffers_[i];
        dest.WriteUInt(buffer->GetVertexCount());
        dest.WriteUInt(buffer->GetElementMask());
        dest.WriteUInt(morphRangeStarts_[i]);
        dest.WriteUInt(morphRangeCounts_[i]);
        dest.Write(buffer->GetShadowData(), buffer->GetVertexCount() * buffer->GetVertexSize());
    }
    // Write index buffers
    dest.WriteUInt(indexBuffers_.Size());
    for (unsigned i = 0; i < indexBuffers_.Size(); ++i)
    {
        IndexBuffer* buffer = indexBuffers_[i];
        dest.WriteUInt(buffer->GetIndexCount());
        dest.WriteUInt(buffer->GetIndexSize());
        dest.Write(buffer->GetShadowData(), buffer->GetIndexCount() * buffer->GetIndexSize());
    }
    // Write geometries
    dest.WriteUInt(geometries_.Size());
    for (unsigned i = 0; i < geometries_.Size(); ++i)
    {
        // Write bone mappings
        dest.WriteUInt(geometryBoneMappings_[i].Size());
        for (unsigned j = 0; j < geometryBoneMappings_[i].Size(); ++j)
            dest.WriteUInt(geometryBoneMappings_[i][j]);

        // Write the LOD levels
        dest.WriteUInt(geometries_[i].Size());
        for (unsigned j = 0; j < geometries_[i].Size(); ++j)
        {
            Geometry* geometry = geometries_[i][j];
            dest.WriteFloat(geometry->GetLodDistance());
            dest.WriteUInt(geometry->GetPrimitiveType());
            dest.WriteUInt(LookupVertexBuffer(geometry->GetVertexBuffer(0), vertexBuffers_));
            dest.WriteUInt(LookupIndexBuffer(geometry->GetIndexBuffer(), indexBuffers_));
            dest.WriteUInt(geometry->GetIndexStart());
            dest.WriteUInt(geometry->GetIndexCount());
        }
    }

    // Write morphs
    dest.WriteUInt(morphs_.Size());
    for (unsigned i = 0; i < morphs_.Size(); ++i)
    {
        dest.WriteString(morphs_[i].name_);
        dest.WriteUInt(morphs_[i].buffers_.Size());

        // Write morph vertex buffers
        for (HashMap<unsigned, VertexBufferMorph>::ConstIterator j = morphs_[i].buffers_.Begin();
             j != morphs_[i].buffers_.End(); ++j)
        {
            dest.WriteUInt(j->first_);
            dest.WriteUInt(j->second_.elementMask_);
            dest.WriteUInt(j->second_.vertexCount_);

            // Base size: size of each vertex index
            unsigned vertexSize = sizeof(unsigned);
            // Add size of individual elements
            if (j->second_.elementMask_ & MASK_POSITION)
                vertexSize += sizeof(Vector3);
            if (j->second_.elementMask_ & MASK_NORMAL)
                vertexSize += sizeof(Vector3);
            if (j->second_.elementMask_ & MASK_TANGENT)
                vertexSize += sizeof(Vector3);

            dest.Write(j->second_.morphData_.Get(), vertexSize * j->second_.vertexCount_);
        }
    }

    // Write skeleton
    skeleton_.Save(dest);

    // Write bounding box
    dest.WriteBoundingBox(boundingBox_);

    // Write geometry centers
    for (unsigned i = 0; i < geometryCenters_.Size(); ++i)
        dest.WriteVector3(geometryCenters_[i]);

    // ATOMIC BEGIN

    dest.WriteUInt(MODEL_VERSION);

    // animation resources

    ResourceRefList animList(Animation::GetTypeStatic());
    animList.names_.Resize(animationsResources_.Size());
    for (unsigned i = 0; i < animationsResources_.Size(); ++i)
        animList.names_[i] = GetResourceName(animationsResources_[i]);
    dest.WriteResourceRefList(animList);

    // ATOMIC END


    return true;
}
//=============================================================================
//=============================================================================
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 );
}