//! 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(); } }
void CTriangleSelector::updateFromMesh(const IMesh* mesh) const { if (!mesh) return; u32 meshBuffers = mesh->getMeshBufferCount(); u32 triangleCount = 0; BoundingBox.reset(0.f, 0.f, 0.f); for (u32 i = 0; i < meshBuffers; ++i) { IMeshBuffer* buf = mesh->getMeshBuffer(i); u32 idxCnt = buf->getIndexBuffer()->getIndexCount(); video::IVertexAttribute* attribute = buf->getVertexBuffer()->getVertexDescriptor()->getAttributeBySemantic(video::EVAS_POSITION); if(!attribute) continue; u8* offset = static_cast<u8*>(buf->getVertexBuffer()->getVertices()); offset += attribute->getOffset(); for (u32 index = 0; index < idxCnt; index += 3) { core::vector3df* position0 = (core::vector3df*)(offset + buf->getVertexBuffer()->getVertexSize() * buf->getIndexBuffer()->getIndex(index+0)); core::vector3df* position1 = (core::vector3df*)(offset + buf->getVertexBuffer()->getVertexSize() * buf->getIndexBuffer()->getIndex(index+1)); core::vector3df* position2 = (core::vector3df*)(offset + buf->getVertexBuffer()->getVertexSize() * buf->getIndexBuffer()->getIndex(index+2)); core::triangle3df& tri = Triangles[triangleCount++]; tri.pointA = *position0; tri.pointB = *position1; tri.pointC = *position2; BoundingBox.addInternalPoint(tri.pointA); BoundingBox.addInternalPoint(tri.pointB); BoundingBox.addInternalPoint(tri.pointC); } } }
/* 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; }
/* 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; }