diff --git a/modules/ovis/include/opencv2/ovis.hpp b/modules/ovis/include/opencv2/ovis.hpp index 0c605999634..d2a5437838b 100644 --- a/modules/ovis/include/opencv2/ovis.hpp +++ b/modules/ovis/include/opencv2/ovis.hpp @@ -414,6 +414,23 @@ CV_EXPORTS_W void createGridMesh(const String& name, const Size2f& size, const S */ CV_EXPORTS_W void createTriangleMesh(const String& name, InputArray vertices, InputArray normals = noArray(), InputArray indices = noArray()); +/** + * Loads a mesh from a known resource location. + * + * The file format is determined by the file extension. Supported formats are Ogre @c .mesh and everything that Assimp can load. + * @param meshname Name of the mesh file + * @param vertices vertex coordinates, each value contains 3 floats + * @param indices per-face list of vertices, each value contains 3 ints + * @param normals per-vertex normals, each value contains 3 floats + * @param colors per-vertex colors, each value contains 4 uchars + * @param texCoords per-vertex texture coordinates, each value contains 2 floats + * + * @see addResourceLocation() + */ +CV_EXPORTS_W void loadMesh(const String& meshname, OutputArray vertices, OutputArray indices, + OutputArray normals = noArray(), OutputArray colors = noArray(), + OutputArray texCoords = noArray()); + /// @deprecated use setMaterialProperty CV_EXPORTS_W void updateTexture(const String& name, InputArray image); //! @} diff --git a/modules/ovis/src/ovis.cpp b/modules/ovis/src/ovis.cpp index 38dfcbc2ee0..a0286aca524 100644 --- a/modules/ovis/src/ovis.cpp +++ b/modules/ovis/src/ovis.cpp @@ -31,7 +31,7 @@ static Vector2 toOGRE_SS = Vector2(1, -1); WindowScene::~WindowScene() {} -void _createTexture(const String& name, Mat image) +void _createTexture(const String& name, Mat image, int mipmaps) { PixelFormat format; switch(image.type()) @@ -62,7 +62,7 @@ void _createTexture(const String& name, Mat image) if(!tex) { tex = texMgr.createManual(name, RESOURCEGROUP_NAME, TEX_TYPE_2D, image.cols, image.rows, - MIP_DEFAULT, format); + mipmaps, format); } PixelBox box(image.cols, image.rows, 1, format, image.ptr()); @@ -441,7 +441,7 @@ class WindowSceneImpl : public WindowScene String name = sceneMgr->getName() + "_Background"; - _createTexture(name, image.getMat()); + _createTexture(name, image.getMat(), 0); // ensure bgplane is visible bgplane->setVisible(true); @@ -808,7 +808,7 @@ class WindowSceneImpl : public WindowScene String name = "_" + sceneMgr->getName() + "_DefaultBackground"; Mat_ img = (Mat_(2, 1) << Vec3b(2, 1, 1), Vec3b(240, 120, 120)); - _createTexture(name, img); + _createTexture(name, img, 0); MaterialPtr mat = MaterialManager::getSingleton().create(name, RESOURCEGROUP_NAME); Pass* rpass = mat->getTechniques()[0]->getPasses()[0]; @@ -1155,5 +1155,77 @@ void updateTexture(const String& name, InputArray image) CV_Assert(tex); _createTexture(name, image.getMat()); } + +void loadMesh(const String& meshname, OutputArray vertices, OutputArray indices, OutputArray normals, OutputArray colors, OutputArray texCoords) +{ + CV_Assert(_app); + + auto mesh = MeshManager::getSingleton().load(meshname, RESOURCEGROUP_NAME); + auto smeshes = mesh->getSubMeshes(); + CV_Assert(smeshes.size() == 1); + + auto smesh = smeshes.front(); + + CV_Assert(smesh->operationType == RenderOperation::OT_TRIANGLE_LIST); + + if (auto ibuf = smesh->indexData->indexBuffer) + { + auto idtype = ibuf->getType() == HardwareIndexBuffer::IT_16BIT ? CV_16S : CV_32S; + auto imat = Mat(smesh->indexData->indexCount, 3, idtype); + ibuf->readData(0, ibuf->getSizeInBytes(), imat.ptr()); + imat.copyTo(indices); + } + + auto vertexData = smesh->useSharedVertices ? mesh->sharedVertexData : smesh->vertexData; + DefaultHardwareBufferManagerBase swhbm; + + // download all buffers to CPU for reorganization + auto tmpVertexData = vertexData->clone(true, &swhbm); + auto tgtDecl = swhbm.createVertexDeclaration(); + tgtDecl->addElement(0, 0, VET_FLOAT3, VES_POSITION); // separate position buffer + + bool has_normals = vertexData->vertexDeclaration->findElementBySemantic(VES_NORMAL); + bool has_texcoords = vertexData->vertexDeclaration->findElementBySemantic(VES_TEXTURE_COORDINATES); + bool has_colors = vertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE); + if (has_normals) + tgtDecl->addElement(1, 0, VET_FLOAT3, VES_NORMAL); // separate normal buffer + if (has_texcoords) + tgtDecl->addElement(2, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES); // separate texcoord buffer + if (has_colors) + tgtDecl->addElement(3, 0, VET_UBYTE4_NORM, VES_DIFFUSE); // separate color buffer + + tmpVertexData->reorganiseBuffers(tgtDecl); + + // copy data + auto vertmat = Mat(vertexData->vertexCount, 3, CV_32F); + auto posbuf = tmpVertexData->vertexBufferBinding->getBuffer(0); + posbuf->readData(0, posbuf->getSizeInBytes(), vertmat.ptr()); + vertmat.copyTo(vertices); + + if(has_normals && normals.needed()) + { + auto normmat = Mat(vertexData->vertexCount, 3, CV_32F); + auto nbuf = tmpVertexData->vertexBufferBinding->getBuffer(1); + nbuf->readData(0, nbuf->getSizeInBytes(), normmat.ptr()); + normmat.copyTo(normals); + } + + if(has_texcoords && texCoords.needed()) + { + auto texmat = Mat(vertexData->vertexCount, 2, CV_32F); + auto tbuf = tmpVertexData->vertexBufferBinding->getBuffer(2); + tbuf->readData(0, tbuf->getSizeInBytes(), texmat.ptr()); + texmat.copyTo(texCoords); + } + + if(has_colors && colors.needed()) + { + auto colmat = Mat(vertexData->vertexCount, 4, CV_8U); + auto cbuf = tmpVertexData->vertexBufferBinding->getBuffer(3); + cbuf->readData(0, cbuf->getSizeInBytes(), colmat.ptr()); + colmat.copyTo(colors); + } +} + } } diff --git a/modules/ovis/src/precomp.hpp b/modules/ovis/src/precomp.hpp index 3111ee60dab..ff4be085b4e 100644 --- a/modules/ovis/src/precomp.hpp +++ b/modules/ovis/src/precomp.hpp @@ -18,7 +18,7 @@ struct Application; extern Ptr _app; extern const char* RESOURCEGROUP_NAME; -void _createTexture(const String& name, Mat image); +void _createTexture(const String& name, Mat image, int mipmaps = Ogre::MIP_DEFAULT); } }