📄 readerwriterdw.cpp
字号:
} inline void setmx(Matrix *m) { mx=m;}private: Vec4 colour; std::vector<Vec3> verts; dwmaterial *themat; unsigned short nverts,nfaces,nedges; unsigned short nfaceverts; unsigned short nopens; _face *faces; _dwedge *edges; int *openings; unsigned short *fc1, *fc2; // openings[i] is in faces[fc1[i]] to faces[fc2[i]] Matrix *tmat; Matrix *mx; // current uvw transform for currently tessealting face};void _face::tessellate(const std::vector<Vec3> verts, const dwmaterial *themat, GLUtesselator *ts, _dwobj *dwob, const Matrix * /*tmat*/) const { int nvall=getallverts(); int nused=0; avertex *poses=new avertex[2*nvall]; // passed to Tessellator to redraw Matrix mx; // texture matrix transform to plane settrans(mx, nrm, verts,themat); dwob->setmx(&mx); // may be used by combine callback to define txcoord gluTessBeginPolygon(ts, dwob); gluTessBeginContour(ts); /**/ for (int j=0; j<nv; j++) { Vec3 uv; uv=mx*verts[idx[j]]; setposes(poses[nused], j, verts); poses[nused].uv[0]=uv[0]; poses[nused].uv[1]=uv[1]; gluTessVertex(ts, (double *)&(poses[nused]), (double *)(poses+nused)); nused++; } gluTessEndContour(ts); for (int k=0; k<nop; k++) { // now holes in the face gluTessBeginContour(ts); for (int j=0; j<opening[k].nv; j++) { Vec3 uv; uv=mx*verts[opening[k].idx[j]]; opening[k].setposes(poses[nused], j, verts); poses[nused].nrmv*=-1; // get to agree with base polygon poses[nused].nrmv=nrm; poses[nused].uv[0]=uv[0]; poses[nused].uv[1]=uv[1]; gluTessVertex(ts, (double *)&(poses[nused]), (double *)(poses+nused)); nused++; } gluTessEndContour(ts);/* */ } gluTessEndPolygon(ts); delete [] poses;}void prims::combine( GLdouble coords[3], avertex *d[4], GLfloat w[4], avertex **dataOut , _dwobj *dwob) { avertex *newv = new avertex(); // (avertex *)calloc(1, sizeof(avertex)); newv->pos[0] = coords[0]; newv->pos[1] = coords[1]; newv->pos[2] = coords[2]; newv->uv[0] = newv->uv[1] =0; newv->nrmv[0] = newv->nrmv[1] = newv->nrmv[2] =0; for (int i=0; i<4; i++) { if (d[i]) { newv->uv[0] = w[i]*d[i]->uv[0]; newv->uv[1] = w[i]*d[i]->uv[1]; newv->nrmv[0] = w[i]*d[i]->nrmv[0]; newv->nrmv[1] = w[i]*d[i]->nrmv[1]; newv->nrmv[2] = w[i]*d[i]->nrmv[2]; } } dwob->makeuv(newv->uv, newv->pos); newv->idx=dwob->addvtx(coords[0], coords[1], coords[2]); *dataOut = newv;}void _dwobj::buildDrawable(Group *grp, const osgDB::ReaderWriter::Options *options){ // current DWobject complete; make a drawable, and add it to a osg::Group if (nfaces>0) { if (themat->isType(dwmaterial::PointLight) || themat->isType(dwmaterial::SpotLight)) { Vec4 pos; pos.set(0.0f,0.0f,0.0f,0.0f); for (int i=0; i<nverts; i++) { pos[0]+=verts[i].x(); pos[1]+=verts[i].y(); pos[2]+=verts[i].z(); } pos/=nverts; pos[3]=1.0f; LightSource *ls=themat->makeLight(pos); grp->addChild(ls); } else { Geode *geode = new Geode; int nfnvf=0; // number of vertices for faces plus holes int i; // a general counter for (i=0; i<nfaces; i++) { // for each face faces[i].setnorm(verts); // set its normal and any hole normals nfnvf+=faces[i].getallverts(); // get total vertices in object, defines dimensions of NEW arrays } GLUtesselator* ts=gluNewTess(); gluTessCallback(ts, GLU_TESS_BEGIN, (GLU_TESS_CALLBACK) myFaceBegin); gluTessCallback(ts, GLU_TESS_VERTEX, (GLU_TESS_CALLBACK) myVertex); gluTessCallback(ts, GLU_TESS_END, (GLU_TESS_CALLBACK) myFaceEnd); gluTessCallback(ts, GLU_TESS_ERROR, (GLU_TESS_CALLBACK) error); gluTessCallback(ts, GLU_TESS_COMBINE_DATA, (GLU_TESS_CALLBACK) combineCallback); // for (int nvf=0; nvf<6; nvf++) { // for each length of face // for Geometry we dont need to collect prim types individually // prd.setmode(nvf , nfnvf); // filter out only this type of tessellated face prd=new prims; prd->settmat(tmat); osg::Geometry *gset = new osg::Geometry; prd->setGeometry(gset); StateSet *dstate=themat->make(options); gset->setStateSet( dstate ); grp->addChild( geode ); // add to the world outside geode->addDrawable(gset); // each face adds a primitive to the geometry, after it is tessellated for (i=0; i<nfaces; i++) { // for each face, collect up prd->tessellate(faces[i],verts, themat, ts, this); } for (i=0; i<nopens; i++) { // for each hole, join up front & back with Quads if (fc1 && fc2) { faces[fc1[i]].link(openings[i*2], &faces[fc2[i]],openings[i*2+1],verts, themat); } } // for each opening prd->buildGeometry(); gluDeleteTess(ts); delete prd; } } // nfaces>0 verts.clear();}////////// tessellation completeclass ReaderWriterDW : public osgDB::ReaderWriter{ public: ReaderWriterDW() { supportsExtension("dw","Designer Workbench model format"); } virtual const char* className() const { return "Design Workshop Database Reader"; } virtual ReadResult 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 fileName = osgDB::findDataFile( file, options ); if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; _dwobj obj; enum reading {NONE, MATERIAL, OBJECT}; //unsigned short nrecs=0; // number of records read after a divider (numVerts, numFaces, numOpenings...) int nexpected=0; // number of records to be read in a block dwmaterial *matpalet=NULL; int nmat=-1; // current element of matpalet being modified int nmn=0; // number of materials found reading rdg=NONE; char buff[256]; notify(INFO)<< "ReaderWriterDW::readNode( "<<fileName.c_str()<<" )\n";#ifdef _MSC_VER notify(osg::NOTICE)<< "MS Visual C++ version "<<_MSC_VER<<"\n";#endif FILE *fp; if( (fp = osgDB::fopen( fileName.c_str(), "r" )) == (FILE *)0L ) { return std::string("Unable to open file \""+fileName+"\""); } Group *grp = new Group; // code for setting up the database path so that internally referenced file are searched for on relative paths. osg::ref_ptr<Options> local_opt = options ? static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options; local_opt->setDatabasePath(osgDB::getFilePath(fileName)); while( !feof( fp ) ) { // reads the Design Workshop format in ASCII if (dwfgets( buff, sizeof( buff ), fp )) { if( buff[0] == '#' ) continue; else if( strncmp(buff,"numMaterials:",13)==0) { // No of materials nmn=atoi(buff+14); matpalet=new dwmaterial[nmn]; } else if( strncmp(buff,"Material:",9)==0) { // No of materials dwfgets(buff, sizeof( buff ), fp ); nmat++; rdg=MATERIAL; int id=atoi(buff); matpalet[nmat].setid(id); // current material to be modified } else if (strncmp(buff, "Phase:",6)==0) { } else if (strncmp(buff, "CurrPhase:",10)==0) { } else if (strncmp(buff, "numPhases:",10)==0) { } else if (strncmp(buff, "Opacity:",8)==0) { float opacity=atof(buff+8); matpalet[nmat].setopacity(opacity); } else if (strncmp(buff, "FallOff:",8)==0) { float fo=atof(buff+8); matpalet[nmat].setFallOff(fo); } else if (strncmp(buff, "InnerHalfAngle:",15)==0) { float ha=atof(buff+15); matpalet[nmat].setHalfAngleIn(ha); } else if (strncmp(buff, "OuterHalfAngle:",15)==0) { float ha=atof(buff+15); matpalet[nmat].setHalfAngleOut(ha); } else if (strncmp(buff, "Brightness:",11)==0) { float br=atof(buff+11); matpalet[nmat].setBright(br); } else if (strncmp(buff, "Attentuation:",13)==0) { // oops - they can't spell matpalet[nmat].setAtten(buff+13); } else if (strncmp(buff, "MaterialType:",13)==0) { matpalet[nmat].setType(buff+14); } else if (strncmp(buff, "SpecularReflectivity:",21)==0) { float spec=atof(buff+21); matpalet[nmat].setspecular(spec); } else if (strncmp(buff, "SmoothnessExponent:",19)==0) { float spec=atof(buff+19); matpalet[nmat].setspecexp(spec*128.0f/100.0f); // convert to 0-128 range from percent } else if (strncmp(buff, "TextureWidthAndHeight:",22)==0) { char *ct=strchr(buff+22,','); float repx=atof(buff+23), repy=atof(ct+1); matpalet[nmat].settxrep(repx, repy); } else if (strncmp(buff, "PictureFile:",12)==0) { char *end=strchr(buff,'\n'); // end of line if (end) *end='\0'; // removed matpalet[nmat].setfname(buff); } else if( strncmp(buff,"Extrusion:",10)==0 || strncmp(buff,"Cube:",5)==0 || strncmp(buff,"Polyline:",9)==0 || strncmp(buff,"Polyhedron:",11)==0) { rdg=OBJECT; obj.buildDrawable(grp, options); obj.reset(); } else if( strncmp(buff,"Mat:",4)==0) { int mt=atoi(buff+4); for (int j=0; j<nmn; j++) { if (matpalet[j].getid() == mt) obj.setmat(&(matpalet[j])); } } else if( strncmp(buff,"Color:",6)==0) { float rgb[3]; if (rdg==MATERIAL) { // get material colour sscanf(buff+6,"%f %f %f", &rgb[0], &rgb[1], &rgb[2]); matpalet[nmat].setcolour(rgb); } else if (rdg==OBJECT) { float rgb[3]; sscanf(buff+6,"%f %f %f", &rgb[0], &rgb[1], &rgb[2]); rgb[0]/=65536.0f; // convert to range 0-1 rgb[1]/=65536.0f; // convert to range 0-1 rgb[2]/=65536.0f; // convert to range 0-1 obj.setcolour(rgb); } } else if( strncmp(buff,"numVerts:",9)==0) { nexpected=atoi(buff+9); obj.readVerts(fp, nexpected); nexpected=0; } else if( strncmp(buff,"numFaces:",9)==0) { nexpected=atoi(buff+9); obj.readFaces(fp, nexpected); nexpected=0; } else if( strncmp(buff,"numEdges:",9)==0) { nexpected=atoi(buff+9); obj.readEdges(fp, nexpected); //nrecs=0; // a numVerts is followed by nv vetex postiions } else if( strncmp(buff,"numOpenings:",12)==0) { nexpected=atoi(buff+12); //nrecs=0; // a numVerts is followed by nv vetex postiions if (nexpected>0) obj.readOpenings(fp, nexpected); } else if( strncmp(buff,"UVW:",4)==0) { // texture application matrix double mx[3][3]; sscanf(buff+4,"%lf %lf %lf %lf %lf %lf %lf %lf %lf", &mx[0][0], &mx[0][1], &mx[0][2], &mx[1][0], &mx[1][1], &mx[1][2], &mx[2][0], &mx[2][1], &mx[2][2]); obj.settmat(Matrix(mx[0][0],mx[0][1],mx[0][2],0.0, mx[1][0],mx[1][1],mx[1][2],0.0, mx[2][0],mx[2][1],mx[2][2],0.0, 0.0 ,0.0 ,0.0 ,1.0)); } } } fclose( fp ); obj.buildDrawable(grp, options); // tidy up any remaining objects return grp; }private:};int dwfgets(char *clin, int max, FILE *fin){ // replace fgets to detect EOL = char 13 as well as Creturn=10 GWM 111100 // Macintosh produced files (such as those obtainable //from the great buildings site at www.Artifice.com) use 13 format, PC models use 10. int nread=0; char c1=1; do { if (!feof( fin )) { clin[nread]=c1=fgetc(fin); nread++; } } while (nread<max && c1!= 13 && c1!= 10 && feof( fin )== 0 ); if (nread>0) clin[nread-1]='\0'; // null terminate and remove training blank return nread;}// now register with osg::Registry to instantiate the above// reader/writer.REGISTER_OSGPLUGIN(dw, ReaderWriterDW)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -