📄 readerwriterdw.cpp
字号:
#include <stdio.h>#include <string.h>// reading a design workshop file utility// (c) GW Michel, 2001-2003.// (c) 2003 - modified to use Geometry rather than old GeoSet.// Design Workshop format files can be downloaded from www.artifice.com// Design Workshop editor can be downloaded from www.artifice.com = Mac & Win95/98/NT versions are available.// DW Lite is completely free, produces textured 3D models// aimed mostly at the architectural world. Flat polygons are generally produced// No ability to produce smooth shading, unfortunately. // But it is the best bangs per buck. (Anything/nothing = infinite value, and this is quite a lot/nothing)#include <osg/CullFace>#include <osg/Geode>#include <osg/Group>#include <osg/Geometry>#include <osg/Light>#include <osg/LightSource>#include <osg/Material>#include <osg/Texture2D>#include <osg/TexEnv>#include <osg/StateSet>#include <osg/Notify>#include <osgDB/FileNameUtils>#include <osgDB/Registry>#include <osgDB/ReadFile>#include <osgDB/FileUtils>#include <osg/GLU>using namespace osg;#ifndef WIN32 #define CALLBACK #endifclass _dwobj; // predefine for later callint dwfgets(char *clin, int max, FILE *fin); // , end of line= 13 as well as Creturn=10class dwmaterial {// design workshop material, to be translated to OGLpublic: typedef enum {Properties,TiledTexture,FullFace, SpotLight,PointLight} mttype; dwmaterial() { type=Properties; opacity=1; specular=0; specexp=0; fname="";TextureWidth=1; TextureHeight=1; ctx=NULL; tx=NULL; id=0; dstate=NULL;colour[0]=colour[1]=colour[2]=colour[3]=1; bright=halfIn=halfOut=falloff=0;atyp=NONE; _lightnum=1; } ~dwmaterial() { } void settexture(const osgDB::ReaderWriter::Options *options) { if (!dstate) dstate = new StateSet; if (isTextured()) { // shares common textures if (!ctx || !tx) { // new texture needed if (fname.length()>0) { ctx=osgDB::readImageFile(fname.c_str(),options); if (ctx) { ctx->setFileName(fname); tx=new Texture2D; tx->setImage(ctx); tx->setWrap(Texture2D::WRAP_S, Texture2D::REPEAT); tx->setWrap(Texture2D::WRAP_T, Texture2D::REPEAT); } osg::TexEnv* texenv = new osg::TexEnv; texenv->setMode(osg::TexEnv::MODULATE); dstate->setTextureAttribute(0, texenv ); } } if (ctx && tx) { // texture exists dstate->setTextureAttributeAndModes(0,tx,osg::StateAttribute::ON); } } } StateSet *make(const osgDB::ReaderWriter::Options *options) { // returns the OSG material if (!dstate) { // if it does not exist, then make it dstate = new StateSet; osg::Material* osgMaterial = new osg::Material; dstate->setAttribute(osgMaterial); if (opacity<0.99) { osgMaterial->setTransparency(Material::FRONT_AND_BACK, opacity); dstate->setMode(GL_BLEND,StateAttribute::ON); dstate->setRenderingHint(StateSet::TRANSPARENT_BIN); colour[3]=opacity; } osgMaterial->setAmbient(Material::FRONT_AND_BACK,colour); osgMaterial->setDiffuse(Material::FRONT_AND_BACK,colour); Vec4 colspec=colour*specular; colspec[3]=colour[3]; osgMaterial->setSpecular(Material::FRONT_AND_BACK,colspec); osgMaterial->setShininess(Material::FRONT_AND_BACK,specexp); dstate->setMode( GL_LIGHTING, StateAttribute::ON ); dstate->setMode( GL_CULL_FACE, StateAttribute::ON ); osg::CullFace *cf = new osg::CullFace; // to define non-default culling cf->setMode(osg::CullFace::BACK); dstate->setAttribute(cf); dstate->setTextureMode(0,GL_TEXTURE_2D,StateAttribute::OFF); settexture(options); } return dstate; } inline int isType(mttype t1) const {return (type==t1 ); } inline int isTextured() {return (type==TiledTexture || type==FullFace ); } void setcolour(const float rgb[3]) { colour[0]=rgb[0]; colour[1]=rgb[1]; colour[2]=rgb[2]; } void settxrep(const float repx, const float repy) { TextureWidth=repx; TextureHeight=repy; } inline float getRepWid() const { return TextureWidth;} inline float getRepHt() const { return TextureHeight;} inline int isFullFace() const { return type==FullFace;} inline int getid() const { return id;} inline void setid(const int i) { id=i;} inline void setopacity(float o) { opacity=o;} inline void setspecular(float o) { specular=o;} inline void setspecexp(float o) { specexp=o;} void setType(const char *buff) { if (strncmp(buff,"Tiled_Texture",13)==0) type=dwmaterial::TiledTexture; else if (strncmp(buff,"Spot_Light",11)==0) type=dwmaterial::SpotLight; else if (strncmp(buff,"Point_Light",11)==0) type=dwmaterial::PointLight; else if (strncmp(buff,"Properties",11)==0) type=dwmaterial::Properties; else if (strncmp(buff,"Full_Face_Texture",16)==0) type=dwmaterial::FullFace; } void setfname(const char *buff) { //fname=new char[strlen(buff+13)+5]; fname= (buff+13); fname+= ".tga"; } LightSource *makeLight(const Vec4 pos) { Light *lt= new Light; Vec4 cdef; cdef[0]=cdef[1]=cdef[2]=0.0f; cdef[3]=0.0f; lt->setLightNum(_lightnum++); lt->setSpecular(colour*bright/2.0f); lt->setDiffuse(colour*bright/4.0f); lt->setAmbient(cdef); if (atyp==NONE) ; else if (atyp==INVERSE_DIST) { lt->setLinearAttenuation(1.0f); lt->setConstantAttenuation(0.01f); } lt->setPosition(pos); LightSource *ls=new LightSource(); ls->setLight(lt); return ls; } void setAtten(const char *buff) { if (strstr(buff,"kQ3AttenuationTypeNone")) atyp=NONE; else if (strstr(buff,"kQ3AttenuationTypeInverseDistance")) atyp=INVERSE_DIST; // else if (strstr(buff,"kQ3AttenuationTypeNone")) ; } void setBright(const float br) { bright=br;} void setHalfAngleIn(const float ha) { halfIn=ha;} void setHalfAngleOut(const float ha) { halfOut=ha;} void setFallOff(const float fo) { falloff=fo;} const Vec4 getcolour() { return colour;}private: int id; Vec4 colour; // the ambient/diffuse+alpha colour mttype type; float opacity, specular, specexp; // transp, specularity properties float TextureWidth, TextureHeight; std::string fname; // picture file enum atten {NONE, INVERSE_DIST, INVERSE_SQUARE} atyp; float bright,halfIn,halfOut,falloff; // light brightness Image *ctx; Texture2D *tx; int _lightnum; StateSet *dstate; // used to represent the dw material in OSG};// structure to use as data for tessellationtypedef struct { double pos[3]; // must be double for the tessellator to detect vertices Vec2 uv; // texture coordainte - may not be used? Vec3 nrmv; // surface normal int idx; // index in the verts[] array} avertex;class _face {public: _face() { nVertStart=0; opening=NULL; idx=NULL; nv=0; nop=0; nset=0; nrm[0]=nrm[1]=nrm[2]=0;} ~_face() { delete [] idx;} void setnv(const int n){ nv=n; idx=new int[n];} void addvtx(const int n){ if (nset < nv) { idx[nset]=n; nset++; } } void addholevtx(const int nvtot) { if (opening) { opening[nop-1].addvtx(nvtot); } } void setNBegin(int n1) {nVertStart=n1;} void norm(Vec3 &n, const Vec3 side, const Vec3 s2) const { n=s2^side; // perpendicular n.normalize(); // unit norm } const Vec3 getnorm(void) const { return nrm; } // use the predefined normal void getside12(Vec3 &s1, Vec3 &s2, const std::vector<Vec3> verts) const { int ic=0; // counter for later vertices to ensure not coincident int i1=idx[0]; // first vertex of face int i2=idx[1]; // second, must be non-coincident while (i2==i1 && ic<nv-1) { ic++; i2=idx[ic]; } int i3=idx[ic]; // third, must be non-coincident while (ic<nv-1 && (i3==i2 || i3==i1)) { ic++; i3=idx[ic]; } if(ic>=nv) { printf("Invalid vertices %d of %d. I1-3 %d %d %d.\n", ic, nv, i1, i2, i3); } if(i1>=static_cast<int>(verts.size()) || i2>=static_cast<int>(verts.size()) || i3>=static_cast<int>(verts.size())) { printf("Invalid indices %d, %d, %d max allowed %d.\n", i1,i2,i3,static_cast<int>(verts.size()));//, errm } s1=(verts[i2]-verts[i1]); // side 1 of face s2=(verts[i3]-verts[i2]); // side 2 of face } void getnorm(const std::vector<Vec3> verts) { Vec3 side, s2; // used in cross product to find normal getside12(side,s2, verts); norm(nrm, s2, side); } void settrans(Matrix &mx, const Vec3 nrm, const std::vector<Vec3> verts, const dwmaterial *mat) const { // define the matrix perpendcular to normal for mapping textures float wid=mat->getRepWid(); float ht=mat->getRepHt(); Vec3 r1, r2,r3; // 3 rows of rotation matrix if (mat->isFullFace()) { // set wid, ht from polygon Vec3 s2; // want transformed u coordinate parallel to 'r1' getside12(r1,s2, verts); // r1 = edge of first side// printf("fullface s2 %f %f %f\n", s2.x(),s2.y(),s2.z());//, errm r3=nrm; float len=r1.length(); r1=r1/len; r2=r3^r1; r1=r1/len; r2=r2/s2.length(); } else { // mat.nrm= (0,0,1) AND mat (0,1,0) => (0,a,b) // the transformation is unitary - preserves lengths; and // converts points on a plane into (s,t, constant) coords for use with texturing // Rinv.(0,0,1) = (nrm) implies R since Rinv=R(transpose) r3=nrm; // already a unit vector // mat.(010) = (0ab) -> Minv.(0ab) = (010); and this row DOT nrm=0 if (r3.z() < 0.99f && r3.z() > -0.99f) { // not face parallel to ground - choose r1 perpendicular to nrm & 001 r2.set(0,0,1); // therefore r1 is in plane of face. r1=r2^r3; r1.normalize(); } else { // parallel to ground - make perpendicular to edge 1 of face r1=verts[idx[1]]-verts[idx[0]]; r1.normalize(); } r2=r3^r1; } for (int j=0; j<3; j++) { // and create the transpose matrix (inverse of rotation matrix) mx(0,j)=r1[j]; mx(1,j)=r2[j]; mx(2,j)=r3[j]; } // mx.postTrans(mx,0.5f,0.5f,0.0f); if (mat->isFullFace()) { // set offset such that mx*verts[idx[0]] -> uv=(0,0) Vec3 pos; pos=mx*verts[idx[0]]; mx(0,3)=-pos.x(); mx(1,3)=-pos.y(); mx(2,3)=-pos.z(); } else { // scale inversely to the texture preferred repeat size mx(0,0)*=1.0f/wid; mx(1,0)*=1.0f/wid; mx(0,1)*=1.0f/ht; mx(1,1)*=1.0f/ht; mx(0,3)=0.5f/wid; mx(1,3)=0.5f/ht; } // mx.postScale(mx,1.0f/themat->TextureWidth, 1.0f/themat->TextureHeight,1); } inline int setnvop(const unsigned short n) { // add a new hole in this face with n vertices _face *oldop=opening; opening=new _face[nop+1]; for (int i=0; i<nop; i++) opening[i].move(&oldop[i]); delete [] oldop; opening[nop].setnv(n); nop++; return (nop-1); } void move(class _face *oldop) { *this=*oldop; oldop->idx=NULL;} inline int getnv() { return nv;} inline int getvert(const int j) { return idx[j];} inline int complete() { return (idx && nv>0 && nset==nv);} // face has all defined inline int holecomplete() { if (!opening) return 1; // no hole, so it is complete return opening[nop-1].complete();} // latest opening in face has all vertices defined int getallverts(void) const { int ntot=nv; for (int i=0; i<nop; i++) ntot+=opening[i].getnv(); return ntot; } void setnorm(const std::vector<Vec3> verts) { // set the face normal getnorm(verts); for (int i=0; i<nop; i++) { opening[i].setnorm(verts); if (nrm*opening[i].nrm > 0.0f) { // normals are parallel - reverse order of vertices opening[i].reverse(); opening[i].setnorm(verts); } } } void setposes(avertex &poses, const int j, const std::vector<Vec3> verts) const { poses.pos[0]=verts[idx[j]].x(); poses.pos[1]=verts[idx[j]].y(); poses.pos[2]=verts[idx[j]].z(); poses.nrmv=nrm;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -