📄 ac3d.cpp
字号:
{ osg::notify(osg::FATAL) << "osgDB ac3d reader: could not find texture \"" << name << "\"" << std::endl; return false; } mImage = osgDB::readImageFile(absFileName, options); if (!mImage.valid()) { osg::notify(osg::FATAL) << "osgDB ac3d reader: could not read texture \"" << name << "\"" << std::endl; return false; } mTexture2DRepeat->setImage(mImage.get()); mTexture2DClamp->setImage(mImage.get()); mTranslucent = mImage->isImageTranslucent(); // Use a shared modulate TexEnv mModulateTexEnv = modulateTexEnv; return true; } void setRepeat(bool repeat) { mRepeat = repeat; } bool valid() const { return mImage.valid(); } std::string getFileName() const { if (!mImage.valid()) return std::string(); return mImage->getFileName(); } void toTextureStateSet(osg::StateSet* stateSet) const { if (!valid()) return; stateSet->setTextureAttribute(0, mModulateTexEnv.get()); if (mRepeat) stateSet->setTextureAttribute(0, mTexture2DRepeat.get()); else stateSet->setTextureAttribute(0, mTexture2DClamp.get()); stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON); if (mTranslucent) setTranslucent(stateSet); }private: osg::ref_ptr<osg::TexEnv> mModulateTexEnv; osg::ref_ptr<osg::Texture2D> mTexture2DClamp; osg::ref_ptr<osg::Texture2D> mTexture2DRepeat; osg::ref_ptr<osg::Image> mImage; bool mTranslucent; bool mRepeat;};class FileData{ public: FileData(const osgDB::ReaderWriter::Options* options) : mOptions(options), mLightIndex(1) { mModulateTexEnv = new osg::TexEnv; mModulateTexEnv->setDataVariance(osg::Object::STATIC); mModulateTexEnv->setMode(osg::TexEnv::MODULATE); } TextureData toTextureData(const std::string& texName) { TextureDataMap::iterator i = mTextureStates.find(texName); if (i == mTextureStates.end()) mTextureStates[texName].setTexture(texName, mOptions.get(), mModulateTexEnv.get()); return mTextureStates[texName]; } osg::Light* getNextLight() { osg::Light* light = new osg::Light; light->setDataVariance(osg::Object::STATIC); light->setLightNum(mLightIndex++); return light; } void addMaterial(const MaterialData& material) { mMaterials.push_back(material); } unsigned getNumMaterials() const { return mMaterials.size(); } const MaterialData& getMaterial(unsigned idx) const { return mMaterials[idx]; }private: /// Stores the ac3d file reader options, only used for reading texture files osg::ref_ptr<osgDB::ReaderWriter::Options const> mOptions; /// The list of ac3d MATERIALS std::vector<MaterialData> mMaterials; /// Local per model texture attribute cache. /// ... images are usualy cached in the registries object cache typedef std::map<std::string, TextureData> TextureDataMap; TextureDataMap mTextureStates; /// A common shared TexEnv set to modulate osg::ref_ptr<osg::TexEnv> mModulateTexEnv; /// Hack to include light nodes from ac3d into the scenegraph unsigned mLightIndex;};struct RefData { RefData(const osg::Vec3& _weightedNormal, const osg::Vec2& _texCoord, bool _smooth) : weightedFlatNormal(_weightedNormal), weightedFlatNormalLength(_weightedNormal.length()), texCoord(_texCoord), smooth(_smooth) { } // weighted flat surface normal osg::Vec3 weightedFlatNormal; float weightedFlatNormalLength; osg::Vec2 texCoord; // resulting vertex normal osg::Vec3 finalNormal; // if zero no need to smooth unsigned smooth;};struct VertexData { VertexData(const osg::Vec3& vertex) : _vertex(vertex) {} unsigned addRefData(const RefData& refData) { unsigned index = _refs.size(); _refs.push_back(refData); return index; } void collect(float cosCreaseAngle, const RefData& ref) { unsigned size = _refs.size(); for (unsigned i = 0; i < size; ++i) { if (_refs[i].smooth == ~0u) { float dot = _refs[i].weightedFlatNormal*ref.weightedFlatNormal; float lengths = _refs[i].weightedFlatNormalLength*ref.weightedFlatNormalLength; if (cosCreaseAngle*lengths <= dot) { // Ok put that into the current set _refs[i].smooth = ref.smooth; collect(cosCreaseAngle, _refs[i]); } } } } void smoothNormals(float cosCreaseAngle) { // compute sets of vertices smoothed to the same normal // if smooth is zero we do not need to smooth // in a first pass mark all refs not yet in a set to ~0u unsigned size = _refs.size(); for (unsigned i = 0; i < size; ++i) { if (_refs[i].smooth) { _refs[i].smooth = ~0u; } } // Now collect the sets unsigned currentSet = 1; for (unsigned i = 0; i < size; ++i) { if (_refs[i].smooth == ~0u) { _refs[i].smooth = currentSet++; collect(cosCreaseAngle, _refs[i]); } } // smooth and normalize the sets for (--currentSet; 0 < currentSet; --currentSet) { osg::Vec3 normal(0, 0, 0); for (unsigned i = 0; i < size; ++i) { if (_refs[i].smooth == currentSet) { normal += _refs[i].weightedFlatNormal; } } normal.normalize(); for (unsigned i = 0; i < size; ++i) { if (_refs[i].smooth == currentSet) { _refs[i].finalNormal = normal; } } } // normalize the ones which do not need smoothing for (unsigned i = 0; i < size; ++i) { if (_refs[i].smooth == 0) { _refs[i].finalNormal = _refs[i].weightedFlatNormal; _refs[i].finalNormal.normalize(); } } } osg::Vec3 _vertex; std::vector<RefData> _refs;};struct VertexIndex { VertexIndex(unsigned _vertexIndex = 0, unsigned _refIndex = 0) : vertexIndex(_vertexIndex), refIndex(_refIndex) { } unsigned vertexIndex; unsigned refIndex;};class VertexSet : public osg::Referenced {public: VertexSet() : _dirty(true) { } void reserve(unsigned n) { _vertices.reserve(n); } unsigned size() const { return _vertices.size(); } void setCreaseAngle(float crease) { _dirty = true; if (crease <= 0) _cosCreaseAngle = 1; else if (180 <= crease) _cosCreaseAngle = -1; else _cosCreaseAngle = cosf(osg::DegreesToRadians(crease)); } void addVertex(const osg::Vec3& vertex) { _dirty = true; _vertices.push_back(vertex); } const osg::Vec3& getVertex(unsigned index) { return _vertices[index]._vertex; } const osg::Vec3& getVertex(const VertexIndex& vertexIndex) { return _vertices[vertexIndex.vertexIndex]._vertex; } const osg::Vec3& getNormal(const VertexIndex& vertexIndex) { if (_dirty) smoothNormals(); return _vertices[vertexIndex.vertexIndex]._refs[vertexIndex.refIndex].finalNormal; } const osg::Vec2& getTexCoord(const VertexIndex& vertexIndex) { return _vertices[vertexIndex.vertexIndex]._refs[vertexIndex.refIndex].texCoord; } VertexIndex addRefData(unsigned i, const RefData& refData) { if (_vertices.size() <= i) { osg::notify(osg::FATAL) << "osgDB ac3d reader: internal error, got invalid vertex index!" << std::endl; return VertexIndex(0, 0); } _dirty = true; return VertexIndex(i, _vertices[i].addRefData(refData)); }private: void smoothNormals() { std::vector<VertexData>::iterator i; for (i = _vertices.begin(); i != _vertices.end(); ++i) { i->smoothNormals(_cosCreaseAngle); } _dirty = false; } std::vector<VertexData> _vertices; float _cosCreaseAngle; bool _dirty;};class PrimitiveBin : public osg::Referenced{ public: PrimitiveBin(unsigned flags, VertexSet* vertexSet) : _geode(new osg::Geode), _vertexSet(vertexSet), _flags(flags) { _geode->setDataVariance(osg::Object::STATIC); } virtual bool beginPrimitive(unsigned nRefs) = 0; virtual bool vertex(unsigned vertexIndex, const osg::Vec2& texCoord) = 0; virtual bool endPrimitive() = 0; virtual osg::Geode* finalize(const MaterialData& material, const TextureData& textureData) = 0; protected: bool isLineLoop() const { return (_flags & SurfaceTypeLineLoop)!=0; } bool isLineStrip() const { return (_flags & SurfaceTypeLineStrip)!=0; } bool isTwoSided() const { return (_flags & SurfaceTwoSided)!=0; } bool isSmooth() const { return (_flags & SurfaceShaded)!=0; } osg::ref_ptr<osg::Geode> _geode; osg::ref_ptr<VertexSet> _vertexSet; private: unsigned _flags;};class LineBin : public PrimitiveBin{ private: osg::ref_ptr<osg::Geometry> _geometry; osg::ref_ptr<osg::Vec3Array> _vertices; osg::ref_ptr<osg::Vec2Array> _texCoords; struct Ref { osg::Vec2 texCoord;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -