Hi,

I'm a total beginner in OSG and have a strange Problem that i couldn't solve 
and I don't know where it comes from. 
In my little program I create a texture with an Image texImgB(16x16px) and a 
second texture with a bigger Image texImgRG (256x256px). 

h**p://img15.imageshack.us/i/texturesv.png

I created a textureMatrix for each texture, so that the textures will be 
rendered to a Quad from the Perspective of a Viewer (vProjMat - 
ProjectionMatrix, vTransMat - Transformation Matrix). The only diffrence 
between both texture matrices is that I scale the matrix of the 
texImgRG-Texture by 16 in r,s coordinates. So the texImgRG gets 16x smaler than 
before:

h**p://img15.imageshack.us/i/correcte.png

Now the problem:
When i render both textures to the quad and blend them together, the texture 
with the Image texImgB is translated 2px down and left.
Thats the top-right corner of the picture i get from a camera ProjCam (pProjMat 
- ProjectionMatrix, pTransMat - TransformationMatrix) that looks exactly on the 
same face as the Viewer. 

h**p://img715.imageshack.us/i/cornerj.png

Why this? And how can i change my code, so that the texture-Images are not 
Translated to each other? 

Here is my code:

Code:

#include <osg/Node>
#include <osg/Camera>
#include <osg/CameraNode>
#include <osg/Group>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Texture2D>
#include <osg/Program>
#include <osgViewer/Viewer>
#include <osg/Vec3>
#include <osg/Vec4>
#include <osg/Matrix>
#include <osg/MatrixTransform>
#include <osg/TexGen>
#include <osg/TexEnv>
#include <osg/TexMat>
#include <osg/StateSet>
#include <osg/PositionAttitudeTransform>  //Bewegungen

#include <osgDB/WriteFile>
#include <osgDB/ReadFile>
#include <osgDB/FileUtils>

#include <osgGA/TrackballManipulator>

#include <cmath>
#include <iostream>


static osg::Geometry* createQuad(       double breite = 4,                      
//Breite der Bodenplatte
                                                                        double 
hoehe = 3,                       //Höhe der Bodenplatte
                                                                        double 
auflBreite = 10,         //Auflösung der Breite
                                                                        double 
auflHoehe = 10)          //Auflösung der Höhe
{
        double deltaBreite = (breite / auflBreite);
        double deltaHoehe = (hoehe / auflHoehe);
        
        
        osg::Geometry* quadGeometry = new osg::Geometry();
        osg::Vec3Array* quadVertices = new osg::Vec3Array;
        osg::Vec3Array* quadNormals = new osg::Vec3Array;
        osg::Vec4Array* quadColors = new osg::Vec4Array;
        osg::Vec2Array* quadTexcoords = new osg::Vec2Array;
        osg::Vec2 dx_texcoord(1.0f/(float)(auflBreite),0.0f);
    osg::Vec2 dz_texcoord(0.0f,1.0f/(float)(auflHoehe));

        //Vertices über kartesische Koordinaten festlegen
        float vx = 0;
        float vy = 0;
        float vz = 0;
        
        for (int i=0; i<=auflBreite; ++i)
        {
                for (int j=0; j<=auflHoehe; ++j)
                {
                        //Vektor-Koordinaten
                        vx = (deltaBreite * i)-(breite/2);
                        vy = 0;
                        vz = (deltaHoehe * j)-(hoehe/2);
                        quadVertices->push_back(osg::Vec3(vx,vy,vz));
                        quadNormals->push_back( osg::Vec3(0,1,0) );
                        quadTexcoords->push_back( osg::Vec2(dx_texcoord*i + 
dz_texcoord*j));
                        quadColors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
                }
        }
        quadGeometry->setVertexArray( quadVertices );
        quadGeometry->setTexCoordArray(0, quadTexcoords);
        quadGeometry->setColorArray(quadColors);
        quadGeometry->setColorBinding(osg::Geometry::BIND_OVERALL);
        quadGeometry->setNormalArray( quadNormals );
        quadGeometry->setNormalBinding( osg::Geometry::BIND_PER_VERTEX );
        

        //Jewils 4 Vertices zu Primitive "Quad" verbinden
        for (int i=0; i<auflHoehe; ++i)
        {
                for (int j=0; j<auflBreite; ++j)
                {
                        osg::DrawElementsUInt* quadPrim = new 
osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
                        quadPrim->push_back(i*(auflBreite+1)+j);
                        quadPrim->push_back(i*(auflBreite+1)+j+1);
                        quadPrim->push_back((i+1)*(auflBreite+1)+j+1);
                        quadPrim->push_back((i+1)*(auflBreite+1)+j);

                        quadGeometry->addPrimitiveSet(quadPrim);
                }
        }

    return quadGeometry;
}



