//------------------------------------------------------------------------------------------------
void VertexIndexToShape::addIndexData(IndexData* data, const unsigned int offset) {
    const unsigned int prev_size = mIndexCount;
    mIndexCount += (unsigned int)data->indexCount;

    unsigned int* tmp_ind = new unsigned int[mIndexCount];
    if(mIndexBuffer) {
        memcpy(tmp_ind, mIndexBuffer, sizeof(unsigned int) * prev_size);
        delete[] mIndexBuffer;
    }
    mIndexBuffer = tmp_ind;

    const unsigned int numTris = (unsigned int) data->indexCount / 3;
    HardwareIndexBufferSharedPtr ibuf = data->indexBuffer;
    const bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT);
    unsigned int index_offset = prev_size;

    if(use32bitindexes) {
        const unsigned int* pInt = static_cast<unsigned int*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
        for(unsigned int k = 0; k < numTris; ++k) {
            mIndexBuffer[index_offset ++] = offset + *pInt++;
            mIndexBuffer[index_offset ++] = offset + *pInt++;
            mIndexBuffer[index_offset ++] = offset + *pInt++;
        }
        ibuf->unlock();
    } else {
        const unsigned short* pShort = static_cast<unsigned short*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
        for(unsigned int k = 0; k < numTris; ++k) {
            mIndexBuffer[index_offset ++] = offset + static_cast<unsigned int>(*pShort++);
            mIndexBuffer[index_offset ++] = offset + static_cast<unsigned int>(*pShort++);
            mIndexBuffer[index_offset ++] = offset + static_cast<unsigned int>(*pShort++);
        }
        ibuf->unlock();
    }

}
	//---------------------------------------------------------------------
	void TangentSpaceCalc::processFaces(Result& result)
	{
		// Quick pre-check for triangle strips / fans
		for (OpTypeList::iterator ot = mOpTypes.begin(); ot != mOpTypes.end(); ++ot)
		{
			if (*ot != RenderOperation::OT_TRIANGLE_LIST)
			{
				// Can't split strips / fans
				setSplitMirrored(false);
				setSplitRotated(false);
			}
		}

		for (size_t i = 0; i < mIDataList.size(); ++i)
		{
			IndexData* i_in = mIDataList[i];
			RenderOperation::OperationType opType = mOpTypes[i];

			// Read data from buffers
			uint16 *p16 = 0;
			uint32 *p32 = 0;

			HardwareIndexBufferSharedPtr ibuf = i_in->indexBuffer;
			if (ibuf->getType() == HardwareIndexBuffer::IT_32BIT)
			{
				p32 = static_cast<uint32*>(
					ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
				// offset by index start
				p32 += i_in->indexStart;
			}
			else
			{
				p16 = static_cast<uint16*>(
					ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
				// offset by index start
				p16 += i_in->indexStart;
			}
			// current triangle
			size_t vertInd[3] = { 0, 0, 0 };
			// loop through all faces to calculate the tangents and normals
			size_t faceCount = opType == RenderOperation::OT_TRIANGLE_LIST ? 
				i_in->indexCount / 3 : i_in->indexCount - 2;
			for (size_t f = 0; f < faceCount; ++f)
			{
				bool invertOrdering = false;
				// Read 1 or 3 indexes depending on type
				if (f == 0 || opType == RenderOperation::OT_TRIANGLE_LIST)
				{
					vertInd[0] = p32? *p32++ : *p16++;
					vertInd[1] = p32? *p32++ : *p16++;
					vertInd[2] = p32? *p32++ : *p16++;
				}
				else if (opType == RenderOperation::OT_TRIANGLE_FAN)
				{
					// Element 0 always remains the same
					// Element 2 becomes element 1
					vertInd[1] = vertInd[2];
					// read new into element 2
					vertInd[2] = p32? *p32++ : *p16++;
				}
				else if (opType == RenderOperation::OT_TRIANGLE_STRIP)
				{
					// Shunt everything down one, but also invert the ordering on 
					// odd numbered triangles (== even numbered i's)
					// we interpret front as anticlockwise all the time but strips alternate
					if (f & 0x1)
					{
						// odd tris (index starts at 3, 5, 7)
						invertOrdering = true;
					}
					vertInd[0] = vertInd[1];
					vertInd[1] = vertInd[2];			
					vertInd[2] = p32? *p32++ : *p16++;
				}

				// deal with strip inversion of winding
				size_t localVertInd[3];
				localVertInd[0] = vertInd[0];
				if (invertOrdering)
				{
					localVertInd[1] = vertInd[2];
					localVertInd[2] = vertInd[1];
				}
				else
				{
					localVertInd[1] = vertInd[1];
					localVertInd[2] = vertInd[2];
				}


				// For each triangle
				//   Calculate tangent & binormal per triangle
				//   Note these are not normalised, are weighted by UV area
				Vector3 faceTsU, faceTsV, faceNorm;
				calculateFaceTangentSpace(localVertInd, faceTsU, faceTsV, faceNorm);

				// Skip invalid UV space triangles
				if (faceTsU.isZeroLength() || faceTsV.isZeroLength())
					continue;

				addFaceTangentSpaceToVertices(i, f, localVertInd, faceTsU, faceTsV, faceNorm, result);

			}


			ibuf->unlock();
		}

	}
	//---------------------------------------------------------------------
	void TangentSpaceCalc::extendBuffers(VertexSplits& vertexSplits)
	{
		if (!vertexSplits.empty())
		{
			// ok, need to increase the vertex buffer size, and alter some indexes

			// vertex buffers first
			VertexBufferBinding* newBindings = HardwareBufferManager::getSingleton().createVertexBufferBinding();
			const VertexBufferBinding::VertexBufferBindingMap& bindmap = 
				mVData->vertexBufferBinding->getBindings();
			for (VertexBufferBinding::VertexBufferBindingMap::const_iterator i = 
				bindmap.begin(); i != bindmap.end(); ++i)
			{
				HardwareVertexBufferSharedPtr srcbuf = i->second;
				// Derive vertex count from buffer not vertex data, in case using
				// the vertexStart option in vertex data
				size_t newVertexCount = srcbuf->getNumVertices() + vertexSplits.size();
				// Create new buffer & bind
				HardwareVertexBufferSharedPtr newBuf = 
					HardwareBufferManager::getSingleton().createVertexBuffer(
					srcbuf->getVertexSize(), newVertexCount, srcbuf->getUsage(), 
					srcbuf->hasShadowBuffer());
				newBindings->setBinding(i->first, newBuf);

				// Copy existing contents (again, entire buffer, not just elements referenced)
				newBuf->copyData(*(srcbuf.get()), 0, 0, srcbuf->getNumVertices() * srcbuf->getVertexSize(), true);

				// Split vertices, read / write from new buffer
				char* pBase = static_cast<char*>(newBuf->lock(HardwareBuffer::HBL_NORMAL));
				for (VertexSplits::iterator spliti = vertexSplits.begin(); 
					spliti != vertexSplits.end(); ++spliti)
				{
					const char* pSrcBase = pBase + spliti->first * newBuf->getVertexSize();
					char* pDstBase = pBase + spliti->second * newBuf->getVertexSize();
					memcpy(pDstBase, pSrcBase, newBuf->getVertexSize());
				}
				newBuf->unlock();

			}

			// Update vertex data
			// Increase vertex count according to num splits
			mVData->vertexCount += vertexSplits.size();
			// Flip bindings over to new buffers (old buffers released)
			HardwareBufferManager::getSingleton().destroyVertexBufferBinding(mVData->vertexBufferBinding);
			mVData->vertexBufferBinding = newBindings;

			// If vertex size requires 32bit index buffer
			if (mVData->vertexCount > 65536)
			{
				for (size_t i = 0; i < mIDataList.size(); ++i)
				{
					// check index size
					IndexData* idata = mIDataList[i];
					HardwareIndexBufferSharedPtr srcbuf = idata->indexBuffer;
					if (srcbuf->getType() == HardwareIndexBuffer::IT_16BIT)
					{
						size_t indexCount = srcbuf->getNumIndexes();

						// convert index buffer to 32bit.
						HardwareIndexBufferSharedPtr newBuf =
							HardwareBufferManager::getSingleton().createIndexBuffer(
							HardwareIndexBuffer::IT_32BIT, indexCount,
							srcbuf->getUsage(), srcbuf->hasShadowBuffer());

						uint16* pSrcBase = static_cast<uint16*>(srcbuf->lock(HardwareBuffer::HBL_NORMAL));
						uint32* pBase = static_cast<uint32*>(newBuf->lock(HardwareBuffer::HBL_NORMAL));

						size_t j = 0;
						while (j < indexCount)
						{
							*pBase++ = *pSrcBase++;
							++j;
						}

						srcbuf->unlock();
						newBuf->unlock();

						// assign new index buffer.
						idata->indexBuffer = newBuf;
					}
				}
			}
		}

	}
Exemplo n.º 4
0
    //---------------------------------------------------------------------
    void ProgressiveMesh::addWorkingData(const VertexData * vertexData, 
        const IndexData * indexData)
    {
        // Insert blank working data, then fill 
        mWorkingData.push_back(PMWorkingData());

        PMWorkingData& work = mWorkingData.back();

        // Build vertex list
		// Resize face list (this will always be this big)
		work.mFaceVertList.resize(vertexData->vertexCount);
		// Also resize common vert list to max, to avoid reallocations
		work.mVertList.resize(vertexData->vertexCount);

		// locate position element & hte buffer to go with it
		const VertexElement* posElem = vertexData->vertexDeclaration->findElementBySemantic(VES_POSITION);
		HardwareVertexBufferSharedPtr vbuf = 
			vertexData->vertexBufferBinding->getBuffer(posElem->getSource());
		// lock the buffer for reading
		unsigned char* pVertex = static_cast<unsigned char*>(
			vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
		float* pFloat;
		Vector3 pos;
		// Map for identifying duplicate position vertices
		typedef std::map<Vector3, size_t, vectorLess> CommonVertexMap;
		CommonVertexMap commonVertexMap;
		CommonVertexMap::iterator iCommonVertex;
		size_t numCommon = 0;
        size_t i = 0;
        for (i = 0; i < vertexData->vertexCount; ++i, pVertex += vbuf->getVertexSize())
        {
			posElem->baseVertexPointerToElement(pVertex, &pFloat);

            pos.x = *pFloat++;
            pos.y = *pFloat++;
            pos.z = *pFloat++;

			// Try to find this position in the existing map 
			iCommonVertex = commonVertexMap.find(pos);
			if (iCommonVertex == commonVertexMap.end())
			{
				// Doesn't exist, so create it
				PMVertex* commonVert = &(work.mVertList[numCommon]);
				commonVert->setDetails(pos, numCommon);
				commonVert->removed = false;
				commonVert->toBeRemoved = false;
				commonVert->seam = false;

				// Enter it in the map
				commonVertexMap.insert(CommonVertexMap::value_type(pos, numCommon) );
				// Increment common index
				++numCommon;

				work.mFaceVertList[i].commonVertex = commonVert;
				work.mFaceVertList[i].realIndex = i;
			}
			else
			{
				// Exists already, reference it
				PMVertex* existingVert = &(work.mVertList[iCommonVertex->second]);
				work.mFaceVertList[i].commonVertex = existingVert;
				work.mFaceVertList[i].realIndex = i;

				// Also tag original as a seam since duplicates at this location
				work.mFaceVertList[i].commonVertex->seam = true;

			}
			
        }
		vbuf->unlock();

		mNumCommonVertices = numCommon;

        // Build tri list
        size_t numTris = indexData->indexCount / 3;
		unsigned short* pShort;
		unsigned int* pInt;
		HardwareIndexBufferSharedPtr ibuf = indexData->indexBuffer;
		bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT);
		if (use32bitindexes)
		{
			pInt = static_cast<unsigned int*>(
				ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
		}
		else
		{
			pShort = static_cast<unsigned short*>(
				ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
		}
        work.mTriList.resize(numTris); // assumed tri list
        for (i = 0; i < numTris; ++i)
        {
			PMFaceVertex *v0, *v1, *v2;
			// use 32-bit index always since we're not storing
			unsigned int vindex = use32bitindexes? *pInt++ : *pShort++;
			v0 = &(work.mFaceVertList[vindex]);
			vindex = use32bitindexes? *pInt++ : *pShort++;
			v1 = &(work.mFaceVertList[vindex]);
			vindex = use32bitindexes? *pInt++ : *pShort++;
			v2 = &(work.mFaceVertList[vindex]);

			work.mTriList[i].setDetails(i, v0, v1, v2);

            work.mTriList[i].removed = false;

        }
		ibuf->unlock();

    }
Exemplo n.º 5
0
//-----------------------------------------------------------------------------------------
bool TemplateUtils::getMeshInformation(const Mesh* mesh,
                        size_t &vertex_count,
						OgreVector3Array &vertices,
                        size_t &index_count,
                        LongArray &indices,
						const Vector3 position,
                        const Quaternion &orient,
                        const Vector3 &scale)
{
    bool added_shared = false;
    size_t current_offset = 0;
    size_t shared_offset = 0;
    size_t next_offset = 0;
    size_t index_offset = 0;
 
    vertex_count = index_count = 0;
 
    // Calculate how many vertices and indices we're going to need
    for ( unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
    {
        SubMesh* submesh = mesh->getSubMesh(i);
		if(!submesh) {
			Exception(Exception::ERR_INTERNAL_ERROR,"Could not load submesh at index :" + i,"Mesh::getSubMesh");
		}
        // We only need to add the shared vertices once
        if(submesh->useSharedVertices)
        {
            if( !added_shared )
            {
                vertex_count += mesh->sharedVertexData->vertexCount;
                added_shared = true;
            }
        }
        else
        {
            vertex_count += submesh->vertexData->vertexCount;
        }
        // Add the indices
        index_count += submesh->indexData->indexCount;
    }
 
    // Allocate space for the vertices and indices

	// NO VALID DATA SHOULD BE PRESENT IN THE FOLLOWING 2 ARRAYS
	// UNTIL AFTER THE NEXT FOR LOOP

	/*
    vertices = new Ogre::Vector3 [vertex_count];
	std::vector<Ogre::Vector3> vertices [vertex_count];
    indices = new unsigned long [index_count];
	std::vector<long> indices [index_count];
	*/

	vertices.resize(vertex_count);
    indices.resize(index_count);

    added_shared = false;
 
    // Run through the submeshes again, adding the data into the arrays
    for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
    {
        SubMesh* submesh = mesh->getSubMesh(i);
		if(!submesh) {
			Exception(Exception::ERR_INTERNAL_ERROR,"Could not load submesh at index :" + i,"Mesh::getSubMesh");
		}
        VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;
 
        if ((!submesh->useSharedVertices) || (submesh->useSharedVertices && !added_shared))
        {
            if(submesh->useSharedVertices)
            {
                added_shared = true;
                shared_offset = current_offset;
            }
 
            const VertexElement* posElem =
                vertex_data->vertexDeclaration->findElementBySemantic(VES_POSITION);
 
            HardwareVertexBufferSharedPtr vbuf =
                vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
 
            unsigned char* vertex =
                static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
 
            // There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double
            //  as second argument. So make it float, to avoid trouble when Ogre::Real will
            //  be comiled/typedefed as double:
            //Ogre::Real* pReal;
            float* pReal;
 
            for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
            {
                posElem->baseVertexPointerToElement(vertex, &pReal);
                Vector3 pt(pReal[0], pReal[1], pReal[2]);
                vertices[current_offset + j] = (orient * (pt * scale)) + position;
            }
 
            vbuf->unlock();
            next_offset += vertex_data->vertexCount;
        }
 
        IndexData* index_data = submesh->indexData;
        size_t numTris = index_data->indexCount / 3;
        HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
 
        bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT);
 
        unsigned int* pLong = static_cast<unsigned int*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
        unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);
 
        size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset;
 
        if ( use32bitindexes )
        {
            for ( size_t k = 0; k < numTris*3; ++k)
            {
                indices[index_offset++] = pLong[k] + static_cast<unsigned long>(offset);
            }
        }
        else
        {
            for ( size_t k = 0; k < numTris*3; ++k)
            {
                indices[index_offset++] = static_cast<unsigned long>(pShort[k]) +
                                          static_cast<unsigned long>(offset);
            }
        }
 
        ibuf->unlock();
        current_offset = next_offset;
    }
	return true;
}
Exemplo n.º 6
0
void OgreToBulletMesh::getMeshInformation(MeshPtr mesh, unsigned& vertex_count, std::vector<Vector3>& vertices,
									unsigned& index_count, std::vector<unsigned>& indices, const Vector3& position,
									const Quaternion& orientation, const Vector3& scale)
{
	bool added_shared = false;
	unsigned current_offset = 0;
	unsigned shared_offset = 0;
	unsigned next_offset = 0;
	unsigned index_offset = 0;

	vertex_count = index_count = 0;

	for (uint16_t i = 0; i < mesh->getNumSubMeshes(); ++i) 
	{
		SubMesh* submesh = mesh->getSubMesh(i);
		if (submesh->useSharedVertices) 
		{
			if (!added_shared) 
			{
				vertex_count += mesh->sharedVertexData->vertexCount;
				added_shared = true;
			}
		}
		else
			vertex_count += submesh->vertexData->vertexCount;

		index_count += submesh->indexData->indexCount;
	}

	vertices.clear();
	vertices.reserve(vertex_count);
	indices.clear();
	indices.reserve(index_count);
	added_shared = false;

	for (uint16_t i = 0; i < mesh->getNumSubMeshes(); ++i) 
	{
		SubMesh* submesh = mesh->getSubMesh(i);
		VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;

		if (!submesh->useSharedVertices || (submesh->useSharedVertices && !added_shared)) 
		{
			if (submesh->useSharedVertices) 
			{
				added_shared = true;
				shared_offset = current_offset;
			}

			const VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(VertexElementSemantic::VES_POSITION);
			HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());

			uint8_t* vertex = (uint8_t*)vbuf->lock(HardwareBuffer::LockOptions::HBL_READ_ONLY);
			float* pReal;

			for (int j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize()) 
			{
				posElem->baseVertexPointerToElement(vertex, &pReal);
				Vector3 pt(pReal[0], pReal[1], pReal[2]);
				vertices[current_offset + j] = (orientation * (pt * scale)) + position;
			}
			vbuf->unlock();
			next_offset += vertex_data->vertexCount;
		}

		IndexData* index_data = submesh->indexData;
		uint numTris = index_data->indexCount / 3;
		HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;

		bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IndexType::IT_32BIT);

		uint* pLong = (uint*)ibuf->lock(HardwareBuffer::LockOptions::HBL_READ_ONLY);
		ushort* pShort = (ushort*)pLong;
		uint offset = submesh->useSharedVertices ? shared_offset : current_offset;
		if (use32bitindexes)
			for (int k = 0; k < index_data->indexCount; ++k)
				indices[index_offset++] = pLong[k] + offset;
		else
			for (int k = 0; k < index_data->indexCount; ++k)
				indices[index_offset++] = (uint)pShort[k] + (uint)offset;
		ibuf->unlock();
		current_offset = next_offset;
	}
}
Exemplo n.º 7
0
/// reads out mesh vertices and indices
/// must be called before rayintersect if the mesh has moved/deformed, probably every frame for animated meshes and mousepicking
/// calling it once for static meshes is enough
/// code is based on OgreOpCode MeshCollisionShape::convertMeshData
void	MeshShape::Update			(Ogre::Entity *pEntity) {
	// if (!pEntity) return;
	if (mpMesh.isNull()) return;
	if (pEntity && mbInitialised && !pEntity->hasSkeleton()) return; // no need to update static models every frame...
	mbInitialised = true;
	//printf("#### MeshShape::Update\n");
	//printf("MeshShape::Update skeleton=%d\n",pEntity->hasSkeleton()?1:0);
		
	//assert(pEntity->getMesh().get() == mpMesh.get() && "mesh pointer changed ! (ogrecaching/garbage collection?)");
	
	mlVertices.clear();
	mlIndices.clear();
		
	bool added_shared = false;
	size_t current_offset = 0;
	size_t shared_offset = 0;
	size_t next_offset = 0;
	size_t index_offset = 0;
	int numOfSubs = 0;

	// true if the entity is possibly animated (=has skeleton) , this means Update should be called every frame
	bool useSoftwareBlendingVertices = pEntity && pEntity->hasSkeleton();

	if (useSoftwareBlendingVertices)
	{
		pEntity->_updateAnimation();
	}

	// Run through the submeshes again, adding the data into the arrays
	for ( size_t i = 0; i < mpMesh->getNumSubMeshes(); ++i) {
		SubMesh* submesh = mpMesh->getSubMesh(i);
		bool useSharedVertices = submesh->useSharedVertices;

		//----------------------------------------------------------------
		// GET VERTEXDATA
		//----------------------------------------------------------------
		const VertexData * vertex_data;
		if(useSoftwareBlendingVertices)
				vertex_data = useSharedVertices ? pEntity->_getSkelAnimVertexData() : pEntity->getSubEntity(i)->_getSkelAnimVertexData();
		else	vertex_data = useSharedVertices ? mpMesh->sharedVertexData : submesh->vertexData;

		if((!useSharedVertices)||(useSharedVertices && !added_shared))
		{
			if(useSharedVertices)
			{
				added_shared = true;
				shared_offset = current_offset;
			}

			const VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
			
			HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());

			unsigned char* vertex =
				static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_READ_ONLY));

			// There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double
			//  as second argument. So make it float, to avoid trouble when Ogre::Real is
			//  comiled/typedefed as double:
			float* pReal;

			mlVertices.reserve(mlVertices.size()+vertex_data->vertexCount);
			for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
			{
				posElem->baseVertexPointerToElement(vertex, &pReal);
				if (mlVertices.size() == 0) {
					mvMin.x = mvMax.x = pReal[0];
					mvMin.y = mvMax.y = pReal[1];
					mvMin.z = mvMax.z = pReal[2];
				} else {
					if (mvMin.x > pReal[0]) mvMin.x = pReal[0];
					if (mvMin.y > pReal[1]) mvMin.y = pReal[1];
					if (mvMin.z > pReal[2]) mvMin.z = pReal[2];
					if (mvMax.x < pReal[0]) mvMax.x = pReal[0];
					if (mvMax.y < pReal[1]) mvMax.y = pReal[1];
					if (mvMax.z < pReal[2]) mvMax.z = pReal[2];
				}
				mlVertices.push_back(Vector3(pReal[0],pReal[1],pReal[2]));
			}

			vbuf->unlock();
			next_offset += vertex_data->vertexCount;
		}
		
		
		// TODO : GET TEXCOORD DATA
		// TODO : GET FACE-MATERIAL MAP, or at least material cound....
		// TODO : no need to update index, texcoord and material buffers for animation !
		
		// TODO : const VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES);
		// for texture alpha checking, VertexElementType should be VET_FLOAT2 

		//----------------------------------------------------------------
		// GET INDEXDATA
		//----------------------------------------------------------------
		IndexData* index_data = submesh->indexData;
		size_t numTris = index_data->indexCount / 3;
		HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;

		bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT);

		::uint32 *pLong = static_cast< ::uint32*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
		::uint16* pShort = reinterpret_cast< ::uint16*>(pLong);

		size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset;

		mlIndices.reserve(mlIndices.size()+3*numTris);
		if ( use32bitindexes )
		{
			for ( size_t k = 0; k < numTris*3; ++k)
			{
				mlIndices.push_back(pLong[k] + static_cast<int>(offset));
			}
		}
		else
		{
			for ( size_t k = 0; k < numTris*3; ++k)
			{
				mlIndices.push_back(static_cast<int>(pShort[k]) + static_cast<int>(offset));
			}
		}

		ibuf->unlock();

		current_offset = next_offset;
	}
	//mvMid = 0.5*(mvMin + mvMax);
	//mfBoundRad = 0.5 * (mvMax - mvMin).length();
}