Hi,

I can't find the solution to my problem in any of the other posts, so I'm 
writing in a new thread.

For a lighting event here in Eindhoven (NL) our company is going to project an 
image on a building using big ass beamers. It's an event which follows up after 
Glow (http://www.gloweindhoven.nl/). Our idea was to have an interactive 
application running between two users and the image projected by the big ass 
beamer. We're going to capture the movements of two users that are "throwing 
paint" at a building. All the user does is make the gesture, and my application 
extrapolates the course the paint will fly at the building. To round it off; a 
nice animated splash of paint is then projected on the building.

So I decided OSG would be a decent way to make this happen. Well... I got most 
things in place. Someone supplied a sequence of transparent PNG images for me 
to display. I used libpng to load them and put them in a osg::Image object 
which I then proceed to put in an osg::ImageSequence object. I then proceed to 
do some things I read on these forums to make the loaded PNG appear as a 
transparent texture-on-a-quad in my view.

And this actually works:


Code:

SplashContainer
LichtStadEindhovenApp::Splash(
        osg::Vec3f position,
        osg::Vec2f scale,
        DWORD color,
        float speed,
        int nsplash)
{
        SplashContainer cont;
        osg::ref_ptr<osg::ImageSequence> tmpImageSequence = new 
osg::ImageSequence();

        for ( int k = 0 ; k < splash[nsplash]->size() ; k += 1 )
        {
                
tmpImageSequence->addImage(LoadBitmapPNG(splash[nsplash]->operator 
[](k).c_str(), color));
        }

        osg::ref_ptr<osg::Geode> geode = new osg::Geode();
        osg::ref_ptr<osg::PositionAttitudeTransform> texPAT = new 
osg::PositionAttitudeTransform();

    osg::ref_ptr<osg::Geometry> quad1 = createTexturedQuadGeometry(
        osg::Vec3d(0.0, 0.0, 0.0),                      //Center vector
                osg::Vec3d(0.0, 0.0, scale.x()),        //Width vector
        osg::Vec3d(scale.y(), 0.0, 0.0),        //Height vector
        1.0,                                                            
//Texture coordinates left
        1.0);                                                           
//Texture coordinatse top

        texPAT->setPosition(position);

        mNavTrans->addChild(texPAT.get());
        texPAT->addChild(geode);
        osg::Quat q(osg::DegreesToRadians(90.0f), osg::Vec3f(0.0f, 1.0f, 0.0f));
        texPAT->setAttitude(q);
    geode->addDrawable(quad1.get());

        osg::ref_ptr<osg::Texture2D> splashTexture = new 
osg::Texture2D(tmpImageSequence);
        osg::ref_ptr<osg::StateSet> stateset = quad1->getOrCreateStateSet();

    stateset->setTextureAttributeAndModes(0, splashTexture.get(), 
osg::StateAttribute::ON);
    stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);

        osg::ref_ptr<osg::BlendFunc> texture_blending_function = new 
osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);
    stateset->setAttributeAndModes(texture_blending_function.get(), 
osg::StateAttribute::ON);
    stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
        
        osg::ref_ptr<osg::AlphaFunc> alpha_transparency_function = new 
osg::AlphaFunc();
        
alpha_transparency_function->setFunction(osg::AlphaFunc::ComparisonFunction::ALWAYS,
 0.5);
        stateset->setAttributeAndModes(alpha_transparency_function.get(), 
osg::StateAttribute::ON );

        stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);

        quad1->setStateSet(stateset.get());

        cont.geode = geode;
        cont.imgseq = tmpImageSequence;
        cont.pos = texPAT;
        cont.f_incr = speed;
        cont.f_time = 0.0f;
        if ( nsplash == 1 || nsplash == 2 )
                cont.bSaveLastFrame = false;
        else
                cont.bSaveLastFrame = true;

        printf("ptr count 1: %d\n", tmpImageSequence->referenceCount());
        m_vecSplashes.push_back(cont);
        printf("ptr count 2: %d\n", 
m_vecSplashes[m_vecSplashes.size()-1].imgseq->referenceCount());

        nThrown += 1;

        return cont;
}




