//! Sets a new mesh
		void CInstancedMeshSceneNode::setMesh(IMesh* mesh)
		{
			video::IVideoDriver* driver = SceneManager->getVideoDriver();
			if (baseMesh)
			{
				baseMesh->drop();
				baseMesh = NULL;
			}

			if (mesh)
			{
				mesh->grab();

				baseMesh = mesh;

				IMeshBuffer* renderBuffer = baseMesh->getMeshBuffer(0);

				while (renderBuffer->getVertexBufferCount() > 1)
					renderBuffer->removeVertexBuffer(1);

				// TODO add getter and so that the smaller value isnt erased
				// maybe the func isnt longer needed so delete it
				driver->setMinHardwareBufferVertexCount(renderBuffer->getVertexBuffer()->getVertexCount());

				renderBuffer->setHardwareMappingHint(scene::EHM_STATIC);

				video::IVertexDescriptor* index = SceneManager->getVideoDriver()->getVertexDescriptor("BaseInstanceIndex");

				if (!index)
				{
					video::IVertexDescriptor* stdv = SceneManager->getVideoDriver()->getVertexDescriptor(0);
					index = SceneManager->getVideoDriver()->addVertexDescriptor("BaseInstanceIndex");

					for (u32 i = 0; i < stdv->getAttributeCount(); ++i)
					{
						index->addAttribute(stdv->getAttribute(i)->getName(), stdv->getAttribute(i)->getElementCount(), stdv->getAttribute(i)->getSemantic(), stdv->getAttribute(i)->getType(), stdv->getAttribute(i)->getBufferID());
					}

					index->addAttribute("InstancingMatrix1", 4, video::EVAS_TEXCOORD1, video::EVAT_FLOAT, 1);
					index->addAttribute("InstancingMatrix2", 4, video::EVAS_TEXCOORD2, video::EVAT_FLOAT, 1);
					index->addAttribute("InstancingMatrix3", 4, video::EVAS_TEXCOORD3, video::EVAT_FLOAT, 1);
					index->addAttribute("InstancingMatrix4", 4, video::EVAS_TEXCOORD4, video::EVAT_FLOAT, 1);

					index->setInstanceDataStepRate(video::EIDSR_PER_INSTANCE, 1);
				}

				IVertexBuffer* instanceBuffer = new CVertexBuffer<core::matrix4>();

				renderBuffer->setVertexDescriptor(index);
				renderBuffer->addVertexBuffer(instanceBuffer);

				renderBuffer->getVertexBuffer(0)->setHardwareMappingHint(scene::EHM_STATIC);
				renderBuffer->getVertexBuffer(1)->setHardwareMappingHint(scene::EHM_STATIC);
				renderBuffer->getIndexBuffer()->setHardwareMappingHint(scene::EHM_STATIC);
				instanceBuffer->drop();
			}
		}
