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