osgdb_<расширение файла>.dll
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("cessna.osg");
osg::ref_ptr<osg:Image> image = osgDB::readImageFile("picture.png");
$ osgconv cessna.osg cessna.3ds
mingw_osgdb_<расширение файла>.dll
osgdb_<расширение файла>d.dll
mingw_osgdb_<расширение файла>d.dll
$ osgviewer worldmap.shp.ogr
node = osgDB::readNodeFile("cessna.osg.0,0,90.rot");
Method | Description |
---|---|
supportsExtensions () | It accepts two string parameters: file extension and description. The method is always called in the constructor of a subclass. |
acceptsExtension () | Returns true if the extension passed in as an argument is supported by the plugin. |
fileExists () | Allows you to determine whether this file (the path is passed as a parameter) on the disk (returns true if successful) |
readNode () | Accepts the file name and options as an osgDB :: Option object. Functions for reading data from a file are implemented by the developer. |
writeNode () | Accepts the name of the node, the desired file name and options. Functions for writing data to disk are implemented by the developer. |
readImage () | Reading raster image data from disk |
writeImage () | Burn bitmap to disk |
osgDB::ReaderWriter::ReadResult readNode( const std::string &file, const osgDB::Options *options) const { // Проверяем что расширение файла поддерживается и файл существует bool recognizableExtension = ...; bool fileExists = ...; if (!recognizableExtension) return ReadResult::FILE_NOT_HANDLED; if (!fileExists) return ReadResult::FILE_NOT_FOUND; // Конструируем подграф сцены в соответствии со спецификацией загружаемого формата osg::Node *root = ...; // В случае ошибок в процессе выполнения каких-либо операций возвращаем сообщения об ошибке. // В случае успеха - возвращаем корневую ноду подграфа сцены bool errorInParsing = ...; if (errorInParsing) return ReadResult::ERROR_IN_READING_FILE; return root; }
// Параметры не передаются osg::Node* node1 = osgDB::readNodeFile("cow.osg"); // Параметры передаются через строку string osg::Node* node2 = osgDB::readNodeFile("cow.osg", new osgDB::Options(string));
osgDB::ReaderWriter::ReadResult readNode( const std::string &file, const osgDB::Options *options) const { ... osgDB::ifstream stream(file.c_str(), std::ios::binary); if (!stream) return ReadResult::ERROR_IN_READING_FILE; return readNode(stream, options); } ... osgDB::ReaderWriter::ReadResult readNode( std::istream &stream, const osgDB::Options *options) const { // Формируем граф сцены в соответствии с форматом файла osg::Node *root = ...; return root; }
vertex: 1.0 1.0 0.0 vertex: 1.0 -1.0 0.0 vertex: -1.0 -1.0 0.0 vertex: -1.0 1.0 0.0 vertex: 0.0 0.0 2.0 face: 0 1 2 3 face: 0 3 4 face: 1 0 4 face: 2 1 4 face: 3 2 4
TEMPLATE = lib CONFIG += plugin CONFIG += no_plugin_name_prefix TARGET = osgdb_pmd win32-g++: TARGET = $$join(TARGET,,mingw_,) win32 { OSG_LIB_DIRECTORY = $$(OSG_BIN_PATH) OSG_INCLUDE_DIRECTORY = $$(OSG_INCLUDE_PATH) DESTDIR = $$(OSG_PLUGINS_PATH) CONFIG(debug, debug|release) { TARGET = $$join(TARGET,,,d) LIBS += -L$$OSG_LIB_DIRECTORY -losgd LIBS += -L$$OSG_LIB_DIRECTORY -losgViewerd LIBS += -L$$OSG_LIB_DIRECTORY -losgDBd LIBS += -L$$OSG_LIB_DIRECTORY -lOpenThreadsd LIBS += -L$$OSG_LIB_DIRECTORY -losgUtild } else { LIBS += -L$$OSG_LIB_DIRECTORY -losg LIBS += -L$$OSG_LIB_DIRECTORY -losgViewer LIBS += -L$$OSG_LIB_DIRECTORY -losgDB LIBS += -L$$OSG_LIB_DIRECTORY -lOpenThreads LIBS += -L$$OSG_LIB_DIRECTORY -losgUtil } INCLUDEPATH += $$OSG_INCLUDE_DIRECTORY } unix { DESTDIR = /usr/lib/osgPlugins-3.7.0 CONFIG(debug, debug|release) { TARGET = $$join(TARGET,,,d) LIBS += -losgd LIBS += -losgViewerd LIBS += -losgDBd LIBS += -lOpenThreadsd LIBS += -losgUtild } else { LIBS += -losg LIBS += -losgViewer LIBS += -losgDB LIBS += -lOpenThreads LIBS += -losgUtil } } INCLUDEPATH += ./include HEADERS += $$files(./include/*.h) SOURCES += $$files(./src/*.cpp)
TEMPLATE = lib
CONFIG += plugin
CONFIG += no_plugin_name_prefix
TARGET = osgdb_pmd
win32-g++: TARGET = $$join(TARGET,,mingw_,)
DESTDIR = $$(OSG_PLUGINS_PATH)
DESTDIR = /usr/lib/osgPlugins-3.7.0
# chmod 666 /usr/lib/osgPlugins-3.7.0
node = osdDB::readNodeFile("piramide.pmd");
$ osgviewer piramide.pmd
#ifndef MAIN_H #define MAIN_H #include <osg/Geometry> #include <osg/Geode> #include <osgDB/FileNameUtils> #include <osgDB/FileUtils> #include <osgDB/Registry> #include <osgUtil/SmoothingVisitor> //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ struct face_t { std::vector<unsigned int> indices; }; //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ struct pmd_mesh_t { osg::ref_ptr<osg::Vec3Array> vertices; osg::ref_ptr<osg::Vec3Array> normals; std::vector<face_t> faces; pmd_mesh_t() : vertices(new osg::Vec3Array) , normals(new osg::Vec3Array) { } osg::Vec3 calcFaceNormal(const face_t &face) const { osg::Vec3 v0 = (*vertices)[face.indices[0]]; osg::Vec3 v1 = (*vertices)[face.indices[1]]; osg::Vec3 v2 = (*vertices)[face.indices[2]]; osg::Vec3 n = (v1 - v0) ^ (v2 - v0); return n * (1 / n.length()); } }; //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ class ReaderWriterPMD : public osgDB::ReaderWriter { public: ReaderWriterPMD(); virtual ReadResult readNode(const std::string &filename, const osgDB::Options *options) const; virtual ReadResult readNode(std::istream &stream, const osgDB::Options *options) const; private: pmd_mesh_t parsePMD(std::istream &stream) const; std::vector<std::string> parseLine(const std::string &line) const; }; #endif
#include "main.h" //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ ReaderWriterPMD::ReaderWriterPMD() { supportsExtension("pmd", "PMD model file"); } //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ osgDB::ReaderWriter::ReadResult ReaderWriterPMD::readNode( const std::string &filename, const osgDB::Options *options) const { std::string ext = osgDB::getLowerCaseFileExtension(filename); if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; std::string fileName = osgDB::findDataFile(filename, options); if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; std::ifstream stream(fileName.c_str(), std::ios::in); if (!stream) return ReadResult::ERROR_IN_READING_FILE; return readNode(stream, options); } //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ osgDB::ReaderWriter::ReadResult ReaderWriterPMD::readNode( std::istream &stream, const osgDB::Options *options) const { (void) options; pmd_mesh_t mesh = parsePMD(stream); osg::ref_ptr<osg::Geometry> geom = new osg::Geometry; geom->setVertexArray(mesh.vertices.get()); for (size_t i = 0; i < mesh.faces.size(); ++i) { osg::ref_ptr<osg::DrawElementsUInt> polygon = new osg::DrawElementsUInt(osg::PrimitiveSet::POLYGON, 0); for (size_t j = 0; j < mesh.faces[i].indices.size(); ++j) polygon->push_back(mesh.faces[i].indices[j]); geom->addPrimitiveSet(polygon.get()); } geom->setNormalArray(mesh.normals.get()); geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE_SET); osg::ref_ptr<osg::Geode> geode = new osg::Geode; geode->addDrawable(geom.get()); return geode.release(); } //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ pmd_mesh_t ReaderWriterPMD::parsePMD(std::istream &stream) const { pmd_mesh_t mesh; while (!stream.eof()) { std::string line; std::getline(stream, line); std::vector<std::string> tokens = parseLine(line); if (tokens[0] == "vertex") { osg::Vec3 point; std::istringstream iss(tokens[1]); iss >> point.x() >> point.y() >> point.z(); mesh.vertices->push_back(point); } if (tokens[0] == "face") { unsigned int idx = 0; std::istringstream iss(tokens[1]); face_t face; while (!iss.eof()) { iss >> idx; face.indices.push_back(idx); } mesh.faces.push_back(face); mesh.normals->push_back(mesh.calcFaceNormal(face)); } } return mesh; } //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ std::string delete_symbol(const std::string &str, char symbol) { std::string tmp = str; tmp.erase(std::remove(tmp.begin(), tmp.end(), symbol), tmp.end()); return tmp; } //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ std::vector<std::string> ReaderWriterPMD::parseLine(const std::string &line) const { std::vector<std::string> tokens; std::string tmp = delete_symbol(line, '\r'); size_t pos = 0; std::string token; while ( (pos = tmp.find(':')) != std::string::npos ) { token = tmp.substr(0, pos); tmp.erase(0, pos + 1); if (!token.empty()) tokens.push_back(token); } tokens.push_back(tmp); return tokens; } REGISTER_OSGPLUGIN( pmd, ReaderWriterPMD )
struct face_t { std::vector<unsigned int> indices; };
struct pmd_mesh_t { osg::ref_ptr<osg::Vec3Array> vertices; osg::ref_ptr<osg::Vec3Array> normals; std::vector<face_t> faces; pmd_mesh_t() : vertices(new osg::Vec3Array) , normals(new osg::Vec3Array) { } osg::Vec3 calcFaceNormal(const face_t &face) const { osg::Vec3 v0 = (*vertices)[face.indices[0]]; osg::Vec3 v1 = (*vertices)[face.indices[1]]; osg::Vec3 v2 = (*vertices)[face.indices[2]]; osg::Vec3 n = (v1 - v0) ^ (v2 - v0); return n * (1 / n.length()); } };
pmd_mesh_t() : vertices(new osg::Vec3Array) , normals(new osg::Vec3Array) { }
class ReaderWriterPMD : public osgDB::ReaderWriter { public: ReaderWriterPMD(); virtual ReadResult readNode(const std::string &filename, const osgDB::Options *options) const; virtual ReadResult readNode(std::istream &stream, const osgDB::Options *options) const; private: pmd_mesh_t parsePMD(std::istream &stream) const; std::vector<std::string> parseLine(const std::string &line) const; };
ReaderWriterPMD::ReaderWriterPMD() { supportsExtension("pmd", "PMD model file"); }
osgDB::ReaderWriter::ReadResult ReaderWriterPMD::readNode( const std::string &filename, const osgDB::Options *options) const { // Получаем расширение из пути к файлу std::string ext = osgDB::getLowerCaseFileExtension(filename); // Проверяем, поддерживает ли плагин это расширение if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; // Проверяем, имеется ли данный файл на диске std::string fileName = osgDB::findDataFile(filename, options); if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; // Связваем поток ввода с файлом std::ifstream stream(fileName.c_str(), std::ios::in); if (!stream) return ReadResult::ERROR_IN_READING_FILE; // Вызываем основную рабочую перегрузку метода readNode() return readNode(stream, options); }
osgDB::ReaderWriter::ReadResult ReaderWriterPMD::readNode( std::istream &stream, const osgDB::Options *options) const { (void) options; // Парсим файл *.pmd извлекая из него данные о геометрии pmd_mesh_t mesh = parsePMD(stream); // Создаем геометрию объекта osg::ref_ptr<osg::Geometry> geom = new osg::Geometry; // Задаем массив вершин geom->setVertexArray(mesh.vertices.get()); // Формируем грани объекта for (size_t i = 0; i < mesh.faces.size(); ++i) { // Создаем примитив типа GL_POLYGON с пустым списком индексов вершин (второй параметр - 0) osg::ref_ptr<osg::DrawElementsUInt> polygon = new osg::DrawElementsUInt(osg::PrimitiveSet::POLYGON, 0); // Заполняем индексы вершин для текущей грани for (size_t j = 0; j < mesh.faces[i].indices.size(); ++j) polygon->push_back(mesh.faces[i].indices[j]); // Добаляем грань к геометрии geom->addPrimitiveSet(polygon.get()); } // Задаем массив нормалей geom->setNormalArray(mesh.normals.get()); // Указываем OpenGL, что каждая нормаль применяется к примитиву geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE_SET); // Создаем листовой узел графа сцены и добавляем в него сформированную нами геометрию osg::ref_ptr<osg::Geode> geode = new osg::Geode; geode->addDrawable(geom.get()); // Возвращаем готовый листовой узел return geode.release(); }
REGISTER_OSGPLUGIN( pmd, ReaderWriterPMD )
pmd_mesh_t ReaderWriterPMD::parsePMD(std::istream &stream) const { pmd_mesh_t mesh; // Читаем файл построчно while (!stream.eof()) { // Получаем из файла очередную строку std::string line; std::getline(stream, line); // Разбиваем строку на составлящие - тип данный и параметры std::vector<std::string> tokens = parseLine(line); // Если тип данных - вершина if (tokens[0] == "vertex") { // Читаем координаты вершины из списка параметров osg::Vec3 point; std::istringstream iss(tokens[1]); iss >> point.x() >> point.y() >> point.z(); // Добавляем вершину в массив вершин mesh.vertices->push_back(point); } // Если тип данных - грань if (tokens[0] == "face") { // Читаем все индексы вершин грани из списка параметров unsigned int idx = 0; std::istringstream iss(tokens[1]); face_t face; while (!iss.eof()) { iss >> idx; face.indices.push_back(idx); } // Добавляем грань в список граней mesh.faces.push_back(face); // Вычисляем нормаль к грани mesh.normals->push_back(mesh.calcFaceNormal(face)); } } return mesh; }
std::vector<std::string> ReaderWriterPMD::parseLine(const std::string &line) const { std::vector<std::string> tokens; // Формируем временную строку, удаляя из текущей строки символ возврата каретки (для Windows) std::string tmp = delete_symbol(line, '\r'); size_t pos = 0; std::string token; // Ищем разделитель типа данных и параметров, разбивая строку на два токена: // тип данных и сами данные while ( (pos = tmp.find(':')) != std::string::npos ) { // Выделяем токен типа данных (vertex или face в данном случае) token = tmp.substr(0, pos); // Удаляем найденный токен из строки вместе с разделителем tmp.erase(0, pos + 1); if (!token.empty()) tokens.push_back(token); } // Помещаем оставшуюся часть строки в список токенов tokens.push_back(tmp); return tokens; }
std::string delete_symbol(const std::string &str, char symbol) { std::string tmp = str; tmp.erase(std::remove(tmp.begin(), tmp.end(), symbol), tmp.end()); return tmp; }
osgUtil::SmoothingVisitor::smooth(*geom);
//geom->setNormalArray(mesh.normals.get()); //geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE_SET); osgUtil::SmoothingVisitor::smooth(*geom);
Source: https://habr.com/ru/post/438296/