Hi Robert,

I've spent the past four days playing with PNG files on 3DS objects, and I 
think I may have come across a small issue with the 3DS loader.

At the company where I work we model literally thousands of 3DS models for all 
types of objects. Most don't have transparent textures applied to them, but a 
few do. The issue is that a texture may have an alpha channel defined, yet its 
3DS material definition is not marked as being an alpha source, or transparent. 
This can happen for any number of modelling reasons (so I'm told) but the net 
effect is that when a 3DS object is loaded with such a material applied, the 
stateset creation for the 3DS geometry omits to add the GL_BLEND attribute as 
neither of the conditions that it currently tests for are satisfied under this 
scenario.

However, one thing that is apparently an indication of transparency/alpha 
information that we do make use of when modelling, but that the 3DS reader 
omits to test, is that we assign to the transparent texture to the opacity_map 
of the 3DS material structure.

Now, having discussed with our modellers the theory behind the opacity map, it 
seems that it is safe to say that if an opacity map is specified, then the 
reader should really apply the GL_BLEND attribute as it is an indication of 
some form of blending being required between materials.

With this in mind, I have made a minor change to the function createStateSet 
below, from the ReaderWriter3DS.cpp file, that checks for an opacity map having 
been specified, and in such a scenario the GL_BLEND attribute is applied to the 
geometry. This fixed our issue, and thought it might be helpful to others.

Kind regards

Neil Hughes.

osg::StateSet* ReaderWriter3DS::ReaderObject::createStateSet(Lib3dsMaterial 
*mat, const osgDB::ReaderWriter::Options* options)
{
    if (mat==NULL) return NULL;

    osg::StateSet* stateset = new osg::StateSet;

    osg::Material* material = new osg::Material;

    float transparency = mat->transparency;
    float alpha = 1.0f-transparency;

    osg::Vec4 ambient(mat->ambient[0],mat->ambient[1],mat->ambient[2],alpha);
    osg::Vec4 diffuse(mat->diffuse[0],mat->diffuse[1],mat->diffuse[2],alpha);
    osg::Vec4 
specular(mat->specular[0],mat->specular[1],mat->specular[2],alpha);
    specular *= mat->shin_strength;

    float shininess = mat->shininess;
        material->setName(mat->name);
    material->setAmbient(osg::Material::FRONT_AND_BACK,ambient);
    material->setDiffuse(osg::Material::FRONT_AND_BACK,diffuse);
    material->setSpecular(osg::Material::FRONT_AND_BACK,specular);
    material->setShininess(osg::Material::FRONT_AND_BACK,shininess*128.0f);

    stateset->setAttribute(material);

    bool textureTransparancy=false;
    osg::Texture2D* texture1_map = 
createTexture(&(mat->texture1_map),"texture1_map",textureTransparancy, options);
    if (texture1_map)
    {
        
stateset->setTextureAttributeAndModes(0,texture1_map,osg::StateAttribute::ON);
        
        if (!textureTransparancy)
        {        
            // from an email from Eric Hamil, September 30, 2003.
            // According to the 3DS spec, and other
            // software (like Max, Lightwave, and Deep Exploration) a 3DS 
material that has
            // a non-white diffuse base color and a 100% opaque bitmap texture, 
will show the
            // texture with no influence from the base color.
            
            // so we'll override material back to white.
            // and no longer require the decal hack below...
#if 0
            // Eric orignal fallback
            osg::Vec4 white(1.0f,1.0f,1.0f,alpha);
            material->setAmbient(osg::Material::FRONT_AND_BACK,white);
            material->setDiffuse(osg::Material::FRONT_AND_BACK,white);
            material->setSpecular(osg::Material::FRONT_AND_BACK,white);
#else
            // try alternative to avoid staturating with white
            // setting white as per OpenGL defaults.
            
material->setAmbient(osg::Material::FRONT_AND_BACK,osg::Vec4(0.2f,0.2f,0.2f,alpha));
            
material->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(0.8f,0.8f,0.8f,alpha));
            
material->setSpecular(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,0.0f,alpha));
#endif            
        }
        
// no longer required...        
//         bool decal = false;
//         
//         // not sure exactly how to interpret what is best for .3ds
//         // but the default text env MODULATE doesn't work well, and
//         // DECAL seems to work better.
//         osg::TexEnv* texenv = new osg::TexEnv;
//         if (decal)
//         {
//             texenv->setMode(osg::TexEnv::DECAL);
//         }
//         else
//         {
//             texenv->setMode(osg::TexEnv::MODULATE);
//         }
//        stateset->setTextureAttribute(0,texenv);
    }

        //if (transparency>0.0f || textureTransparancy)
    if (transparency>0.0f || textureTransparancy || mat->opacity_map.flags!=0)
    {
        stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
        stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
    }

/*
    osg::ref_ptr<osg::Texture> texture1_mask = 
createTexture(&(mat->texture1_mask),"texture1_mask",textureTransparancy);
    osg::ref_ptr<osg::Texture> texture2_map = 
createTexture(&(mat->texture2_map),"texture2_map",textureTransparancy);
    osg::ref_ptr<osg::Texture> texture2_mask = 
createTexture(&(mat->texture2_mask),"texture2_mask",textureTransparancy);
    osg::ref_ptr<osg::Texture> opacity_map = 
createTexture(&(mat->opacity_map),"opacity_map",textureTransparancy);
    osg::ref_ptr<osg::Texture> opacity_mask = 
createTexture(&(mat->opacity_mask),"opacity_mask",textureTransparancy);
    osg::ref_ptr<osg::Texture> bump_map = 
createTexture(&(mat->bump_map),"bump_map",textureTransparancy);
    osg::ref_ptr<osg::Texture> bump_mask = 
createTexture(&(mat->bump_mask),"bump_mask",textureTransparancy);
    osg::ref_ptr<osg::Texture> specular_map = 
createTexture(&(mat->specular_map),"specular_map",textureTransparancy);
    osg::ref_ptr<osg::Texture> specular_mask = 
createTexture(&(mat->specular_mask),"specular_mask",textureTransparancy);
    osg::ref_ptr<osg::Texture> shininess_map = 
createTexture(&(mat->shininess_map),"shininess_map",textureTransparancy);
    osg::ref_ptr<osg::Texture> shininess_mask = 
createTexture(&(mat->shininess_mask),"shininess_mask",textureTransparancy);
    osg::ref_ptr<osg::Texture> self_illum_map = 
createTexture(&(mat->self_illum_map),"self_illum_map",textureTransparancy);
    osg::ref_ptr<osg::Texture> self_illum_mask = 
createTexture(&(mat->self_illum_mask),"self_illum_mask",textureTransparancy);
    osg::ref_ptr<osg::Texture> reflection_map = 
createTexture(&(mat->reflection_map),"reflection_map",textureTransparancy);
    osg::ref_ptr<osg::Texture> reflection_mask = 
createTexture(&(mat->reflection_mask),"reflection_mask",textureTransparancy);
*/
    return stateset;
}










_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

Reply via email to