Пример #1
0
	void IndexBuffer::AddFromIndexData(Ogre::IndexData* indexData, const unsigned int offset)
	{
		// Get vertex count
		const unsigned int addedCount = indexData->indexCount;

		if(_reserved < _size + addedCount)
		{
			Reserve(_size + addedCount);
		}

		Ogre::HardwareIndexBufferSharedPtr hardwareBuffer = indexData->indexBuffer;
		const bool use32bitindexes = (hardwareBuffer->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);

		if (use32bitindexes) 
		{
			const unsigned int* curIndex = static_cast<unsigned int*>
				(hardwareBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
			for(unsigned int k = 0; k < addedCount; ++k)
			{
				_buffer.push_back(offset + (*curIndex++));
			}
		}
		else
		{
			const unsigned short* curIndex = static_cast<unsigned short*>
				(hardwareBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
			for(unsigned int k = 0; k < addedCount; ++k)
			{
				_buffer.push_back(offset + static_cast<unsigned int>(*curIndex++));
			}
		}
		_size = _buffer.size();
		hardwareBuffer->unlock();
	}
Пример #2
0
void ESKOgre::createFakeEntity(Ogre::SceneManager *mSceneMgr) {
	Ogre::MeshPtr msh = Ogre::MeshManager::getSingleton().createManual(name + "_skeleton", XENOVIEWER_RESOURCE_GROUP);
	msh->setSkeletonName(name);

	Ogre::SubMesh* sub = msh->createSubMesh();
	const size_t nVertices = 3;
	const size_t nVertCount = 3;
	const size_t vbufCount = nVertCount*nVertices;
	float *vertices = (float *)malloc(sizeof(float)*vbufCount);

	for (size_t i = 0; i < nVertices; i++) {
		vertices[i*nVertCount] = 0.0;
		vertices[i*nVertCount + 1] = 0.0;
		vertices[i*nVertCount + 2] = 0.0;
	}

	const size_t ibufCount = 3;
	unsigned short *faces = (unsigned short *)malloc(sizeof(unsigned short) * ibufCount);

	for (size_t i = 0; i < ibufCount; i++) {
		faces[i] = i;
	}

	msh->sharedVertexData = new Ogre::VertexData();
	msh->sharedVertexData->vertexCount = nVertices;

	Ogre::VertexDeclaration* decl = msh->sharedVertexData->vertexDeclaration;
	size_t offset = 0;

	decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
	offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);

	Ogre::HardwareVertexBufferSharedPtr vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(offset, msh->sharedVertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
	vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true);
	Ogre::VertexBufferBinding* bind = msh->sharedVertexData->vertexBufferBinding;
	bind->setBinding(0, vbuf);
	Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, ibufCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
	ibuf->writeData(0, ibuf->getSizeInBytes(), faces, true);
	sub->useSharedVertices = true;
	sub->indexData->indexBuffer = ibuf;
	sub->indexData->indexCount = ibufCount;
	sub->indexData->indexStart = 0;

	msh->_setBounds(Ogre::AxisAlignedBox(-100, -100, -100, 100, 100, 100));
	msh->_setBoundingSphereRadius(100);
	msh->load();

	free(faces);
	free(vertices);

	skeleton_entity = mSceneMgr->createEntity(name + "_skeleton");
	skeleton_node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
	skeleton_node->attachObject(skeleton_entity);
	skeleton_node->setVisible(false);
}
Пример #3
0
void processIndexData(IndexData* indexData)
{
	if (!mFlipVertexWinding)
	{
		// Nothing to do.
		return;
	}

	if (indexData->indexCount % 3 != 0)
	{
        printf("Index number is not a multiple of 3, no vertex winding flipping possible. Skipped.");
        return;
	}

	//print("Flipping index order for vertex winding flipping.", V_HIGH);
	Ogre::HardwareIndexBufferSharedPtr buffer = indexData->indexBuffer;
	unsigned char* data = static_cast<unsigned char*>(buffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));

	if(buffer->getType() == Ogre::HardwareIndexBuffer::IT_16BIT)
	{
		// 16 bit
		//print("using 16bit indices", V_HIGH);

		for (size_t i = 0; i < indexData->indexCount; i+=3)
		{
			Ogre::uint16 * i0 = (Ogre::uint16*)(data+0 * buffer->getIndexSize());
			Ogre::uint16* i2 = (Ogre::uint16*)(data+2 * buffer->getIndexSize());

			// flip
			Ogre::uint16 tmp = *i0;
			*i0 = *i2;
			*i2 = tmp;

			data += 3 * buffer->getIndexSize();
		}
	}
	else
	{
		// 32 bit
		//print("using 32bit indices", V_HIGH);

		for (size_t i = 0; i < indexData->indexCount; i+=3)
		{
			Ogre::uint32* i0 = (Ogre::uint32*)(data+0 * buffer->getIndexSize());
			Ogre::uint32* i2 = (Ogre::uint32*)(data+2 * buffer->getIndexSize());

			// flip
			Ogre::uint32 tmp = *i0;
			*i0 = *i2;
			*i2 = tmp;

			data += 3 * buffer->getIndexSize();
		}
	}

	buffer->unlock();
}
Пример #4
0
Ogre::SubMesh *EMDOgre::createOgreSubmesh(EMDTriangles *triangles, Ogre::MeshPtr mesh) {
	Ogre::SubMesh *sub = mesh->createSubMesh();
	const size_t ibufCount = triangles->faces.size();
	unsigned short *faces = (unsigned short *)malloc(sizeof(unsigned short) * ibufCount);
	for (size_t i = 0; i<ibufCount; i++) {
		faces[i] = triangles->faces[i];
	}

	Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, ibufCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
	ibuf->writeData(0, ibuf->getSizeInBytes(), faces, true);
	sub->useSharedVertices = true;
	sub->indexData->indexBuffer = ibuf;
	sub->indexData->indexCount = ibufCount;
	sub->indexData->indexStart = 0;
	free(faces);
	return sub;
}
Пример #5
0
	//------------------------------------------------------------------------------------------------
	void VertexIndexToShape::addIndexData(Ogre::IndexData *data, const unsigned int offset)
	{
		const unsigned int prev_size = mIndexCount;
		mIndexCount += (unsigned int)data->indexCount;

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

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

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

	}
void GPUBillboardSet::createVertexDataForVertexShaderOnly(const std::vector<PhotoSynth::Vertex>& vertices)
{
	// Setup render operation
	mRenderOp.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST; 
	mRenderOp.vertexData = OGRE_NEW Ogre::VertexData();
	mRenderOp.vertexData->vertexCount = vertices.size() * 4; 
	mRenderOp.vertexData->vertexStart = 0; 
	mRenderOp.useIndexes = true; 
	mRenderOp.indexData = OGRE_NEW Ogre::IndexData();
	mRenderOp.indexData->indexCount = vertices.size() * 6;
	mRenderOp.indexData->indexStart = 0;

	// Vertex format declaration
	unsigned short sourceBufferIdx = 0;
	Ogre::VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration;
    size_t currOffset = 0;
	decl->addElement(sourceBufferIdx, currOffset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
	currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
	decl->addElement(sourceBufferIdx, currOffset, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE);
	currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR);
	decl->addElement(sourceBufferIdx, currOffset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 0);
	currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);

	// Create vertex buffer
    Ogre::HardwareVertexBufferSharedPtr vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
		decl->getVertexSize(sourceBufferIdx),
        mRenderOp.vertexData->vertexCount,
        Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);

    // Bind vertex buffer
    Ogre::VertexBufferBinding* bind = mRenderOp.vertexData->vertexBufferBinding;
	bind->setBinding(sourceBufferIdx, vbuf);

	// Fill vertex buffer (see http://www.ogre3d.org/docs/manual/manual_59.html#SEC287)
	Ogre::RenderSystem* renderSystem = Ogre::Root::getSingletonPtr()->getRenderSystem();
	unsigned char* pVert = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
	Ogre::Real* pReal;
	Ogre::RGBA* pRGBA;
	Ogre::VertexDeclaration::VertexElementList elems = decl->findElementsBySource(sourceBufferIdx);
	Ogre::VertexDeclaration::VertexElementList::iterator itr;

	const Ogre::Vector2 uvs[4] = {	Ogre::Vector2( -1.f, 1.f ),
									Ogre::Vector2( -1.f, -1.f ),
									Ogre::Vector2( 1.f, -1.f ),
									Ogre::Vector2( 1.f, 1.f ) };
	for (unsigned int i=0; i<vertices.size(); ++i )
	{
		const PhotoSynth::Vertex& vertex = vertices[i];
		for ( unsigned int j=0; j<4; j++ )
		{
			for (itr=elems.begin(); itr!=elems.end(); ++itr)
			{
				Ogre::VertexElement& elem = *itr;
				if (elem.getSemantic() == Ogre::VES_POSITION)
				{
					elem.baseVertexPointerToElement(pVert, &pReal);
					*pReal = vertex.position.x; *pReal++;
					*pReal = vertex.position.y; *pReal++;
					*pReal = vertex.position.z; *pReal++;
				}
				else if (elem.getSemantic() == Ogre::VES_DIFFUSE)
				{
					elem.baseVertexPointerToElement(pVert, &pRGBA);
					renderSystem->convertColourValue(vertex.color, pRGBA);
				}
				else if (elem.getSemantic() == Ogre::VES_TEXTURE_COORDINATES && elem.getIndex() == 0)
				{
					elem.baseVertexPointerToElement(pVert, &pReal);
					*pReal = uvs[j].x; *pReal++;
					*pReal = uvs[j].y; *pReal++;
				}
			}
			// Go to next vertex 
			pVert += vbuf->getVertexSize();
		}
	}
	vbuf->unlock();

	// Create index buffer
	if (mRenderOp.indexData->indexCount>=65536)
	{
		Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( 
			Ogre::HardwareIndexBuffer::IT_32BIT, 
			mRenderOp.indexData->indexCount, 
			Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);

		mRenderOp.indexData->indexBuffer = ibuf;
		Ogre::uint32* indices = static_cast<Ogre::uint32*>(ibuf->lock( Ogre::HardwareBuffer::HBL_DISCARD));

		Ogre::uint32 indexFirstVertex = 0;
		const Ogre::uint32 inds[6] = {	0, 1, 2, 3, 0, 2 };
		for (unsigned int i=0; i<vertices.size(); ++i)
		{
			for (unsigned int j=0; j<6; ++j)
			{
				*indices = indexFirstVertex + inds[j];
				indices++;
			}
			indexFirstVertex +=4;
		}
		ibuf->unlock();
	}
	else
	{
		Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
			Ogre::HardwareIndexBuffer::IT_16BIT, 
			mRenderOp.indexData->indexCount, 
			Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);

		mRenderOp.indexData->indexBuffer = ibuf;
		Ogre::uint16* indices = static_cast<Ogre::uint16*>( ibuf->lock( Ogre::HardwareBuffer::HBL_DISCARD ) );

		Ogre::uint32 indexFirstVertex = 0;
		const Ogre::uint16 inds[6] = {	0, 1, 2, 3, 0, 2 };
		for ( unsigned int i=0; i<vertices.size(); ++i )
		{
			for ( unsigned int j=0; j<6; ++j )
			{
				*indices = indexFirstVertex + inds[j];
				indices++;
			}
			indexFirstVertex +=4;
		}
		ibuf->unlock();
	}

    // Set material
    this->setMaterial("GPUBillboard");
}
bool ShaderParticleRenderer::allocateBuffers(size_t iNumParticles)
{
    // prepare vertex declaration
    if (mVertexData->vertexDeclaration->getElementCount() == 0) {
        VertexDeclaration* pDecl = mVertexData->vertexDeclaration;
        size_t ofs = 0;
        ofs += pDecl->addElement(0, ofs, VET_FLOAT4, VES_POSITION).getSize();				// position
        if (mVertexFormatColour)
            ofs += pDecl->addElement(0, ofs, VET_FLOAT4, VES_DIFFUSE).getSize();			// diffuse colour

        // other data are stored in vertex as texture coordinates
        ushort ix = 0;
        if (mVertexFormatTexture)
            ofs += pDecl->addElement(0, ofs, VET_FLOAT2, VES_TEXTURE_COORDINATES, ix++).getSize();	// general texture coord

        if (mVertexFormatSize)
            ofs += pDecl->addElement(0, ofs, VET_FLOAT2, VES_TEXTURE_COORDINATES, ix++).getSize();	// particle size

        if (mVertexFormatRotation || mVertexFormatRotationSpeed) {
            if (mVertexFormatRotation && mVertexFormatRotationSpeed)
                ofs += pDecl->addElement(0, ofs, VET_FLOAT2, VES_TEXTURE_COORDINATES, ix++).getSize();	// current rotation and rotation speed
            else
                ofs += pDecl->addElement(0, ofs, VET_FLOAT1, VES_TEXTURE_COORDINATES, ix++).getSize();	// current rotation or rotation speed
        }

        if (mVertexFormatDirection)
            ofs += pDecl->addElement(0, ofs, VET_FLOAT3, VES_TEXTURE_COORDINATES, ix++).getSize();	// particle direction (as speed)

        // add packed times
        size_t iNumTimes = 0;
        if (mVertexFormatTTL) iNumTimes++;
        if (mVertexFormatTotalTTL) iNumTimes++;
        if (mVertexFormatTimeFragment) iNumTimes++;
        if (mVertexFormatTimeFragmentInv) iNumTimes++;
        switch(iNumTimes) {
            case 1:
                ofs += pDecl->addElement(0, ofs, VET_FLOAT1, VES_TEXTURE_COORDINATES, ix++).getSize();
                break;
            case 2:
                ofs += pDecl->addElement(0, ofs, VET_FLOAT2, VES_TEXTURE_COORDINATES, ix++).getSize();
                break;
            case 3:
                ofs += pDecl->addElement(0, ofs, VET_FLOAT3, VES_TEXTURE_COORDINATES, ix++).getSize();
                break;
            case 4:
                ofs += pDecl->addElement(0, ofs, VET_FLOAT4, VES_TEXTURE_COORDINATES, ix++).getSize();
                break;
        }

        // add custom parameters
        ofs += pDecl->addElement(0, ofs, VET_FLOAT4, VES_TEXTURE_COORDINATES, ix++).getSize();
        assert(ix <= 8);

        // cache vertex size
        mVertexSize = pDecl->getVertexSize(0);
    }

    Ogre::HardwareVertexBufferSharedPtr pVB;
    if (mVertexData->vertexBufferBinding->isBufferBound(0))
        pVB = mVertexData->vertexBufferBinding->getBuffer(0);

    // prepare vertex buffer
    if (pVB.isNull() || pVB->getNumVertices() < iNumParticles * 4) {
        assert(iNumParticles * 4 < 65536); // we are using 16bit index buffer
        pVB = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(mVertexSize, 4 * iNumParticles, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
        if (pVB.isNull())
            return false;

        mVertexData->vertexBufferBinding->setBinding(0, pVB);
    }

    // prepare index buffer
    Ogre::HardwareIndexBufferSharedPtr pIB = mIndexData->indexBuffer;
    if (pIB.isNull() || pIB->getNumIndexes() < iNumParticles * 6) {
        pIB = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, iNumParticles * 6, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
        if (pIB.isNull())
            return false;

        mIndexData->indexBuffer = pIB;

        // fill
        Ogre::uint16* pDataIB = reinterpret_cast<Ogre::uint16*>(pIB->lock(Ogre::HardwareBuffer::HBL_NORMAL));
        for (Ogre::uint16 k=0; k<static_cast<Ogre::uint16>(iNumParticles); ++k) {
            pDataIB[0] = k*4 + 0;
            pDataIB[1] = k*4 + 1;
            pDataIB[2] = k*4 + 2;

            pDataIB[3] = k*4 + 0;
            pDataIB[4] = k*4 + 2;
            pDataIB[5] = k*4 + 3;
            pDataIB += 6;
        }
        pIB->unlock();
    }

    return true;
}
Пример #8
0
void Renderer::FindClosestPolygon(Ogre::Entity* entity, float& closestDistance,
                                       Ogre::Vector3& position, Ogre::Vector3& normal)
{
    closestDistance = std::numeric_limits<float>::max();    // default value (means
                                                            // nothing detected)

    // Get transformation
    Ogre::SceneNode* parentNode = entity->getParentSceneNode();
    Ogre::Vector3 parentPos;
    Ogre::Quaternion parentOrientation;
    Ogre::Vector3 parentScale;
    if (parentNode)
    {
        parentPos = parentNode->_getDerivedPosition();
        parentOrientation = parentNode->_getDerivedOrientation();
        parentScale = parentNode->_getDerivedScale();
    }
    else
    {
        parentPos = Ogre::Vector3::ZERO;
        parentOrientation = Ogre::Quaternion::IDENTITY;
        parentScale = Ogre::Vector3::UNIT_SCALE;
    }

    // Handle animated entities
    bool isAnimated = entity->hasSkeleton();
    if (isAnimated)
    {
        entity->addSoftwareAnimationRequest(false);
        entity->_updateAnimation();
    }

    // Loop through each submesh
    Ogre::MeshPtr mesh = entity->getMesh();
    for (uint i = 0; i < mesh->getNumSubMeshes(); ++i)
    {
        Ogre::SubMesh* subMesh = mesh->getSubMesh(i);

        // Ignore anything that isn't a triangle List
        if (subMesh->operationType != Ogre::RenderOperation::OT_TRIANGLE_LIST)
            continue;

        // Get the vertex data
        Ogre::VertexData* vertexData;
        if (subMesh->useSharedVertices)
        {
            if (isAnimated)
                vertexData = entity->_getSkelAnimVertexData();
            else
                vertexData = mesh->sharedVertexData;
        }
        else
        {
            if (isAnimated)
                vertexData = entity->getSubEntity(i)->_getSkelAnimVertexData();
            else
                vertexData = subMesh->vertexData;
        }

        // Get the size of one vertex
        const Ogre::VertexElement* posEl =
            vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
        Ogre::HardwareVertexBufferSharedPtr vBuff =
            vertexData->vertexBufferBinding->getBuffer(posEl->getSource());
        uint vertexSize = vBuff->getVertexSize();

        // Save pointer to first vertex
        short* pVertex = (short*)vBuff->lock(Ogre::HardwareBuffer::HBL_READ_ONLY);
        short* pStartVertex = pVertex;

        // Get the index buffer
        // If it is null then skip as it must be a point cloud
        Ogre::HardwareIndexBufferSharedPtr iBuff = subMesh->indexData->indexBuffer;

        if (iBuff.isNull())
            continue;

        uint* pLong = (uint*)iBuff->lock(Ogre::HardwareBuffer::HBL_READ_ONLY);
        uint16_t* pShort = (uint16_t*)pLong;

        // Look through each vertex and check each triangle with the ray
        Ogre::Vector3 vertexPos;
        Ogre::Vector3 vertex1;
        Ogre::Vector3 vertex2;
        float* pReal;
        uint index;
        for (uint k = 0; k < subMesh->indexData->indexCount; k++)
        {
            // Read index value
            if (iBuff->getType() == Ogre::HardwareIndexBuffer::IT_32BIT)    // if 32bit indexes
            {
                index = (uint)pLong[k];
            }
            else
            {
                index = (uint)pShort[k];
            }

            // Read referenced vertex
            pVertex = pStartVertex + (vertexSize * index);              // calculate pointer
            posEl->baseVertexPointerToElement(pVertex, &pReal);         // read vertex
            vertexPos = Ogre::Vector3(pReal[0], pReal[1], pReal[2]);    // read position values

            // Apply world transformations
            if (parentNode)
                vertexPos = (parentOrientation * (vertexPos * parentScale)) + parentPos;

            // Figure out triangle and calculate the distance if it's the closest
            switch (k % 3)
            {
            case 0:
                vertex1 = vertexPos;
                break;

            case 1:
                vertex2 = vertexPos;
                break;

            case 2:
                RayToTriangleCheck(vertex1, vertex2, vertexPos, closestDistance, position, normal);
                break;

            default:
                break;
            }
        }

        iBuff->unlock();
        vBuff->unlock();
    }

    if (isAnimated)
    {
        entity->removeSoftwareAnimationRequest(false);
    }
}
Пример #9
0
// Get the mesh information for the given mesh.
// Code found on this forum link: http://www.ogre3d.org/wiki/index.php/RetrieveVertexData
void CollisionTools::GetMeshInformation(const Ogre::MeshPtr mesh,
                                size_t &vertex_count,
                                Ogre::Vector3* &vertices,
                                size_t &index_count,
                                Ogre::uint32* &indices,
                                const Ogre::Vector3 &position,
                                const Ogre::Quaternion &orient,
                                const Ogre::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)
    {
        Ogre::SubMesh* submesh = mesh->getSubMesh( i );

        // 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
    vertices = new Ogre::Vector3[vertex_count];
    indices = new Ogre::uint32[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)
    {
        Ogre::SubMesh* submesh = mesh->getSubMesh(i);

        Ogre::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 Ogre::VertexElement* posElem =
                vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);

            Ogre::HardwareVertexBufferSharedPtr vbuf =
                vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());

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

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

            for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
            {
                posElem->baseVertexPointerToElement(vertex, &pReal);

                Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]);

                vertices[current_offset + j] = (orient * (pt * scale)) + position;
            }

            vbuf->unlock();
            next_offset += vertex_data->vertexCount;
        }


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

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

        Ogre::uint32*  pLong = static_cast<Ogre::uint32*>(ibuf->lock(Ogre::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<Ogre::uint32>(offset);
            }
        }
        else
        {
            for ( size_t k = 0; k < numTris*3; ++k)
            {
                indices[index_offset++] = static_cast<Ogre::uint32>(pShort[k]) +
                    static_cast<Ogre::uint32>(offset);
            }
        }

        ibuf->unlock();
        current_offset = next_offset;
    }
}
Пример #10
0
void NIFMeshLoader::createSubMesh(Ogre::Mesh *mesh, const Nif::NiTriShape *shape)
{
    const Nif::NiTriShapeData *data = shape->data.getPtr();
    const Nif::NiSkinInstance *skin = (shape->skin.empty() ? NULL : shape->skin.getPtr());
    std::vector<Ogre::Vector3> srcVerts = data->vertices;
    std::vector<Ogre::Vector3> srcNorms = data->normals;
    Ogre::HardwareBuffer::Usage vertUsage = Ogre::HardwareBuffer::HBU_STATIC;
    bool vertShadowBuffer = false;

    bool geomMorpherController = false;
    if(!shape->controller.empty())
    {
        Nif::ControllerPtr ctrl = shape->controller;
        do {
            if(ctrl->recType == Nif::RC_NiGeomMorpherController)
            {
                vertUsage = Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY;
                vertShadowBuffer = true;
                geomMorpherController = true;
                break;
            }
        } while(!(ctrl=ctrl->next).empty());
    }

    if(skin != NULL)
    {
        vertUsage = Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY;
        vertShadowBuffer = true;

        // Only set a skeleton when skinning. Unskinned meshes with a skeleton will be
        // explicitly attached later.
        mesh->setSkeletonName(mName);

        // Convert vertices and normals to bone space from bind position. It would be
        // better to transform the bones into bind position, but there doesn't seem to
        // be a reliable way to do that.
        std::vector<Ogre::Vector3> newVerts(srcVerts.size(), Ogre::Vector3(0.0f));
        std::vector<Ogre::Vector3> newNorms(srcNorms.size(), Ogre::Vector3(0.0f));

        const Nif::NiSkinData *data = skin->data.getPtr();
        const Nif::NodeList &bones = skin->bones;
        for(size_t b = 0;b < bones.length();b++)
        {
            Ogre::Matrix4 mat;
            mat.makeTransform(data->bones[b].trafo.trans, Ogre::Vector3(data->bones[b].trafo.scale),
                              Ogre::Quaternion(data->bones[b].trafo.rotation));
            mat = bones[b]->getWorldTransform() * mat;

            const std::vector<Nif::NiSkinData::VertWeight> &weights = data->bones[b].weights;
            for(size_t i = 0;i < weights.size();i++)
            {
                size_t index = weights[i].vertex;
                float weight = weights[i].weight;

                newVerts.at(index) += (mat*srcVerts[index]) * weight;
                if(newNorms.size() > index)
                {
                    Ogre::Vector4 vec4(srcNorms[index][0], srcNorms[index][1], srcNorms[index][2], 0.0f);
                    vec4 = mat*vec4 * weight;
                    newNorms[index] += Ogre::Vector3(&vec4[0]);
                }
            }
        }

        srcVerts = newVerts;
        srcNorms = newNorms;
    }
    else
    {
        Ogre::SkeletonManager *skelMgr = Ogre::SkeletonManager::getSingletonPtr();
        if(skelMgr->getByName(mName).isNull())
        {
            // No skinning and no skeleton, so just transform the vertices and
            // normals into position.
            Ogre::Matrix4 mat4 = shape->getWorldTransform();
            for(size_t i = 0;i < srcVerts.size();i++)
            {
                Ogre::Vector4 vec4(srcVerts[i].x, srcVerts[i].y, srcVerts[i].z, 1.0f);
                vec4 = mat4*vec4;
                srcVerts[i] = Ogre::Vector3(&vec4[0]);
            }
            for(size_t i = 0;i < srcNorms.size();i++)
            {
                Ogre::Vector4 vec4(srcNorms[i].x, srcNorms[i].y, srcNorms[i].z, 0.0f);
                vec4 = mat4*vec4;
                srcNorms[i] = Ogre::Vector3(&vec4[0]);
            }
        }
    }

    // Set the bounding box first
    BoundsFinder bounds;
    bounds.add(&srcVerts[0][0], srcVerts.size());
    if(!bounds.isValid())
    {
        float v[3] = { 0.0f, 0.0f, 0.0f };
        bounds.add(&v[0], 1);
    }

    mesh->_setBounds(Ogre::AxisAlignedBox(bounds.minX()-0.5f, bounds.minY()-0.5f, bounds.minZ()-0.5f,
                                          bounds.maxX()+0.5f, bounds.maxY()+0.5f, bounds.maxZ()+0.5f));
    mesh->_setBoundingSphereRadius(bounds.getRadius());

    // This function is just one long stream of Ogre-barf, but it works
    // great.
    Ogre::HardwareBufferManager *hwBufMgr = Ogre::HardwareBufferManager::getSingletonPtr();
    Ogre::HardwareVertexBufferSharedPtr vbuf;
    Ogre::HardwareIndexBufferSharedPtr ibuf;
    Ogre::VertexBufferBinding *bind;
    Ogre::VertexDeclaration *decl;
    int nextBuf = 0;

    Ogre::SubMesh *sub = mesh->createSubMesh();

    // Add vertices
    sub->useSharedVertices = false;
    sub->vertexData = new Ogre::VertexData();
    sub->vertexData->vertexStart = 0;
    sub->vertexData->vertexCount = srcVerts.size();

    decl = sub->vertexData->vertexDeclaration;
    bind = sub->vertexData->vertexBufferBinding;
    if(srcVerts.size())
    {
        vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3),
                                            srcVerts.size(), vertUsage, vertShadowBuffer);
        vbuf->writeData(0, vbuf->getSizeInBytes(), &srcVerts[0][0], true);

        decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
        bind->setBinding(nextBuf++, vbuf);
    }

    // Vertex normals
    if(srcNorms.size())
    {
        vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3),
                                            srcNorms.size(), vertUsage, vertShadowBuffer);
        vbuf->writeData(0, vbuf->getSizeInBytes(), &srcNorms[0][0], true);

        decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
        bind->setBinding(nextBuf++, vbuf);
    }

    // Vertex colors
    const std::vector<Ogre::Vector4> &colors = data->colors;
    if(colors.size())
    {
        Ogre::RenderSystem *rs = Ogre::Root::getSingleton().getRenderSystem();
        std::vector<Ogre::RGBA> colorsRGB(colors.size());
        for(size_t i = 0;i < colorsRGB.size();i++)
        {
            Ogre::ColourValue clr(colors[i][0], colors[i][1], colors[i][2], colors[i][3]);
            rs->convertColourValue(clr, &colorsRGB[i]);
        }
        vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR),
                                            colorsRGB.size(), Ogre::HardwareBuffer::HBU_STATIC);
        vbuf->writeData(0, vbuf->getSizeInBytes(), &colorsRGB[0], true);
        decl->addElement(nextBuf, 0, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE);
        bind->setBinding(nextBuf++, vbuf);
    }

    // Texture UV coordinates
    size_t numUVs = data->uvlist.size();
    if (numUVs)
    {
        size_t elemSize = Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);

        for(size_t i = 0; i < numUVs; i++)
            decl->addElement(nextBuf, elemSize*i, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, i);

        vbuf = hwBufMgr->createVertexBuffer(decl->getVertexSize(nextBuf), srcVerts.size(),
                                            Ogre::HardwareBuffer::HBU_STATIC);

        std::vector<Ogre::Vector2> allUVs;
        allUVs.reserve(srcVerts.size()*numUVs);
        for (size_t vert = 0; vert<srcVerts.size(); ++vert)
            for(size_t i = 0; i < numUVs; i++)
                allUVs.push_back(data->uvlist[i][vert]);

        vbuf->writeData(0, elemSize*srcVerts.size()*numUVs, &allUVs[0], true);

        bind->setBinding(nextBuf++, vbuf);
    }

    // Triangle faces
    const std::vector<short> &srcIdx = data->triangles;
    if(srcIdx.size())
    {
        ibuf = hwBufMgr->createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, srcIdx.size(),
                                           Ogre::HardwareBuffer::HBU_STATIC);
        ibuf->writeData(0, ibuf->getSizeInBytes(), &srcIdx[0], true);
        sub->indexData->indexBuffer = ibuf;
        sub->indexData->indexCount = srcIdx.size();
        sub->indexData->indexStart = 0;
    }

    // Assign bone weights for this TriShape
    if(skin != NULL)
    {
        Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(mName);

        const Nif::NiSkinData *data = skin->data.getPtr();
        const Nif::NodeList &bones = skin->bones;
        for(size_t i = 0;i < bones.length();i++)
        {
            Ogre::VertexBoneAssignment boneInf;
            boneInf.boneIndex = skel->getBone(bones[i]->name)->getHandle();

            const std::vector<Nif::NiSkinData::VertWeight> &weights = data->bones[i].weights;
            for(size_t j = 0;j < weights.size();j++)
            {
                boneInf.vertexIndex = weights[j].vertex;
                boneInf.weight = weights[j].weight;
                sub->addBoneAssignment(boneInf);
            }
        }
    }

    const Nif::NiTexturingProperty *texprop = NULL;
    const Nif::NiMaterialProperty *matprop = NULL;
    const Nif::NiAlphaProperty *alphaprop = NULL;
    const Nif::NiVertexColorProperty *vertprop = NULL;
    const Nif::NiZBufferProperty *zprop = NULL;
    const Nif::NiSpecularProperty *specprop = NULL;
    const Nif::NiWireframeProperty *wireprop = NULL;
    bool needTangents = false;

    shape->getProperties(texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop);
    std::string matname = NIFMaterialLoader::getMaterial(data, mesh->getName(), mGroup,
                                                         texprop, matprop, alphaprop,
                                                         vertprop, zprop, specprop,
                                                         wireprop, needTangents);
    if(matname.length() > 0)
        sub->setMaterialName(matname);

    // build tangents if the material needs them
    if (needTangents)
    {
        unsigned short src,dest;
        if (!mesh->suggestTangentVectorBuildParams(Ogre::VES_TANGENT, src,dest))
            mesh->buildTangentVectors(Ogre::VES_TANGENT, src,dest);
    }

    // Create a dummy vertex animation track if there's a geom morpher controller
    // This is required to make Ogre create the buffers we will use for software vertex animation
    if (srcVerts.size() && geomMorpherController)
        mesh->createAnimation("dummy", 0)->createVertexTrack(1, sub->vertexData, Ogre::VAT_MORPH);
}
Пример #11
0
    void Utils::GetMeshInformation(
        const Ogre::MeshPtr mesh,
        size_t &vertexCount,
        Ogre::Vector3* &vertices,
        size_t &indexCount,
        unsigned* &indices) 
    {
        bool addShared = false;
        size_t currentOffset = 0;
        size_t shared_offset = 0;
        size_t nextOffset = 0;
        size_t indexOffset = 0;


        vertexCount = indexCount = 0;

        for ( unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) {
            Ogre::SubMesh* submesh = mesh->getSubMesh(i);
            if(submesh->useSharedVertices) {
                if( !addShared ) {
                    vertexCount += mesh->sharedVertexData->vertexCount;
                    addShared = true;
                }
            }
            else {
                vertexCount += submesh->vertexData->vertexCount;
            }
            indexCount += submesh->indexData->indexCount;
        }


        vertices = new Ogre::Vector3[vertexCount];
        indices = new unsigned[indexCount];

        addShared = false;

        for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) {
            Ogre::SubMesh* submesh = mesh->getSubMesh(i);

            Ogre::VertexData* vertexData = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;

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

                const Ogre::VertexElement* posElem =
                    vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);

                Ogre::HardwareVertexBufferSharedPtr vbuf =
                    vertexData->vertexBufferBinding->getBuffer(posElem->getSource());

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

                float* pReal;

                for( size_t j = 0; j < vertexData->vertexCount; ++j, vertex += vbuf->getVertexSize()) {
                    posElem->baseVertexPointerToElement(vertex, &pReal);
                    Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]);
                    vertices[currentOffset + j] = pt;
                }
                
                vbuf->unlock();
                nextOffset += vertexData->vertexCount;
            }


            Ogre::IndexData* indexData = submesh->indexData;
            size_t numTris = indexData->indexCount / 3;
            Ogre::HardwareIndexBufferSharedPtr ibuf = indexData->indexBuffer;
            
            bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);

            unsigned long* pLong = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
            unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);

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

            if ( use32bitindexes ) {
                for ( size_t k = 0; k < numTris*3; ++k) {
                    indices[indexOffset++] = pLong[k] + static_cast<unsigned long>(offset);
                }
            }
            else {
                for ( size_t k = 0; k < numTris*3; ++k) {
                    indices[indexOffset++] = static_cast<unsigned long>(pShort[k]) +
                                              static_cast<unsigned long>(offset);
                }
            }

            ibuf->unlock();
            currentOffset = nextOffset;
        }
    }
Пример #12
0
void RoR::GfxEnvmap::SetupEnvMap()
{
    m_rtt_texture = Ogre::TextureManager::getSingleton().getByName("EnvironmentTexture");

    for (int face = 0; face < NUM_FACES; face++)
    {
        m_render_targets[face] = m_rtt_texture->getBuffer(face)->getRenderTarget();
        m_cameras[face] = gEnv->sceneManager->createCamera("EnvironmentCamera-" + TOSTRING(face));
        m_cameras[face]->setAspectRatio(1.0);
        m_cameras[face]->setProjectionType(Ogre::PT_PERSPECTIVE);
        m_cameras[face]->setFixedYawAxis(false);
        m_cameras[face]->setFOVy(Ogre::Degree(90));
        m_cameras[face]->setNearClipDistance(0.1f);
        m_cameras[face]->setFarClipDistance(gEnv->mainCamera->getFarClipDistance());

        Ogre::Viewport* v = m_render_targets[face]->addViewport(m_cameras[face]);
        v->setOverlaysEnabled(false);
        v->setClearEveryFrame(true);
        v->setBackgroundColour(gEnv->mainCamera->getViewport()->getBackgroundColour());
        m_render_targets[face]->setAutoUpdated(false);
    }

    m_cameras[0]->setDirection(+Ogre::Vector3::UNIT_X);
    m_cameras[1]->setDirection(-Ogre::Vector3::UNIT_X);
    m_cameras[2]->setDirection(+Ogre::Vector3::UNIT_Y);
    m_cameras[3]->setDirection(-Ogre::Vector3::UNIT_Y);
    m_cameras[4]->setDirection(-Ogre::Vector3::UNIT_Z);
    m_cameras[5]->setDirection(+Ogre::Vector3::UNIT_Z);

    if (App::diag_envmap.GetActive())
    {
        // create fancy mesh for debugging the envmap
        Ogre::Overlay* overlay = Ogre::OverlayManager::getSingleton().create("EnvMapDebugOverlay");
        if (overlay)
        {
            Ogre::Vector3 position = Ogre::Vector3::ZERO;
            float scale = 1.0f;

            Ogre::MeshPtr mesh = Ogre::MeshManager::getSingletonPtr()->createManual("cubeMapDebug", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
            // create sub mesh
            Ogre::SubMesh* sub = mesh->createSubMesh();

            // Initialize render operation
            sub->operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST;
            //
            sub->useSharedVertices = true;
            mesh->sharedVertexData = new Ogre::VertexData;
            sub->indexData = new Ogre::IndexData;

            // Create vertex declaration
            size_t offset = 0;
            mesh->sharedVertexData->vertexDeclaration->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
            offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
            mesh->sharedVertexData->vertexDeclaration->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_TEXTURE_COORDINATES);

            // Create and bind vertex buffer
            mesh->sharedVertexData->vertexCount = 14;
            Ogre::HardwareVertexBufferSharedPtr vertexBuffer =
                Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
                    mesh->sharedVertexData->vertexDeclaration->getVertexSize(0),
                    mesh->sharedVertexData->vertexCount,
                    Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
            mesh->sharedVertexData->vertexBufferBinding->setBinding(0, vertexBuffer);

            // Vertex data
            static const float vertexData[] = {
                // Position      Texture coordinates    // Index
                0.0, 2.0, -1.0, 1.0, 1.0, //  0
                0.0, 1.0, -1.0, -1.0, 1.0, //  1
                1.0, 2.0, -1.0, 1.0, -1.0, //  2
                1.0, 1.0, -1.0, -1.0, -1.0, //  3
                2.0, 2.0, 1.0, 1.0, -1.0, //  4
                2.0, 1.0, 1.0, -1.0, -1.0, //  5
                3.0, 2.0, 1.0, 1.0, 1.0, //  6
                3.0, 1.0, 1.0, -1.0, 1.0, //  7
                4.0, 2.0, -1.0, 1.0, 1.0, //  8
                4.0, 1.0, -1.0, -1.0, 1.0, //  9
                1.0, 3.0, -1.0, 1.0, 1.0, // 10
                2.0, 3.0, 1.0, 1.0, 1.0, // 11
                1.0, 0.0, -1.0, -1.0, 1.0, // 12
                2.0, 0.0, 1.0, -1.0, 1.0, // 13
            };

            // Fill vertex buffer
            float* pData = static_cast<float*>(vertexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD));
            for (size_t vertex = 0, i = 0; vertex < mesh->sharedVertexData->vertexCount; vertex++)
            {
                // Position
                *pData++ = position.x + scale * vertexData[i++];
                *pData++ = position.y + scale * vertexData[i++];
                *pData++ = 0.0;

                // Texture coordinates
                *pData++ = vertexData[i++];
                *pData++ = vertexData[i++];
                *pData++ = vertexData[i++];
            }
            vertexBuffer->unlock();

            // Create index buffer
            sub->indexData->indexCount = 36;
            Ogre::HardwareIndexBufferSharedPtr indexBuffer =
                Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
                    Ogre::HardwareIndexBuffer::IT_16BIT,
                    sub->indexData->indexCount,
                    Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
            sub->indexData->indexBuffer = indexBuffer;

            // Index data
            static const Ogre::uint16 indexData[] = {
                // Indices         // Face
                 0,  1,  2,        //  0
                 2,  1,  3,        //  1
                 2,  3,  4,        //  2
                 4,  3,  5,        //  3
                 4,  5,  6,        //  4
                 6,  5,  7,        //  5
                 6,  7,  8,        //  6
                 8,  7,  9,        //  7
                10,  2, 11,        //  8
                11,  2,  4,        //  9
                 3, 12,  5,        // 10
                 5, 12, 13,        // 11
            };

            // Fill index buffer
            indexBuffer->writeData(0, indexBuffer->getSizeInBytes(), indexData, true);

            mesh->_setBounds(Ogre::AxisAlignedBox::BOX_INFINITE);
            mesh->_setBoundingSphereRadius(10);
            mesh->load();

            Ogre::Entity* e = gEnv->sceneManager->createEntity(mesh->getName());
            e->setCastShadows(false);
            e->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY - 1);
            e->setVisible(true);

            e->setMaterialName("tracks/EnvMapDebug");
            Ogre::SceneNode* mDebugSceneNode = new Ogre::SceneNode(gEnv->sceneManager);
            mDebugSceneNode->attachObject(e);
            mDebugSceneNode->setPosition(Ogre::Vector3(0, 0, -5));
            mDebugSceneNode->setFixedYawAxis(true, Ogre::Vector3::UNIT_Y);
            mDebugSceneNode->setVisible(true);
            mDebugSceneNode->_update(true, true);
            mDebugSceneNode->_updateBounds();
            overlay->add3D(mDebugSceneNode);
            overlay->show();
        }
    }
}
void
TerrainTileEditable::createGeometry(TerrainData* data, int xbase, int zbase, int xsize, int zsize)
{
    destoryGeometry();

    // build the material backet map
    MaterialBucketMap materialBucketMap;
    buildMaterialBucketMap(materialBucketMap);

	// Build renderables
    for (MaterialBucketMap::const_iterator im = materialBucketMap.begin(); im != materialBucketMap.end(); ++im)
	{
        const MaterialBucket* mb = &im->second;

        TerrainTileEditableRenderable* renderable = new TerrainTileEditableRenderable(this, mb->layerIndex);
        mRenderables.push_back(renderable);

        size_t numQuads = mb->grids.size();
        size_t indexCount = numQuads * 6;

		renderable->mMaterial = mb->material;

		Ogre::HardwareIndexBufferSharedPtr indexBuffer =
			Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
				Ogre::HardwareIndexBuffer::IT_16BIT,
				indexCount,
				Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);

		Ogre::IndexData* indexData = new Ogre::IndexData;
		indexData->indexBuffer = indexBuffer;
		indexData->indexStart = 0;
		indexData->indexCount = indexCount;

        renderable->mRenderOp.indexData = indexData;
        renderable->mRenderOp.vertexData = mVertexDatas[mb->layerIndex];
        renderable->mRenderOp.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST;
        renderable->mRenderOp.useIndexes = true;

		ushort* pIndices = static_cast<ushort*>(indexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD));
        for (GridIdList::const_iterator igrid = mb->grids.begin(); igrid != mb->grids.end(); ++igrid)
		{
            size_t grid = *igrid;
            const TerrainData::GridInfo& gridInfo = data->mGridInfos[grid];
            const TerrainData::Corner* corners = gridInfo.getCorners();
            int x = grid % data->mXSize - xbase;
            int z = grid / data->mXSize - zbase;
            assert(x < xsize && z < zsize);
            size_t index = (z*xsize + x) * 4;

            *pIndices++ = index + corners[1];
            *pIndices++ = index + corners[0];
            *pIndices++ = index + corners[2];

            *pIndices++ = index + corners[1];
            *pIndices++ = index + corners[2];
            *pIndices++ = index + corners[3];
		}
		indexBuffer->unlock();
	}

    for (size_t layerIndex = 0; layerIndex < 2; ++layerIndex)
    {
        fillLayerBuffer(layerIndex, mVertexDatas.back()->vertexBufferBinding->getBuffer(layerIndex+1));
    }

    mGeometryOutOfDate = false;
}
Пример #14
0
        CompoundCollisionShape* CollisionShapeManager::PerformConvexDecomposition(const String& Name, Graphics::Mesh* ObjectMesh, Whole Depth, Real CPercent, Real PPercent, Boole UseAllSubmeshes)
        {
            //new submesh friendly code
            Ogre::MeshPtr myMesh = ObjectMesh->_GetInternalMesh();
            Ogre::SubMesh* subMesh = NULL;
            Ogre::IndexData*  indexData = NULL;
            Ogre::VertexData* vertexData = NULL;
            Boole use32bitindexes = false;
            unsigned int currtriCount = 0;
            unsigned int triCount = 0;
            unsigned int vCount = 0;
            unsigned int iCount = 0;
            Whole VertPrevSize = 0;
            Whole IndiPrevSize = 0;
            Boole SharedVerts = myMesh->getSubMesh(0)->useSharedVertices;

            Whole* VertPerSubMesh = NULL;

            if(UseAllSubmeshes)
            {
                VertPerSubMesh = new Whole[myMesh->getNumSubMeshes()];
                for( Whole X = 0 ; X < myMesh->getNumSubMeshes() ; X++ )
                {
                    vCount += SharedVerts ? myMesh->sharedVertexData->vertexCount : myMesh->getSubMesh(X)->vertexData->vertexCount;
                    iCount += myMesh->getSubMesh(X)->indexData->indexCount;
                    VertPerSubMesh[X] = SharedVerts ? myMesh->sharedVertexData->vertexCount : myMesh->getSubMesh(X)->vertexData->vertexCount;
                }
            }else{
                vCount += SharedVerts ? myMesh->sharedVertexData->vertexCount : myMesh->getSubMesh(0)->vertexData->vertexCount;
                iCount += myMesh->getSubMesh(0)->indexData->indexCount;
            }

            Ogre::Vector3* vertices = new Ogre::Vector3[vCount];
            unsigned int* indices  = new unsigned int[iCount];

            for( unsigned short int SubMeshIndex = 0 ; SubMeshIndex < myMesh->getNumSubMeshes() ; SubMeshIndex++ )
            {
                if( !UseAllSubmeshes && (SubMeshIndex > 0) )
                    break;
                if( SharedVerts && (SubMeshIndex > 0) )
                    break;

                subMesh = myMesh->getSubMesh(SubMeshIndex);
                indexData = subMesh->indexData;
                vertexData = SharedVerts ? myMesh->sharedVertexData : myMesh->getSubMesh(SubMeshIndex)->vertexData;

                const Ogre::VertexElement* posElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
                Ogre::HardwareVertexBufferSharedPtr vBuffer = vertexData->vertexBufferBinding->getBuffer(posElem->getSource());
                Ogre::HardwareIndexBufferSharedPtr iBuffer = indexData->indexBuffer;
                currtriCount=indexData->indexCount/3;
                triCount+=(indexData->indexCount/3);

                unsigned char* vertex = static_cast<unsigned char*>(vBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
                float* pReal = NULL;
                for( size_t j = 0 ; j < vertexData->vertexCount ; j++, vertex += vBuffer->getVertexSize() )
                {
                    posElem->baseVertexPointerToElement(vertex, &pReal);
                    vertices[j + VertPrevSize].x = *pReal++;
                    vertices[j + VertPrevSize].y = *pReal++;
                    vertices[j + VertPrevSize].z = *pReal++;
                }
                vBuffer->unlock();
                size_t index_offset = 0;
                use32bitindexes = (iBuffer->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);

                unsigned long* pLong = static_cast<unsigned long*>(iBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
                unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);

                if( use32bitindexes )
                {
                    for (size_t k = 0; k < currtriCount*3; ++k)
                    {
                        if(SubMeshIndex > 0 && VertPerSubMesh) {
                            indices[index_offset+IndiPrevSize] = pLong[k] + VertPerSubMesh[SubMeshIndex];
                        }else{
                            indices[index_offset+IndiPrevSize] = pLong[k];
                        }
                        index_offset++;
                    }
                }else{
                    for( size_t k = 0 ; k < currtriCount * 3 ; ++k )
                    {
                        if(SubMeshIndex > 0 && VertPerSubMesh) {
                            indices[index_offset+IndiPrevSize] = (static_cast<unsigned long>(pShort[k])) + VertPerSubMesh[SubMeshIndex];
                        }else{
                            indices[index_offset+IndiPrevSize] = static_cast<unsigned long>(pShort[k]);
                        }
                        index_offset++;
                    }
                }
                iBuffer->unlock();

                VertPrevSize += vertexData->vertexCount;
                IndiPrevSize += indexData->indexCount;
            }

            ConvexDecomposition::DecompDesc desc;
            desc.mVcount = vertexData->vertexCount;
            desc.mTcount = triCount;
            desc.mVertices = &vertices[0].x;
            desc.mIndices = &indices[0];
            unsigned int maxv  = 16;
            float skinWidth    = 0.0;
            desc.mDepth        = Depth;
            desc.mCpercent     = CPercent;
            desc.mPpercent     = PPercent;
            desc.mMaxVertices  = maxv;
            desc.mSkinWidth    = skinWidth;

            Internal::MezzConvexDecomposition decomp;
            desc.mCallback = &decomp;

            ConvexBuilder cb(desc.mCallback);
            cb.process(desc);

            CompoundCollisionShape* compound = new CompoundCollisionShape(Name);
            btTransform trans;
            trans.setIdentity();
            for (int i=0;i<decomp.m_convexShapes.size();i++)
            {
                std::stringstream namestream;
                namestream << Name << "Child" << i;
                Vector3 centroid(decomp.m_convexCentroids[i]);
                ConvexHullCollisionShape* convexShape = new ConvexHullCollisionShape(namestream.str(),decomp.m_convexShapes[i]);
                compound->AddChildShape(convexShape,centroid);
            }
            delete[] vertices;
            delete[] indices;
            delete[] VertPerSubMesh;
            return compound;
        }
Пример #15
0
void GeometryFactory::generateSphericDome (const Ogre::String &name, int segments, DomeType type) {
    // Return now if already exists
    if (Ogre::MeshManager::getSingleton ().resourceExists (name)) {
        return;
    }

    Ogre::LogManager::getSingleton ().logMessage (
        "Caelum: Creating " + name + " sphere mesh resource...");

    // Use the mesh manager to create the mesh
    Ogre::MeshPtr msh = Ogre::MeshManager::getSingleton ().createManual (name, RESOURCE_GROUP_NAME);
    // Create a submesh
    Ogre::SubMesh *sub = msh->createSubMesh ();

    // Create the shared vertex data
    Ogre::VertexData *vertexData = new Ogre::VertexData ();
    msh->sharedVertexData = vertexData;

    // Define the vertices' format
    Ogre::VertexDeclaration *vertexDecl = vertexData->vertexDeclaration;
    size_t currOffset = 0;
    // Position
    vertexDecl->addElement (0, currOffset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
    currOffset += Ogre::VertexElement::getTypeSize (Ogre::VET_FLOAT3);
    // Normal
    vertexDecl->addElement (0, currOffset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
    currOffset += Ogre::VertexElement::getTypeSize (Ogre::VET_FLOAT3);
    // Texture coordinates
    vertexDecl->addElement (0, currOffset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 0);
    currOffset += Ogre::VertexElement::getTypeSize (Ogre::VET_FLOAT2);

    // Allocate the vertex buffer
    switch (type) {
    case DT_GRADIENTS:
        vertexData->vertexCount = segments * (segments - 1) + 2;
        break;
    case DT_STARFIELD:
        vertexData->vertexCount = (segments + 1) * (segments + 1);
        break;
    };
    Ogre::HardwareVertexBufferSharedPtr vBuf = Ogre::HardwareBufferManager::getSingleton ().createVertexBuffer (vertexDecl->getVertexSize (0), vertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
    Ogre::VertexBufferBinding *binding = vertexData->vertexBufferBinding;
    binding->setBinding (0, vBuf);

    float *pVertex = static_cast<float *>(vBuf->lock (Ogre::HardwareBuffer::HBL_DISCARD));

    // Allocate the index buffer
    switch (type) {
    case DT_GRADIENTS:
        sub->indexData->indexCount = 2 * segments * (segments - 1) * 3;
        break;
    case DT_STARFIELD:
        sub->indexData->indexCount = 2 * (segments - 1) * segments * 3;
        break;
    };
    sub->indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton ().createIndexBuffer (Ogre::HardwareIndexBuffer::IT_16BIT, sub->indexData->indexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
    Ogre::HardwareIndexBufferSharedPtr iBuf = sub->indexData->indexBuffer;
    unsigned short *pIndices = static_cast<unsigned short *>(iBuf->lock (Ogre::HardwareBuffer::HBL_DISCARD));

    // Fill the buffers
    switch (type) {
    case DT_GRADIENTS:
        fillGradientsDomeBuffers (pVertex, pIndices, segments);
        break;
    case DT_STARFIELD:
        fillStarfieldDomeBuffers (pVertex, pIndices, segments);
        break;
    };

    // Close the vertex buffer
    vBuf->unlock ();

    // Close the index buffer
    iBuf->unlock ();

    // Finishing it...
    sub->useSharedVertices = true;
    msh->_setBounds (Ogre::AxisAlignedBox (-1, -1, -1, 1, 1, 1), false);
    msh->_setBoundingSphereRadius (1);
    msh->load ();

    Ogre::LogManager::getSingleton ().logMessage (
        "Caelum: generateSphericDome DONE");
}
Пример #16
0
GrassPatch::GrassPatch(int nb_blades, int nb_blade_segments, float width, float height, Ogre::SceneManager* ScnMgr)
{
	int		i, nb_particles;

	// Create the particle field
	nb_particles = nb_blades * (nb_blade_segments + 1);
	m_Particles = new GrassParticleField(nb_particles, 1);

	// Allocate the blade list
	m_Blades = new Blade *[nb_blades];
	m_NbBlades = nb_blades;
	Ogre::Radian *angle = new Ogre::Radian(Ogre::Math::PI * ((rand()%1000) / 1000.0f));

	// Create the blades of grass
	for (i = 0; i < nb_blades; i++)
	{
		m_Blades[i] = new Blade(m_Particles,
								i * (nb_blade_segments + 1),
								nb_blade_segments,
								4 + ((rand()%1000) / 1000.0f)*0.5f,
								0.3f + ((rand()%1000) / 1000.0f)*0.1f,
								width / 2 - ((rand()%1000) / 500.0f) * width,
								height / 2 - ((rand()%1000) / 500.0f) * height,
								*angle);
		m_Blades[i]->moving = true;
		m_Blades[i]->timeout = 0;
	}
	m_VertexCount = nb_blades * m_Blades[0]->GetStrippedVertexCount();
	m_TriangleCount = ((nb_blade_segments - 1) << 1) + 1;
 
    mvertexData = new Ogre::VertexData ();

    // Vertex declaration
	Ogre::VertexDeclaration* decl = mvertexData->vertexDeclaration;
	Ogre::VertexBufferBinding* binding = mvertexData->vertexBufferBinding;         
    
    size_t offset = 0;

    //position
	decl->addElement (POSITION_BINDING, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); 
	offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);

    // normal here
	decl->addElement(POSITION_BINDING, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
	offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
     
    // Diffuse Color
    decl->addElement(POSITION_BINDING, offset, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE);  
	offset += Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR);
    
    // texture here
	decl->addElement(POSITION_BINDING, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES);  
	offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);

   //position updated each frame 
	Ogre::HardwareVertexBufferSharedPtr vbuf1 = 
           Ogre::HardwareBufferManager::getSingleton().createVertexBuffer (offset,        // size of one whole vertex
																		   m_VertexCount,                                // number of vertices
																		   Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, // usage
                                                                            false);                                      // no shadow buffer

	binding->setBinding(POSITION_BINDING, vbuf1);
 

	Ogre::HardwareVertexBufferSharedPtr vVertices = binding->getBuffer(POSITION_BINDING);
	Ogre::Real *pVertices = static_cast<Ogre::Real*>( vVertices->lock( Ogre::HardwareBuffer::HBL_DISCARD ) );

    // Colour up the blades
	for (i = 0; i < m_NbBlades; i++)
        m_Blades[i]->Paint (i, pVertices); 
       
	vVertices->unlock();

    // Index buffer to handle triangle strip vertex buffer as triangle list
     
    // Create index buffer 
      int nIndexes = m_TriangleCount*3*m_NbBlades;
   
      Ogre::HardwareIndexBufferSharedPtr iBuf = 
            Ogre::HardwareBufferManager::getSingleton().createIndexBuffer (Ogre::HardwareIndexBuffer::IT_32BIT, 
                                                                nIndexes, 
                                                                Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, 
                                                                false); 

      // Fill index buffer 
      unsigned int* pIdx = static_cast<unsigned int*> (iBuf->lock (Ogre::HardwareBuffer::HBL_DISCARD)); 
               
       unsigned int j = 0;
        for (i = 0; i < m_NbBlades; i++)
	        m_Blades[i]->UpdateIndexBuffer(&j, i, pIdx);

      iBuf->unlock ();
          

    mRenderOp.vertexData = mvertexData;
//	mRenderOp.vertexData->vertexCount = m_VertexCount;
    mRenderOp.vertexData->vertexCount= nIndexes;
	mRenderOp.vertexData->vertexStart = 0;  

    mRenderOp.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST;
    mRenderOp.indexData = new Ogre::IndexData();
    mRenderOp.indexData->indexBuffer = iBuf; 
    mRenderOp.indexData->indexCount = nIndexes; 
    mRenderOp.indexData->indexStart = 0;  

	mRenderOp.useIndexes = true; 
      
    mRenderOp.srcRenderable = this;

    setMaterial ("Examples/Grass");  
 
    // setup radius the bounding box of this SimpleRenderable to big values to be sure to achieve drawing.
    mRadius = 100;
	setBoundingBox(Ogre::AxisAlignedBox(-300, -300, -300, 600, 600, 600));

 }
Пример #17
0
Mesh loadMesh(const std::string& meshName)
{
	Mesh result;

	bool addedShared = false;
	size_t currentOffset = 0;
	size_t sharedOffset = 0;
	size_t nextOffset = 0;
	size_t indexOffset = 0;

	const v3 scale        = v3::UNIT_SCALE;
	const v3 position     = v3::ZERO;
	const qv4 orientation = qv4::IDENTITY;

	Ogre::MeshManager* mm = Ogre::MeshManager::getSingletonPtr();
	
	if (! mm)
	{
		initOgreForMeshLoading();
		mm = Ogre::MeshManager::getSingletonPtr();
	}

	Ogre::MeshPtr mesh = mm->load(meshName, "General");

	// Calculate how many result.mVertices and result.mIndices we're going to need
	for (unsigned short i=0; i < mesh->getNumSubMeshes(); ++i)
	{
		Ogre::SubMesh* subMesh = mesh->getSubMesh(i);

		// We only need to add the shared result.mVertices once
		if (subMesh->useSharedVertices)
		{
			if (!addedShared)
			{
				result.mVertexCount += mesh->sharedVertexData->vertexCount;
				addedShared = true;
			}
		}
		else
		{
			result.mVertexCount += subMesh->vertexData->vertexCount;
		}

		result.mIndexCount += subMesh->indexData->indexCount;
	}

	result.mVertices.reset(new v3[result.mVertexCount]);
	result.mIndices.reset(new u32[result.mIndexCount]);

	addedShared = false;

	// Run through the sub-meshes again, adding the data into the arrays
	for (unsigned short i=0; i < mesh->getNumSubMeshes(); ++i)
	{
		Ogre::SubMesh* subMesh = mesh->getSubMesh(i);

		Ogre::VertexData* vertexData = subMesh->useSharedVertices ? mesh->sharedVertexData : subMesh->vertexData;

		if((!subMesh->useSharedVertices) || (subMesh->useSharedVertices && !addedShared))
		{
			if(subMesh->useSharedVertices)
			{
				addedShared = true;
				sharedOffset = currentOffset;
			}

			const Ogre::VertexElement* posElem = 
			    vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);

			Ogre::HardwareVertexBufferSharedPtr vbuf = 
			    vertexData->vertexBufferBinding->getBuffer(posElem->getSource());

			unsigned char* vertex =	static_cast<unsigned char*>(vbuf->lock(Ogre::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 compiled/typedefed as double:

			float* pReal;

			for( size_t j = 0; j < vertexData->vertexCount; ++j, vertex += vbuf->getVertexSize())
			{
				posElem->baseVertexPointerToElement(vertex, &pReal);
				v3 pt(pReal[0], pReal[1], pReal[2]);
				result.mVertices[currentOffset + j] = (orientation * (pt * scale)) + position;
			}

			vbuf->unlock();
			nextOffset += vertexData->vertexCount;
		}

		Ogre::IndexData* index_data = subMesh->indexData;
		size_t numTris = index_data->indexCount / 3;
		Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;

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

		unsigned long*  pLong = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
		unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);


		size_t offset = (subMesh->useSharedVertices)? sharedOffset : currentOffset;

		if (use32bitindexes)
		{
			for (size_t k = 0; k < numTris*3; ++k)
			{
				result.mIndices[indexOffset++] = pLong[k] + static_cast<unsigned long>(offset);
			}
		}
		else
		{
			for (size_t k = 0; k < numTris*3; ++k)
			{
				result.mIndices[indexOffset++] = static_cast<unsigned long>(pShort[k]) + static_cast<unsigned long>(offset);
			}
		}

		ibuf->unlock();
		currentOffset = nextOffset;
	}
	
	return result;
}
Пример #18
0
void GetTrianglesFromMesh(Ogre::Mesh* mesh, std::vector<float3>& dest)
{
    dest.clear();
    
    try
    {

    for(uint i = 0; i < mesh->getNumSubMeshes(); ++i)
    {
        Ogre::SubMesh* submesh = mesh->getSubMesh(i);
        
        Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;
        const Ogre::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
        Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
        unsigned char* vertices = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
        size_t vertexSize = vbuf->getVertexSize();
        float* pReal = 0;
        
        Ogre::IndexData* index_data = submesh->indexData;
        size_t numTris = index_data->indexCount / 3;
        Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
        u32*  pLong = static_cast<u32*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
        u16* pShort = reinterpret_cast<u16*>(pLong);
        bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
        
        if (use32bitindexes)
        {
            for(size_t k = 0; k < numTris * 3; k += 3)
            {
                uint i1 = pLong[k];
                uint i2 = pLong[k+1];
                uint i3 = pLong[k+2];
                
                posElem->baseVertexPointerToElement(vertices + i1 * vertexSize, &pReal);
                dest.push_back(float3(pReal[0], pReal[1], pReal[2]));
                    
                posElem->baseVertexPointerToElement(vertices + i2 * vertexSize, &pReal);
                dest.push_back(float3(pReal[0], pReal[1], pReal[2]));
                    
                posElem->baseVertexPointerToElement(vertices + i3 * vertexSize, &pReal);
                dest.push_back(float3(pReal[0], pReal[1], pReal[2]));
                

            }
        }
        else
        {
            for(size_t k = 0; k < numTris * 3; k += 3)
            {
                uint i1 = pShort[k];
                uint i2 = pShort[k+1];
                uint i3 = pShort[k+2];
                
                posElem->baseVertexPointerToElement(vertices + i1 * vertexSize, &pReal);
                dest.push_back(float3(pReal[0], pReal[1], pReal[2]));
                    
                posElem->baseVertexPointerToElement(vertices + i2 * vertexSize, &pReal);
                dest.push_back(float3(pReal[0], pReal[1], pReal[2]));
                    
                posElem->baseVertexPointerToElement(vertices + i3 * vertexSize, &pReal);
                dest.push_back(float3(pReal[0], pReal[1], pReal[2]));
            }
        }
        
        vbuf->unlock();
        ibuf->unlock();
    }

    } catch(Ogre::Exception &e)
    {
        ///\todo Fix Ogre to not allow meshes like this to be successfully created.
        LogError("GetTrianglesFromMesh failed for mesh! Ogre threw an exception: " + QString(e.what()));
        dest.clear();
    }
}
Пример #19
0
void MilkshapePlugin::doExportMesh(msModel* pModel)
{


    // Create singletons
    Ogre::SkeletonManager skelMgr;
    Ogre::DefaultHardwareBufferManager defHWBufMgr;
	Ogre::LogManager& logMgr = Ogre::LogManager::getSingleton();
	Ogre::MeshManager meshMgr;


    //
    // choose filename
    //
    OPENFILENAME ofn;
    memset (&ofn, 0, sizeof (OPENFILENAME));

    char szFile[MS_MAX_PATH];
    char szFileTitle[MS_MAX_PATH];
    char szDefExt[32] = "mesh";
    char szFilter[128] = "OGRE .mesh Files (*.mesh)\0*.mesh\0All Files (*.*)\0*.*\0\0";
    szFile[0] = '\0';
    szFileTitle[0] = '\0';

    ofn.lStructSize = sizeof (OPENFILENAME);
    ofn.lpstrDefExt = szDefExt;
    ofn.lpstrFilter = szFilter;
    ofn.lpstrFile = szFile;
    ofn.nMaxFile = MS_MAX_PATH;
    ofn.lpstrFileTitle = szFileTitle;
    ofn.nMaxFileTitle = MS_MAX_PATH;
    ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;
    ofn.lpstrTitle = "Export to OGRE Mesh";

    if (!::GetSaveFileName (&ofn))
        return /*0*/;

    logMgr.logMessage("Creating Mesh object...");
    Ogre::MeshPtr ogreMesh = Ogre::MeshManager::getSingleton().create("export", 
        Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
    logMgr.logMessage("Mesh object created.");

    bool foundBoneAssignment = false;

    // No shared geometry
    int i;
	int wh, numbones;
	int intweight[3], intbones[3];
    size_t j;
    Ogre::Vector3 min, max, currpos;
    Ogre::Real maxSquaredRadius;
    bool first = true;
    for (i = 0; i < msModel_GetMeshCount (pModel); i++)
    {
        msMesh *pMesh = msModel_GetMeshAt (pModel, i);

        logMgr.logMessage("Creating SubMesh object...");
        Ogre::SubMesh* ogreSubMesh = ogreMesh->createSubMesh();
        logMgr.logMessage("SubMesh object created.");
        // Set material
        logMgr.logMessage("Getting SubMesh Material...");
        int matIdx = msMesh_GetMaterialIndex(pMesh);

        if (matIdx == -1)
        {
            // No material, use blank
            ogreSubMesh->setMaterialName("BaseWhite");
            logMgr.logMessage("No Material, using default 'BaseWhite'.");
        }
        else
        {

            msMaterial *pMat = msModel_GetMaterialAt(pModel, matIdx);
            ogreSubMesh->setMaterialName(pMat->szName);
            logMgr.logMessage("SubMesh Material Done.");
        }


        logMgr.logMessage("Setting up geometry...");
        // Set up mesh geometry
        ogreSubMesh->vertexData = new Ogre::VertexData();
        ogreSubMesh->vertexData->vertexCount = msMesh_GetVertexCount (pMesh);
        ogreSubMesh->vertexData->vertexStart = 0;
        Ogre::VertexBufferBinding* bind = ogreSubMesh->vertexData->vertexBufferBinding;
        Ogre::VertexDeclaration* decl = ogreSubMesh->vertexData->vertexDeclaration;
        // Always 1 texture layer, 2D coords
        #define POSITION_BINDING 0
        #define NORMAL_BINDING 1
        #define TEXCOORD_BINDING 2
        decl->addElement(POSITION_BINDING, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
        decl->addElement(NORMAL_BINDING, 0, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
        decl->addElement(TEXCOORD_BINDING, 0, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES);
        // Create buffers
        Ogre::HardwareVertexBufferSharedPtr pbuf = Ogre::HardwareBufferManager::getSingleton().
            createVertexBuffer(decl->getVertexSize(POSITION_BINDING), ogreSubMesh->vertexData->vertexCount,
                Ogre::HardwareBuffer::HBU_DYNAMIC, false);
        Ogre::HardwareVertexBufferSharedPtr nbuf = Ogre::HardwareBufferManager::getSingleton().
            createVertexBuffer(decl->getVertexSize(NORMAL_BINDING), ogreSubMesh->vertexData->vertexCount,
                Ogre::HardwareBuffer::HBU_DYNAMIC, false);
        Ogre::HardwareVertexBufferSharedPtr tbuf = Ogre::HardwareBufferManager::getSingleton().
            createVertexBuffer(decl->getVertexSize(TEXCOORD_BINDING), ogreSubMesh->vertexData->vertexCount,
                Ogre::HardwareBuffer::HBU_DYNAMIC, false);
        bind->setBinding(POSITION_BINDING, pbuf);
        bind->setBinding(NORMAL_BINDING, nbuf);
        bind->setBinding(TEXCOORD_BINDING, tbuf);

        ogreSubMesh->useSharedVertices = false;

        float* pPos = static_cast<float*>(
            pbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));

        logMgr.logMessage("Doing positions and texture coords...");
        for (j = 0; j < ogreSubMesh->vertexData->vertexCount; ++j)
        {
            logMgr.logMessage("Doing vertex " + Ogre::StringConverter::toString(j));
            msVertex *pVertex = msMesh_GetVertexAt (pMesh, (int)j);
			msVertexEx *pVertexEx=msMesh_GetVertexExAt(pMesh, (int)j);
            msVec3 Vertex;
            msVertex_GetVertex (pVertex, Vertex);

            *pPos++ = Vertex[0];
            *pPos++ = Vertex[1];
            *pPos++ = Vertex[2];
            // Deal with bounds
            currpos = Ogre::Vector3(Vertex[0], Vertex[1], Vertex[2]);
            if (first)
            {
                min = max = currpos;
                maxSquaredRadius = currpos.squaredLength();
                first = false;
            }
            else
            {
                min.makeFloor(currpos);
                max.makeCeil(currpos);
                maxSquaredRadius = std::max(maxSquaredRadius, currpos.squaredLength());
            }

            int boneIdx = msVertex_GetBoneIndex(pVertex);
            if (boneIdx != -1)
            {
				foundBoneAssignment = true;
				numbones = 1;
				intbones[0] = intbones[1] = intbones[2] = -1;
				intweight[0] = intweight[1] = intweight[2] = 0;
				for(wh = 0; wh < 3; ++wh) 
				{
					intbones[wh] = msVertexEx_GetBoneIndices(pVertexEx, wh);
					if(intbones[wh] == -1) 
						break;

					++numbones;
					intweight[wh] = msVertexEx_GetBoneWeights(pVertexEx, wh);

				} // for(k)
				Ogre::VertexBoneAssignment vertAssign;
				vertAssign.boneIndex = boneIdx;
				vertAssign.vertexIndex = (unsigned int)j;
				if(numbones == 1) 
				{
					vertAssign.weight = 1.0;
				} // single assignment
				else 
				{
					vertAssign.weight=(Ogre::Real)intweight[0]/100.0;
				}
				ogreSubMesh->addBoneAssignment(vertAssign);
				if(numbones > 1) 
				{
					// this somewhat contorted logic is because the first weight [0] matches to the bone assignment
					// located with pVertex. The next two weights [1][2] match up to the first two bones found
					// with pVertexEx [0][1]. The weight for the fourth bone, if present, is the unassigned weight
					for(wh = 0; wh < 3; wh++) 
					{
						boneIdx = intbones[wh];
						if(boneIdx == -1) 
							break;
						vertAssign.boneIndex = boneIdx;
						vertAssign.vertexIndex = (unsigned int)j;
						if(wh == 2) 
						{ 
							// fourth weight is 1.0-(sumoffirstthreeweights)
							vertAssign.weight = 1.0-(((Ogre::Real)intweight[0]/100.0)+
								((Ogre::Real)intweight[1]/100.0)+((Ogre::Real)intweight[2]/100.0));
						}
						else 
						{
							vertAssign.weight=(Ogre::Real)intweight[wh+1];
						}
						ogreSubMesh->addBoneAssignment(vertAssign);
					} // for(k)
				} // if(numbones)
			}

        }
        pbuf->unlock();

        float* pTex = static_cast<float*>(
            tbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
        logMgr.logMessage("Doing uvs, normals and indexes (v2)...");

        // Aargh, Milkshape uses stupid separate normal indexes for the same vertex like 3DS
        // Normals aren't described per vertex but per triangle vertex index
        // Pain in the arse, we have to do vertex duplication again if normals differ at a vertex (non smooth)
        // WHY don't people realise this format is a pain for passing to 3D APIs in vertex buffers?
        float* pNorm = static_cast<float*>(
            nbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
        ogreSubMesh->indexData->indexCount = msMesh_GetTriangleCount (pMesh) * 3;
        // Always use 16-bit buffers, Milkshape can't handle more anyway
        Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton().
            createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT,
            ogreSubMesh->indexData->indexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
        ogreSubMesh->indexData->indexBuffer = ibuf;
        unsigned short *pIdx = static_cast<unsigned short*>(
            ibuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
        for (j = 0; j < ogreSubMesh->indexData->indexCount; j+=3)
        {
            msTriangle *pTriangle = msMesh_GetTriangleAt (pMesh, (int)j/3);
			msTriangleEx *pTriangleEx=msMesh_GetTriangleExAt(pMesh, (int)j/3);
            word nIndices[3];
            msTriangle_GetVertexIndices (pTriangle, nIndices);
            msVec3 Normal;
            msVec2 uv;
            int k, vertIdx;

            for (k = 0; k < 3; ++k)
            {
                vertIdx = nIndices[k];
                // Face index
                pIdx[j+k] = vertIdx;

                // Vertex normals
                // For the moment, ignore any discrepancies per vertex
				msTriangleEx_GetNormal(pTriangleEx, k, &Normal[0]);
				msTriangleEx_GetTexCoord(pTriangleEx, k, &uv[0]);
				pTex[(vertIdx*2)]=uv[0];
				pTex[(vertIdx*2)+1]=uv[1];
                pNorm[(vertIdx*3)] = Normal[0];
                pNorm[(vertIdx*3)+1] = Normal[1];
                pNorm[(vertIdx*3)+2] = Normal[2];
            }

        } // Faces
        nbuf->unlock();
        ibuf->unlock();
        tbuf->unlock();

        // Now use Ogre's ability to reorganise the vertex buffers the best way
        Ogre::VertexDeclaration* newDecl = 
            ogreSubMesh->vertexData->vertexDeclaration->getAutoOrganisedDeclaration(
                foundBoneAssignment, false);
        Ogre::BufferUsageList bufferUsages;
        for (size_t u = 0; u <= newDecl->getMaxSource(); ++u)
            bufferUsages.push_back(Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
        ogreSubMesh->vertexData->reorganiseBuffers(newDecl, bufferUsages);


        logMgr.logMessage("Geometry done.");
    } // SubMesh

    // Set bounds
    ogreMesh->_setBoundingSphereRadius(Ogre::Math::Sqrt(maxSquaredRadius));
    ogreMesh->_setBounds(Ogre::AxisAlignedBox(min, max), false);


    // Keep hold of a Skeleton pointer for deletion later
    // Mesh uses Skeleton pointer for skeleton name
    Ogre::SkeletonPtr pSkel;

    if (exportSkeleton && foundBoneAssignment)
    {
        // export skeleton, also update mesh to point to it
        pSkel = doExportSkeleton(pModel, ogreMesh);
    }
    else if (!exportSkeleton && foundBoneAssignment)
    {
        // We've found bone assignments, but skeleton is not to be exported
        // Prompt the user to find the skeleton
        if (!locateSkeleton(ogreMesh))
            return;

    }

    // Export
    logMgr.logMessage("Creating MeshSerializer..");
    Ogre::MeshSerializer serializer;
    logMgr.logMessage("MeshSerializer created.");

    // Generate LODs if required
    if (generateLods)
    {
        // Build LOD depth list
        Ogre::Mesh::LodDistanceList distList;
        float depth = 0;
        for (unsigned short depthidx = 0; depthidx < numLods; ++depthidx)
        {
            depth += lodDepthIncrement;
            distList.push_back(depth);
        }

        ogreMesh->generateLodLevels(distList, lodReductionMethod, lodReductionAmount);
    }

    if (generateEdgeLists)
    {
        ogreMesh->buildEdgeList();
    }

    if (generateTangents)
    {
		unsigned short src, dest;
		ogreMesh->suggestTangentVectorBuildParams(tangentSemantic, src, dest);
		ogreMesh->buildTangentVectors(tangentSemantic, src, dest, tangentsSplitMirrored, tangentsSplitRotated, tangentsUseParity);
    }

    // Export
    Ogre::String msg;
	msg  = "Exporting mesh data to file '" + Ogre::String(szFile) + "'";
    logMgr.logMessage(msg);
    serializer.exportMesh(ogreMesh.getPointer(), szFile);
    logMgr.logMessage("Export successful");

    Ogre::MeshManager::getSingleton().remove(ogreMesh->getHandle());
    if (!pSkel.isNull())
        Ogre::SkeletonManager::getSingleton().remove(pSkel->getHandle());

	if (exportMaterials && msModel_GetMaterialCount(pModel) > 0)
	{
		doExportMaterials(pModel);
	}
}
Пример #20
0
        mesh::mesh(const std::string &mn, const mat4 &tf, const world &_world):
        /** Don't know if world() is the best thing to pass but it works for now **/
            _mesh(NewtonMeshCreate(_world))
        {
            Ogre::MeshPtr meshPtr;
            try
            {
                meshPtr = Ogre::MeshPtr(Ogre::MeshManager::getSingleton().load(mn,
                    Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME));
            }
            catch(...)
            {
                return;
            }

            const Ogre::Mesh &mesh = *meshPtr;

            NewtonMeshBeginFace(_mesh);

            for (unsigned smi = 0; smi < mesh.getNumSubMeshes(); smi++) {
                Ogre::SubMesh *subMesh = mesh.getSubMesh(smi);

                Ogre::VertexData *vertexData =
                    (subMesh->useSharedVertices) ?
                        vertexData = mesh.sharedVertexData : vertexData = subMesh->vertexData;

                Ogre::VertexDeclaration *vertexDecl = vertexData->vertexDeclaration;
                const Ogre::VertexElement *element = vertexDecl->findElementBySemantic(Ogre::VES_POSITION);

                Ogre::HardwareVertexBufferSharedPtr vertexHVBSP =
                    vertexData->vertexBufferBinding->getBuffer(element->getSource());
                unsigned char *vPtr = (unsigned char*)(vertexHVBSP->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));

                Ogre::IndexData *indexData = subMesh->indexData;
                size_t numIndices = indexData->indexCount;
                size_t numTris = numIndices / 3;

                // get pointer!
                Ogre::HardwareIndexBufferSharedPtr indexHIBSP = indexData->indexBuffer;

                // 16 or 32 bit indices?
                bool indicesAre32Bit = (indexHIBSP->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
                unsigned long *longPtr = NULL;
                unsigned short *shortPtr = NULL;

                if (indicesAre32Bit)
                    longPtr = static_cast<unsigned long*>(
                        indexHIBSP->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
                else
                    shortPtr = static_cast<unsigned short*>(
                        indexHIBSP->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));

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

                for (size_t i = 0; i < numTris; i++) {
                    vec3 triVertices[3];
                    unsigned char *vOffset = NULL;
                    float *vertexPosPtr = NULL;
                    int idx = 0;

                    for (int j = 0; j < 3; j++) {
                        if (indicesAre32Bit)
                            idx = longPtr[iOffset + j];
                        else
                            idx = shortPtr[iOffset + j];

                        vOffset = vPtr + (idx * vertexHVBSP->getVertexSize());
                        element->baseVertexPointerToElement(vOffset, &vertexPosPtr);

                        triVertices[j].x = *vertexPosPtr; vertexPosPtr++;
                        triVertices[j].y = *vertexPosPtr; vertexPosPtr++;
                        triVertices[j].z = *vertexPosPtr; vertexPosPtr++;

                        triVertices[j] = tf * triVertices[j];
                    }

                    // _mesh, 3 vertices (triangle), (float = 4 bytes) * 3
                    // index = index of sub mesh (easy to recognize)
                    NewtonMeshAddFace(_mesh, 3, &triVertices[0].x, sizeof(float) * 3, smi);

                    iOffset += 3;
                }

                //unlock the buffers!
                vertexHVBSP->unlock();
                indexHIBSP->unlock();
            }

            NewtonMeshEndFace(_mesh);
        }
Пример #21
0
void PhysicsManager::getMeshInformation(Ogre::MeshPtr mesh,size_t &vertex_count,Vector3* &vertices, size_t &index_count, unsigned* &indices, const Ogre::Vector3 &position,  const Ogre::Quaternion &orient,const Ogre::Vector3 &scale)
{
	vertex_count = index_count = 0;

	bool added_shared = false;
	size_t current_offset = vertex_count;
	size_t shared_offset = vertex_count;
	size_t next_offset = vertex_count;
	size_t index_offset = index_count;
	size_t prev_vert = vertex_count;
	size_t prev_ind = index_count;

	// Calculate how many vertices and indices we're going to need
	for(int i = 0;i < mesh->getNumSubMeshes();i++)
	{
		SubMesh* submesh = mesh->getSubMesh(i);

		// We only need to add the shared vertices once
		if(submesh->useSharedVertices)
		{
			if(!added_shared)
			{
				VertexData* vertex_data = mesh->sharedVertexData;
				vertex_count += vertex_data->vertexCount;
				added_shared = true;
			}
		}
		else
		{
			VertexData* vertex_data = submesh->vertexData;
			vertex_count += vertex_data->vertexCount;
		}

		// Add the indices
		Ogre::IndexData* index_data = submesh->indexData;
		index_count += index_data->indexCount;
	}

	// Allocate space for the vertices and indices
	vertices = new Vector3[vertex_count];
	indices = new unsigned[index_count];

	added_shared = false;

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

		Ogre::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 Ogre::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
			Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
			unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
			Ogre::Real* pReal;

			for(size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
			{
				posElem->baseVertexPointerToElement(vertex, &pReal);

				Vector3 pt;

				pt.x = (*pReal++);
				pt.y = (*pReal++);
				pt.z = (*pReal++);

				pt = (orient * (pt * scale)) + position;

				vertices[current_offset + j].x = pt.x;
				vertices[current_offset + j].y = pt.y;
				vertices[current_offset + j].z = pt.z;
			}
			vbuf->unlock();
			next_offset += vertex_data->vertexCount;
		}

		Ogre::IndexData* index_data = submesh->indexData;

		size_t numTris = index_data->indexCount / 3;
		unsigned short* pShort;
		unsigned int* pInt;
		Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
		bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
		if (use32bitindexes) pInt = static_cast<unsigned int*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
		else pShort = static_cast<unsigned short*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));

		for(size_t k = 0; k < numTris; ++k)
		{
			size_t offset = (submesh->useSharedVertices)?shared_offset:current_offset;

			unsigned int vindex = use32bitindexes? *pInt++ : *pShort++;
			indices[index_offset + 0] = vindex + offset;
			vindex = use32bitindexes? *pInt++ : *pShort++;
			indices[index_offset + 1] = vindex + offset;
			vindex = use32bitindexes? *pInt++ : *pShort++;
			indices[index_offset + 2] = vindex + offset;

			index_offset += 3;
		}
		ibuf->unlock();
		current_offset = next_offset;
	}
}
Пример #22
0
void ChunkBase::generateMesh()
{
	if (!mIsModified) return;

	generateVertices();

	if (isEmpty) {

		return;
	}

	uint32_t numVertices, numIndices;
	if (mNumVertices > DefaultFaces * 4) {
		// more vertices than the default buffer can hold -> allocate new one;
		if (mVertexBufferCreated) {
			removeMesh();
		}

		numVertices = mNumVertices;
		numIndices = mNumIndices;
	} else {
		numVertices = DefaultFaces * 4;
		numIndices = DefaultFaces * 6;
	}

	if (!mVertexBufferCreated) {
		mMeshPtr = Ogre::MeshManager::getSingleton().createManual(mChunkName, "Game");
		Ogre::SubMesh* sub = mMeshPtr->createSubMesh();
		
		/// Create vertex data structure for 8 vertices shared between submeshes
		mMeshPtr->sharedVertexData = new Ogre::VertexData();
		mMeshPtr->sharedVertexData->vertexCount = mNumVertices;
 
		/// Create declaration (memory format) of vertex data
		Ogre::VertexDeclaration* decl = mMeshPtr->sharedVertexData->vertexDeclaration;
    
		size_t offset = 0;
		// 1st buffer
		decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
		offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
		decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
		offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
		decl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES);
		offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
    
		/// Allocate vertex buffer of the requested number of vertices (vertexCount) and bytes per vertex (offset)
		Ogre::HardwareVertexBufferSharedPtr vbuf = Ogre::HardwareBufferManager::getSingleton().
			createVertexBuffer(offset, numVertices, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
    
		/// Upload the vertex data to the card
		vbuf->writeData(0, (decl->getVertexSize(0) * mNumVertices), mVertices, true);
 
		/// Set vertex buffer binding so buffer 0 is bound to our vertex buffer
		Ogre::VertexBufferBinding* bind = mMeshPtr->sharedVertexData->vertexBufferBinding; 
		bind->setBinding(0, vbuf);

		/// Allocate index buffer of the requested number of vertices (ibufCount) 
		Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton().
			createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, numIndices, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
 
		/// Upload the index data to the card
		ibuf->writeData(0, (ibuf->getIndexSize() * mNumIndices), mIndices, true);
 
		/// Set parameters of the submesh
		sub->indexData->indexBuffer = ibuf;
		sub->indexData->indexCount = mNumIndices;

		/// Set bounding information (for culling)
		mMeshPtr->_setBounds(Ogre::AxisAlignedBox(0, 0, 0, Ogre::Real(ChunkSizeX), Ogre::Real(mHighestCube), Ogre::Real(ChunkSizeZ)));
		mMeshPtr->_setBoundingSphereRadius((Ogre::Real) std::sqrt((float) (2 * 16 * 16 + 128 * 128)));
 
		/// Notify -Mesh object that it has been loaded
		mMeshPtr->load();

		mVertexBufferCreated = true;
	} else {
		Ogre::VertexDeclaration* decl = mMeshPtr->sharedVertexData->vertexDeclaration;

		mMeshPtr->sharedVertexData->vertexCount = mNumVertices;
		Ogre::SubMesh* sub = mMeshPtr->getSubMesh(0);
		sub->indexData->indexCount = mNumIndices;

		/// Upload the new vertex data to the card
		Ogre::HardwareVertexBufferSharedPtr vbuf = mMeshPtr->sharedVertexData->vertexBufferBinding->getBuffer(0);
		vbuf->writeData(0, (decl->getVertexSize(0) * mNumVertices), mVertices, true);

		/// Upload the index data to the card
		Ogre::HardwareIndexBufferSharedPtr ibuf = sub->indexData->indexBuffer;
		ibuf->writeData(0, (ibuf->getIndexSize() * mNumIndices), mIndices, true);

		mMeshPtr->_setBounds(Ogre::AxisAlignedBox(0, 0, 0, Ogre::Real(ChunkSizeX), Ogre::Real(mHighestCube), Ogre::Real(ChunkSizeZ)));
		mMeshPtr->load();
	}
}
Пример #23
0
void OgreMeshAsset::CreateKdTree()
{
    meshData.Clear();
    normals.clear();
    uvs.clear();
    subMeshTriangleCounts.clear();
    for(unsigned short i = 0; i < ogreMesh->getNumSubMeshes(); ++i)
    {
        Ogre::SubMesh *submesh = ogreMesh->getSubMesh(i);
        assert(submesh);
        
        Ogre::VertexData *vertexData = submesh->useSharedVertices ? ogreMesh->sharedVertexData : submesh->vertexData;
        assert(vertexData);
        
        const Ogre::VertexElement *posElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
        if (!posElem)
        {
            subMeshTriangleCounts.push_back(0);
            continue; // No position element. Ignore this submesh.
        }
        
        Ogre::HardwareVertexBufferSharedPtr vbufPos = vertexData->vertexBufferBinding->getBuffer(posElem->getSource());

        unsigned char *pos = (unsigned char*)vbufPos->lock(Ogre::HardwareBuffer::HBL_READ_ONLY);
        assert(pos);
        size_t posOffset = posElem->getOffset();
        size_t posSize = vbufPos->getVertexSize();
        
        // Texcoord element is not mandatory
        unsigned char *texCoord = 0;
        size_t texOffset = 0;
        size_t texSize = 0;
        Ogre::HardwareVertexBufferSharedPtr vbufTex;
        const Ogre::VertexElement *texElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES);
        if (texElem)
        {
            vbufTex = vertexData->vertexBufferBinding->getBuffer(texElem->getSource());
            // Check if the texcoord buffer is different than the position buffer, in that case lock it separately
            if (vbufTex != vbufPos)
                texCoord = static_cast<unsigned char*>(vbufTex->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
            else
                texCoord = pos;
            texOffset = texElem->getOffset();
            texSize = vbufTex->getVertexSize();
        }
        
        Ogre::IndexData *indexData = submesh->indexData;
        Ogre::HardwareIndexBufferSharedPtr ibuf = indexData->indexBuffer;

        u32 *pLong = (u32*)ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY);
        u16 *pShort = (u16*)pLong;
        const bool use32BitIndices = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
        
        for(unsigned j = 0; j+2 < indexData->indexCount; j += 3)
        {
            unsigned i0, i1, i2;
            if (use32BitIndices)
            {
                i0 = pLong[j];
                i1 = pLong[j+1];
                i2 = pLong[j+2];
            }
            else
            {
                i0 = pShort[j];
                i1 = pShort[j+1];
                i2 = pShort[j+2];
            }
            
            float3 v0 = *(float3*)(pos + posOffset + i0 * posSize);
            float3 v1 = *(float3*)(pos + posOffset + i1 * posSize);
            float3 v2 = *(float3*)(pos + posOffset + i2 * posSize);
            Triangle t(v0, v1, v2);
            meshData.AddObjects(&t, 1);

            if (texElem)
            {
                uvs.push_back(*((float2*)(texCoord + texOffset + i0 * texSize)));
                uvs.push_back(*((float2*)(texCoord + texOffset + i1 * texSize)));
                uvs.push_back(*((float2*)(texCoord + texOffset + i2 * texSize)));
            }

            float3 edge1 = v1 - v0;
            float3 edge2 = v2 - v0;
            float3 normal = edge1.Cross(edge2);
            normal.Normalize();
            normals.push_back(normal);
        }
        subMeshTriangleCounts.push_back((int)(indexData->indexCount / 3));
        
        vbufPos->unlock();
        if (!vbufTex.isNull() && vbufTex != vbufPos)
            vbufTex->unlock();
        ibuf->unlock();
    }

    {
        PROFILE(OgreMeshAsset_KdTree_Build);
        meshData.Build();
    }
}
void TutorialApplication::createSphere(const std::string& strName, const float r, const int nRings, const int nSegments) {
	Ogre::MeshPtr pSphere = Ogre::MeshManager::getSingleton().createManual(Ogre::String(strName), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
	Ogre::SubMesh *pSphereVertex = pSphere->createSubMesh();
 
	pSphere->sharedVertexData = new Ogre::VertexData();
	Ogre::VertexData* vertexData = pSphere->sharedVertexData;
 
	// define the vertex format
	Ogre::VertexDeclaration* vertexDecl = vertexData->vertexDeclaration;
	size_t currOffset = 0;
	// positions
	vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
	currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
	// normals
	vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
	currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
	// two dimensional texture coordinates
	vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 0);
	currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
 
	// allocate the vertex buffer
	vertexData->vertexCount = (nRings + 1) * (nSegments+1);
	Ogre::HardwareVertexBufferSharedPtr vBuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
	Ogre::VertexBufferBinding* binding = vertexData->vertexBufferBinding;
	binding->setBinding(0, vBuf);
	float* pVertex = static_cast<float*>(vBuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
 
	// allocate index buffer
	pSphereVertex->indexData->indexCount = 6 * nRings * (nSegments + 1);
	pSphereVertex->indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, pSphereVertex->indexData->indexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
	Ogre::HardwareIndexBufferSharedPtr iBuf = pSphereVertex->indexData->indexBuffer;
	unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
 
	float fDeltaRingAngle = (Ogre::Math::PI / nRings);
	float fDeltaSegAngle = (2 * Ogre::Math::PI / nSegments);
	unsigned short wVerticeIndex = 0 ;
 
	// Generate the group of rings for the sphere
	for( int ring = 0; ring <= nRings; ring++ ) {
		float r0 = r * sinf (ring * fDeltaRingAngle);
		float y0 = r * cosf (ring * fDeltaRingAngle);
 
        // Generate the group of segments for the current ring
        for(int seg = 0; seg <= nSegments; seg++) {
			float x0 = r0 * sinf(seg * fDeltaSegAngle);
            float z0 = r0 * cosf(seg * fDeltaSegAngle);
 
            // Add one vertex to the strip which makes up the sphere
            *pVertex++ = x0;
            *pVertex++ = y0;
            *pVertex++ = z0;
 
            Ogre::Vector3 vNormal = Ogre::Vector3(x0, y0, z0).normalisedCopy();
            *pVertex++ = vNormal.x;
            *pVertex++ = vNormal.y;
            *pVertex++ = vNormal.z;
 
            *pVertex++ = (float) seg / (float) nSegments;
            *pVertex++ = (float) ring / (float) nRings;
 
            if (ring != nRings) {
				// each vertex (except the last) has six indices pointing to it
                *pIndices++ = wVerticeIndex + nSegments + 1;
                *pIndices++ = wVerticeIndex;               
                *pIndices++ = wVerticeIndex + nSegments;
                *pIndices++ = wVerticeIndex + nSegments + 1;
                *pIndices++ = wVerticeIndex + 1;
                *pIndices++ = wVerticeIndex;
                wVerticeIndex ++;
            }
        }; // end for seg
    } // end for ring
 
	// Unlock
	vBuf->unlock();
	iBuf->unlock();
	// Generate face list
	pSphereVertex->useSharedVertices = true;
 
    // the original code was missing this line:
    pSphere->_setBounds( Ogre::AxisAlignedBox( Ogre::Vector3(-r, -r, -r), Ogre::Vector3(r, r, r) ), false );
    pSphere->_setBoundingSphereRadius(r);
    // this line makes clear the mesh is loaded (avoids memory leaks)
    pSphere->load();
}
Пример #25
0
void OgreMeshRay::GetMeshInformation(const Ogre::ManualObject* manual,
		size_t& vertex_count, Ogre::Vector3*& vertices, size_t& index_count,
		unsigned long*& indices, const Ogre::Vector3& position,
		const Ogre::Quaternion& orient, const Ogre::Vector3& scale) {
	std::vector<Ogre::Vector3> returnVertices;
	std::vector<unsigned long> returnIndices;
	unsigned long thisSectionStart = 0;
	for (unsigned int i = 0, size = manual->getNumSections(); i < size; ++i) {
		Ogre::ManualObject::ManualObjectSection* section = manual->getSection(
				i);
		Ogre::RenderOperation* renderOp = section->getRenderOperation();

		std::vector<Ogre::Vector3> pushVertices;
		//Collect the vertices
		{
			const Ogre::VertexElement* vertexElement =
					renderOp->vertexData->vertexDeclaration->findElementBySemantic(
							Ogre::VES_POSITION);
			Ogre::HardwareVertexBufferSharedPtr vertexBuffer =
					renderOp->vertexData->vertexBufferBinding->getBuffer(
							vertexElement->getSource());

			char* verticesBuffer = static_cast<char*>(vertexBuffer->lock(
					Ogre::HardwareBuffer::HBL_READ_ONLY));
			float* positionArrayHolder;

			thisSectionStart = returnVertices.size() + pushVertices.size();

			pushVertices.reserve(renderOp->vertexData->vertexCount);

			for (unsigned int j = 0; j < renderOp->vertexData->vertexCount;
					++j) {
				vertexElement->baseVertexPointerToElement(
						verticesBuffer + j * vertexBuffer->getVertexSize(),
						&positionArrayHolder);
				Ogre::Vector3 vertexPos = Ogre::Vector3(positionArrayHolder[0],
						positionArrayHolder[1], positionArrayHolder[2]);
				vertexPos = (orient * (vertexPos * scale)) + position;
				pushVertices.push_back(vertexPos);
			}

			vertexBuffer->unlock();
		}
		//Collect the indices
		{
			if (renderOp->useIndexes) {
				Ogre::HardwareIndexBufferSharedPtr indexBuffer =
						renderOp->indexData->indexBuffer;

				if (indexBuffer.isNull()
						|| renderOp->operationType
								!= Ogre::RenderOperation::OT_TRIANGLE_LIST) {
					//No triangles here, so we just drop the collected vertices and move along to the next section.
					continue;
				} else {
					returnVertices.reserve(
							returnVertices.size() + pushVertices.size());
					returnVertices.insert(returnVertices.end(),
							pushVertices.begin(), pushVertices.end());
				}

				unsigned int* pLong =
						static_cast<unsigned int*>(indexBuffer->lock(
								Ogre::HardwareBuffer::HBL_READ_ONLY));
				unsigned short* pShort =
						reinterpret_cast<unsigned short*>(pLong);

				returnIndices.reserve(
						returnIndices.size() + renderOp->indexData->indexCount);

				for (size_t j = 0; j < renderOp->indexData->indexCount; ++j) {
					unsigned long index;
					//We also have got to remember that for a multi section object, each section has
					//different vertices, so the indices will not be correct. To correct this, we
					//have to add the position of the first vertex in this section to the index

					//(At least I think so...)
					if (indexBuffer->getType()
							== Ogre::HardwareIndexBuffer::IT_32BIT)
						index = static_cast<unsigned long>(pLong[j])
								+ thisSectionStart;
					else
						index = static_cast<unsigned long>(pShort[j])
								+ thisSectionStart;

					returnIndices.push_back(index);
				}

				indexBuffer->unlock();
			}
		}
	}

	//Now we simply return the data.
	index_count = returnIndices.size();
	vertex_count = returnVertices.size();
	vertices = new Ogre::Vector3[vertex_count];
	for (unsigned long i = 0; i < vertex_count; ++i)
		vertices[i] = returnVertices[i];
	indices = new unsigned long[index_count];
	for (unsigned long i = 0; i < index_count; ++i)
		indices[i] = returnIndices[i];

	//All done.
	return;
}
Пример #26
0
void MeshUtils::meshBuffersToArrays(const Ogre::MeshPtr& mesh, Ogre::Vector3* vertices, unsigned long* indices)
{
	bool added_shared = false;
	size_t current_offset = 0;
	size_t shared_offset = 0;
	size_t next_offset = 0;
	size_t index_offset = 0;

	//const Ogre::Vector3 &position = ent->getParentNode()->_getDerivedPosition();
	//const Ogre::Quaternion &orient = ent->getParentNode()->_getDerivedOrientation();
	//const Ogre::Vector3 &scale = ent->getParentNode()->_getDerivedScale();

	const Ogre::Vector3 &position = Ogre::Vector3::ZERO;
	const Ogre::Quaternion &orient = Ogre::Quaternion::IDENTITY;
	const Ogre::Vector3 &scale = Ogre::Vector3::UNIT_SCALE;

	Ogre::Mesh::SubMeshIterator itr = mesh->getSubMeshIterator();
	while (itr.hasMoreElements()) {
			Ogre::SubMesh* submesh = itr.getNext();

			Ogre::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 Ogre::VertexElement* posElem =
					    vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);

					Ogre::HardwareVertexBufferSharedPtr vbuf =
					    vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());

					unsigned char* vertex =
					    static_cast<unsigned char*> (vbuf->lock(Ogre::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 k = 0; k < vertex_data->vertexCount; ++k, vertex += vbuf->getVertexSize()) {
							posElem->baseVertexPointerToElement(vertex, &pReal);

							Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]);

							vertices[current_offset + k] = (orient * (pt * scale)) + position;
							//vertices[current_offset + k] = pt;
						}

					vbuf->unlock();
					next_offset += vertex_data->vertexCount;
				}


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

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

			unsigned long* pLong = static_cast<unsigned long*> (ibuf->lock(Ogre::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;
		}
}
Ogre::SceneNode *TutorialApplication::loadBSP(std::shared_ptr<l2p::UModel> m, bool ignoreNonVisible) {
  l2p::Name name = m->package->name;
  std::vector<float> vertex_data;
  std::vector<uint32_t> index_buf;
  l2p::Box bounds;

  // Build vertex and index buffer.
  for (auto ni = m->nodes.begin(), ne = m->nodes.end(); ni != ne; ++ni) {
    l2p::BSPNode &n = *ni;
    l2p::BSPSurface &s = m->surfaces[n.surface];

    if (ignoreNonVisible && ignoreNode(m.get(), n, s))
      continue;

    uint32_t vert_start = vertex_data.size() / 8;

    const Ogre::Vector3 uvec = ogre_cast(m->vectors[s.U]);
    const Ogre::Vector3 vvec = ogre_cast(m->vectors[s.V]);
    const Ogre::Vector3 base = ogre_cast(m->points[s.base]);
    int usize = 0;
    int vsize = 0;
    std::shared_ptr<l2p::UTexture> mat = s.material;
    if (mat) {
      usize = mat->USize;
      vsize = mat->VSize;
    }

    if (usize == 0 || vsize == 0)
      usize = vsize = 64;

    // Vertex buffer.
    if (n.num_verticies > 0) {
      l2p::Vector Normal = m->vectors[s.normal];

      for (uint32_t vert_index = 0; vert_index < n.num_verticies; ++vert_index) {
        const l2p::Vector &pos = m->points[m->vertexes[n.vert_pool + vert_index].vertex];
        const Ogre::Vector3 dist(ogre_cast(pos) - base);
        const Ogre::Vector2 tcoord((dist | uvec) / float(usize), (dist | vvec) / float(vsize));
        bounds += pos;
        vertex_data.push_back(pos.X);
        vertex_data.push_back(pos.Y);
        vertex_data.push_back(pos.Z);
        vertex_data.push_back(Normal.X);
        vertex_data.push_back(Normal.Y);
        vertex_data.push_back(Normal.Z);
        vertex_data.push_back(tcoord.x);
        vertex_data.push_back(tcoord.y);
      }

      if (s.flags & l2p::PF_TwoSided) {
        for (uint32_t vert_index = 0; vert_index < n.num_verticies; ++vert_index) {
          const l2p::Vector &pos = m->points[m->vertexes[n.vert_pool + vert_index].vertex];
          const Ogre::Vector3 dist(ogre_cast(pos) - base);
          const Ogre::Vector2 tcoord((dist | uvec) / float(usize), (dist | vvec) / float(vsize));
          vertex_data.push_back(pos.X);
          vertex_data.push_back(pos.Y);
          vertex_data.push_back(pos.Z);
          vertex_data.push_back(Normal.X);
          vertex_data.push_back(Normal.Y);
          vertex_data.push_back(-Normal.Z);
          vertex_data.push_back(tcoord.x);
          vertex_data.push_back(tcoord.y);
        }
      }
    }

    // Index buffer.
    for (int verti = 2; verti < n.num_verticies; ++verti) {
      index_buf.push_back(vert_start);
      index_buf.push_back(vert_start + verti - 1);
      index_buf.push_back(vert_start + verti);
    }
    if (s.flags & l2p::PF_TwoSided) {
      for (int verti = 2; verti < n.num_verticies; ++verti) {
        index_buf.push_back(vert_start);
        index_buf.push_back(vert_start + verti);
        index_buf.push_back(vert_start + verti - 1);
      }
    }
  }

  if (vertex_data.size() == 0 || index_buf.size() == 0)
    return nullptr;

  Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().createManual(Ogre::String(name) + Ogre::String(m->name), "General");
  Ogre::VertexData  *data = new Ogre::VertexData();
  mesh->sharedVertexData = data;
  data->vertexCount = vertex_data.size() / 8;

  Ogre::VertexDeclaration *decl = data->vertexDeclaration;
  uint32_t offset = 0;
  decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
  offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
  decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
  offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
  decl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES);
  offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);

  Ogre::HardwareVertexBufferSharedPtr vbuf =
    Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
      offset,
      data->vertexCount,
      Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
  vbuf->writeData(0, vbuf->getSizeInBytes(), &vertex_data.front(), true);
  data->vertexBufferBinding->setBinding(0, vbuf);

  // Setup index buffer.
  Ogre::HardwareIndexBufferSharedPtr ibuf =
    Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
      Ogre::HardwareIndexBuffer::IT_32BIT,
      index_buf.size(),
      Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);

  ibuf->writeData(0, ibuf->getSizeInBytes(), &index_buf.front(), true);
  Ogre::SubMesh *subMesh = mesh->createSubMesh();
  subMesh->useSharedVertices = true;
  subMesh->indexData->indexBuffer = ibuf;
  subMesh->indexData->indexCount  = index_buf.size();
  subMesh->indexData->indexStart  = 0;

  mesh->_setBounds(Ogre::AxisAlignedBox(bounds.min.X, bounds.min.Y, bounds.min.Z, bounds.max.X, bounds.max.Y, bounds.max.Z));
  mesh->_setBoundingSphereRadius((std::max(bounds.max.X - bounds.min.X, std::max(bounds.max.Y - bounds.min.Y, bounds.max.Z - bounds.min.Z))) / 2.0);

  mesh->load();

  Ogre::Entity *ent = mSceneMgr->createEntity(Ogre::String(name) + Ogre::String(m->name) + "E", Ogre::String(name) + Ogre::String(m->name));
  ent->setUserAny(Ogre::Any(static_cast<l2p::UObject*>(m.get())));
  ent->setMaterialName("StaticMesh/Default");
  Ogre::SceneNode *node = mUnrealCordNode->createChildSceneNode();
  node->attachObject(ent);

  return node;
}
Пример #28
0
	/*求对象rend和射线ray的全部交点到射线原点的距离
	*/
	vector<Ogre::Real> BaseManager::Intersect(const Ogre::Ray& ray,Ogre::Renderable *rend){
		Ogre::RenderOperation op;
		Ogre::VertexElementType vtype;
		size_t offset,pkgsize,source,indexNums,vertexNums;
		vector<Ogre::Real> result;

		rend->getRenderOperation( op );

		if( !op.indexData || 
			op.operationType==Ogre::RenderOperation::OT_LINE_LIST || 
			op.operationType==Ogre::RenderOperation::OT_LINE_STRIP ||
			op.operationType==Ogre::RenderOperation::OT_POINT_LIST )
			return result;

		Ogre::VertexDeclaration* pvd = op.vertexData->vertexDeclaration;

		source = -1;
		for( size_t i = 0;i < pvd->getElementCount();++i ){
			if( pvd->getElement(i)->getSemantic()==Ogre::VES_POSITION ){
				source = pvd->getElement(i)->getSource();
				offset = pvd->getElement(i)->getOffset();
				vtype = pvd->getElement(i)->getType();
				break;
			}
		}
		if( source == - 1 || vtype != Ogre::VET_FLOAT3 ) //别的格式目前没有考虑
			return result;

		/*source对应与一个缓存区
		  getVertexSize(source)求缓存区中一个紧密数据包的大小
		  例如:一个数据包里面包括POSITION,COLOR,NORMAL,TEXCROOD然后在这个缓冲
			区中循环。而getVertexSize求出这个包的字节大小
		  例如POSITION(FLOAT3) TEXCROOD(FLOAT2) 这样前面的是12字节后面的是8字节
			getVertexSize返回20
		*/
		pkgsize = pvd->getVertexSize(source);

		Ogre::HardwareVertexBufferSharedPtr hvb = op.vertexData->vertexBufferBinding->getBuffer(source);
		Ogre::HardwareIndexBufferSharedPtr ivb = op.indexData->indexBuffer;
		Ogre::HardwareIndexBuffer::IndexType indexType = op.indexData->indexBuffer->getType();
		/*先将顶点数据复制一份,然后变换到世界坐标系
		*/
		vertexNums = hvb->getNumVertices();
		indexNums = ivb->getNumIndexes();
		 
		boost::scoped_array<float> vp( new float[3*vertexNums] );
		boost::scoped_array<unsigned int> ip( new unsigned int[indexNums] );
		
		{
			Ogre::Vector3 p3;
			Ogre::Matrix4 mat;
			rend->getWorldTransforms( &mat );
			float* preal = (float*)hvb->lock( Ogre::HardwareBuffer::HBL_READ_ONLY );
			float* ptarget = vp.get();
			//这里考虑到对齐,我假设offset和pkgsize都可以被sizeof(float)整除
			preal += offset/sizeof(float);
			size_t strip = pkgsize/sizeof(float);
			for( size_t i = 0; i < vertexNums;++i ){
				p3.x = *preal;
				p3.y = *(preal+1);
				p3.z = *(preal+2);
				p3 = mat * p3;
				*ptarget++ = p3.x;
				*ptarget++ = p3.y;
				*ptarget++ = p3.z;
				preal += strip;
			}
			hvb->unlock();
		}
		//拷贝出顶点数据
		
		{
			unsigned int* pindex32 = ip.get();
			
			if( indexType==Ogre::HardwareIndexBuffer::IT_16BIT ){
				unsigned short* pi16 = (unsigned short*)ivb->lock( Ogre::HardwareBuffer::HBL_READ_ONLY );
				copy( pi16,pi16+indexNums,pindex32 );
			}else
				memcpy( pindex32,ivb->lock( Ogre::HardwareBuffer::HBL_READ_ONLY ),ivb->getSizeInBytes() );
			ivb->unlock();
		}
		/*数据都准备好了,vp保存了变换好的顶点,ip保存了顶点索引
			下面根据情况求交点
		*/
		switch( op.operationType ){
			case Ogre::RenderOperation::OT_TRIANGLE_LIST:
				{ /* 0,1,2 组成一个三角 3,4,5 下一个...
				  */
					Ogre::Vector3 a[3],n;
					int index,k = 0;
					float* preal = vp.get();
					unsigned int* pindex = ip.get();
					for( size_t i = 0;i<indexNums;++i ){
						if( pindex[i] < vertexNums ){
							index = pindex[i]*3; //对应与格式VET_FLOAT3
							a[k].x = preal[index];
							a[k].y = preal[index+1];
							a[k].z = preal[index+2];
							if( k == 2 ){//三个点都填满了
								//这里使用的是Math3d的求交函数,而不是Ogre::Math的
								//原因就在于Ogre::Math的求交点函数不能得到射线背面那个负的交点
								std::pair<bool,Ogre::Real> res = Math3d::intersects(ray,a[0],a[1],a[2],true,true);
								if( res.first )
									result.push_back( res.second );
								k = 0;
							}else
								k++;
						}else{
							WARNING_LOG("Game::Intersect"<<" Invalid index rang out" << " pindex["<<i<<"]="<<pindex[i] << "("<<vertexNums<<")");
							return result;
						}
					}
				}
				break;
			case Ogre::RenderOperation::OT_TRIANGLE_FAN:
				{/* 0,1,2组成一个三角 0,2,3 组成下一个 0,3,4...
				 */
					assert( false||"Game::Intersect can't support OT_TRIANGLE_FAN " );
				}
				break;
			case Ogre::RenderOperation::OT_TRIANGLE_STRIP:
				{//0,1,2组成第一个三角 1,2,3 组成下一个 2,3,4...
					assert( false||"Game::Intersect can't support OT_TRIANGLE_STRIP " );
				}
				break;
			default:;
		}
		return result;
	}
Пример #29
0
void MapView::createTerrain()
{
	unsigned int sizeX = mMap->getTerrainSize().x;
	unsigned int sizeZ = mMap->getTerrainSize().z;

	mTileX = 33;
	mTileZ = 33;

	unsigned int tileCount = ((sizeX - 1) / (mTileX - 1)) * ((sizeZ - 1) / (mTileZ - 1));
	unsigned int vertexPerTile = mTileX * mTileZ;
	unsigned int trianglesPerTile = (mTileX - 1) * (mTileZ - 1) * 2;

	mMeshes.resize(tileCount);
	mEntities.resize(tileCount);
	mSceneNodes.resize(tileCount);

	// vertexPerTile * 3 vertices * 2 texture coordinates * 3 colours * 3 normals
	VertexVector vertices(vertexPerTile * 11);

	// trianglesPerTile * 3 indices per each triangle
	IndexVector indices[3] =
	{
		IndexVector(trianglesPerTile * 3    ),
		IndexVector(trianglesPerTile * 3 / 4),
		IndexVector(trianglesPerTile * 3 / 8)
	};

	unsigned int vertexIndex, indexIndex = 0, tileIndex = 0;

	for (unsigned int zIndex = 0; zIndex < mTileZ - 1; ++zIndex)
	{
		for (unsigned int xIndex = 0; xIndex < mTileX - 1; ++xIndex)
		{
			indices[0][indexIndex++] =  zIndex      * mTileX + xIndex;
			indices[0][indexIndex++] = (zIndex + 1) * mTileX + xIndex;
			indices[0][indexIndex++] =  zIndex      * mTileX + xIndex + 1;

			indices[0][indexIndex++] = (zIndex + 1) * mTileX + xIndex;
			indices[0][indexIndex++] = (zIndex + 1) * mTileX + xIndex + 1;
			indices[0][indexIndex++] =  zIndex      * mTileX + xIndex + 1;
		}
	}

	indexIndex = 0;

	for (unsigned int zIndex = 0; zIndex < mTileZ - 1; zIndex += 2)
	{
		for (unsigned int xIndex = 0; xIndex < mTileX - 1; xIndex += 2)
		{
			indices[1][indexIndex++] =  zIndex      * mTileX + xIndex;
			indices[1][indexIndex++] = (zIndex + 2) * mTileX + xIndex;
			indices[1][indexIndex++] =  zIndex      * mTileX + xIndex + 2;

			indices[1][indexIndex++] = (zIndex + 2) * mTileX + xIndex;
			indices[1][indexIndex++] = (zIndex + 2) * mTileX + xIndex + 2;
			indices[1][indexIndex++] =  zIndex      * mTileX + xIndex + 2;
		}
	}

	indexIndex = 0;

	for (unsigned int zIndex = 0; zIndex < mTileZ - 1; zIndex += 4)
	{
		for (unsigned int xIndex = 0; xIndex < mTileX - 1; xIndex += 4)
		{
			indices[2][indexIndex++] =  zIndex      * mTileX + xIndex;
			indices[2][indexIndex++] = (zIndex + 4) * mTileX + xIndex;
			indices[2][indexIndex++] =  zIndex      * mTileX + xIndex + 4;

			indices[2][indexIndex++] = (zIndex + 4) * mTileX + xIndex;
			indices[2][indexIndex++] = (zIndex + 4) * mTileX + xIndex + 4;
			indices[2][indexIndex++] =  zIndex      * mTileX + xIndex + 4;
		}
	}

	float scaleX = mMap->getSize().x / (float)(sizeX - 1);
	float scaleZ = mMap->getSize().z / (float)(sizeZ - 1);

	for (unsigned int zTile = 0; zTile < (sizeZ - 1); zTile += (mTileZ - 1))
	{
		for (unsigned int xTile = 0; xTile < (sizeX - 1); xTile += (mTileX - 1))
		{
			vertexIndex = 0;

			for (unsigned int zVertex = zTile; zVertex < zTile + mTileZ; ++zVertex)
			{
				for (unsigned int xVertex = xTile; xVertex < xTile + mTileX; ++xVertex)
				{
					float yVertex = mMap->getTerrainData()[zVertex * sizeX + xVertex];

					vertices[vertexIndex++] = (float)xVertex * scaleX;
					vertices[vertexIndex++] = (float)yVertex;
					vertices[vertexIndex++] = (float)zVertex * scaleZ;

					vertices[vertexIndex++] = (float)xVertex / (float)(sizeX - 1);
					vertices[vertexIndex++] = (float)zVertex / (float)(sizeZ - 1);

					vertices[vertexIndex++] = 1.0f;
					vertices[vertexIndex++] = 1.0f;
					vertices[vertexIndex++] = 1.0f;

					vertices[vertexIndex++] = 0.0f;
					vertices[vertexIndex++] = 1.0f;
					vertices[vertexIndex++] = 0.0f;
				}
			}

			std::string name =
				"MapView_" + Convert::ToString(mID) +
				"_Tile_" + Convert::ToString(tileIndex);

			// Create mesh.
			mMeshes[tileIndex] = Ogre::MeshManager::getSingleton().createManual(
				name, "General").get();

			// Create one submesh.
			Ogre::SubMesh* subMesh = mMeshes[tileIndex]->createSubMesh();

			// Create vertex data structure for vertices shared between submeshes.
			mMeshes[tileIndex]->sharedVertexData = new Ogre::VertexData();
			mMeshes[tileIndex]->sharedVertexData->vertexCount = vertexPerTile;

			// Create declaration (memory format) of vertex data.
			Ogre::VertexDeclaration* decl =
				mMeshes[tileIndex]->sharedVertexData->vertexDeclaration;

			size_t offset = 0;

			// 1st buffer
			decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
			offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);

			decl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES);
			offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);

			decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_DIFFUSE);
			offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);

			decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
			offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);

			// Allocate vertex buffer of the requested number of vertices (vertexPerTile)
			// and bytes per vertex (offset).
			Ogre::HardwareVertexBufferSharedPtr vbuf =
				Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
				offset, vertexPerTile, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);

			// Upload the vertex data to the card
			vbuf->writeData(0, vbuf->getSizeInBytes(), &(vertices.front()), true);

			// Set vertex buffer binding so buffer 0 is bound to our vertex buffer.
			Ogre::VertexBufferBinding* bind =
				mMeshes[tileIndex]->sharedVertexData->vertexBufferBinding; 
			bind->setBinding(0, vbuf);

			// Allocate index buffer of the requested number of vertices .
			Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton().
				createIndexBuffer(
				Ogre::HardwareIndexBuffer::IT_16BIT, 
				trianglesPerTile * 3,
				Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);

			// Upload the index data to the card.
			ibuf->writeData(0, ibuf->getSizeInBytes(), &(indices[0].front()), true);

			/// Set parameters of the submesh
			subMesh->useSharedVertices = true;
			subMesh->indexData->indexBuffer = ibuf;
			subMesh->indexData->indexCount = indices[0].size();
			subMesh->indexData->indexStart = 0;
			subMesh->setMaterialName("terrain");

			float xMin = vertices[0];
			float yMin = vertices[1];
			float zMin = vertices[2];

			float xMax = vertices[0];
			float yMax = vertices[1];
			float zMax = vertices[2];

			for (unsigned int i = 0; i < vertexPerTile * 11; i += 11)
			{
				if (vertices[i    ] < xMin) xMin = vertices[i    ]; else
				if (vertices[i    ] > xMax) xMax = vertices[i    ];

				if (vertices[i + 1] < yMin) yMin = vertices[i + 1]; else
				if (vertices[i + 1] > yMax) yMax = vertices[i + 1];

				if (vertices[i + 2] < zMin) zMin = vertices[i + 2]; else
				if (vertices[i + 2] > zMax) zMax = vertices[i + 2];
			}

			// Set bounding information (for culling).
			mMeshes[tileIndex]->_setBounds(Ogre::AxisAlignedBox(xMin, yMin, zMin, xMax, yMax, zMax));
			mMeshes[tileIndex]->_setBoundingSphereRadius(1.0f);

			// Notify Mesh object that it has been loaded.
			mMeshes[tileIndex]->load();

			// Create entity.
			mEntities[tileIndex] = createEntity(name, name);
			mEntities[tileIndex]->setCastShadows(false);
			mEntities[tileIndex]->setUserAny(Ogre::Any(this));

			// Create scene node.
			mSceneNodes[tileIndex] = createSceneNode();
			mSceneNodes[tileIndex]->attachObject(mEntities[tileIndex]);

			// Advance to next tile.
			tileIndex++;
		}
	}
}
/* ----------------------------------------------------------------------- 
 | the function describe retrieve vertexbuffer from Ogre entity :   
 | (Ref:http://www.ogre3d.org/tikiwiki/tiki-index.php?page=RetrieveVertexData)
 |
 | @prama in : Ogre entity
 | @pamra out : vertex buffer, size of vertexbuffer, vertex indices, sizeof vertex indices
   ----------------------------------------------------------------------- */
void
getVertexBuffer(Ogre::Entity* ent, void* &vertices, size_t& vertexCount, void* &indices, size_t& indexCount)
{
    bool added_shared = false;
    size_t current_offset = 0;
    size_t shared_offset = 0;
    size_t next_offset = 0;
    size_t index_offset = 0;
 
    vertexCount = indexCount = 0;
 
    const Ogre::MeshPtr& mesh = ent->getMesh();

    // Calculate vertexCount, indexCount
    for ( Ogre::ushort i = 0; i < mesh->getNumSubMeshes(); ++i)
    {
        Ogre::SubMesh* subMesh = mesh->getSubMesh(i);        
        if (subMesh->useSharedVertices)
        {
            if( !added_shared )
            {
                vertexCount += mesh->sharedVertexData->vertexCount;
                added_shared = true;
            }

            vertexCount += mesh->sharedVertexData->vertexCount;
        }
        else
            vertexCount += subMesh->vertexData->vertexCount;
        
        indexCount += subMesh->indexData->indexCount;
    }
    
    // Alloc vertices, indices
    vertices = new Ogre::Vector3[ vertexCount ];
    indices = new Ogre::ulong[ indexCount ];
  
    added_shared = false;

    // Assign vertices data, indices data
    for (Ogre::ushort i = 0; i < mesh->getNumSubMeshes(); ++i)
    {
        Ogre::SubMesh* subMesh = mesh->getSubMesh(i);
        Ogre::VertexData* vertexData = subMesh->useSharedVertices ? mesh->sharedVertexData : subMesh->vertexData;

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

        // Retrieve vertices        
        const Ogre::VertexElement* posElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
        Ogre::HardwareVertexBufferSharedPtr vbuf = vertexData->vertexBufferBinding->getBuffer(posElem->getSource());
        
        Ogre::uchar* vertex = static_cast<Ogre::uchar*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
        Ogre::Real* data;
        
        for (size_t j = 0 ; j < vertexData->vertexCount ; ++j, vertex += vbuf->getVertexSize())
        {
            posElem->baseVertexPointerToElement(vertex, &data);
            Ogre::Vector3 origin(data[0], data[1], data[2]);
            // ((Ogre::Vector3*)vertices)[ current_offset + j ] = (orient * (origin * scale)) + position;
            ((Ogre::Vector3*)vertices)[ current_offset + j ] = origin;
        } // End for
        
        vbuf->unlock();
        next_offset += vertexData->vertexCount;
        } // End if

        // Retrieve indices
        Ogre::IndexData* indexData = subMesh->indexData;
        size_t trisCount = indexData->indexCount / 3;

        Ogre::HardwareIndexBufferSharedPtr ibuf = indexData->indexBuffer;
        bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);

        void* index = (ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));       
        Ogre::ulong offset = (subMesh->useSharedVertices) ? shared_offset : current_offset; 
        for (Ogre::ulong k = 0; k < trisCount * 3; ++k)
        {
            if ( use32bitindexes )
                ((Ogre::ulong*)indices)[ index_offset++ ] = ((Ogre::ulong*)index)[ k + offset ];
            else
                ((Ogre::ulong*)indices)[ index_offset++ ] = ((Ogre::ushort*)index)[ k + offset ];
        }

        ibuf->unlock();
        current_offset = next_offset;        
    } // End for
}