//Main-Funktion
int main( int argc, char **argv )
{
        // ArgumentParser, verwaltet Übergebene Argumente
    osg::ArgumentParser arguments(&argc,argv);


        //----------------------------
        //Globale Einstellungen
        //----------------------------
        //Projektor
                double fovyDeg = 20;                                            
//Öffnungswinkel (in Grad) des Projektions-Frustums
                float aspectR = 4.0f/3.0f;                                      
//Aspect Ratio
                float p_dist = 1.0f;                                            
//Abstand des Projektors zum Screen
                float near=0.1f;                                                
        //Clipping-Ebenen des Frustums (Nähe)
                float far=100.0f;                                               
        //Clipping-Ebenen des Frustums (Ferne)
                float pRotX=0.0f;                                               
        //Verschiebung des Projektors in x-Richtung
                arguments.read("--pRotX", pRotX);
                float pRotY=0.0f;                                               
        //Verschiebung des Projektors in y-Richtung
                arguments.read("--pRotY", pRotY);
                float pRotZ=0.0f;                                               
        //Verschiebung des Projektors in y-Richtung
                arguments.read("--pRotZ", pRotZ);
                float pTransX=0.0f;                                             
        //Verschiebung des Projektors in x-Richtung
                arguments.read("--pTransX", pTransX);
                float pTransY=0.0f;                                             
        //Verschiebung des Projektors in y-Richtung
                arguments.read("--pTransY", pTransY);
                float pTransZ=0.0f;                                             
        //Verschiebung des Projektors in y-Richtung
                arguments.read("--pTransZ", pTransZ);
        //Viewer
                float vTransX=0.0f;                                             
        //Verschiebung des Viewers in x-Richtugn
                arguments.read("--vTransX", vTransX);
                float vTransY=0.0f;                                             
        //Verschiebung des Viewers in y-Richtugn
                arguments.read("--vTransY", vTransY);
                float vTransZ=0.0f;                                             
        //Verschiebung des Viewers in z-Richtugn
                arguments.read("--vTransZ", vTransZ);
        //Texturgröße
                unsigned int tex_width =  4096;
                unsigned int tex_height = 4096;

        //--------------------------------------------------
        // Projektor
        //--------------------------------------------------
        float dx, dz;                                                           
//Größe des Bildschirms x-Breite, z-Höhe
        float fovy = (fovyDeg/360)*(2.0*osg::PI);       //FOVy in Rad
        dz= 2.0f*(tan(fovy/2.0)*p_dist);
        dx= aspectR * dz;

        //Projection Matrix des Projektors (Frustum)
        osg::Matrix pProjMat;
        pProjMat.makePerspective(fovyDeg, aspectR, near, far);
        osg::Matrix pProjMatInv = osg::Matrix::inverse(pProjMat); //invertiert

        //Transformations Matrix des Projektors
        osg::Matrix pTransMat;
        pTransMat.makeRotate(-osg::PI/2,osg::X_AXIS);  //Kamera guckt 
standartmäßig in z-Richtung, wollen aber y! -> 90°Drehung des KS 
        pTransMat = pTransMat * 
osg::Matrix::rotate(pRotX,osg::X_AXIS,pRotZ,osg::Y_AXIS,-pRotY,osg::Z_AXIS); 
//Rot des Projektors
        pTransMat = pTransMat * 
osg::Matrix::translate(osg::Vec3(pTransX,pTransY,pTransZ));     //Verschiebung 
des Projektors                                                           
        osg::Matrix pTransMatInv = osg::Matrix::inverse(pTransMat); //invertiert


        //--------------------------------------------------
        // VIEWER
        //--------------------------------------------------
        float mc_dist;                                                          
//Distanz vom Auge des Betrachters zum Screen
        float mc_left, mc_right, mc_top, mc_bottom; //Ausdehnungs-Parameter des 
Frustums
        float n_over_d;                                                         
//near:mc_dist (Strahlensatz)

        mc_dist=p_dist-vTransY;
        n_over_d=near/mc_dist;
        mc_right        =  n_over_d * (dx/2.0f - vTransX);
        mc_left         = -n_over_d * (dx/2.0f + vTransX);
        mc_top          =  n_over_d * (dz/2.0f - vTransZ);
        mc_bottom       = -n_over_d * (dz/2.0f + vTransZ);

        //Projection Matrix des Views (ViewFrustum)
        osg::Matrix vProjMat;
        vProjMat.makeFrustum(mc_left, mc_right, mc_bottom, mc_top, near, far);
        osg::Matrix vProjMatInv = osg::Matrix::inverse(vProjMat); //invertiert

        //Transformations Matrix des Views
        osg::Matrix vTransMat;
        vTransMat.makeRotate(osg::PI/2,osg::X_AXIS);  //Viewer standartmäßig in 
z-Richtung, wollen aber y! -> 90°Drehung 
        vTransMat = vTransMat * 
osg::Matrix::translate(osg::Vec3(vTransX,vTransY,vTransZ));     
//Orientierung(oben)
        osg::Matrix vTransMatInv = osg::Matrix::inverse(vTransMat); //invertiert


        //--------------------------------------------------
        // Projektionsgeometrie Transformieren
        //--------------------------------------------------
        //Transformationsmatrix der Projektionsgeometrie
        osg::Matrix sTransMat;
        sTransMat.set(  osg::Matrix::translate(0.0f,2.0f,0.0f)*
                                        osg::Matrix::scale(1.0f,1.0f,1.0f)*
                                        osg::Matrix::rotate(0.0f, osg::Z_AXIS));

        osg::Matrix sTransMatInv = osg::Matrix::inverse(sTransMat); //invertiert

//------------------------
//SCREEN - Geometrie auf die Projektion erfolgt
//------------------------
        osg::Geode* geodeScreen = new osg::Geode();
        //Projektionsgeometrie hinzufügen
        geodeScreen->addDrawable(createQuad(4,4,10,10));

        //ProjGeometrie Transformieren
        osg::MatrixTransform* transScreen = new osg::MatrixTransform();  
        transScreen->setMatrix(sTransMat);
        transScreen->addChild(geodeScreen);

        
        //--------------------------------------------------
        // Textur 
        //--------------------------------------------------
        //Bild erstellen, in dem Texturkoordinaten pro Pixel gespeichert werden 
(Für RGBA -> 4*8Bit)

        //Statemachine erstellen
        osg::StateSet* stateScreen = new osg::StateSet();
        transScreen->setStateSet(stateScreen);  //Textur hinzufügen
        
        // Textur Rot
        //--------------------------------------------------
        //RotWerte: 8Bit
        int imgBreiteRG = 256;
    int imgHoeheRG = 256;
        unsigned char *dataRG;
    dataRG = new unsigned char[imgBreiteRG*imgHoeheRG*4]; 
//höhe*breite*farbtiefe[R,G,B,Alpha]
    for (int y=0; y<imgHoeheRG; ++y) {
                int border=255;
        for (int x=0; x<imgBreiteRG; ++x) {
                        dataRG[x*4+y*imgBreiteRG*4+0] = 255; //Rot-Wert (8bit)
            dataRG[x*4+y*imgBreiteRG*4+1] = border; //Grün-Wert (8bit)
            dataRG[x*4+y*imgBreiteRG*4+2] = border;
            dataRG[x*4+y*imgBreiteRG*4+3] = 255;
                        border=0;
        }
    }
        osg::Image* texImgRG = new osg::Image();
        texImgRG->setImage(imgBreiteRG, imgHoeheRG, 1, 4, GL_RGBA, 
GL_UNSIGNED_BYTE, dataRG, osg::Image::USE_NEW_DELETE, 1);

        //Textur für RG-Werte erstellen und Bild einbinden
        osg::Texture2D* texturRG = new osg::Texture2D();
        texturRG->setInternalFormat(GL_RGBA);
        texturRG->setFilter(osg::Texture2D::MIN_FILTER, 
osg::Texture2D::NEAREST);
        texturRG->setFilter(osg::Texture2D::MAG_FILTER, 
osg::Texture2D::NEAREST);
        texturRG->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT);
        texturRG->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT);
        texturRG->setImage(texImgRG);
        stateScreen->setTextureAttributeAndModes(0, 
texturRG,osg::StateAttribute::ON); //(TexUnit, Texturtyp, Attribut)

        //Decal-Mode setzen
        osg::TexEnv* texEnvRG = new osg::TexEnv();
        texEnvRG->setMode(osg::TexEnv::DECAL);
        stateScreen->setTextureAttributeAndModes(0, 
texEnvRG,osg::StateAttribute::ON); //(TexUnit, Texturtyp, Attribut)

        //Generiere Texturkoordinaten in x-z-Ebene automatisch
        osg::TexGen* texGenRG = new osg::TexGen();
        texGenRG->setMode(osg::TexGen::EYE_LINEAR);
        texGenRG->setPlane(osg::TexGen::S,osg::Plane(1.0f,0.0f,0.0f,0.0f)); 
        texGenRG->setPlane(osg::TexGen::T,osg::Plane(0.0f,1.0f,0.0f,0.0f));
        texGenRG->setPlane(osg::TexGen::R,osg::Plane(0.0f,0.0f,1.0f,0.0f));
        texGenRG->setPlane(osg::TexGen::Q,osg::Plane(0.0f,0.0f,0.0f,1.0f));
        stateScreen->setTextureAttributeAndModes(0, 
texGenRG,osg::StateAttribute::ON); //(TexUnit, Texturtyp, Attribut)
        
        //Texturmatrix erstellen
        osg::TexMat* texMatRG= new osg::TexMat();
        stateScreen->setTextureAttributeAndModes(0, 
texMatRG,osg::StateAttribute::ON); //(TexUnit, Texturtyp, Attribut)

        //Textur-Scaling
        osg::Matrix scaleTex1;  //Textur geht von -1 nach 1 wegen vProjMat auf 
Einheitswürfel, wollen aber von 0 nach 1
        scaleTex1.makeScale(osg::Vec3(0.5f,0.5f,1.0f));         //Texturgröße 
wird halbiert -> Image verdoppelt sich in Größe 

        osg::Matrix scaleTex2;  //Textur soll 16x in jede Richtung wiederholt 
werden -> bessere Auflösung
        scaleTex2.makeScale(osg::Vec3(16.0f,16.0f,1.0f));       //Scale-Faktor 
(x,y,z) 

        //Textur-Trans
        osg::Matrix transTex1;
        transTex1.makeTranslate(osg::Vec3(0.5f,0.5f,0.0f));     //Scale-Faktor 
(x,y,z)

        texMatRG->setMatrix(sTransMat * vTransMatInv * vProjMat * scaleTex1 * 
transTex1 * scaleTex2);

        // Textur Blau
        //--------------------------------------------------
        //BlauWerte: 1*8Bit
        int imgBreiteB = 16;
    int imgHoeheB = 16;
        unsigned char *dataB;
    dataB = new unsigned char[imgBreiteB*imgHoeheB*4]; 
//höhe*breite*farbtiefe[R,G,B,Alpha]
    for (int y=0; y<imgHoeheB; ++y) {
                int border2 = 255;
        for (int x=0; x<imgBreiteB; ++x) {
            dataB[x*4+y*imgBreiteB*4+0] = 0;
            dataB[x*4+y*imgBreiteB*4+1] = border2;
            dataB[x*4+y*imgBreiteB*4+2] = x+(y*imgBreiteB); //Blau-Wert (8bit)
            dataB[x*4+y*imgBreiteB*4+3] = 255;
                        border2 = 0;
        }
    }
        osg::Image* texImgB = new osg::Image();
        texImgB->setImage(imgBreiteB, imgHoeheB, 1, 4, GL_RGBA, 
GL_UNSIGNED_BYTE, dataB, osg::Image::USE_NEW_DELETE, 1);

        //Textur für B-Wert erstellen und Bild einbinden
        osg::Texture2D* texturB = new osg::Texture2D();
        texturB->setInternalFormat(GL_RGBA);
        texturB->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST);
        texturB->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST);
        texturB->setWrap(osg::Texture2D::WRAP_S, 
osg::Texture2D::CLAMP_TO_BORDER);
        texturB->setWrap(osg::Texture2D::WRAP_T, 
osg::Texture2D::CLAMP_TO_BORDER);
        texturB->setBorderColor(osg::Vec4(0.0f,0.0f,0.0f,0.0f));
        texturB->setImage(texImgB);
        stateScreen->setTextureAttributeAndModes(1, 
texturB,osg::StateAttribute::ON); //(TexUnit, Texturtyp, Attribut)

        //Blend-Mode setzen
        osg::TexEnv* texEnvB = new osg::TexEnv();
        texEnvB->setMode(osg::TexEnv::BLEND);
        texEnvB->setColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); //Welche Kanal soll 
geblendet werden -> hier blau
        stateScreen->setTextureAttributeAndModes(1, 
texEnvB,osg::StateAttribute::ON); //(TexUnit, Texturtyp, Attribut)

        //Generiere Texturkoordinaten in x-z-Ebene automatisch
        osg::TexGen* texGenB = new osg::TexGen();
        texGenB->setMode(osg::TexGen::EYE_LINEAR);
        texGenB->setPlane(osg::TexGen::S,osg::Plane(1.0f,0.0f,0.0f,0.0f)); 
        texGenB->setPlane(osg::TexGen::T,osg::Plane(0.0f,1.0f,0.0f,0.0f));
        texGenB->setPlane(osg::TexGen::R,osg::Plane(0.0f,0.0f,1.0f,0.0f)); 
        texGenB->setPlane(osg::TexGen::Q,osg::Plane(0.0f,0.0f,0.0f,1.0f));
        stateScreen->setTextureAttributeAndModes(1, 
texGenB,osg::StateAttribute::ON); //(TexUnit, Texturtyp, Attribut)
        
        //Texturmatrix erstellen
        osg::TexMat* texMatB = new osg::TexMat();
        stateScreen->setTextureAttributeAndModes(1, 
texMatB,osg::StateAttribute::ON); //(TexUnit, Texturtyp, Attribut)

        texMatB->setMatrix(sTransMat * vTransMatInv * vProjMat * scaleTex1 * 
transTex1);

//--------------------------------------------------
// QUAD für distImg
//--------------------------------------------------
        //Quad zur visualisierung des distImg
        osg::Geode* geodeImgQuad = new osg::Geode();
        geodeImgQuad->addDrawable(createQuad());

        // StateSet mit Texture StateAttributen.
    osg::StateSet* stateImgQuad = new osg::StateSet();
        stateImgQuad->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
        geodeImgQuad->setStateSet(stateImgQuad);

        //Quad transformieren
        osg::MatrixTransform* transImgQuad = new osg::MatrixTransform();
        transImgQuad->setMatrix(osg::Matrix::translate(4.0f, 0.0f, 0.0f));
        transImgQuad->addChild(geodeImgQuad);

        //Textur erstellen
        //--------------------------
    
    osg::Texture2D* textureQuad = new osg::Texture2D;
    textureQuad->setTextureSize(tex_width, tex_height);
    textureQuad->setInternalFormat(GL_RGBA);
        
textureQuad->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::NEAREST);
        
textureQuad->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::NEAREST);
    stateImgQuad->setTextureAttributeAndModes(0, textureQuad, 
osg::StateAttribute::ON);
        
//--------------------------------------------------
// Kamera(Sicht Projektor) - Render2Texture (Rendert verzerrtes Projektorbild 
auf Textur eines Quads)
//--------------------------------------------------
        osg::CameraNode* projCam = new osg::CameraNode();

        //zum Test auf FBO festlegen
        osg::CameraNode::RenderTargetImplementation renderImplementation = 
osg::CameraNode::FRAME_BUFFER_OBJECT;

        //Screen soll gerendert werden
        projCam->addChild(transScreen);

        //Lage und Projektion festlegen
        projCam->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
        projCam->setViewMatrix(pTransMat);
        projCam->setProjectionMatrix(pProjMat);

        // set up the background color and clear mask.
        projCam->setClearColor(osg::Vec4(0.0f,0.0f,0.0f,1.0f));
        projCam->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
        // set up projection.
        
projCam->setComputeNearFarMode(osg::CameraNode::DO_NOT_COMPUTE_NEAR_FAR);

        // setze Sichtfenster
        projCam->setViewport(0,0,tex_width,tex_height);

        // Camera vor Haupt-Kamera des viewers rendern lassen
        projCam->setRenderOrder(osg::CameraNode::PRE_RENDER);

        //render-Modus festlegen
        projCam->setRenderTargetImplementation(renderImplementation);
                
        // Bild aus Kameransicht erstellen und speichern
        osg::Image* distImg = new osg::Image();
        distImg->allocateImage(tex_width,tex_height,1,GL_RGBA,GL_UNSIGNED_BYTE);
        projCam->attach(osg::CameraNode::COLOR_BUFFER, distImg);

//--------------------------------------------------
// Scenengraph initialisieren
//--------------------------------------------------
        //Gruppe zur Dartellung des DistortionImages
        osg::Group* imgGroup = new osg::Group();
        imgGroup->getOrCreateStateSet()->setMode(GL_LIGHTING, 
osg::StateAttribute::OFF);
        imgGroup->getOrCreateStateSet()->setMode(GL_BLEND, 
osg::StateAttribute::ON);

        //GeoNodes zu imgGroup hinzuügen
        imgGroup->addChild(transScreen);
        imgGroup->addChild(projCam);

        // Viewer erstellen
        osgViewer::Viewer viewer;
        viewer.setSceneData( imgGroup );
        viewer.setCameraManipulator(new osgGA::TrackballManipulator);

        while (!viewer.done())
        {
                viewer.frame();
                osgDB::writeImageFile(*distImg,"distort.png");
                osgDB::writeImageFile(*texImgB,"texImgB.png");
                osgDB::writeImageFile(*texImgRG,"texImgRG.png");
        }
        return 0;
}






I would be grateful for any help...!

Cheers,
Jochen[/img]

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





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

Reply via email to