Hi,

instead of attaching a material, just check what colours the createTexturedQuadGeometry assigns to the quad. I think if you modify the alpha there it should work. OSG by default uses GL_MODULATE to get the final colour from the quad colours and the texture colours. Make sure blending is on for all the transparent geometry you draw (quad and whatever you are drawing over it later).

jp

Rene Bokhorst wrote:
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


--
This message is subject to the CSIR's copyright terms and conditions, e-mail legal notice, and implemented Open Document Format (ODF) standard. The full disclaimer details can be found at http://www.csir.co.za/disclaimer.html.

This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean. MailScanner thanks Transtec Computers for their support.

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

Reply via email to