📄 ac3d.cpp
字号:
unsigned index; }; std::vector<Ref> _refs; public: LineBin(unsigned flags, VertexSet* vertexSet) : PrimitiveBin(flags, vertexSet), _geometry(new osg::Geometry), _vertices(new osg::Vec3Array), _texCoords(new osg::Vec2Array) { _geometry->setDataVariance(osg::Object::STATIC); _vertices->setDataVariance(osg::Object::STATIC); _texCoords->setDataVariance(osg::Object::STATIC); _geometry->setVertexArray(_vertices.get()); _geometry->setTexCoordArray(0, _texCoords.get()); osg::StateSet* stateSet = _geode->getOrCreateStateSet(); stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF); } virtual bool beginPrimitive(unsigned nRefs) { // Check if we have enough for a line or someting broken ... if (nRefs < 2) { osg::notify(osg::WARN) << "osgDB ac3d reader: detected line with less than 2 vertices!" << std::endl; return false; } _refs.reserve(nRefs); _refs.resize(0); return true; } virtual bool vertex(unsigned vertexIndex, const osg::Vec2& texCoord) { Ref ref; ref.index = vertexIndex; ref.texCoord = texCoord; _refs.push_back(ref); return true; } virtual bool endPrimitive() { GLint type; if (isLineLoop()) type = osg::PrimitiveSet::LINE_LOOP; else if (isLineStrip()) type = osg::PrimitiveSet::LINE_STRIP; else { osg::notify(osg::FATAL) << "osgDB ac3d reader: non surface flags in surface bin!" << std::endl; return false; } unsigned nRefs = _refs.size(); unsigned start = _vertices->size(); for (unsigned i = 0; i < nRefs; ++i) { osg::Vec3 vertex = _vertexSet->getVertex(_refs[i].index); _vertices->push_back(vertex); _texCoords->push_back(_refs[i].texCoord); } _geometry->addPrimitiveSet(new osg::DrawArrays(type, start, nRefs)); return true; } virtual osg::Geode* finalize(const MaterialData& material, const TextureData& textureData) { _geode->addDrawable(_geometry.get()); material.toStateSet(_geode->getOrCreateStateSet()); _geometry->setColorArray(material.getColorArray()); _geometry->setColorBinding(osg::Geometry::BIND_OVERALL); _geometry->setNormalBinding(osg::Geometry::BIND_OFF); return _geode.get(); }};class SurfaceBin : public PrimitiveBin { private: struct Ref { osg::Vec2 texCoord; unsigned index; }; std::vector<Ref> _refs; struct TriangleData { VertexIndex index[3]; }; std::vector<TriangleData> _triangles; struct QuadData { VertexIndex index[4]; }; std::vector<QuadData> _quads; struct PolygonData { std::vector<VertexIndex> index; }; std::vector<PolygonData> _polygons; std::vector<PolygonData> _toTessellatePolygons; public: SurfaceBin(unsigned flags, VertexSet *vertexSet) : PrimitiveBin(flags, vertexSet) { } virtual bool beginPrimitive(unsigned nRefs) { _refs.reserve(nRefs); _refs.clear(); // Check if we have enough for a line or someting broken ... if (nRefs < 3) { osg::notify(osg::WARN) << "osgDB ac3d reader: detected surface with less than 3 vertices!" << std::endl; return false; } return true; } virtual bool vertex(unsigned vertexIndex, const osg::Vec2& texCoord) { Ref ref; ref.index = vertexIndex; ref.texCoord = texCoord; _refs.push_back(ref); return true; } virtual bool endPrimitive() { unsigned nRefs = _refs.size(); // Compute the normal times the enclosed area. // During that check if the surface is convex. If so, put in the surface as such. bool needTessellation = false; osg::Vec3 prevEdgeNormal; osg::Vec3 weightedNormal(0, 0, 0); osg::Vec3 v0 = _vertexSet->getVertex(_refs[0].index); for (unsigned i = 2; i < nRefs; ++i) { osg::Vec3 side1 = _vertexSet->getVertex(_refs[i-1].index) - v0; osg::Vec3 side2 = _vertexSet->getVertex(_refs[i].index) - v0; osg::Vec3 newNormal = side1^side2; if (!needTessellation) { if (3 < nRefs && newNormal*weightedNormal < 0) { needTessellation = true; } if (i < 3) { prevEdgeNormal = newNormal; } else // if (3 <= i) // due to the for loop { osg::Vec3 sideim1 = _vertexSet->getVertex(_refs[i-1].index) - _vertexSet->getVertex(_refs[i-2].index); osg::Vec3 sidei = _vertexSet->getVertex(_refs[i].index) - _vertexSet->getVertex(_refs[i-2].index); osg::Vec3 edgeNormal = sideim1^sidei; if (edgeNormal*prevEdgeNormal < 0) { needTessellation = true; } prevEdgeNormal = edgeNormal; } } weightedNormal += newNormal; } if (needTessellation) { unsigned polygonIndex = _toTessellatePolygons.size(); _toTessellatePolygons.resize(polygonIndex + 1); for (unsigned i = 0; i < nRefs; ++i) { RefData refData(weightedNormal, _refs[i].texCoord, isSmooth()); VertexIndex vertexIndex = _vertexSet->addRefData(_refs[i].index, refData); _toTessellatePolygons[polygonIndex].index.push_back(vertexIndex); } } else if (nRefs == 3) { unsigned triangleIndex = _triangles.size(); _triangles.resize(triangleIndex + 1); for (unsigned i = 0; i < 3; ++i) { RefData refData(weightedNormal, _refs[i].texCoord, isSmooth()); VertexIndex vertexIndex = _vertexSet->addRefData(_refs[i].index, refData); _triangles[triangleIndex].index[i] = vertexIndex; } } else if (nRefs == 4) { unsigned quadIndex = _quads.size(); _quads.resize(quadIndex + 1); for (unsigned i = 0; i < 4; ++i) { RefData refData(weightedNormal, _refs[i].texCoord, isSmooth()); VertexIndex vertexIndex = _vertexSet->addRefData(_refs[i].index, refData); _quads[quadIndex].index[i] = vertexIndex; } } else { unsigned polygonIndex = _polygons.size(); _polygons.resize(polygonIndex + 1); for (unsigned i = 0; i < nRefs; ++i) { RefData refData(weightedNormal, _refs[i].texCoord, isSmooth()); VertexIndex vertexIndex = _vertexSet->addRefData(_refs[i].index, refData); _polygons[polygonIndex].index.push_back(vertexIndex); } } return true; } void pushVertex(const VertexIndex& vertexIndex, osg::Vec3Array* vertexArray, osg::Vec3Array* normalArray, osg::Vec2Array* texcoordArray) { vertexArray->push_back(_vertexSet->getVertex(vertexIndex)); normalArray->push_back(_vertexSet->getNormal(vertexIndex)); if (texcoordArray) texcoordArray->push_back(_vertexSet->getTexCoord(vertexIndex)); } virtual osg::Geode* finalize(const MaterialData& material, const TextureData& textureData) { osg::StateSet* stateSet = _geode->getOrCreateStateSet(); material.toStateSet(stateSet); textureData.toTextureStateSet(stateSet); stateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON); // Single- or doublesided culling if (isTwoSided()) { stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); } else { osg::CullFace* cullFace = new osg::CullFace; cullFace->setDataVariance(osg::Object::STATIC); cullFace->setMode(osg::CullFace::BACK); stateSet->setAttribute(cullFace); stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::ON); } // Flat or smooth shading osg::ShadeModel* shadeModel = new osg::ShadeModel; shadeModel->setDataVariance(osg::Object::STATIC); if (isSmooth()) shadeModel->setMode(osg::ShadeModel::SMOOTH); else shadeModel->setMode(osg::ShadeModel::FLAT); stateSet->setAttribute(shadeModel); // Set up the arrays, allways store texture coords, may be we need them later ... osg::Geometry* geometry = new osg::Geometry; _geode->addDrawable(geometry); geometry->setDataVariance(osg::Object::STATIC); geometry->setColorArray(material.getColorArray()); geometry->setColorBinding(osg::Geometry::BIND_OVERALL); geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); osg::Vec3Array* normalArray = new osg::Vec3Array; normalArray->setDataVariance(osg::Object::STATIC); geometry->setNormalArray(normalArray); osg::Vec3Array* vertexArray = new osg::Vec3Array; vertexArray->setDataVariance(osg::Object::STATIC); geometry->setVertexArray(vertexArray); osg::Vec2Array* texcoordArray = 0; if (textureData.valid()) { texcoordArray = new osg::Vec2Array; texcoordArray->setDataVariance(osg::Object::STATIC); geometry->setTexCoordArray(0, texcoordArray); } // At first handle the the polygons to tessellate, fix them and append the other polygons later if (!_toTessellatePolygons.empty()) { unsigned start = vertexArray->size(); osg::DrawArrayLengths* drawArrayLengths = new osg::DrawArrayLengths(osg::PrimitiveSet::POLYGON, start); drawArrayLengths->reserve(_toTessellatePolygons.size()); for (unsigned i = 0; i < _toTessellatePolygons.size(); ++i) { for (unsigned j = 0; j < _toTessellatePolygons[i].index.size(); ++j) { pushVertex(_toTessellatePolygons[i].index[j], vertexArray, normalArray, texcoordArray); } drawArrayLengths->push_back(_toTessellatePolygons[i].index.size()); } geometry->addPrimitiveSet(drawArrayLengths); osgUtil::Tessellator Tessellator; Tessellator.retessellatePolygons(*geometry); } // handle triangles if (!_triangles.empty()) { unsigned start = vertexArray->size(); for (unsigned i = 0; i < _triangles.size(); ++i) { for (unsigned j = 0; j < 3; ++j) { pushVertex(_triangles[i].index[j], vertexArray, normalArray, texcoordArray); } } osg::DrawArrays* drawArray = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, start, 3*_triangles.size()); geometry->addPrimitiveSet(drawArray); } // handle quads if (!_quads.empty()) { unsigned start = vertexArray->size(); for (unsigned i = 0; i < _quads.size(); ++i) { for (unsigned j = 0; j < 4; ++j) { pushVertex(_quads[i].index[j], vertexArray, normalArray, texcoordArray); } } osg::DrawArrays* drawArray = new osg::DrawArrays(osg::PrimitiveSet::QUADS, start, 4*_quads.size()); geometry->addPrimitiveSet(drawArray); } // handle polygons if (!_polygons.empty()) { unsigned start = vertexArray->size(); osg::DrawArrayLengths* drawArrayLengths = new osg::DrawArrayLengths(osg::PrimitiveSet::POLYGON, start); drawArrayLengths->reserve(_polygons.size()); for (unsigned i = 0; i < _polygons.size(); ++i) { for (unsigned j = 0; j < _polygons[i].index.size(); ++j) { pushVertex(_polygons[i].index[j], vertexArray, normalArray, texcoordArray); } drawArrayLengths->push_back(_polygons[i].index.size()); } geometry->addPrimitiveSet(drawArrayLengths); } return _geode.get(); }};struct Bins{ PrimitiveBin* getOrCreatePrimitiveBin(unsigned flags, VertexSet* vertexSet) { if ((flags & SurfaceTypeLineLoop) || (flags & SurfaceTypeLineStrip)) { if (!lineBin.valid()) { lineBin = new LineBin(flags, vertexSet); } return lineBin.get(); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -