Beispiel #1
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;
}
Beispiel #2
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);
    }
}
Beispiel #3
0
// Get the mesh information for the given mesh.
// Code found in Wiki: www.ogre3d.org/wiki/index.php/RetrieveVertexData
void OgreMeshRay::GetMeshInformation(const Ogre::MeshPtr mesh,
		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) {
	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, size = mesh->getNumSubMeshes(); i < size; ++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 unsigned long[index_count];

	added_shared = false;

	// Run through the submeshes again, adding the data into the arrays
	for (unsigned short i = 0, size = mesh->getNumSubMeshes(); i < size; ++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::Real or a double
			//  as second argument. So make it float, to avoid trouble when Ogre::Real will
			//  be comiled/typedefed as double:
			//      Ogre::Real* pReal;
			float* pReal;

			for (size_t j = 0; j < vertex_data->vertexCount;
					++j, vertex += vbuf->getVertexSize()) {
				posElem->baseVertexPointerToElement(vertex, &pReal);
				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;
		if (ibuf.isNull())
			continue; // need to check if index buffer is valid (which will be not if the mesh doesn't have triangles like a pointcloud)

		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;
		size_t index_start = index_data->indexStart;
		size_t last_index = numTris * 3 + index_start;

		if (use32bitindexes) {
			for (size_t k = index_start; k < last_index; ++k) {
				indices[index_offset++] = pLong[k]
						+ static_cast<unsigned long>(offset);
			}

		} else {
			for (size_t k = index_start; k < last_index; ++k) {
				indices[index_offset++] = static_cast<unsigned long>(pShort[k])
						+ static_cast<unsigned long>(offset);
			}
		}

		ibuf->unlock();
		current_offset = next_offset;
	}
}
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;
}