X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fscene%2Fmaterial%2FTextureBuilder.cxx;h=797dae25c816c54aaeeeb32c2e9d0829f7035ecb;hb=d36170879c9394064b37fc9acb3d12d451f2be82;hp=9cf9cd4e644e00da15e93137c8f104ecc3c4038f;hpb=72f301c6558758c71c65f5a647be7efa034468dc;p=simgear.git diff --git a/simgear/scene/material/TextureBuilder.cxx b/simgear/scene/material/TextureBuilder.cxx index 9cf9cd4e..797dae25 100644 --- a/simgear/scene/material/TextureBuilder.cxx +++ b/simgear/scene/material/TextureBuilder.cxx @@ -19,6 +19,7 @@ #endif #include "TextureBuilder.hxx" +#include "mipmap.hxx" #include "Pass.hxx" @@ -67,7 +68,7 @@ osg::Texture* TextureBuilder::buildFromType(Effect* effect, const string& type, typedef boost::tuple TexTuple; + string, MipMapTuple> TexTuple; EffectNameValue texEnvModesInit[] = { @@ -131,10 +132,10 @@ void TextureUnitBuilder::buildAttribute(Effect* effect, Pass* pass, texture = TextureBuilder::buildFromType(effect, type, prop, options); } - catch (BuilderException& ) { - SG_LOG(SG_INPUT, SG_ALERT, "No image file, " + catch (BuilderException& e) { + SG_LOG(SG_INPUT, SG_ALERT, e.getFormattedMessage() << ", " << "maybe the reader did not set the filename attribute, " - << "using white on " << pass->getName()); + << "using white for type '" << type << "' on '" << pass->getName() << "', in " << prop->getPath() ); texture = StateAttributeFactory::instance()->getWhiteTexture(); } pass->setTextureAttributeAndModes(unit, texture); @@ -181,7 +182,6 @@ EffectNameValue wrapModesInit[] = }; EffectPropertyMap wrapModes(wrapModesInit); - TexTuple makeTexTuple(Effect* effect, const SGPropertyNode* props, const SGReaderWriterXMLOptions* options, const string& texType) @@ -213,9 +213,16 @@ TexTuple makeTexTuple(Effect* effect, const SGPropertyNode* props, string imageName; if (pImage) imageName = pImage->getStringValue(); - string absFileName = osgDB::findDataFile(imageName, options); + string absFileName = SGModelLib::findDataFile(imageName, options); + + const SGPropertyNode* pMipmapControl + = getEffectPropertyChild(effect, props, "mipmap-control"); + MipMapTuple mipmapFunctions( AUTOMATIC, AUTOMATIC, AUTOMATIC, AUTOMATIC ); + if ( pMipmapControl ) + mipmapFunctions = makeMipMapTuple(effect, pMipmapControl, options); + return TexTuple(absFileName, minFilter, magFilter, sWrap, tWrap, rWrap, - texType); + texType, mipmapFunctions); } void setAttrs(const TexTuple& attrs, Texture* tex, @@ -228,8 +235,9 @@ void setAttrs(const TexTuple& attrs, Texture* tex, osgDB::ReaderWriter::ReadResult result = osgDB::Registry::instance()->readImage(imageName, options); if (result.success()) { - osg::Image* image = result.getImage(); - tex->setImage(GL_FRONT_AND_BACK, image); + osg::ref_ptr image = result.getImage(); + image = computeMipmap( image.get(), attrs.get<7>() ); + tex->setImage(GL_FRONT_AND_BACK, image.get()); int s = image->s(); int t = image->t(); if (s <= t && 32 <= s) { @@ -408,6 +416,7 @@ TextureBuilder::Registrar installNoise("noise", new NoiseBuilder); } + // Image names for all sides typedef boost::tuple CubeMapTuple; @@ -444,77 +453,192 @@ public: const SGReaderWriterXMLOptions* options); protected: typedef map > CubeMap; + typedef map > CrossCubeMap; CubeMap _cubemaps; + CrossCubeMap _crossmaps; }; +// I use this until osg::CopyImage is fixed +// This one assumes images are the same format and sizes are correct +void copySubImage(const osg::Image* srcImage, int src_s, int src_t, int width, int height, + osg::Image* destImage, int dest_s, int dest_t) +{ + for(int row = 0; rowdata(src_s, src_t+row, 0); + unsigned char* destData = destImage->data(dest_s, dest_t+row, 0); + memcpy(destData, srcData, (width*destImage->getPixelSizeInBits())/8); + } +} + + Texture* CubeMapBuilder::build(Effect* effect, const SGPropertyNode* props, - const SGReaderWriterXMLOptions* options) + const SGReaderWriterXMLOptions* options) { // First check that there is a tag const SGPropertyNode* texturesProp = getEffectPropertyChild(effect, props, "images"); - if (!texturesProp) { - throw BuilderException("no for cube map"); + const SGPropertyNode* crossProp = getEffectPropertyChild(effect, props, "image"); + if (!texturesProp && !crossProp) { + throw BuilderException("no images defined for cube map"); return NULL; // This is redundant } - CubeMapTuple _tuple = makeCubeMapTuple(effect, texturesProp); + // Using 6 separate images + if(texturesProp) { - CubeMap::iterator itr = _cubemaps.find(_tuple); - if (itr != _cubemaps.end()) - return itr->second.get(); + SG_LOG(SG_INPUT, SG_DEBUG, "try 6 images "); - TextureCubeMap* cubeTexture = new osg::TextureCubeMap; + CubeMapTuple _tuple = makeCubeMapTuple(effect, texturesProp); - // TODO: Read these from effect file? Maybe these are sane for all cuebmaps? - cubeTexture->setFilter(osg::Texture3D::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR); - cubeTexture->setFilter(osg::Texture3D::MAG_FILTER, osg::Texture::LINEAR); - cubeTexture->setWrap(osg::Texture3D::WRAP_S, osg::Texture::CLAMP_TO_EDGE); - cubeTexture->setWrap(osg::Texture3D::WRAP_T, osg::Texture::CLAMP_TO_EDGE); - cubeTexture->setWrap(osg::Texture3D::WRAP_R, osg::Texture::CLAMP_TO_EDGE); + CubeMap::iterator itr = _cubemaps.find(_tuple); + if (itr != _cubemaps.end()) + return itr->second.get(); - osgDB::ReaderWriter::ReadResult result = - osgDB::Registry::instance()->readImage(_tuple.get<0>(), options); - if(result.success()) { - osg::Image* image = result.getImage(); - cubeTexture->setImage(TextureCubeMap::POSITIVE_X, image); - } - result = osgDB::Registry::instance()->readImage(_tuple.get<1>(), options); - if(result.success()) { - osg::Image* image = result.getImage(); - cubeTexture->setImage(TextureCubeMap::NEGATIVE_X, image); - } - result = osgDB::Registry::instance()->readImage(_tuple.get<2>(), options); - if(result.success()) { - osg::Image* image = result.getImage(); - cubeTexture->setImage(TextureCubeMap::POSITIVE_Y, image); - } - result = osgDB::Registry::instance()->readImage(_tuple.get<3>(), options); - if(result.success()) { - osg::Image* image = result.getImage(); - cubeTexture->setImage(TextureCubeMap::NEGATIVE_Y, image); - } - result = osgDB::Registry::instance()->readImage(_tuple.get<4>(), options); - if(result.success()) { - osg::Image* image = result.getImage(); - cubeTexture->setImage(TextureCubeMap::POSITIVE_Z, image); - } - result = osgDB::Registry::instance()->readImage(_tuple.get<5>(), options); - if(result.success()) { - osg::Image* image = result.getImage(); - cubeTexture->setImage(TextureCubeMap::NEGATIVE_Z, image); + TextureCubeMap* cubeTexture = new osg::TextureCubeMap; + + // TODO: Read these from effect file? Maybe these are sane for all cuebmaps? + cubeTexture->setFilter(osg::Texture3D::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR); + cubeTexture->setFilter(osg::Texture3D::MAG_FILTER, osg::Texture::LINEAR); + cubeTexture->setWrap(osg::Texture3D::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + cubeTexture->setWrap(osg::Texture3D::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + cubeTexture->setWrap(osg::Texture3D::WRAP_R, osg::Texture::CLAMP_TO_EDGE); + + osgDB::ReaderWriter::ReadResult result = + osgDB::Registry::instance()->readImage(_tuple.get<0>(), options); + if(result.success()) { + osg::Image* image = result.getImage(); + cubeTexture->setImage(TextureCubeMap::POSITIVE_X, image); + } + result = osgDB::Registry::instance()->readImage(_tuple.get<1>(), options); + if(result.success()) { + osg::Image* image = result.getImage(); + cubeTexture->setImage(TextureCubeMap::NEGATIVE_X, image); + } + result = osgDB::Registry::instance()->readImage(_tuple.get<2>(), options); + if(result.success()) { + osg::Image* image = result.getImage(); + cubeTexture->setImage(TextureCubeMap::POSITIVE_Y, image); + } + result = osgDB::Registry::instance()->readImage(_tuple.get<3>(), options); + if(result.success()) { + osg::Image* image = result.getImage(); + cubeTexture->setImage(TextureCubeMap::NEGATIVE_Y, image); + } + result = osgDB::Registry::instance()->readImage(_tuple.get<4>(), options); + if(result.success()) { + osg::Image* image = result.getImage(); + cubeTexture->setImage(TextureCubeMap::POSITIVE_Z, image); + } + result = osgDB::Registry::instance()->readImage(_tuple.get<5>(), options); + if(result.success()) { + osg::Image* image = result.getImage(); + cubeTexture->setImage(TextureCubeMap::NEGATIVE_Z, image); + } + + _cubemaps[_tuple] = cubeTexture; + + return cubeTexture; } - _cubemaps[_tuple] = cubeTexture; - return cubeTexture; + // Using 1 cross image + else if(crossProp) { + SG_LOG(SG_INPUT, SG_DEBUG, "try cross map "); + + std::string texname = crossProp->getStringValue(); + + // Try to find existing cube map + CrossCubeMap::iterator itr = _crossmaps.find(texname); + if (itr != _crossmaps.end()) + return itr->second.get(); + + osgDB::ReaderWriter::ReadResult result = + osgDB::Registry::instance()->readImage(texname, options); + if(result.success()) { + osg::Image* image = result.getImage(); + image->flipVertical(); // Seems like the image coordinates are somewhat funny, flip to get better ones + + //cubeTexture->setResizeNonPowerOfTwoHint(false); + + // Size of a single image, 4 rows and 3 columns + int width = image->s() / 3; + int height = image->t() / 4; + int depth = image->r(); + + TextureCubeMap* cubeTexture = new osg::TextureCubeMap; + + // Copy the 6 sub-images and push them + for(int n=0; n<6; n++) { + + SG_LOG(SG_INPUT, SG_DEBUG, "Copying the " << n << "th sub-images and pushing it" ); + + osg::ref_ptr subimg = new osg::Image(); + subimg->allocateImage(width, height, depth, image->getPixelFormat(), image->getDataType()); // Copy attributes + + // Choose correct image + switch(n) { + case 0: // Front + copySubImage(image, width, 0, width, height, subimg.get(), 0, 0); + cubeTexture->setImage(TextureCubeMap::POSITIVE_Y, subimg.get()); + cubeTexture->setWrap(osg::Texture3D::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + cubeTexture->setWrap(osg::Texture3D::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + cubeTexture->setWrap(osg::Texture3D::WRAP_R, osg::Texture::CLAMP_TO_EDGE); + break; + case 1: // Left + copySubImage(image, 0, height, width, height, subimg.get(), 0, 0); + cubeTexture->setImage(TextureCubeMap::NEGATIVE_X, subimg.get()); + cubeTexture->setWrap(osg::Texture2D::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + cubeTexture->setWrap(osg::Texture3D::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + cubeTexture->setWrap(osg::Texture3D::WRAP_R, osg::Texture::CLAMP_TO_EDGE); + break; + case 2: // Top + copySubImage(image, width, height, width, height, subimg.get(), 0, 0); + cubeTexture->setImage(TextureCubeMap::POSITIVE_Z, subimg.get()); + cubeTexture->setWrap(osg::Texture3D::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + cubeTexture->setWrap(osg::Texture3D::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + cubeTexture->setWrap(osg::Texture3D::WRAP_R, osg::Texture::CLAMP_TO_EDGE); + break; + case 3: // Right + copySubImage(image, width*2, height, width, height, subimg.get(), 0, 0); + cubeTexture->setImage(TextureCubeMap::POSITIVE_X, subimg.get()); + cubeTexture->setWrap(osg::Texture3D::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + cubeTexture->setWrap(osg::Texture3D::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + cubeTexture->setWrap(osg::Texture3D::WRAP_R, osg::Texture::CLAMP_TO_EDGE); + break; + case 4: // Back + copySubImage(image, width, height*2, width, height, subimg.get(), 0, 0); + cubeTexture->setImage(TextureCubeMap::NEGATIVE_Y, subimg.get()); + cubeTexture->setWrap(osg::Texture3D::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + cubeTexture->setWrap(osg::Texture3D::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + cubeTexture->setWrap(osg::Texture3D::WRAP_R, osg::Texture::CLAMP_TO_EDGE); + break; + case 5: // Bottom + copySubImage(image, width, height*3, width, height, subimg.get(), 0, 0); + cubeTexture->setImage(TextureCubeMap::NEGATIVE_Z, subimg.get()); + cubeTexture->setWrap(osg::Texture3D::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + cubeTexture->setWrap(osg::Texture3D::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + cubeTexture->setWrap(osg::Texture3D::WRAP_R, osg::Texture::CLAMP_TO_EDGE); + break; + }; + + } + + _crossmaps[texname] = cubeTexture; + + return cubeTexture; + + } else { + throw BuilderException("Could not load cube cross"); + } + } + + return NULL; } namespace { TextureBuilder::Registrar installCubeMap("cubemap", new CubeMapBuilder); } - - EffectNameValue combineParamInit[] = { {"replace", TexEnvCombine::REPLACE},