//---------------------------------------------------------------------
	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;
			
		}

	}
Example #2
0
    // ------------------------------------------------------------------------
    void ShadowCaster::extrudeVertices(
        const HardwareVertexBufferSharedPtr& vertexBuffer, 
        size_t originalVertexCount, const Vector4& light, Real extrudeDist)
    {
        assert (vertexBuffer->getVertexSize() == sizeof(float) * 3
            && "Position buffer should contain only positions!");

        // Extrude the first area of the buffer into the second area
        // Lock the entire buffer for writing, even though we'll only be
        // updating the latter because you can't have 2 locks on the same
        // buffer
        float* pSrc = static_cast<float*>(
            vertexBuffer->lock(HardwareBuffer::HBL_NORMAL));

        // TODO: We should add extra (ununsed) vertices ensure source and
        // destination buffer have same alignment for slight performance gain.
        float* pDest = pSrc + originalVertexCount * 3;

        OptimisedUtil::getImplementation()->extrudeVertices(
            light, extrudeDist,
            pSrc, pDest, originalVertexCount);

        vertexBuffer->unlock();

    }
Example #3
0
    //-----------------------------------------------------------------------
    size_t
    MeshInformer::getVertices(Vector3* pDst,
                              const VertexData* vertexData)
    {
        const VertexElement* posElem = vertexData->vertexDeclaration->findElementBySemantic(VES_POSITION);
        HardwareVertexBufferSharedPtr vbuf = vertexData->vertexBufferBinding->getBuffer(posElem->getSource());
        size_t vertex_stride = vbuf->getVertexSize();
        size_t vertexCount = vertexData->vertexCount;

        void* pBase = vbuf->lock(
            vertex_stride * vertexData->vertexStart,
            vertex_stride * vertexCount,
            HardwareBuffer::HBL_READ_ONLY);

        uchar* pSrc; posElem->baseVertexPointerToElement(pBase, &pSrc);
        for (size_t i = 0; i < vertexCount; ++i, pSrc += vertex_stride, ++pDst)
        {
            const float* pFloat = reinterpret_cast<const float*>(pSrc);
            pDst->x = pFloat[0];
            pDst->y = pFloat[1];
            pDst->z = pFloat[2];
        }

        vbuf->unlock();

        return vertexCount;
    }
Example #4
0
//--------------------------------------------------------------------------
void MeshLodTests::addProfile(LodConfig& config)
{
    // Get the first two vertices and put the edge into the profile
    // It doesn't matter if there is no such edge, because edges are removed and created dynamically.
    // The vertex positions should exist or you get an assert.
    VertexData* vertexData = config.mesh->getSubMesh(0)->vertexData;
    const VertexElement* elemPos = vertexData->vertexDeclaration->findElementBySemantic(VES_POSITION);
    HardwareVertexBufferSharedPtr vbuf = vertexData->vertexBufferBinding->getBuffer(elemPos->getSource());
    assert(vbuf->getNumVertices() > 2);
    unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
    float* pFloat;
    elemPos->baseVertexPointerToElement(vertex, &pFloat);
    ProfiledEdge edge;
    edge.src.x = *pFloat++;
    edge.src.y = *pFloat++;
    edge.src.z = *pFloat;
    vertex += vbuf->getVertexSize();
    elemPos->baseVertexPointerToElement(vertex, &pFloat);
    edge.dst.x = *pFloat++;
    edge.dst.y = *pFloat++;
    edge.dst.z = *pFloat;
    edge.cost = LodData::NEVER_COLLAPSE_COST;
    config.advanced.profile.push_back(edge);
    vbuf->unlock();
}
 //-----------------------------------------------------------------------
 HardwareVertexBufferSharedPtr 
 HardwareBufferManagerBase::makeBufferCopy(
     const HardwareVertexBufferSharedPtr& source,
     HardwareBuffer::Usage usage, bool useShadowBuffer)
 {
     return this->createVertexBuffer(
         source->getVertexSize(), 
         source->getNumVertices(),
         usage, useShadowBuffer);
 }
Example #6
0
void SkyManager::ModVertexAlpha(Entity* ent, unsigned int meshType)
{
    // Get the vertex colour buffer of this mesh
    const Ogre::VertexElement* ves_diffuse = ent->getMesh()->getSubMesh(0)->vertexData->vertexDeclaration->findElementBySemantic( Ogre::VES_DIFFUSE );
    HardwareVertexBufferSharedPtr colourBuffer = ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource());

    // Lock
    void* pData = colourBuffer->lock(HardwareBuffer::HBL_NORMAL);

    // Iterate over all vertices
    int vertex_size = colourBuffer->getVertexSize();
    float * currentVertex = NULL;
    for (unsigned int i=0; i<colourBuffer->getNumVertices(); ++i)
    {
        // Get a pointer to the vertex colour
        ves_diffuse->baseVertexPointerToElement( pData, &currentVertex );

        unsigned char alpha=0;
        if (meshType == 0) alpha = i%2 ? 0 : 255; // this is a cylinder, so every second vertex belongs to the bottom-most row
        else if (meshType == 1)
        {
            if (i>= 49 && i <= 64) alpha = 0; // bottom-most row
            else if (i>= 33 && i <= 48) alpha = 64; // second bottom-most row
            else alpha = 255;
        }

        uint8 tmpR = static_cast<uint8>(255);
        uint8 tmpG = static_cast<uint8>(255);
        uint8 tmpB = static_cast<uint8>(255);
        uint8 tmpA = static_cast<uint8>(alpha);

        // This does not matter since R and B are always 1.
        /*VertexElementType format = Root::getSingleton().getRenderSystem()->getColourVertexElementType();
        switch (format)
        {
        case VET_COLOUR_ARGB:
            std::swap(tmpR, tmpB);
            break;
        case VET_COLOUR_ABGR:
            break;
        default:
            break;
        }*/

        // Modify
        *((uint32*)currentVertex) = tmpR | (tmpG << 8) | (tmpB << 16) | (tmpA << 24);

        // Move to the next vertex
        pData = static_cast<unsigned char *> (pData) + vertex_size;
    }

    // Unlock
    ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource())->unlock();
}
  void DebugRectangle2D::setCorners(Real left, Real top, Real right, Real bottom)
  {
    VertexDeclaration * const decl = mRenderOp.vertexData->vertexDeclaration;
    const VertexElement* poselem = decl->findElementBySemantic(VES_POSITION);
    const VertexElement* colorelem = decl->findElementBySemantic(VES_DIFFUSE);

    HardwareVertexBufferSharedPtr vbuf =
    mRenderOp.vertexData->vertexBufferBinding->getBuffer(POSITION_BINDING);

    const size_t vertexSize = vbuf->getVertexSize ();
    float *pPos;
    RGBA *pColor;
    Root * const root = Root::getSingletonPtr();

    uchar* pMain = static_cast<uchar *>(
        vbuf->lock(HardwareBuffer::HBL_DISCARD));

//    #define V3(AX, AY, AZ, ACOLOR) poselem->baseVertexPointerToElement(pMain, &pPos); \
//            *pPos++ = AX; *pPos++ =  AY; *pPos++ =  AZ; \
//            pMain += vertexSize;

#define V3(A_X, A_Y, A_Z, ACOLOR) poselem->baseVertexPointerToElement(pMain, &pPos); \
			*pPos++ = static_cast <float> (A_X); \
			*pPos++ = static_cast <float> (A_Y); \
			*pPos++ = static_cast <float> (A_Z); \
            colorelem->baseVertexPointerToElement(pMain, &pColor); \
            root->convertColourValue (ACOLOR, pColor); \
            pMain += vertexSize;

    V3(left, top, -1.0f, ColourValue::White)
    V3(left, bottom, -1.0f, ColourValue::White)
    V3(right, bottom, -1.0f, ColourValue::White)
    V3(right, top, -1.0f, ColourValue::White)

    vbuf->unlock();

    HardwareIndexBufferSharedPtr iBuf = mRenderOp.indexData->indexBuffer;
    ushort* pIdx = static_cast<ushort*>(
        iBuf->lock(0, iBuf->getSizeInBytes(),HardwareBuffer::HBL_DISCARD));

    *pIdx++ = static_cast<ushort> (0); *pIdx++ = static_cast<ushort> (1); // line 1
    *pIdx++ = static_cast<ushort> (1); *pIdx++ = static_cast<ushort> (2);// line 2
    *pIdx++ = static_cast<ushort> (2); *pIdx++ = static_cast<ushort> (3);// line 3
    *pIdx++ = static_cast<ushort> (3); *pIdx++ = static_cast<ushort> (0);// line 4

    iBuf->unlock();
  }
Example #8
0
void SkyManager::ModVertexAlpha(Entity* ent, unsigned int meshType)
{
    // Get the vertex colour buffer of this mesh
    const Ogre::VertexElement* ves_diffuse = ent->getMesh()->getSubMesh(0)->vertexData->vertexDeclaration->findElementBySemantic( Ogre::VES_DIFFUSE );
    HardwareVertexBufferSharedPtr colourBuffer = ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource());

    // Lock
    void* pData = colourBuffer->lock(HardwareBuffer::HBL_NORMAL);

    // Iterate over all vertices
    int vertex_size = colourBuffer->getVertexSize();
    float * currentVertex = NULL;
    for (unsigned int i=0; i<colourBuffer->getNumVertices(); ++i)
    {
        // Get a pointer to the vertex colour
        ves_diffuse->baseVertexPointerToElement( pData, &currentVertex );

        unsigned char alpha=0;
        if (meshType == 0) alpha = i%2 ? 0 : 255; // this is a cylinder, so every second vertex belongs to the bottom-most row
        else if (meshType == 1)
        {
            if (i>= 49 && i <= 64) alpha = 0; // bottom-most row
            else if (i>= 33 && i <= 48) alpha = 64; // second bottom-most row
            else alpha = 255;
        }
        // NB we would have to swap R and B depending on rendersystem specific VertexElementType, but doesn't matter since they are both 1
        uint8 tmpR = static_cast<uint8>(255);
        uint8 tmpG = static_cast<uint8>(255);
        uint8 tmpB = static_cast<uint8>(255);
        uint8 tmpA = static_cast<uint8>(alpha);

        // Modify
        *((uint32*)currentVertex) = tmpR | (tmpG << 8) | (tmpB << 16) | (tmpA << 24);

        // Move to the next vertex
        pData = static_cast<unsigned char *> (pData) + vertex_size;
    }

    // Unlock
    ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource())->unlock();
}
AxisAlignedBox getVertexDataAabb( VertexData* vd, const Ogre::Matrix4& transform)
{
	AxisAlignedBox aabb;

	const VertexElement* ve = vd->vertexDeclaration->findElementBySemantic(VES_POSITION);
	HardwareVertexBufferSharedPtr vb = vd->vertexBufferBinding->getBuffer(ve->getSource());

	unsigned char* data = static_cast<unsigned char*>(
	vb->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));

	for (size_t i = 0; i < vd->vertexCount; ++i)
	{
		float* v;
		ve->baseVertexPointerToElement(data, &v);
		aabb.merge(transform * Ogre::Vector3(v[0], v[1], v[2]));

		data += vb->getVertexSize();
	}
	vb->unlock();

	return aabb;
}
	//---------------------------------------------------------------------
	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;
					}
				}
			}
		}

	}
    //---------------------------------------------------------------------
    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();

    }
Example #12
0
    void BtOgreSoftBody::updateOgreMesh()
    {
        Ogre::Node *ogreNode = mEntity->getParentNode();

        //printf("updateOgreMesh %d %s %s\n", internalId, mEntity->getName().c_str(), ogreNode->getName().c_str());

        MeshPtr mesh = mEntity->getMesh();
        Mesh::SubMeshIterator subMeshI = mesh->getSubMeshIterator();
        SubMesh* subMesh = NULL;

        VertexData* vData = NULL;
        VertexDeclaration* vDeclaration = NULL;
        const VertexElement* vPosElement = NULL;

        bool isSharedVerticesAdded = false;
        unsigned short bufferIndex = 0;
        HardwareVertexBufferSharedPtr vBuffer;

        // Can not do arithmetic operations on void*
        unsigned char* lockedMem = NULL;
        float* vPosition;

        btSoftBody::tNodeArray& btNodes = mSoftBody->m_nodes;
        //printf("Bullet nodes size %d\n", btNodes.size());

        int ogreVertexIdx = 0;
        btVector3 btPosOffset;

        while (subMeshI.hasMoreElements())
        {
            subMesh = subMeshI.getNext();

            if (subMesh->useSharedVertices)
            {

                if (isSharedVerticesAdded)
                {
                    continue;
                }

                vData = mesh->sharedVertexData;

                // We need to add shared vertices only once
                isSharedVerticesAdded = true;

            }
            else
            {
                vData = subMesh->vertexData;
            }

            vDeclaration = vData->vertexDeclaration;
            vPosElement = vDeclaration->findElementBySemantic(VES_POSITION);

            bufferIndex = vPosElement->getSource();
            vBuffer = vData->vertexBufferBinding->getBuffer(bufferIndex);

            // Lock the buffer before reading from it
            lockedMem = static_cast<unsigned char*>(vBuffer->lock(HardwareBuffer::HBL_DISCARD));

            // Read each vertex
            for (unsigned int i = 0; i < vData->vertexCount; ++i)
            {
                vPosElement->baseVertexPointerToElement(lockedMem, &vPosition);

                int idx = getBulletIndex(ogreVertexIdx);
                const btVector3 &btPos = btNodes[idx].m_x;

                if (ogreVertexIdx == 0)
                {
                    btPosOffset = btPos;
                }

                *vPosition++ = btPos.x() - btPosOffset.x();
                *vPosition++ = btPos.y() - btPosOffset.y();
                *vPosition = btPos.z() - btPosOffset.z();

                // Point to the next vertex
                lockedMem += vBuffer->getVertexSize();

                ogreVertexIdx++;
            }

            vBuffer->unlock();
        }

        ogreNode->setPosition(btPosOffset.x(), btPosOffset.y(), btPosOffset.z());

    }
Example #13
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;
	}
}
	void LodInputProviderMesh::addVertexData(LodData* data, VertexData* vertexData, bool useSharedVertexLookup)
	{
		if ((useSharedVertexLookup && !mSharedVertexLookup.empty())) { // We already loaded the shared vertex buffer.
			return;
		}
		OgreAssert(vertexData->vertexCount != 0, "");

		// Locate position element and the buffer to go with it.
		const VertexElement* elemPos = vertexData->vertexDeclaration->findElementBySemantic(VES_POSITION);

		// Only float supported.
		OgreAssert(elemPos->getSize() == 12, "");

		HardwareVertexBufferSharedPtr vbuf = vertexData->vertexBufferBinding->getBuffer(elemPos->getSource());

		// Lock the buffer for reading.
		unsigned char* vStart = static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
		unsigned char* vertex = vStart;
		size_t vSize = vbuf->getVertexSize();
		unsigned char* vEnd = vertex + vertexData->vertexCount * vSize;

		VertexLookupList& lookup = useSharedVertexLookup ? mSharedVertexLookup : mVertexLookup;
		lookup.clear();

		HardwareVertexBufferSharedPtr vNormalBuf;
		unsigned char* vNormal;
		size_t vNormSize;
		const VertexElement* elemNormal = vertexData->vertexDeclaration->findElementBySemantic(VES_NORMAL);

		data->mUseVertexNormals &= (elemNormal != NULL);
		if(data->mUseVertexNormals){
			if(elemNormal->getSource() == elemPos->getSource()){
				// Don't open the same buffer twice. Just copy the pointer.
				vNormalBuf = vbuf;
				vNormal = vStart;
			}  else {
				vNormalBuf = vertexData->vertexBufferBinding->getBuffer(elemNormal->getSource());
				vNormal = static_cast<unsigned char*>(vNormalBuf->lock(HardwareBuffer::HBL_READ_ONLY));
			}
			vNormSize = vNormalBuf->getVertexSize();
		}


		// Loop through all vertices and insert them to the Unordered Map.
		for (; vertex < vEnd; vertex += vSize) {
			float* pFloat;
			elemPos->baseVertexPointerToElement(vertex, &pFloat);
			data->mVertexList.push_back(LodData::Vertex());
			LodData::Vertex* v = &data->mVertexList.back();
			v->position.x = pFloat[0];
			v->position.y = pFloat[1];
			v->position.z = pFloat[2];
			std::pair<LodData::UniqueVertexSet::iterator, bool> ret;
			ret = data->mUniqueVertexSet.insert(v);
			if (!ret.second) {
				// Vertex position already exists.
				data->mVertexList.pop_back();
				v = *ret.first; // Point to the existing vertex.
				v->seam = true;
			} else {
#if OGRE_DEBUG_MODE
				// Needed for an assert, don't remove it.
				v->costHeapPosition = data->mCollapseCostHeap.end();
#endif
				v->seam = false;
			}
			lookup.push_back(v);

			if(data->mUseVertexNormals){
				elemNormal->baseVertexPointerToElement(vNormal, &pFloat);
				if (!ret.second) {
					if(v->normal.x != pFloat[0]){
						v->normal.x += pFloat[0];
						v->normal.y += pFloat[1];
						v->normal.z += pFloat[2];
						if(v->normal.isZeroLength()){
							v->normal = Vector3(1.0, 0.0, 0.0);
						}
						v->normal.normalise();
					}
				} else {
					v->normal.x = pFloat[0];
					v->normal.y = pFloat[1];
					v->normal.z = pFloat[2];
					v->normal.normalise();
				}
				vNormal += vNormSize;
			}
		}
		vbuf->unlock();
		if(data->mUseVertexNormals && elemNormal->getSource() != elemPos->getSource()){
			vNormalBuf->unlock();
		}
	}
    //---------------------------------------------------------------------
    void SubMesh::generateExtremes(size_t count)
    {
        extremityPoints.clear();

		if (count == 0)
			return;

        /* Currently this uses just one criteria: the points must be
         * as far as possible from each other. This at least ensures
         * that the extreme points characterise the submesh as
         * detailed as it's possible.
         */

        VertexData *vert = useSharedVertices ?
            parent->sharedVertexData : vertexData;
        const VertexElement *poselem = vert->vertexDeclaration->
            findElementBySemantic (VES_POSITION);
        HardwareVertexBufferSharedPtr vbuf = vert->vertexBufferBinding->
            getBuffer (poselem->getSource ());
        uint8 *vdata = (uint8 *)vbuf->lock (HardwareBuffer::HBL_READ_ONLY);
        size_t vsz = vbuf->getVertexSize ();

        vector<Cluster>::type boxes;
        boxes.reserve (count);

        // First of all, find min and max bounding box of the submesh
        boxes.push_back (Cluster ());

        if (indexData->indexCount > 0)
        {

            uint elsz = indexData->indexBuffer->getType () == HardwareIndexBuffer::IT_32BIT ?
                4 : 2;
            uint8 *idata = (uint8 *)indexData->indexBuffer->lock (
                indexData->indexStart * elsz, indexData->indexCount * elsz,
                HardwareIndexBuffer::HBL_READ_ONLY);

            for (size_t i = 0; i < indexData->indexCount; i++)
            {
                int idx = (elsz == 2) ? ((uint16 *)idata) [i] : ((uint32 *)idata) [i];
                boxes [0].mIndices.insert (idx);
            }
            indexData->indexBuffer->unlock ();

        }
        else
        {
            // just insert all indexes
            for (size_t i = vertexData->vertexStart; i < vertexData->vertexCount; i++)
            {
                boxes [0].mIndices.insert (static_cast<int>(i));
            }

        }

        boxes [0].computeBBox (poselem, vdata, vsz);

        // Remember the geometrical center of the submesh
        Vector3 center = (boxes [0].mMax + boxes [0].mMin) * 0.5;

        // Ok, now loop until we have as many boxes, as we need extremes
        while (boxes.size () < count)
        {
            // Find the largest box with more than one vertex :)
            Cluster *split_box = NULL;
            Real split_volume = -1;
            for (vector<Cluster>::type::iterator b = boxes.begin ();
                 b != boxes.end (); ++b)
            {
                if (b->empty ())
                    continue;
                Real v = b->volume ();
                if (v > split_volume)
                {
                    split_volume = v;
                    split_box = &*b;
                }
            }

            // If we don't have what to split, break
            if (!split_box)
                break;

            // Find the coordinate axis to split the box into two
            int split_axis = 0;
            Real split_length = split_box->mMax.x - split_box->mMin.x;
            for (int i = 1; i < 3; i++)
            {
                Real l = split_box->mMax [i] - split_box->mMin [i];
                if (l > split_length)
                {
                    split_length = l;
                    split_axis = i;
                }
            }

            // Now split the box into halves
            boxes.push_back (split_box->split (split_axis, poselem, vdata, vsz));
        }

        // Fine, now from every cluster choose the vertex that is most
        // distant from the geometrical center and from other extremes.
        for (vector<Cluster>::type::const_iterator b = boxes.begin ();
             b != boxes.end (); ++b)
        {
            Real rating = 0;
            Vector3 best_vertex;

            for (set<uint32>::type::const_iterator i = b->mIndices.begin ();
                 i != b->mIndices.end (); ++i)
            {
                float *v;
                poselem->baseVertexPointerToElement (vdata + *i * vsz, &v);

                Vector3 vv (v [0], v [1], v [2]);
                Real r = (vv - center).squaredLength ();

                for (vector<Vector3>::type::const_iterator e = extremityPoints.begin ();
                     e != extremityPoints.end (); ++e)
                    r += (*e - vv).squaredLength ();
                if (r > rating)
                {
                    rating = r;
                    best_vertex = vv;
                }
            }

            if (rating > 0)
                extremityPoints.push_back (best_vertex);
        }

        vbuf->unlock ();
    }
    SkeletonPtr MergeSkeleton::bake()
    {    
        MeshCombiner::getSingleton().log( 
             "Baking: New Skeleton started" );

        SkeletonPtr sp = SkeletonManager::getSingleton().create( "mergeSkeleton", 
             ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true );
        
        for( std::vector< Ogre::SkeletonPtr >::iterator it = m_Skeletons.begin();
             it != m_Skeletons.end(); ++it )
        {   
            if(  it == m_Skeletons.begin() )
            {
                MeshCombiner::getSingleton().log( 
                    "Baking: using " + (*it)->getName() + " as the base skeleton"   );

                MeshCombiner::getSingleton().log( 
                    "Baking: adding bones"   );
                Skeleton::BoneIterator bit = (*it)->getBoneIterator();
                while( bit.hasMoreElements() )
                {
                    Bone* bone = bit.getNext();
                    Bone* newbone = sp->createBone( bone->getName(), bone->getHandle() );
                    newbone->setScale( bone->getScale() );
                    newbone->setOrientation( bone->getOrientation() );
                    newbone->setPosition( bone->getPosition() );
                }
                MeshCombiner::getSingleton().log( 
                    "Baking: building bone hierarchy"   );
                // bone hierarchy
                bit = (*it)->getBoneIterator();
                while( bit.hasMoreElements() )
                {
                    Bone* bone = bit.getNext();
                    Node* pnode = bone->getParent();
                    if( pnode != NULL )
                    {
                        Bone* pbone = static_cast<Bone*>( pnode );
                        sp->getBone( pbone->getHandle() )->addChild( sp->getBone( bone->getHandle() ) );
                    }
                }
            }   

            MeshCombiner::getSingleton().log( 
                "Baking: adding animations for " + (*it)->getName() );

            // insert all animations
            for (unsigned short a=0; a < (*it)->getNumAnimations(); ++a )
            {
                Animation* anim = (*it)->getAnimation( a );
                Animation* newanim = sp->createAnimation( anim->getName(), anim->getLength() );

                if( anim->getNumNodeTracks() > 0 )
                    MeshCombiner::getSingleton().log( 
                        "Baking: adding node tracks" );
                for( unsigned short na=0; na < anim->getNumNodeTracks(); ++na )
                {
                    if( anim->hasNodeTrack( na ) )
                    {
                        NodeAnimationTrack* nat = anim->getNodeTrack( na );
                        NodeAnimationTrack* newnat = newanim->createNodeTrack( na );
                        // all key frames
                        for( unsigned short nf=0; nf < nat->getNumKeyFrames(); ++nf )
                        {
                            TransformKeyFrame* tkf = nat->getNodeKeyFrame( nf );
                            TransformKeyFrame* newtkf = newnat->createNodeKeyFrame( tkf->getTime() );
                            newtkf->setRotation( tkf->getRotation() );
                            newtkf->setTranslate( tkf->getTranslate() );
                            newtkf->setScale( tkf->getScale() );
                        }

                        newnat->setAssociatedNode( sp->getBone( nat->getHandle() ) );
                    }
                }

                if( anim->getNumNumericTracks() > 0 )
                    MeshCombiner::getSingleton().log( 
                        "Baking: adding numeric tracks" );
                for( unsigned short na=0; na < anim->getNumNumericTracks(); ++na )
                {
                    if( anim->hasNumericTrack( na ) )
                    {
                        NumericAnimationTrack* nat = anim->getNumericTrack( na );
                        NumericAnimationTrack* newnat = newanim->createNumericTrack( na );

                        // all key frames
                        for( unsigned short nf=0; nf < nat->getNumKeyFrames(); ++nf )
                        {
                            NumericKeyFrame* nkf = nat->getNumericKeyFrame( nf );
                            NumericKeyFrame* newnkf = newnat->createNumericKeyFrame( nkf->getTime() );
                            newnkf->setValue( nkf->getValue() );
                        }
                    }
                }

                if( anim->getNumVertexTracks() > 0 )
                    MeshCombiner::getSingleton().log( 
                        "Baking: adding vertex tracks" );
                for( unsigned short va=0; va < anim->getNumVertexTracks(); ++va )
                {
                    if( anim->hasVertexTrack( va ) )
                    {
                        VertexAnimationTrack* vat = anim->getVertexTrack( va );
                        VertexAnimationTrack* newvat = newanim->createVertexTrack( va, vat->getAnimationType() );

                        // all key frames
                        for( unsigned short nf=0; nf < vat->getNumKeyFrames(); ++nf )
                        {
                            // all morphs
                            VertexMorphKeyFrame* vmkf = vat->getVertexMorphKeyFrame( nf );
                            if( vmkf != NULL )
                            {
                                VertexMorphKeyFrame* newvmkf = newvat->createVertexMorphKeyFrame( vmkf->getTime() );
                                // @todo vertex buffer copying correct??
                                HardwareVertexBufferSharedPtr buf = vmkf->getVertexBuffer();
                                HardwareVertexBufferSharedPtr newbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
                                    buf->getVertexSize(), buf->getNumVertices(), buf->getUsage(), buf->hasShadowBuffer() );
                                newbuf->copyData( *buf.getPointer(), 0, 0, buf->getSizeInBytes() );
                            }

                            // all poses
                            VertexPoseKeyFrame* vpkf = vat->getVertexPoseKeyFrame( nf );
                            if( vpkf != NULL )
                            {
                                VertexPoseKeyFrame* newvpkf = newvat->createVertexPoseKeyFrame( vpkf->getTime() );
                                
                                VertexPoseKeyFrame::PoseRefIterator pit = vpkf->getPoseReferenceIterator();
                                while( pit.hasMoreElements() )
                                {
                                    VertexPoseKeyFrame::PoseRef pr = pit.getNext();
                                    newvpkf->addPoseReference( pr.poseIndex, pr.influence );
                                }
                            }

                        }
                    }
                }
            }
        }           

        return sp;
	}
Example #17
0
    void LodVertexBuffer::fillBuffer( Ogre::VertexData* data )
    {
        vertexCount = data->vertexCount;
        if (vertexCount > 0) {
            // Locate position element and the buffer to go with it.
            const VertexElement* elemPos = data->vertexDeclaration->findElementBySemantic(VES_POSITION);

            // Only float supported.
            OgreAssert(elemPos->getSize() == 12, "");

            HardwareVertexBufferSharedPtr vbuf = data->vertexBufferBinding->getBuffer(elemPos->getSource());
            vertexBuffer = Ogre::SharedPtr<Vector3>(new Vector3[vertexCount]);

            // Lock the buffer for reading.
            unsigned char* vStart = static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
            unsigned char* vertex = vStart;
            size_t vSize = vbuf->getVertexSize();

            const VertexElement* elemNormal = 0;
            HardwareVertexBufferSharedPtr vNormalBuf;
            unsigned char* vNormal = NULL;
            Vector3* pNormalOut = NULL;
            size_t vNormalSize = 0;
            bool useVertexNormals = true;
            elemNormal = data->vertexDeclaration->findElementBySemantic(VES_NORMAL);
            useVertexNormals = useVertexNormals && (elemNormal != 0);
            if(useVertexNormals){
                vertexNormalBuffer = Ogre::SharedPtr<Vector3>(new Vector3[vertexCount]);
                pNormalOut = vertexNormalBuffer.get();
                if(elemNormal->getSource() == elemPos->getSource()){
                    vNormalBuf = vbuf;
                    vNormal = vStart;
                }  else {
                    vNormalBuf = data->vertexBufferBinding->getBuffer(elemNormal->getSource());
                    assert(vNormalBuf->getSizeInBytes() == vbuf->getSizeInBytes());
                    assert(vNormalBuf->getVertexSize() == vbuf->getVertexSize());
                    vNormal = static_cast<unsigned char*>(vNormalBuf->lock(HardwareBuffer::HBL_READ_ONLY));
                }
                vNormalSize = vNormalBuf->getVertexSize();
            }

            // Loop through all vertices and insert them to the Unordered Map.
            Vector3* pOut = vertexBuffer.get();
            Vector3* pEnd = pOut + vertexCount;
            for (; pOut < pEnd; pOut++) {
                float* pFloat;
                elemPos->baseVertexPointerToElement(vertex, &pFloat);
                pOut->x = *pFloat;
                pOut->y = *(++pFloat);
                pOut->z = *(++pFloat);
                vertex += vSize;
                if(useVertexNormals){
                    elemNormal->baseVertexPointerToElement(vNormal, &pFloat);
                    pNormalOut->x = *pFloat;
                    pNormalOut->y = *(++pFloat);
                    pNormalOut->z = *(++pFloat);
                    pNormalOut++;
                    vNormal += vNormalSize;
                }
            }
            vbuf->unlock();
            if(elemNormal && elemNormal->getSource() != elemPos->getSource()){
                vNormalBuf->unlock();
            }
        }
    }
Example #18
0
//---------------------------------------------------------------------
void PlayPen_testMorphAnimationWithNormals::setupContent()
{
	// Cannot change this to true, not possible to use software morph animation + normals with stencil shadows
	// because the former requires pos & normals to be in the same buffer, and the
	// latter requires positions to be on their own.
	bool testStencil = false;

	if (testStencil)
		mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_MODULATIVE);

	mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
	Vector3 dir(-1, -1, 0.5);
	dir.normalise();
	Light* l = mSceneMgr->createLight("light1");
	l->setType(Light::LT_DIRECTIONAL);
	l->setDirection(dir);

	
	MeshPtr mesh = MeshManager::getSingleton().load("sphere.mesh", 
		ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
	
	String morphName = "testmorphwithnormals.mesh";
	mesh = mesh->clone(morphName);

	SubMesh* sm = mesh->getSubMesh(0);
	// Re-organise geometry since this mesh has no animation and all 
	// vertex elements are packed into one buffer
	VertexDeclaration* newDecl = 
		sm->vertexData->vertexDeclaration->getAutoOrganisedDeclaration(false, true, true);
	sm->vertexData->reorganiseBuffers(newDecl);
	if (testStencil)
		sm->vertexData->prepareForShadowVolume(); // need to re-prep since reorganised
	// get the position buffer (which should now be separate);
	const VertexElement* posElem = 
		sm->vertexData->vertexDeclaration->findElementBySemantic(VES_POSITION);
	HardwareVertexBufferSharedPtr origbuf = 
		sm->vertexData->vertexBufferBinding->getBuffer(
			posElem->getSource());

	// Create a new position & normal buffer with updated values
	HardwareVertexBufferSharedPtr newbuf = 
		HardwareBufferManager::getSingleton().createVertexBuffer(
			VertexElement::getTypeSize(VET_FLOAT3) * 2,
			sm->vertexData->vertexCount, 
			HardwareBuffer::HBU_STATIC, true);
	float* pSrc = static_cast<float*>(origbuf->lock(HardwareBuffer::HBL_READ_ONLY));
	float* pDst = static_cast<float*>(newbuf->lock(HardwareBuffer::HBL_DISCARD));

	// Make the sphere turn into a cube
	// Do this just by clamping each of the directions (we shrink it)
	float cubeDimension = 0.3f * mesh->getBoundingSphereRadius();
	size_t srcSkip = origbuf->getVertexSize() / sizeof(float) - 3;
	for (size_t v = 0; v < sm->vertexData->vertexCount; ++v)
	{
		// x/y/z position
		Vector3 pos;
		for (int d = 0; d < 3; ++d)
		{
			if (*pSrc >= 0)
			{
				pos.ptr()[d] = std::min(cubeDimension, *pSrc++);
			}
			else 
			{
				pos.ptr()[d] = std::max(-cubeDimension, *pSrc++);			
			}
			*pDst++ = pos.ptr()[d];
		}
		
		// normal
		// this should point along the major axis
		// unfortunately since vertices are not duplicated at edges there will be
		// some inaccuracy here but the most important thing is to add sharp edges
		Vector3 norm = pos.normalisedCopy();
		norm = norm.primaryAxis();
		*pDst++ = norm.x;
		*pDst++ = norm.y;
		*pDst++ = norm.z;

		pSrc += srcSkip;

	}

	origbuf->unlock();
	newbuf->unlock();
	
	// create a morph animation
	Animation* anim = mesh->createAnimation("testAnim", 10.0f);
	VertexAnimationTrack* vt = anim->createVertexTrack(1, sm->vertexData, VAT_MORPH);
	// re-use start positions for frame 0
	VertexMorphKeyFrame* kf = vt->createVertexMorphKeyFrame(0);
	kf->setVertexBuffer(origbuf);

	// Use translated buffer for mid frame
	kf = vt->createVertexMorphKeyFrame(4.0f);
	kf->setVertexBuffer(newbuf);

	// Pause there
	kf = vt->createVertexMorphKeyFrame(6.0f);
	kf->setVertexBuffer(newbuf);
	
	// re-use start positions for final frame
	kf = vt->createVertexMorphKeyFrame(10.0f);
	kf->setVertexBuffer(origbuf);

	// Export the mesh
	DataStreamPtr stream = Root::getSingleton().createFileStream(morphName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true);
	MeshSerializer ser;
	ser.exportMesh(mesh.get(), stream);
	stream->close();
	
	// Unload old mesh to force reload
	MeshManager::getSingleton().remove(mesh->getHandle());
	mesh->unload();
	mesh.setNull();

	Entity* e = mSceneMgr->createEntity("test", morphName);
	mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
	AnimationState* animState = e->getAnimationState("testAnim");
	animState->setEnabled(true);
	animState->setWeight(1.0f);
	mAnimStateList.push_back(animState);

	e = mSceneMgr->createEntity("test2", morphName);
	mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(200,0,0))->attachObject(e);
	// test hardware morph
	e->setMaterialName("Examples/HardwareMorphAnimationWithNormals");
	animState = e->getAnimationState("testAnim");
	animState->setEnabled(true);
	animState->setWeight(1.0f);
	mAnimStateList.push_back(animState);

	mCamera->setNearClipDistance(0.5);
	mCamera->setPosition(0,100,-400);
	mCamera->lookAt(Vector3::ZERO);
	//mSceneMgr->setShowDebugShadows(true);

	Plane plane;
	plane.normal = Vector3::UNIT_Y;
	plane.d = 200;
	MeshManager::getSingleton().createPlane("Myplane",
		ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, plane,
		1500,1500,10,10,true,1,5,5,Vector3::UNIT_Z);
	Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
	pPlaneEnt->setMaterialName("2 - Default");
	pPlaneEnt->setCastShadows(false);
	mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
	
}
void MeshSerializerTests::assertVertexDataClone(VertexData* a, VertexData* b, MeshVersion version /*= MESH_VERSION_LATEST*/)
{
	CPPUNIT_ASSERT((a == NULL) == (b == NULL));
	if (a) {
		// compare bindings
		{
			const VertexBufferBinding::VertexBufferBindingMap& aBindings = a->vertexBufferBinding->getBindings();
			const VertexBufferBinding::VertexBufferBindingMap& bBindings = b->vertexBufferBinding->getBindings();
			CPPUNIT_ASSERT(aBindings.size() == bBindings.size());
			typedef VertexBufferBinding::VertexBufferBindingMap::const_iterator bindingIterator;
			bindingIterator aIt = aBindings.begin();
			bindingIterator aEndIt = aBindings.end();
			bindingIterator bIt = bBindings.begin();
			for (; aIt != aEndIt; aIt++, bIt++) {
				CPPUNIT_ASSERT(aIt->first == bIt->first);
				CPPUNIT_ASSERT((aIt->second.get() == NULL) == (bIt->second.get() == NULL));
				if (a) {
					CPPUNIT_ASSERT(aIt->second->getManager() == bIt->second->getManager());
					CPPUNIT_ASSERT(aIt->second->getNumVertices() == bIt->second->getNumVertices());
				}
			}
		}

		{
			const VertexDeclaration::VertexElementList& aElements = a->vertexDeclaration->getElements();
			const VertexDeclaration::VertexElementList& bElements = a->vertexDeclaration->getElements();
			CPPUNIT_ASSERT(aElements.size() == bElements.size());
			typedef VertexDeclaration::VertexElementList::const_iterator bindingIterator;
			bindingIterator aIt = aElements.begin();
			bindingIterator aEndIt = aElements.end();
			bindingIterator bIt;
			for (; aIt != aEndIt; aIt++) {
				bIt = std::find(bElements.begin(), bElements.end(), *aIt);
				CPPUNIT_ASSERT(bIt != bElements.end());
#ifndef OGRE_TEST_XMLSERIALIZER
				const VertexElement& aElem = *aIt;
				const VertexElement& bElem = *bIt;
				HardwareVertexBufferSharedPtr abuf = a->vertexBufferBinding->getBuffer(aElem.getSource());
				HardwareVertexBufferSharedPtr bbuf = b->vertexBufferBinding->getBuffer(bElem.getSource());
				unsigned char* avertex = static_cast<unsigned char*>(abuf->lock(HardwareBuffer::HBL_READ_ONLY));
				unsigned char* bvertex = static_cast<unsigned char*>(bbuf->lock(HardwareBuffer::HBL_READ_ONLY));
				size_t avSize = abuf->getVertexSize();
				size_t bvSize = bbuf->getVertexSize();
				size_t elemSize = VertexElement::getTypeSize(aElem.getType());
				unsigned char* avEnd = avertex + a->vertexCount * avSize;
				bool error = false;
				for (; avertex < avEnd; avertex += avSize, bvertex += bvSize) {
					float* afloat, * bfloat;
					aElem.baseVertexPointerToElement(avertex, &afloat);
					bElem.baseVertexPointerToElement(bvertex, &bfloat);
					error |= (memcmp(afloat, bfloat, elemSize) != 0);
				}
				abuf->unlock();
				bbuf->unlock();
				CPPUNIT_ASSERT(!error && "Content of vertex buffer differs!");
#endif /* ifndef OGRE_TEST_XMLSERIALIZER */
			}

		}

		CPPUNIT_ASSERT(a->vertexStart == b->vertexStart);
		CPPUNIT_ASSERT(a->vertexCount == b->vertexCount);
		CPPUNIT_ASSERT(a->hwAnimDataItemsUsed == b->hwAnimDataItemsUsed);

		// Compare hwAnimationData
		{
			const VertexData::HardwareAnimationDataList& aAnimData = a->hwAnimationDataList;
			const VertexData::HardwareAnimationDataList& bAnimData = b->hwAnimationDataList;
			CPPUNIT_ASSERT(aAnimData.size() == bAnimData.size());
			typedef VertexData::HardwareAnimationDataList::const_iterator bindingIterator;
			bindingIterator aIt = aAnimData.begin();
			bindingIterator aEndIt = aAnimData.end();
			bindingIterator bIt = bAnimData.begin();
			for (; aIt != aEndIt; aIt++, bIt++) {
				CPPUNIT_ASSERT(aIt->parametric == bIt->parametric);
				CPPUNIT_ASSERT(aIt->targetBufferIndex == bIt->targetBufferIndex);
			}
		}
	}
}
    void PlanetFilter::initVertexData(int lod, int x, int y, int size, int border) {
        // Prepare new vertex buffer
        VertexData* vertexData = mRenderOp.vertexData;
        
        VertexDeclaration *vertexDeclaration = vertexData->vertexDeclaration;
        size_t offset = 0;
        vertexDeclaration->addElement(0, offset, VET_FLOAT3, VES_POSITION);
        offset += VertexElement::getTypeSize(VET_FLOAT3);
        vertexDeclaration->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
        offset += VertexElement::getTypeSize(VET_FLOAT2);
        vertexDeclaration->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 1);
        offset += VertexElement::getTypeSize(VET_FLOAT2);
        
        HardwareVertexBufferSharedPtr vertexBuffer = HardwareBufferManager::getSingleton()
        .createVertexBuffer(offset, 4, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
        
        vertexData->vertexBufferBinding->setBinding(0, vertexBuffer);
        vertexData->vertexCount = 0;
        
        // Get offsets / pointers into vertex declaration
        const VertexElement* poselem = vertexDeclaration->findElementBySemantic(VES_POSITION);
        const VertexElement* texelem1 = vertexDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES, 0);
        const VertexElement* texelem2 = vertexDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES, 1);
        
        unsigned char* pBase = static_cast<unsigned char*>(vertexBuffer->lock(HardwareBuffer::HBL_DISCARD));
        
        // Calculate tile's position in the virtual cubemap
        Real tileSize = 2.0 / (1 << lod);
        Real borderSize = (Real(border) / size) * tileSize;
        Real left = -1.f + tileSize * x - borderSize;
        Real bottom = -1.f + tileSize * ((1 << lod) - y - 1) - borderSize;
        Real right = left + tileSize + borderSize * 2.0;
        Real top = bottom + tileSize + borderSize * 2.0;

        // Draw a full size quad.
        for (int y = 0; y < 2; ++y) {
            for (int x = 0; x < 2; ++x) {
                float* pPos;
                float* pTex1;
                float* pTex2;
                poselem->baseVertexPointerToElement(pBase, &pPos);
                texelem1->baseVertexPointerToElement(pBase, &pTex1);
                texelem2->baseVertexPointerToElement(pBase, &pTex2);

                Vector3 point = Vector3(x ? -1.0f : 1.0f, y ? -1.0f : 1.0f, -1.0f);

                *pTex1++ = x ? 0.0f : 1.0f; 
                *pTex1++ = y ? 1.0f : 0.0f; 
                // Mystery handedness change, invert y.
                *pTex2++ = x ? left : right;
                *pTex2++ = y ? bottom : top;

                //point = faceTransform * point;
                //point = point * uvScale;
                
                *pPos++ = point.x;
                *pPos++ = point.y;
                *pPos++ = point.z;
                
                pBase += vertexBuffer->getVertexSize();
            }
        }
        
        vertexData->vertexCount += 4;
        
        vertexBuffer->unlock();
    }
Example #21
0
void
CollisionManager::addMesh(MeshPtr pMesh)
{
  using ColDet::CollisionModel3D;
  
  if(modelMap.find(pMesh->getName()) != modelMap.end()) return;
  
  unsigned int numVertices = 0; 
  unsigned int numIndices = 0;  

  // create a new collision model 
  CollisionModel3D* mCollisionModel = ColDet::newCollisionModel3D(); 

  unsigned int i = 0, j = 0; 
  for(i = 0; i < pMesh->getNumSubMeshes(); i++) 
  { 
    SubMesh* pSubMesh = pMesh->getSubMesh(i);        
    if(pSubMesh->vertexData != NULL)
      numVertices += pSubMesh->vertexData->vertexCount;    
    if(pSubMesh->indexData != NULL)
      numIndices += pSubMesh->indexData->indexCount; 
  }  

  // set the number of triangles 
  mCollisionModel->setTriangleNumber(numIndices / 3); 

  // Count the number of vertices and incides so we can Set them 
  unsigned int indexCount = 0, vertListCount = 0;  

  for(i = 0; i < pMesh->getNumSubMeshes(); i++) 
  { 
    SubMesh* pSubMesh = pMesh->getSubMesh(i);    

    if(pSubMesh->vertexData != NULL) {
      const VertexElement* elem = pSubMesh->vertexData->vertexDeclaration->findElementBySemantic(VES_POSITION); 
      HardwareVertexBufferSharedPtr vbuf = pSubMesh->vertexData->vertexBufferBinding->getBuffer(elem->getSource()); 
      
      Real* test = new Real[pSubMesh->vertexData->vertexCount * 3]; 
      float* pDest = test; 
      
      unsigned char* pData = static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_READ_ONLY)); 
      
      for (j = 0; j < pSubMesh->vertexData->vertexCount; j++) { 
        float* pFloat; 
        elem->baseVertexPointerToElement(pData, &pFloat); 
        
        *pDest++ = *pFloat++; 
        *pDest++ = *pFloat++; 
        *pDest++ = *pFloat++; 
        
        pData += vbuf->getVertexSize(); 
      } 
      
      vbuf->unlock(); 

      if(pSubMesh->indexData != NULL) {
        HardwareIndexBufferSharedPtr ibuf = pSubMesh->indexData->indexBuffer; 
        unsigned short* test2 = new unsigned short[pSubMesh->indexData->indexCount];  
        
        ibuf->readData(0, ibuf->getSizeInBytes(), test2); 
        
        float* tri[3];
        
        for (int j = 0; j < pSubMesh->indexData->indexCount; j = j + 3) {      
          for (int k = 0; k < 3; k++) {          
            tri[k] = new float[3]; 
            tri[k][0] =  test[(test2[j + k] * 3) + 0]; 
            tri[k][1] =  test[(test2[j + k] * 3) + 1]; 
            tri[k][2] =  test[(test2[j + k] * 3) + 2]; 
          } 
          mCollisionModel->addTriangle(tri[0], tri[1], tri[2]);      
          
          delete[] tri[0]; 
          delete[] tri[1]; 
          delete[] tri[2]; 
        } 
        delete[] test2;    
      } 
      delete[] test; 
    }
  }
    
  mCollisionModel->finalize();  

  modelMap[pMesh->getName()] = mCollisionModel;
}
static MeshPtr importObject(QDataStream &stream)
{
    using namespace Ogre;

    QVector4D bbMin, bbMax;
    stream >> bbMin >> bbMax;

    float distance, distanceSquared; // Here's a bug for you: writes "double"'s instead of floats
    stream >> distanceSquared >> distance;

    MeshPtr ogreMesh = MeshManager::getSingleton().createManual("conversion",
                                                               ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);

    int vertexCount, indexCount;
    stream >> vertexCount >> indexCount;

    VertexData *vertexData = new VertexData();
    ogreMesh->sharedVertexData = vertexData;

    LogManager::getSingleton().logMessage("Reading geometry...");
    VertexDeclaration* decl = vertexData->vertexDeclaration;
    VertexBufferBinding* bind = vertexData->vertexBufferBinding;
    unsigned short bufferId = 0;

    // Information for calculating bounds
    Vector3 min = Vector3::ZERO, max = Vector3::UNIT_SCALE, pos = Vector3::ZERO;
    Real maxSquaredRadius = -1;
    bool firstVertex = true;

    /*
      Create a vertex definition for our buffer
      */
    size_t offset = 0;

    const VertexElement &positionElement = decl->addElement(bufferId, offset, VET_FLOAT3, VES_POSITION);
    offset += VertexElement::getTypeSize(VET_FLOAT3);

    const VertexElement &normalElement = decl->addElement(bufferId, offset, VET_FLOAT3, VES_NORMAL);
    offset += VertexElement::getTypeSize(VET_FLOAT3);

    // calculate how many vertexes there actually are
    vertexData->vertexCount = vertexCount;

    // Now create the vertex buffer
    HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().
            createVertexBuffer(offset, vertexData->vertexCount,
                               HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);

    // Bind it
    bind->setBinding(bufferId, vbuf);

    // Lock it
    unsigned char *pVert = static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_DISCARD));
    unsigned char *pVertStart = pVert;

    QVector<float> positions;
    positions.reserve(vertexCount * 3);

    // Iterate over all children (vertexbuffer entries)
    for (int i = 0; i < vertexCount; ++i) {
        float *pFloat;

        QVector4D vertex;
        stream >> vertex;
		vertex.setZ(vertex.z() * -1);

        /* Copy over the position */
        positionElement.baseVertexPointerToElement(pVert, &pFloat);
        *(pFloat++) = (float)vertex.x();
        *(pFloat++) = (float)vertex.y();
        *(pFloat++) = (float)vertex.z();

        positions.append(vertex.x());
        positions.append(vertex.y());
        positions.append(vertex.z());

        /* While we're at it, calculate the bounding sphere */
        pos.x = vertex.x();
        pos.y = vertex.y();
        pos.z = vertex.z();

        if (firstVertex) {
            min = max = pos;
            maxSquaredRadius = pos.squaredLength();
            firstVertex = false;
        } else {
            min.makeFloor(pos);
            max.makeCeil(pos);
            maxSquaredRadius = qMax(pos.squaredLength(), maxSquaredRadius);
        }

        pVert += vbuf->getVertexSize();
    }

    // Set bounds
    const AxisAlignedBox& currBox = ogreMesh->getBounds();
    Real currRadius = ogreMesh->getBoundingSphereRadius();
    if (currBox.isNull())
    {
        //do not pad the bounding box
        ogreMesh->_setBounds(AxisAlignedBox(min, max), false);
        ogreMesh->_setBoundingSphereRadius(Math::Sqrt(maxSquaredRadius));
    }
    else
    {
        AxisAlignedBox newBox(min, max);
        newBox.merge(currBox);
        //do not pad the bounding box
        ogreMesh->_setBounds(newBox, false);
        ogreMesh->_setBoundingSphereRadius(qMax(Math::Sqrt(maxSquaredRadius), currRadius));
    }

    /*
       Create faces
     */
    // All children should be submeshes
    SubMesh* sm = ogreMesh->createSubMesh();
    sm->setMaterialName("clippingMaterial");
    sm->operationType = RenderOperation::OT_TRIANGLE_LIST;
    sm->useSharedVertices = true;

    // tri list
    sm->indexData->indexCount = indexCount;

    // Allocate space
    HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
            createIndexBuffer(
                HardwareIndexBuffer::IT_16BIT,
                sm->indexData->indexCount,
                HardwareBuffer::HBU_DYNAMIC,
                false);
    sm->indexData->indexBuffer = ibuf;

    unsigned short *pShort = static_cast<unsigned short*>(ibuf->lock(HardwareBuffer::HBL_DISCARD));

    QVector<EdgeData::Triangle> triangles(indexCount / 3);

    for (int i = 0; i < indexCount / 3; ++i) {
        quint16 i1, i2, i3;

        stream >> i1 >> i2 >> i3;
        *pShort++ = i1;
        *pShort++ = i2;
        *pShort++ = i3;

        triangles[i].vertIndex[0] = i1;
        triangles[i].vertIndex[1] = i2;
        triangles[i].vertIndex[2] = i3;

    }

    /* Recalculate the vertex normals */
    Vector4 *faceNormals = (Vector4*)_aligned_malloc(sizeof(Vector4) * triangles.size(), 16);

    OptimisedUtil *util = OptimisedUtil::getImplementation();
    util->calculateFaceNormals(positions.constData(),
                               triangles.data(),
                               faceNormals,
                               indexCount / 3);

	 // Iterate over all children (vertexbuffer entries)
	pVert = pVertStart;
    for (int i = 0; i < vertexCount; ++i) {
        float *pFloat;

		Vector3 normal = Vector3::ZERO;
		
		int count = 0;

		/* Search for all faces that use this vertex */
		for (int j = 0; j < triangles.size(); ++j) {
			if (triangles[j].vertIndex[0] == i 
				|| triangles[j].vertIndex[1] == i 
				|| triangles[j].vertIndex[2] == i) {
				normal.x += faceNormals[j].x / faceNormals[j].w;
				normal.y += faceNormals[j].y / faceNormals[j].w;
				normal.z += faceNormals[j].z / faceNormals[j].w;
				count++;
			}
		}

		normal.normalise();

        /* Copy over the position */
		normalElement.baseVertexPointerToElement(pVert, &pFloat);
        *(pFloat++) = normal.x;
        *(pFloat++) = normal.y;
        *(pFloat++) = normal.z;
		
        pVert += vbuf->getVertexSize();
    }

    _aligned_free(faceNormals);

    vbuf->unlock();
    ibuf->unlock();

    return ogreMesh;
}
Example #23
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;
}
Example #24
0
	//-----------------------------------------------------------------------------
	ManualObject::ManualObjectSection* ManualObject::end(void)
	{
		if (!mCurrentSection)
		{
			OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
				"You cannot call end() until after you call begin()",
				"ManualObject::end");
		}
		if (mTempVertexPending)
		{
			// bake current vertex
			copyTempVertexToBuffer();
		}

		// pointer that will be returned
		ManualObjectSection* result = NULL;

		RenderOperation* rop = mCurrentSection->getRenderOperation();
		// Check for empty content
		if (rop->vertexData->vertexCount == 0 ||
			(rop->useIndexes && rop->indexData->indexCount == 0))
		{
			// You're wasting my time sonny
			if (mCurrentUpdating)
			{
				// Can't just undo / remove since may be in the middle
				// Just allow counts to be 0, will not be issued to renderer

				// return the finished section (though it has zero vertices)
				result = mCurrentSection;
			}
			else
			{
				// First creation, can really undo
				// Has already been added to section list end, so remove
				mSectionList.pop_back();
				OGRE_DELETE mCurrentSection;

			}
		}
		else // not an empty section
		{

			// Bake the real buffers
			HardwareVertexBufferSharedPtr vbuf;
			// Check buffer sizes
			bool vbufNeedsCreating = true;
			bool ibufNeedsCreating = rop->useIndexes;
            // Work out if we require 16 or 32-bit index buffers
            HardwareIndexBuffer::IndexType indexType = mCurrentSection->get32BitIndices()?  
				HardwareIndexBuffer::IT_32BIT : HardwareIndexBuffer::IT_16BIT;
			if (mCurrentUpdating)
			{
				// May be able to reuse buffers, check sizes
				vbuf = rop->vertexData->vertexBufferBinding->getBuffer(0);
				if (vbuf->getNumVertices() >= rop->vertexData->vertexCount)
					vbufNeedsCreating = false;

				if (rop->useIndexes)
				{
					if ((rop->indexData->indexBuffer->getNumIndexes() >= rop->indexData->indexCount) &&
                        (indexType == rop->indexData->indexBuffer->getType()))
						ibufNeedsCreating = false;
				}

			}
			if (vbufNeedsCreating)
			{
				// Make the vertex buffer larger if estimated vertex count higher
				// to allow for user-configured growth area
				size_t vertexCount = std::max(rop->vertexData->vertexCount, 
					mEstVertexCount);
				vbuf =
					HardwareBufferManager::getSingleton().createVertexBuffer(
						mDeclSize,
						vertexCount,
						mDynamic? HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY : 
							HardwareBuffer::HBU_STATIC_WRITE_ONLY);
				rop->vertexData->vertexBufferBinding->setBinding(0, vbuf);
			}
			if (ibufNeedsCreating)
			{
				// Make the index buffer larger if estimated index count higher
				// to allow for user-configured growth area
				size_t indexCount = std::max(rop->indexData->indexCount, 
					mEstIndexCount);
				rop->indexData->indexBuffer =
					HardwareBufferManager::getSingleton().createIndexBuffer(
						indexType,
						indexCount,
						mDynamic? HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY : 
							HardwareBuffer::HBU_STATIC_WRITE_ONLY);
			}
			// Write vertex data
			vbuf->writeData(
				0, rop->vertexData->vertexCount * vbuf->getVertexSize(), 
				mTempVertexBuffer, true);
			// Write index data
			if(rop->useIndexes)
			{
                if (HardwareIndexBuffer::IT_32BIT == indexType)
                {
                    // direct copy from the mTempIndexBuffer
				    rop->indexData->indexBuffer->writeData(
					    0, 
					    rop->indexData->indexCount 
						    * rop->indexData->indexBuffer->getIndexSize(),
					    mTempIndexBuffer, true);
                }
                else //(HardwareIndexBuffer::IT_16BIT == indexType)
                {
					uint16* pIdx = static_cast<uint16*>(rop->indexData->indexBuffer->lock(HardwareBuffer::HBL_DISCARD));
					uint32* pSrc = mTempIndexBuffer;
                    for (size_t i = 0; i < rop->indexData->indexCount; i++)
                    {
                        *pIdx++ = static_cast<uint16>(*pSrc++);
                    }
					rop->indexData->indexBuffer->unlock();

                }
			}

			// return the finished section
			result = mCurrentSection;

		} // empty section check

		mCurrentSection = 0;
		resetTempAreas();

		// Tell parent if present
		if (mParentNode)
		{
			mParentNode->needUpdate();
		}

		// will return the finished section or NULL if
		// the section was empty (i.e. zero vertices/indices)
		return result;
	}
Example #25
0
    //-----------------------------------------------------------------------
    void InstanceManager::unshareVertices(const Ogre::MeshPtr &mesh)
    {
        // Retrieve data to copy bone assignments
        const Mesh::VertexBoneAssignmentList& boneAssignments = mesh->getBoneAssignments();
        Mesh::VertexBoneAssignmentList::const_iterator it = boneAssignments.begin();
        Mesh::VertexBoneAssignmentList::const_iterator end = boneAssignments.end();
        size_t curVertexOffset = 0;

        // Access shared vertices
        VertexData* sharedVertexData = mesh->sharedVertexData;

        for (size_t subMeshIdx = 0; subMeshIdx < mesh->getNumSubMeshes(); subMeshIdx++)
        {
            SubMesh *subMesh = mesh->getSubMesh(subMeshIdx);

            IndexData *indexData = subMesh->indexData;
            HardwareIndexBuffer::IndexType idxType = indexData->indexBuffer->getType();
            IndicesMap indicesMap = (idxType == HardwareIndexBuffer::IT_16BIT) ? getUsedIndices<uint16>(indexData) :
                                                                                 getUsedIndices<uint32>(indexData);


            VertexData *newVertexData = new VertexData();
            newVertexData->vertexCount = indicesMap.size();
            newVertexData->vertexDeclaration = sharedVertexData->vertexDeclaration->clone();

            for (size_t bufIdx = 0; bufIdx < sharedVertexData->vertexBufferBinding->getBufferCount(); bufIdx++) 
            {
                HardwareVertexBufferSharedPtr sharedVertexBuffer = sharedVertexData->vertexBufferBinding->getBuffer(bufIdx);
                size_t vertexSize = sharedVertexBuffer->getVertexSize();                

                HardwareVertexBufferSharedPtr newVertexBuffer = HardwareBufferManager::getSingleton().createVertexBuffer
                    (vertexSize, newVertexData->vertexCount, sharedVertexBuffer->getUsage(), sharedVertexBuffer->hasShadowBuffer());

                uint8 *oldLock = (uint8*)sharedVertexBuffer->lock(0, sharedVertexData->vertexCount * vertexSize, HardwareBuffer::HBL_READ_ONLY);
                uint8 *newLock = (uint8*)newVertexBuffer->lock(0, newVertexData->vertexCount * vertexSize, HardwareBuffer::HBL_NORMAL);

                IndicesMap::iterator indIt = indicesMap.begin();
                IndicesMap::iterator endIndIt = indicesMap.end();
                for (; indIt != endIndIt; ++indIt)
                {
                    memcpy(newLock + vertexSize * indIt->second, oldLock + vertexSize * indIt->first, vertexSize);
                }

                sharedVertexBuffer->unlock();
                newVertexBuffer->unlock();

                newVertexData->vertexBufferBinding->setBinding(bufIdx, newVertexBuffer);
            }

            if (idxType == HardwareIndexBuffer::IT_16BIT)
            {
                copyIndexBuffer<uint16>(indexData, indicesMap);
            }
            else
            {
                copyIndexBuffer<uint32>(indexData, indicesMap);
            }

            // Store new attributes
            subMesh->useSharedVertices = false;
            subMesh->vertexData = newVertexData;

            // Transfer bone assignments to the submesh
            size_t offset = curVertexOffset + newVertexData->vertexCount;
            for (; it != end; ++it)
            {
                size_t vertexIdx = (*it).first;
                if (vertexIdx > offset)
                    break;

                VertexBoneAssignment boneAssignment = (*it).second;
                boneAssignment.vertexIndex = static_cast<unsigned int>(boneAssignment.vertexIndex - curVertexOffset);
                subMesh->addBoneAssignment(boneAssignment);
            }
            curVertexOffset = newVertexData->vertexCount + 1;
        }

        // Release shared vertex data
        delete mesh->sharedVertexData;
        mesh->sharedVertexData = NULL;
        mesh->clearBoneAssignments();
    }
Example #26
0
   void EffectBillboardChain::updateHardwareBuffers()
    {
       if (mChainElementList.size() < 2)
          return;

       HardwareVertexBufferSharedPtr pVertexBuffer =
          mRenderOp.vertexData->vertexBufferBinding->getBuffer(0);

       void* pBufferStart = pVertexBuffer->lock(HardwareBuffer::HBL_DISCARD);

       // Here. we need to compute the position of the camera in the coordinate system of the billboard chain.
       Vector3 eyePos = mParentNode->_getDerivedOrientation().Inverse() *
                   (m_pCamera->getDerivedPosition() - mParentNode->_getDerivedPosition());

       // Compute the position of the vertices in the chain
	   unsigned int chainSize = mChainElementList.size();
       for (unsigned int i = 0; i < chainSize; i++)
       {
           // 计算新的偏移量,因为每个循环是计算两个顶点,所以要乘以2
           void* pBase = static_cast<void*>(
              static_cast<char*>(pBufferStart) +
              pVertexBuffer->getVertexSize() * i * 2);

           Vector3 chainTangent;
           if (i == 0) chainTangent = mChainElementList[1].position - mChainElementList[0].position;
           else if (i == chainSize - 1) chainTangent = mChainElementList[chainSize - 1].position - mChainElementList[chainSize - 2].position;
           else chainTangent = mChainElementList[i + 1].position - mChainElementList[i - 1].position;

           const Vector3& p1 = mChainElementList[i].position;

           Vector3 vP1ToEye = eyePos - p1;
           Vector3 vPerpendicular = chainTangent.crossProduct(vP1ToEye);
           vPerpendicular.normalise();
           vPerpendicular *= mChainElementList[i].width;

           Vector3 pos0 = p1 - vPerpendicular;
           Vector3 pos1 = p1 + vPerpendicular;

           // vertex 1
           // pos
           float* pFloat = static_cast<float*>(pBase);

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

           // colour
           ColourValue colour = mChainElementList[i].colour;
           RGBA* pColour = static_cast<RGBA*>( static_cast<void*>(pFloat) );
           Root::getSingleton().convertColourValue(colour, pColour);
           pColour++;

           // tex coord
           pFloat = static_cast<float*>( static_cast<void*>(pColour) );
           *pFloat++ = mChainElementList[i].uTexCoord;
           *pFloat++ = 0.0f;

           // vertex 2
           // pos
           *pFloat++ = pos1.x;
           *pFloat++ = pos1.y;
           *pFloat++ = pos1.z;

           // colour
           pColour = static_cast<RGBA*>( static_cast<void*>(pFloat) );
           Root::getSingleton().convertColourValue(colour, pColour);
           pColour++;

           // tex coord
           pFloat = static_cast<float*>( static_cast<void*>(pColour) );
           *pFloat++ = mChainElementList[i].uTexCoord;
           *pFloat++ = 1.0f;
       }

       pVertexBuffer->unlock();
   }
	//-----------------------------------------------------------------------
	void BillboardChain::updateVertexBuffer(Camera* cam)
	{
		setupBuffers();
		HardwareVertexBufferSharedPtr pBuffer =
			mVertexData->vertexBufferBinding->getBuffer(0);
		void* pBufferStart = pBuffer->lock(HardwareBuffer::HBL_DISCARD);

		const Vector3& camPos = cam->getDerivedPosition();
		Vector3 eyePos = mParentNode->_getDerivedOrientation().Inverse() *
			(camPos - mParentNode->_getDerivedPosition()) / mParentNode->_getDerivedScale();

		Vector3 chainTangent;
		for (ChainSegmentList::iterator segi = mChainSegmentList.begin();
			segi != mChainSegmentList.end(); ++segi)
		{
			ChainSegment& seg = *segi;

			// Skip 0 or 1 element segment counts
			if (seg.head != SEGMENT_EMPTY && seg.head != seg.tail)
			{
				size_t laste = seg.head;
				for (size_t e = seg.head; ; ++e) // until break
				{
					// Wrap forwards
					if (e == mMaxElementsPerChain)
						e = 0;

					Element& elem = mChainElementList[e + seg.start];
					assert (((e + seg.start) * 2) < 65536 && "Too many elements!");
					uint16 baseIdx = static_cast<uint16>((e + seg.start) * 2);

					// Determine base pointer to vertex #1
					void* pBase = static_cast<void*>(
						static_cast<char*>(pBufferStart) +
							pBuffer->getVertexSize() * baseIdx);

					// Get index of next item
					size_t nexte = e + 1;
					if (nexte == mMaxElementsPerChain)
						nexte = 0;

					if (e == seg.head)
					{
						// No laste, use next item
						chainTangent = mChainElementList[nexte + seg.start].position - elem.position;
					}
					else if (e == seg.tail)
					{
						// No nexte, use only last item
						chainTangent = elem.position - mChainElementList[laste + seg.start].position;
					}
					else
					{
						// A mid position, use tangent across both prev and next
						chainTangent = mChainElementList[nexte + seg.start].position - mChainElementList[laste + seg.start].position;

					}

					Vector3 vP1ToEye;

					if( mFaceCamera )
						vP1ToEye = eyePos - elem.position;
					else
						vP1ToEye = elem.orientation * mNormalBase;

					Vector3 vPerpendicular = chainTangent.crossProduct(vP1ToEye);
					vPerpendicular.normalise();
					vPerpendicular *= (elem.width * 0.5f);

					Vector3 pos0 = elem.position - vPerpendicular;
					Vector3 pos1 = elem.position + vPerpendicular;

					float* pFloat = static_cast<float*>(pBase);
					// pos1
					*pFloat++ = pos0.x;
					*pFloat++ = pos0.y;
					*pFloat++ = pos0.z;

					pBase = static_cast<void*>(pFloat);

					if (mUseVertexColour)
					{
						RGBA* pCol = static_cast<RGBA*>(pBase);
						Root::getSingleton().convertColourValue(elem.colour, pCol);
						pCol++;
						pBase = static_cast<void*>(pCol);
					}

					if (mUseTexCoords)
					{
						pFloat = static_cast<float*>(pBase);
						if (mTexCoordDir == TCD_U)
						{
							*pFloat++ = elem.texCoord;
							*pFloat++ = mOtherTexCoordRange[0];
						}
						else
						{
							*pFloat++ = mOtherTexCoordRange[0];
							*pFloat++ = elem.texCoord;
						}
						pBase = static_cast<void*>(pFloat);
					}

					// pos2
					pFloat = static_cast<float*>(pBase);
					*pFloat++ = pos1.x;
					*pFloat++ = pos1.y;
					*pFloat++ = pos1.z;
					pBase = static_cast<void*>(pFloat);

					if (mUseVertexColour)
					{
						RGBA* pCol = static_cast<RGBA*>(pBase);
						Root::getSingleton().convertColourValue(elem.colour, pCol);
						pCol++;
						pBase = static_cast<void*>(pCol);
					}

					if (mUseTexCoords)
					{
						pFloat = static_cast<float*>(pBase);
						if (mTexCoordDir == TCD_U)
						{
							*pFloat++ = elem.texCoord;
							*pFloat++ = mOtherTexCoordRange[1];
						}
						else
						{
							*pFloat++ = mOtherTexCoordRange[1];
							*pFloat++ = elem.texCoord;
						}
					}

					if (e == seg.tail)
						break; // last one

					laste = e;

				} // element
			} // segment valid?

		} // each segment



		pBuffer->unlock();


	}
Example #28
0
void OgreNewtonMesh::ParseEntity (MeshPtr mesh, const Matrix4& matrix)
{
	//find number of sub-meshes
	unsigned short sub = mesh->getNumSubMeshes();

	for (unsigned short cs = 0; cs < sub; cs++) {

		SubMesh* const sub_mesh = mesh->getSubMesh(cs);

		//vertex data!
		VertexData* v_data;

		if (sub_mesh->useSharedVertices) {
			v_data = mesh->sharedVertexData;
		} else {
			v_data = sub_mesh->vertexData;
		}

		//let's find more information about the Vertices...
		VertexDeclaration* const v_decl = v_data->vertexDeclaration;

		const VertexElement* const vertexElem = v_decl->findElementBySemantic(VES_POSITION);
		HardwareVertexBufferSharedPtr vertexPtr = v_data->vertexBufferBinding->getBuffer(vertexElem->getSource());
		dNewtonScopeBuffer<Vector3> points(vertexPtr->getNumVertices());
		{
			int size = vertexPtr->getVertexSize();
			int offset = vertexElem->getOffset() / sizeof (float);
			unsigned char* const ptr = static_cast<unsigned char*> (vertexPtr->lock(HardwareBuffer::HBL_READ_ONLY));
			for (int i = 0; i < points.GetElementsCount(); i ++) {
				float* data;
				vertexElem->baseVertexPointerToElement(ptr + i * size, &data);
				points[i] = matrix.transformAffine (Vector3 (data[offset + 0], data[offset + 1], data[offset + 2]));
			}
			vertexPtr->unlock();
		}

		dNewtonScopeBuffer<Vector3> normals;
		const VertexElement* const normalElem = v_decl->findElementBySemantic(VES_NORMAL);
		if (normalElem) {
			HardwareVertexBufferSharedPtr normalPtr = v_data->vertexBufferBinding->getBuffer(normalElem->getSource());
			normals.Init (normalPtr->getNumVertices());

			int size = normalPtr->getVertexSize();
			int offset = vertexElem->getOffset() / sizeof (float);
			unsigned char* const ptr = static_cast<unsigned char*> (normalPtr->lock(HardwareBuffer::HBL_READ_ONLY));
			for (int i = 0; i < normals.GetElementsCount(); i ++) {
				float* data;
				vertexElem->baseVertexPointerToElement(ptr + i * size, &data);
				normals[i] = matrix * Vector3 (data[offset + 0], data[offset + 1], data[offset + 2]);
				normals[i] = normals[i].normalise();
			}
			normalPtr->unlock();
		}


		dNewtonScopeBuffer<Vector3> uvs;
		const VertexElement* const uvElem = v_decl->findElementBySemantic(VES_TEXTURE_COORDINATES);
		if (uvElem) {
			HardwareVertexBufferSharedPtr uvPtr = v_data->vertexBufferBinding->getBuffer(uvElem->getSource());
			uvs.Init (uvPtr->getNumVertices());
		
			int size = uvPtr->getVertexSize();
			int offset = vertexElem->getOffset() / sizeof (float);
			unsigned char* const ptr = static_cast<unsigned char*> (uvPtr->lock(HardwareBuffer::HBL_READ_ONLY));
			for (int i = 0; i < uvs.GetElementsCount(); i ++) {
				float* data;
				uvElem->baseVertexPointerToElement(ptr + i * size, &data);
				uvs[i] = Vector3 (data[offset + 0], data[offset + 1], 0.0f);
			}
			uvPtr->unlock();
		}

		//now find more about the index!!
		IndexData* const i_data = sub_mesh->indexData;
		size_t index_count = i_data->indexCount;
		size_t poly_count = index_count / 3;

		// get pointer!
		HardwareIndexBufferSharedPtr i_sptr = i_data->indexBuffer;

		// 16 or 32 bit indices?
		bool uses32bit = (i_sptr->getType()	== HardwareIndexBuffer::IT_32BIT);
		unsigned long* i_Longptr = NULL;
		unsigned short* i_Shortptr = NULL;

		if (uses32bit) {
			i_Longptr = static_cast<unsigned long*> (i_sptr->lock(HardwareBuffer::HBL_READ_ONLY));
		} else {
			i_Shortptr = static_cast<unsigned short*> (i_sptr->lock(HardwareBuffer::HBL_READ_ONLY));
		}

		//now loop through the indices, getting polygon info!
		int i_offset = 0;

		Real poly_verts[3][12];
		memset (poly_verts, 0, sizeof (poly_verts));
		for (size_t i = 0; i < poly_count; i++)	{
			for (int j = 0; j < 3; j++) {
				// index to first vertex!
				int idx = uses32bit ? i_Longptr[i_offset + j] : i_Shortptr[i_offset + j]; 

				poly_verts[j][0] = points[idx].x;
				poly_verts[j][1] = points[idx].y;
				poly_verts[j][2] = points[idx].z;
				poly_verts[j][3] = 0.0f;

				if (normals.GetElementsCount()) {
					poly_verts[j][4] = normals[idx].x;
					poly_verts[j][5] = normals[idx].y;
					poly_verts[j][6] = normals[idx].z;
				}

				if (uvs.GetElementsCount()) {
					poly_verts[j][7] = uvs[idx].x;
					poly_verts[j][8] = uvs[idx].y;
				}
			}
			AddFace(3, &poly_verts[0][0], 12 * sizeof (Real), cs);
			i_offset += 3;
		}
		i_sptr->unlock();
	}
}
/// 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();
}