📄 readerwriterq3bsp.cpp
字号:
#include <osg/TexEnv>#include <osg/CullFace>#include <osg/Geode>#include <osg/Geometry>#include <osg/Image>#include <osg/Texture2D>#include <osg/PolygonMode>#include <osg/BlendColor>#include <osgDB/ReadFile>#include <osgDB/FileNameUtils>#include <osgDB/FileUtils>#include <assert.h>#include <fstream>#include "BSPLoad.h"class ReaderWriterQ3BSP: public osgDB::ReaderWriter{public: ReaderWriterQ3BSP() { supportsExtension("bsp","Quake3 BSP model format"); } virtual const char* className() const { return "Quake3 BSP Reader"; } virtual ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* options) const;private: osg::Geode* convertFromBSP(BSPLoad& aLoadData,const osgDB::ReaderWriter::Options* options) const; osg::Geometry* createMeshFace(const BSP_LOAD_FACE& aLoadFace,const std::vector<osg::Texture2D*>& aTextureArray, osg::Vec3Array& aVertexArray,std::vector<GLuint>& aIndices, osg::Vec2Array& aTextureDecalCoords,osg::Vec2Array& aTextureLMapCoords ) const; osg::Geometry* createPolygonFace(const BSP_LOAD_FACE& aLoadFace,const std::vector<osg::Texture2D*>& aTextureArray,const std::vector<osg::Texture2D*>& aTextureLMapArray, osg::Vec3Array& aVertexArray, osg::Vec2Array& aTextureDecalCoords,osg::Vec2Array& aTextureLMapCoords ) const; bool loadTextures(const BSPLoad& aLoadData,std::vector<osg::Texture2D*>& aTextureArray) const; bool loadLightMaps(const BSPLoad& aLoadData,std::vector<osg::Texture2D*>& aTextureArray) const;};// Register with Registry to instantiate the above reader/writer.REGISTER_OSGPLUGIN(bsp, ReaderWriterQ3BSP)// Read nodeosgDB::ReaderWriter::ReadResult ReaderWriterQ3BSP::readNode(const std::string& file, const osgDB::ReaderWriter::Options* options) const{ std::string ext = osgDB::getLowerCaseFileExtension(file); if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; std::string file_name = osgDB::findDataFile( file, options ); if (file_name.empty()) return ReadResult::FILE_NOT_FOUND; //osg::notify(osg::INFO) << "ReaderWriterQ3BSP::readNode(" << fileName.c_str() << ")\n"; BSPLoad load_data; load_data.Load(file_name,8); osg::Geode* geode = convertFromBSP(load_data, options); if (!geode) return ReadResult::FILE_NOT_HANDLED; //osg::StateSet* state_set=geode->getOrCreateStateSet(); //state_set->setMode(osg::CullFace::BACK,osg::StateAttribute::ON); return geode; return ReadResult::FILE_NOT_HANDLED;}enum BSP_FACE_TYPE{ bspPolygonFace=1, bspPatch, bspMeshFace, bspBillboard};class BSP_VERTEX{public: osg::Vec3f m_position; float m_decalS, m_decalT; float m_lightmapS, m_lightmapT; BSP_VERTEX operator+(const BSP_VERTEX & rhs) const { BSP_VERTEX result; result.m_position=m_position+rhs.m_position; result.m_decalS=m_decalS+rhs.m_decalS; result.m_decalT=m_decalT+rhs.m_decalT; result.m_lightmapS=m_lightmapS+rhs.m_lightmapS; result.m_lightmapT=m_lightmapT+rhs.m_lightmapT; return result; } BSP_VERTEX operator*(const float rhs) const { BSP_VERTEX result; result.m_position=m_position*rhs; result.m_decalS=m_decalS*rhs; result.m_decalT=m_decalT*rhs; result.m_lightmapS=m_lightmapS*rhs; result.m_lightmapT=m_lightmapT*rhs; return result; }};//every patch (curved surface) is split into biquadratic (3x3) patchesclass BSP_BIQUADRATIC_PATCH{public: BSP_BIQUADRATIC_PATCH():m_vertices(32),m_indices(32) { } ~BSP_BIQUADRATIC_PATCH() { } bool Tessellate(int newTessellation,osg::Geometry* aGeometry); BSP_VERTEX m_controlPoints[9]; // Se accede a ellos en la cargaprotected: int m_tessellation; std::vector<BSP_VERTEX> m_vertices; std::vector<GLuint> m_indices; //arrays for multi_draw_arrays std::vector<int> m_trianglesPerRow; std::vector<GLuint *> m_rowIndexPointers;};//curved surfaceclass BSP_PATCH{public: BSP_PATCH():m_quadraticPatches(32) { } ~BSP_PATCH() { } int m_textureIndex; int m_lightmapIndex; int m_width, m_height; int m_numQuadraticPatches; std::vector<BSP_BIQUADRATIC_PATCH> m_quadraticPatches;};osg::Geode* ReaderWriterQ3BSP::convertFromBSP(BSPLoad& aLoadData,const osgDB::ReaderWriter::Options*) const{ std::vector<osg::Texture2D*> texture_array; loadTextures(aLoadData,texture_array); std::vector<osg::Texture2D*> lightmap_array; loadLightMaps(aLoadData,lightmap_array); osg::Geode* map_geode=new osg::Geode; // Convertir los vertices unsigned int num_load_vertices=aLoadData.m_loadVertices.size(); osg::Vec3Array* vertex_array = new osg::Vec3Array(num_load_vertices); osg::Vec2Array* text_decal_array = new osg::Vec2Array(num_load_vertices); osg::Vec2Array* text_lmap_array = new osg::Vec2Array(num_load_vertices); float scale = 0.03; unsigned int i; for(i=0; i<num_load_vertices; ++i) { BSP_LOAD_VERTEX& vtx=aLoadData.m_loadVertices[i]; //swap y and z and negate z (*vertex_array)[i]=(osg::Vec3d( vtx.m_position[0]*scale, -vtx.m_position[1]*scale, vtx.m_position[2]*scale ) ); //Transfer texture coordinates (Invert t) (*text_decal_array)[i]=(osg::Vec2d(vtx.m_decalS,-vtx.m_decalT) ); //Transfer lightmap coordinates (*text_lmap_array)[i]=(osg::Vec2d(vtx.m_lightmapS,vtx.m_lightmapT) ); } unsigned int num_loadfaces=aLoadData.m_loadFaces.size(); //convert loadFaces to faces for(i=0; i<num_loadfaces; ++i) { const BSP_LOAD_FACE& current_load_face=aLoadData.m_loadFaces[i]; if(current_load_face.m_type!=bspMeshFace) //skip this loadFace if it is not a mesh face continue; osg::Geometry* mesh_geom=createMeshFace(current_load_face,texture_array,*vertex_array,aLoadData.m_loadMeshIndices,*text_decal_array,*text_lmap_array); map_geode->addDrawable(mesh_geom); } for(i=0; i<num_loadfaces; ++i) { const BSP_LOAD_FACE& current_face=aLoadData.m_loadFaces[i]; if(current_face.m_type!=bspPolygonFace) //skip this loadFace if it is not a polygon face continue; osg::Geometry* polygon_geom=createPolygonFace(current_face,texture_array,lightmap_array,*vertex_array,*text_decal_array,*text_lmap_array); map_geode->addDrawable(polygon_geom); } for(i=0; i<num_loadfaces; ++i) { const BSP_LOAD_FACE& current_face=aLoadData.m_loadFaces[i]; if(current_face.m_type!=bspPatch) //skip this loadFace if it is not a patch face continue; //osg::Group* patch_group=new osg::Group; BSP_PATCH current_patch; current_patch.m_textureIndex=current_face.m_texture; current_patch.m_lightmapIndex=current_face.m_lightmapIndex; current_patch.m_width=current_face.m_patchSize[0]; current_patch.m_height=current_face.m_patchSize[1]; osg::Texture2D *texture=texture_array[current_face.m_texture]; osg::Texture2D *lightmap_texture=NULL; if(current_face.m_lightmapIndex>=0) { lightmap_texture=lightmap_array[current_face.m_lightmapIndex]; } else { lightmap_texture=lightmap_array[lightmap_array.size()-1]; } //Create space to hold quadratic patches int numPatchesWide=(current_patch.m_width-1)/2; int numPatchesHigh=(current_patch.m_height-1)/2; current_patch.m_numQuadraticPatches = numPatchesWide*numPatchesHigh; current_patch.m_quadraticPatches.resize(current_patch.m_numQuadraticPatches); //fill in the quadratic patches for(int y=0; y<numPatchesHigh; ++y) { for(int x=0; x<numPatchesWide; ++x) { for(int row=0; row<3; ++row) { for(int point=0; point<3; ++point) { BSP_BIQUADRATIC_PATCH& curr_quadraticpatch=current_patch.m_quadraticPatches[y*numPatchesWide+x]; osg::Vec3f vtx= (*vertex_array) [aLoadData.m_loadFaces[i].m_firstVertexIndex+(y*2*current_patch.m_width+x*2)+ row*current_patch.m_width+point]; curr_quadraticpatch.m_controlPoints[row*3+point].m_position[0] = vtx.x(); curr_quadraticpatch.m_controlPoints[row*3+point].m_position[1] = vtx.y(); curr_quadraticpatch.m_controlPoints[row*3+point].m_position[2] = vtx.z(); } } osg::Geometry* patch_geom = new osg::Geometry; //tessellate the patch osg::StateSet* stateset = patch_geom->getOrCreateStateSet(); if(texture) { stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); } if(lightmap_texture) { stateset->setTextureAttributeAndModes(1,lightmap_texture,osg::StateAttribute::ON); } //patch_group->addChild(map_geode); current_patch.m_quadraticPatches[y*numPatchesWide+x].Tessellate(8/*aCurveTessellation*/,patch_geom); map_geode->addDrawable(patch_geom);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -