diff --git a/examples/osgtesselate/osgtesselate.cpp b/examples/osgtesselate/osgtesselate.cpp index f815d3834..26387a238 100644 --- a/examples/osgtesselate/osgtesselate.cpp +++ b/examples/osgtesselate/osgtesselate.cpp @@ -97,6 +97,8 @@ osg::Geometry *makePolsTwo (void) { osg::Texture2D* texture = new osg::Texture2D; texture->setImage(image); + texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT); + texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT); stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); } gtess->setStateSet( stateset ); @@ -167,6 +169,8 @@ osg::Geometry *makeSideWall (const float xpos) { osg::Texture2D* texture = new osg::Texture2D; texture->setImage(image); + texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT); + texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT); stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); } gtess->setStateSet( stateset ); @@ -262,6 +266,8 @@ osg::Geometry *makeFrontWall (const float zpos) { { osg::Texture2D* texture = new osg::Texture2D; texture->setImage(image); + texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT); + texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT); stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); } gtess->setStateSet( stateset ); @@ -454,6 +460,8 @@ osg::Geometry *makePols (void) { { osg::Texture2D* texture = new osg::Texture2D; texture->setImage(image); + texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT); + texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT); stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); } gtess->setStateSet( stateset ); diff --git a/src/osgPlugins/ac3d/ac3d.cpp b/src/osgPlugins/ac3d/ac3d.cpp index 2cf9c37fd..f221c2f85 100644 --- a/src/osgPlugins/ac3d/ac3d.cpp +++ b/src/osgPlugins/ac3d/ac3d.cpp @@ -41,6 +41,9 @@ using namespace osg; using namespace osgDB; +// define this if you have a recent OSG with pRegistry->getFromObjectCache method +#define USE_TEXTURE_CACHE + class geodeVisitor : public osg::NodeVisitor { // collects geodes from scene sub-graph attached to 'this' public: geodeVisitor(): @@ -154,11 +157,28 @@ class ReaderWriterAC : public osgDB::ReaderWriter private: }; +class appearance : public osg::Referenced { // how a surface is rendered - basic copy of ACsurface + // except that as a ref_ptr it will automatically delete itself when the object has loaded + // and the list of appearances is deleted +public: + appearance(const int imat=-1) {material=imat; + type=0x00; + } + void setMaterial(const int i) { material=i;} + inline int getMaterial(void) const { return material;} + void setSurfaceType(const int i) { type=i;} + inline int getSurfaceType(void) const { return type;} +protected: + ~appearance() { + // osg::notify(osg::WARN) << "deleting material type " << material << std::endl; + } + int material; // index in the ac3d file + int type; // as used in ac3d, onesided etc are held as 0x20, 0x21... +}; + static int line = 0; static char buff[255]; - - static std::vector palette; // change to dynamic array //static int num_palette = 0; static int startmatindex = 0; @@ -228,7 +248,7 @@ Prototype int get_tokens(char *s, int *argc, char *argv[]) st = p; while ((c = *p) && ((c != ' ') && (c != '\t') && (c != '\n') && ( c != 13) && ( c != '\0')) ) p++; - argv[tc++] = st; + if (c != '"') argv[tc++] = st; } } if (*p) p++; @@ -413,10 +433,9 @@ osg::Group *ac_load_object(std::istream &f,const ACObject *parent,const osgDB::R char t[20]; osg::Group *gp=NULL; osg::Geode *geode=NULL; - osg::Vec3Array *normals = NULL; // new osg::Vec3Array; // NULL; ACObject ob; // local storage for stuff taken from AC's loader - osg::Vec3Array *vertpool = new osg::Vec3Array; + osg::ref_ptr vertpool = new osg::Vec3Array; initobject(&ob); // zero data for object if (parent) @@ -499,8 +518,13 @@ osg::Group *ac_load_object(std::istream &f,const ACObject *parent,const osgDB::R { printf("expected quoted name at line %d (got %d tokens)\n", line, numtok); } - else + else { + char *endquot=strrchr(tokv[1],'\"'); + if (endquot>0) { + *endquot='\0'; + } if (gp) gp->setName(tokv[1]); + } } else if (streq(t, "texture")) { @@ -514,14 +538,48 @@ osg::Group *ac_load_object(std::istream &f,const ACObject *parent,const osgDB::R ctmp++; if (*ctmp == '"') *ctmp='\0'; // latest ac3d seems toa dd more quotes than older versions. } +#ifdef USE_TEXTURE_CACHE + osgDB::Registry* pRegistry = osgDB::Registry::instance(); + osg::Texture2D* pTexture = dynamic_cast(pRegistry->getFromObjectCache(osgDB::findDataFile(tokv[1], options))); + if (NULL != pTexture) + { + // Use cached texture + ob.texture = pTexture; + osg::notify(osg::INFO) << "Using cached texture " << pTexture->getImage()->getFileName() <setImage(ctx); ob.texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT); ob.texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT); + pRegistry->addEntryToObjectCache(ctx->getFileName(), ob.texture.get()); + } } +#else + typedef std::map< std::string , Texture2D *> UsedTextureMap; // what textures already used. + + static UsedTextureMap usedtextures; + // gwm 22.04.05 check for already loaded textures + osg::ref_ptr texture = (usedtextures)[tokv[1]]; + if (texture.valid()) { + ob.texture = texture.get();// ac_load_texture(tokv[1]); + } else { + osg::Image *ctx= osgDB::readImageFile(tokv[1], options); + if (ctx) + { // image could be read + ob.texture = new osg::Texture2D;// ac_load_texture(tokv[1]); + ob.texture->setImage(ctx); + ob.texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT); + ob.texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT); + (usedtextures)[tokv[1]]=ob.texture.get(); + } + } +#endif } } else if (streq(t, "texrep")) @@ -600,7 +658,6 @@ osg::Group *ac_load_object(std::istream &f,const ACObject *parent,const osgDB::R ctmp=strtok(NULL,"\n"); } } - normals = new osg::Vec3Array; } sscanf(buff, "%s %d", str, &num); @@ -631,12 +688,12 @@ osg::Group *ac_load_object(std::istream &f,const ACObject *parent,const osgDB::R // the tx coords array for each geometry (Vec2Array list, texslist) // then I add a new geometry to the current Geode for each new material as it is found. - std::vector ia; // list of materials required- generate one geode per material - typedef std::vector geomlist; + std::vector< osg::ref_ptr > ia; // list of materials required- generate one geode per material + typedef std::vector > geomlist; geomlist glist; - typedef std::vector vertslist; + typedef std::vector > vertslist; vertslist vlists; // list of vertices for each glist element - typedef std::vector texslist; + typedef std::vector > texslist; texslist txlists; // list of texture coords for each glist element sscanf(buff, "%s %d", str, &num); @@ -646,14 +703,16 @@ osg::Group *ac_load_object(std::istream &f,const ACObject *parent,const osgDB::R ob.num_surf = num; for (n = 0; n < num; n++) - { - osg::Geometry *geom=NULL; // the surface will be addded to this geometry - osg::Vec3Array *vgeom=NULL; // vertices corresponding to geom taken from vertexpool - osg::Vec2Array *tgeom=NULL; // texture coords corresponding to geom taken from vertexpool + { // add each surface (poly, 2 sided poly, line, polyline) to a geometry suitable for its: + // material index + // lighting (off for line, polyline). + osg::ref_ptr geom=NULL; // the surface will be addded to this geometry + osg::ref_ptr vgeom=NULL; // vertices corresponding to geom taken from vertexpool + osg::ref_ptr tgeom=NULL; // texture coords corresponding to geom taken from vertexpool ACSurface asurf; - osg::UShortArray *nusidx = new osg::UShortArray; // indices into the vertices - osg::Vec2Array *tcs=new osg::Vec2Array; // texture coordinates for this object - ACSurface *news = read_surface(f, &asurf, nusidx, tcs); + osg::ref_ptr nusidx = new osg::UShortArray; // indices into the vertices + osg::ref_ptr tcs=new osg::Vec2Array; // texture coordinates for this object + ACSurface *news = read_surface(f, &asurf, nusidx.get(), tcs.get()); if (news == NULL) { printf("error whilst reading surface at line: %d\n", line); @@ -662,20 +721,27 @@ osg::Group *ac_load_object(std::istream &f,const ACObject *parent,const osgDB::R else { int i=0; - for (std::vector::iterator itr= ia.begin(); itr >::iterator itr= ia.begin(); itrgetMaterial()==asurf.mat) + { // shares material + // check the line type. + if ((*itr)->getSurfaceType()==asurf.flags) { + geom=glist[i]; + vgeom=vlists[i]; + tgeom=txlists[i]; // what is current texture array + } } } - if (!geom) + if (!geom.valid()) { // then we need a new geometry osg::Vec3Array *verts = new osg::Vec3Array; + osg::Vec3Array *normals = new osg::Vec3Array; // 31.03.05 create a new array for each geometry +// fprintf(stdout,"New geom in %s nrms %x are %d nrms\n",gp->getName().c_str(),normals,normals->size()); - osg::Vec2Array *tcrds=new osg::Vec2Array; // texture coordinates for this object + osg::ref_ptr tcrds=new osg::Vec2Array; // texture coordinates for this object vgeom=verts; tgeom=tcrds; // what is current texture array vlists.push_back(verts); @@ -686,12 +752,16 @@ osg::Group *ac_load_object(std::istream &f,const ACObject *parent,const osgDB::R geom->setVertexArray(verts); if (ob.texture.valid()) { - geom->setTexCoordArray(0,tgeom); // share same set of TexCoords + geom->setTexCoordArray(0,tgeom.get()); // share same set of TexCoords } osg::StateSet *dstate = new osg::StateSet; osg::Material*mat=ac_palette_get_material(asurf.mat); if (mat) { - dstate->setMode( GL_LIGHTING, osg::StateAttribute::ON ); + if (asurf.flags & SURFACE_TYPE_CLOSEDLINE || asurf.flags & SURFACE_TYPE_LINE) { + dstate->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); + } else { + dstate->setMode( GL_LIGHTING, osg::StateAttribute::ON ); + } dstate->setAttribute(mat); const osg::Vec4 cdiff =mat->getDiffuse(osg::Material::FRONT_AND_BACK); if (cdiff[3]<0.99) @@ -719,8 +789,10 @@ osg::Group *ac_load_object(std::istream &f,const ACObject *parent,const osgDB::R geom->setStateSet( dstate ); glist.push_back(geom); - geode->addDrawable(geom); - ia.push_back(asurf.mat); + geode->addDrawable(geom.get()); + osg::ref_ptr app=new appearance(asurf.mat); + app->setSurfaceType(asurf.flags); + ia.push_back(app.get()); } osg::Vec3Array* normals = geom->getNormalArray(); @@ -735,6 +807,13 @@ osg::Group *ac_load_object(std::istream &f,const ACObject *parent,const osgDB::R (*vertpool)[i2], (*vertpool)[i3], norm); normals->push_back(norm); + // fprintf(stdout,"New %x are %d nrms\n",normals,normals->size()); + } + else + { + // Generate a dummy normal + osg::Vec3 norm(0, 1, 0); + normals->push_back(norm); } int nstart=(*vgeom).size(); for (i=0; ivalid()) tesselator.retesselatePolygons(**itr); if (needSmooth) { osgUtil::SmoothingVisitor smoother; diff --git a/src/osgUtil/Tesselator.cpp b/src/osgUtil/Tesselator.cpp index f79e823a7..fd706016d 100644 --- a/src/osgUtil/Tesselator.cpp +++ b/src/osgUtil/Tesselator.cpp @@ -209,7 +209,7 @@ void Tesselator::retesselatePolygons(osg::Geometry &geom) { osg::ref_ptr primitive = _Contours[primNo].get(); if (_ttype==TESS_TYPE_POLYGONS || _ttype==TESS_TYPE_DRAWABLE) - { + { // this recovers the 'old' tesselation which just retesselates single polygons. if (primitive->getMode()==osg::PrimitiveSet::POLYGON || _ttype==TESS_TYPE_DRAWABLE) { @@ -231,10 +231,14 @@ void Tesselator::retesselatePolygons(osg::Geometry &geom) } else { - beginTesselation(); + if (primitive->getNumIndices()>3) { // April 2005 gwm only retesselate "complex" polygons + beginTesselation(); addContour(primitive.get(), vertices); - endTesselation(); - collectTesselation(geom); + endTesselation(); + collectTesselation(geom); + } else { // April 2005 gwm triangles don't need to be retesselated + geom.addPrimitiveSet(primitive.get()); + } } }