/* This method has a lot of duplication and overhead. Moreover, the tangents mesh conversion does not really work. I think we need a a proper mesh implementation for octrees, which handle all vertex types internally. Converting all structures to just one vertex type is always problematic.
Thanks to Auria for fixing major parts of this method. */
bool COctreeSceneNode::createTree(IMesh* mesh)
{
	if (!mesh)
		return false;

	MeshName = SceneManager->getMeshCache()->getMeshName(mesh);

    mesh->grab();
	deleteTree();

	Mesh = mesh;

	const u32 beginTime = os::Timer::getRealTime();

	u32 nodeCount = 0;
	u32 polyCount = 0;
	u32 i;

	Box = mesh->getBoundingBox();

	if (mesh->getMeshBufferCount())
	{
		// check for "larger" buffer types
		u32 meshReserve = StdMeshes.size();

		Materials.reallocate(Materials.size()+meshReserve);
		StdMeshesMatID.reallocate(meshReserve);

		for ( i=0; i < mesh->getMeshBufferCount(); ++i)
		{
			IMeshBuffer* b = mesh->getMeshBuffer(i);

			if (b->getVertexBuffer()->getVertexCount() && b->getIndexBuffer()->getIndexCount())
			{
				Materials.push_back(b->getMaterial());

				IMeshBuffer* nchunk = StdMeshes[i];
				StdMeshesMatID.push_back(Materials.size() - 1);

				if (UseVisibilityAndVBOs)
				{
					nchunk->setHardwareMappingHint(scene::EHM_STATIC, scene::EBT_VERTEX);
					nchunk->setHardwareMappingHint(scene::EHM_DYNAMIC, scene::EBT_INDEX);
				}
				else
					nchunk->setHardwareMappingHint(scene::EHM_STATIC);

				SceneManager->getMeshManipulator()->copyVertices(b->getVertexBuffer(), nchunk->getVertexBuffer(), true);

				polyCount += b->getIndexBuffer()->getIndexCount();
				nchunk->getIndexBuffer()->reallocate(b->getIndexBuffer()->getIndexCount());

				for (u32 v=0; v<b->getIndexBuffer()->getIndexCount(); ++v)
					nchunk->getIndexBuffer()->addIndex(b->getIndexBuffer()->getIndex(v));
			}
		}

		StdOctree = new Octree(StdMeshes, StdMeshesMatID, MinimalPolysPerNode);
		nodeCount = StdOctree->getNodeCount();
	}

	const u32 endTime = os::Timer::getRealTime();
	c8 tmp[255];
	sprintf(tmp, "Needed %ums to create Octree SceneNode.(%u nodes, %u polys)",
		endTime - beginTime, nodeCount, polyCount/3);
	os::Printer::log(tmp, ELL_INFORMATION);

	return true;
}
Ejemplo n.º 3
0
/* This method has a lot of duplication and overhead. Moreover, the tangents mesh conversion does not really work. I think we need a a proper mesh implementation for octrees, which handle all vertex types internally. Converting all structures to just one vertex type is always problematic.
Thanks to Auria for fixing major parts of this method. */
bool COctreeSceneNode::createTree(IMesh* mesh)
{
	if (!mesh)
		return false;

	MeshName = SceneManager->getMeshCache()->getMeshName(mesh);

    mesh->grab();
	deleteTree();

	Mesh = mesh;

	const u32 beginTime = os::Timer::getRealTime();

	u32 nodeCount = 0;
	u32 polyCount = 0;
	u32 i;

	Box = mesh->getBoundingBox();

	if (mesh->getMeshBufferCount())
	{
		// check for "larger" buffer types
		u32 meshReserve = StdMeshes.size();

		Materials.reallocate(Materials.size()+meshReserve);
		StdMeshesMatID.reallocate(meshReserve);

		for ( i=0; i < mesh->getMeshBufferCount(); ++i)
		{
			const scene::IMeshManipulator* meshManipulator = SceneManager->getMeshManipulator();

			IMeshBuffer* meshBuffer = mesh->getMeshBuffer(i);
			IMeshBuffer* nchunk = StdMeshes[i];

			// copy vertices

			video::IVertexDescriptor* srcDescriptor = meshBuffer->getVertexDescriptor();
			video::IVertexDescriptor* dstDescriptor = nchunk->getVertexDescriptor();
			const u32 vbCount = meshBuffer->getVertexBufferCount();

			for (u32 j = 0; j < vbCount; ++j)
				meshManipulator->copyVertices(meshBuffer->getVertexBuffer(j), j, srcDescriptor, nchunk->getVertexBuffer(j), j, dstDescriptor, true);

			// copy indices

			scene::IIndexBuffer* srcIndexBuffer = meshBuffer->getIndexBuffer();
			scene::IIndexBuffer* dstIndexBuffer = nchunk->getIndexBuffer();
			meshManipulator->copyIndices(srcIndexBuffer, dstIndexBuffer);

			// copy material

			Materials.push_back(meshBuffer->getMaterial());
			StdMeshesMatID.push_back(Materials.size() - 1);

			// others

			polyCount += dstIndexBuffer->getIndexCount();

			if (UseVBOs)
			{
				if (UseVisibilityAndVBOs)
				{
					nchunk->setHardwareMappingHint(scene::EHM_STATIC, scene::EBT_VERTEX);
					nchunk->setHardwareMappingHint(scene::EHM_DYNAMIC, scene::EBT_INDEX);
				}
				else
					nchunk->setHardwareMappingHint(scene::EHM_STATIC);
			}
			else
			{
				nchunk->setHardwareMappingHint(scene::EHM_NEVER);
			}
		}

		StdOctree = new Octree(StdMeshes, StdMeshesMatID, MinimalPolysPerNode);
		nodeCount = StdOctree->getNodeCount();
	}

	const u32 endTime = os::Timer::getRealTime();
	c8 tmp[255];
	sprintf(tmp, "Needed %ums to create Octree SceneNode.(%u nodes, %u polys)",
		endTime - beginTime, nodeCount, polyCount/3);
	os::Printer::log(tmp, ELL_INFORMATION);

	return true;
}