My problem is is that I also want this quad to be 70% transparent. So that when 
a new quad is placed in front of it, a little bit of the image farther away 
remains visible.

I've read several posts all of which say I should add this piece of code 
somewhere.


Code:

        osg::Material* mat = 
(osg::Material*)stateset->getAttribute(osg::StateAttribute::MATERIAL);
        if ( !mat )
                mat = new osg::Material();
        mat->setAlpha(osg::Material::FRONT_AND_BACK, 0.70f);
        stateset->setAttribute(mat, osg::StateAttribute::ON);




however adding it to the function I described above does nothing to achieve 
anything at all. My tree looks like this


Code:

//                                                             texPAT -- geode 
-- quad
//                                                           /
// mRoot -- mPos -- mTrans -- mNavTrans
//                                               \     \     \
//                                                \     \      texPAT -- geode 
-- quad
//                                                 \      texPAT -- geode -- 
quad
//                                                   texPAT -- geode -- quad




I tried setting the state of mNavTrans to make all underlying objects 
transparent. That didn't work, but I think that's because the individual PNG 
transparency code will override any changes made in the parent node.

At the moment all my images are displayed with correct transparency in the 
image. However I also want to achieve the effect where the quad on which that 
image is printed also becomes transparent. Nothing I do seems to be able to 
change that. Does anybody have any suggestions?

Here's some more interesting code that might shed some more light on my project.


Code:

osg::Image*
LichtStadEindhovenApp::LoadBitmapPNG(
        LPCTSTR szFile,
        DWORD col)
{
        osg::Image* image = new osg::Image();
        HBITMAP hbm = NULL;

        bool retVal = false;
        bool shouldWeLoad = true;
        int size = 0;
        int index = 0;

        int i = 0;
        while ( i < loadedPNGs.size() )
        {
                if ( strcmp(loadedPNGs[i].file.c_str(), szFile) == 0 )
                {
                        //printf("PNG's already loaded, do not load again!\n");
                        shouldWeLoad = false;
                        index = i;
                        break;
                }
                i += 1;
        }
        if ( shouldWeLoad == true )
        {
                // check the header first
                FILE *fp = fopen(szFile, "rb");
                if (!fp)
                        return false;
                BYTE header[8];
                fread(header, 1, 8, fp);
                fseek(fp, 0, SEEK_END);
                size = ftell(fp);
                fclose(fp);
                if (png_sig_cmp(header, 0, 8))
                        return false;
                // now allocate stuff
                png_structp png_ptr = 
png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, user_error_fn, 
user_warning_fn);
                if (!png_ptr)
                        return false;
                png_infop info_ptr = png_create_info_struct(png_ptr);
                if (!info_ptr)
                {
                        png_destroy_read_struct(&png_ptr, (png_infopp)NULL, 
(png_infopp)NULL);
                        return false;
                }
                 
                png_infop end_info = png_create_info_struct(png_ptr);
                if (!end_info)
                {
                        png_destroy_read_struct(&png_ptr, &info_ptr, 
(png_infopp)NULL);
                        return false;
                }
                 
                fp = fopen(szFile, "rb");
                if (fp == NULL)
                        return NULL;

                png_init_io(png_ptr, fp);
                 
                // should really use png_set_rows() to allocate space first, 
rather than doubling up
                 
                png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND | 
PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING, NULL);
                 
                fclose(fp);

                struct PNGInfo pinfo;
                pinfo.file = std::string(szFile);
                pinfo.end_info = end_info;
                pinfo.info_ptr = info_ptr;
                pinfo.png_ptr = png_ptr;
                loadedPNGs.push_back(pinfo);
                index = loadedPNGs.size() - 1;
        }
         
        png_bytep* row_pointers = png_get_rows(loadedPNGs[index].png_ptr, 
loadedPNGs[index].info_ptr);
         
        // now for a tonne of ugly DIB setup crap
         
        int width = loadedPNGs[index].info_ptr->width;
        int height = loadedPNGs[index].info_ptr->height;
        int bpp = loadedPNGs[index].info_ptr->channels * 8;
        int memWidth = (width * (bpp >> 3) + 3) & ~3;
         
        LPBITMAPINFO lpbi = (LPBITMAPINFO) new char[sizeof(BITMAPINFOHEADER) + 
(256 * sizeof(RGBQUAD))];
         
        // create a greyscale palette 
        for (int a_i = 0; a_i < 256; a_i++)
        {
                lpbi->bmiColors[a_i].rgbRed = (BYTE)a_i;
                lpbi->bmiColors[a_i].rgbGreen = (BYTE)a_i;
                lpbi->bmiColors[a_i].rgbBlue = (BYTE)a_i;
                lpbi->bmiColors[a_i].rgbReserved = (BYTE)a_i;
        }
         
        lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        lpbi->bmiHeader.biWidth = width;
        lpbi->bmiHeader.biHeight = -height; // must be negative for top down
        lpbi->bmiHeader.biPlanes = 1;
        lpbi->bmiHeader.biBitCount = bpp;
        lpbi->bmiHeader.biCompression = BI_RGB;
        lpbi->bmiHeader.biSizeImage = memWidth * height;
        lpbi->bmiHeader.biXPelsPerMeter = 0;
        lpbi->bmiHeader.biYPelsPerMeter = 0;
        lpbi->bmiHeader.biClrUsed = 0;
        lpbi->bmiHeader.biClrImportant = 0;
         
        BYTE * pixelData = NULL;
        hbm = ::CreateDIBSection(NULL, lpbi, DIB_RGB_COLORS, (void 
**)&pixelData, NULL, 0 );
        if (hbm && pixelData)
        {
                // now copy the rows
                for (int i = 0; i < height; i++)
                {
                        int bitesize = width * 
loadedPNGs[index].info_ptr->channels;
                        BYTE* buff = new BYTE[bitesize];
                        memset(buff, 0, bitesize);
                        memcpy(buff, row_pointers[i], bitesize);
                        for ( int g = 0 ; g < width ; g += 1 )
                        {
                                buff[(g * loadedPNGs[index].info_ptr->channels) 
+ 0] = GetRValue(col);
                                buff[(g * loadedPNGs[index].info_ptr->channels) 
+ 1] = GetGValue(col);
                                buff[(g * loadedPNGs[index].info_ptr->channels) 
+ 2] = GetBValue(col);
                                buff[(g * loadedPNGs[index].info_ptr->channels) 
+ 3] = 128;
                        }
                        memcpy(pixelData + memWidth * i, buff, bitesize);
                        delete [] buff;
                        buff = NULL;
                }
        }

        // Create data to hold the destination image 
        BYTE* ptrDestImage = new unsigned char[width * height * 4]; 
        BYTE* ptrSourceRow = NULL; 
        BYTE* ptrDestRow = NULL; 

        int iWidth = width; 
        int iHeight = height; 

        // Copy the System::Drawing::Bitmap instance over line by line - this 
gets around the 
        // lack of stride support in the osg::Image. 
        for (int i = 0; i < iHeight; i++) 
        { 
                // Get the source row pointer 
                ptrSourceRow = pixelData + (i * (iWidth * 4)); 

                // Get the destination row pointer 
                ptrDestRow = ptrDestImage + (i * (iWidth * 4)); 

                // Copy the source row to the destination row 
                memcpy(ptrDestRow, ptrSourceRow, iWidth * 4); 
        } 

        // Set the data on the osg::Image 
        image->setImage( 
                iWidth, 
                iHeight, 
                1, 
                GL_RGBA, 
                GL_RGBA, 
                GL_UNSIGNED_BYTE, 
                ptrDestImage, 
                osg::Image::AllocationMode::USE_NEW_DELETE); 

        //delete [] ptrDestImage;
        ::DeleteObject(hbm);
         
        delete (char*) lpbi;

        //png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);

        return image;
}




Thank you!

Cheers,
Rene[/code]

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=18680#18680





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

Reply via email to