Christian Bar
2014-07-16 13:06:33 UTC
Hello! I am experiencing a problem with the QuadTreeTerrain rendering.
With the test project everything works, but when I tried to implement it
inside my project the terrain shows just some little parts of it (also with
wrong triangles, this one seems like an indexing problem).
After lot of trials, it seems to me that the quadtree algorithm does not
work properly when the terrain is not in the origin of the world
coordinates. In my project, the camera is fixed in the origin and the world
moves by the inverse of the camera "virtual" position (there is a transform
with the camera inverse position on top of the scene geometries).
To demonstrate the problem I created a small program by mixing the
"testQuadTreeTerrain" and the "11withoutSSM_complete" tests.
By pressing '1' the camera will be put in the origin and the terrain in a
convenient position to be shown; by pressing '2' the terrain will be in the
origin and the camera in the inverse of the case '1' camera position.
As you can see, in case '2' the terrain is correctly rendered, in case '1'
not.
You can use the button 'q,w,e,a,s,d' to change the position the and
'r,t,y,f,g,h' for rotations, in order to see how the terrain rendering
changes.
I also tried to use the 'terrain->setEyePoint()' and
'terrain->setEyePointValid()', but it works (again) only if the terrain is
in the origin.
What can I do to solve my problem? Thank you!
Christian Bar
Now the test code:
"
#include <OSGGLUT.h>
#include <OSGConfig.h>
#include <OSGSimpleGeometry.h>
#include <OSGGLUTWindow.h>
#include <OSGSolidBackground.h>
#include <OSGDirectionalLight.h>
#include <OSGPerspectiveCamera.h>
#include <OSGTransform.h>
#include <OSGRenderAction.h>
#include <OSGViewport.h>
#include <OSGGradientBackground.h>
#include <OSGTextureBackground.h>
#include <OSGTextureObjChunk.h>
#include <OSGImage.h>
#include <OSGImageForeground.h>
#include <OSGFileGrabForeground.h>
#include "OSGQuadTreeTerrain.h"
#include "OSGImageFileHandler.h"
#include "OSGChunkMaterial.h"
#include "OSGMaterialChunk.h"
#include "OSGTextureObjChunk.h"
#include "OSGTextureEnvChunk.h"
#define ROT 0.1f;
#define TRASL 1.f;
bool updateCameraPos=false;
float tx=-15.f;
float ty=15.f;
float tz=-30.f;
float rx=3.1415f/2.f;
float ry=0.f;
float rz=0.f;
OSG::TransformRecPtr terrainTransCore;
OSG::NodeRecPtr scene;
OSG::QuadTreeTerrainUnrecPtr terrain;
OSG::PerspectiveCameraRecPtr camera;
OSG::TransformRecPtr camTrans;
OSG::ViewportRecPtr viewport;
OSG::WindowRecPtr window;
OSG::NodeRecPtr camBeacon, lightBeacon, lightNode;
OSG::RenderActionRefPtr renderAction;
int setupGLUT(int *argc, char *argv[]);
OSG::MaterialTransitPtr makeTexture (const char* texname)
{
OSG::ImageUnrecPtr image = OSG::ImageFileHandler::the()->read(texname);
SLOG << "Create ChunkMaterial" << std::endl;
OSG::ChunkMaterialUnrecPtr texMatPtr = OSG::ChunkMaterial
::create();
OSG::TextureObjChunkUnrecPtr texChunkPtr =
OSG::TextureObjChunk::create();
OSG::TextureEnvChunkUnrecPtr texEnvChunkPtr =
OSG::TextureEnvChunk::create();
OSG::MaterialChunkUnrecPtr phongChunk = OSG::MaterialChunk
::create();
phongChunk->setDiffuse (OSG::Color4f(1.0f, 1.0f, 1.0f, 1.0f));
phongChunk->setAmbient (OSG::Color4f(0.1f, 0.1f, 0.1f, 1.0f));
phongChunk->setSpecular(OSG::Color4f(0.2f, 0.2f, 0.2f, 1.0f));
phongChunk->setShininess(6);
texChunkPtr->setImage ( image);
texChunkPtr->setWrapS ( GL_CLAMP );
texChunkPtr->setWrapT ( GL_CLAMP );
texChunkPtr->setWrapR ( GL_CLAMP );
texChunkPtr->setMinFilter ( GL_LINEAR );
texChunkPtr->setMagFilter ( GL_LINEAR );
texEnvChunkPtr->setEnvMode(GL_MODULATE);
texMatPtr->addChunk(texChunkPtr, 0);
texMatPtr->addChunk(texEnvChunkPtr, 0);
texMatPtr->addChunk(phongChunk);
return OSG::MaterialTransitPtr(texMatPtr);
}
OSG::NodeTransitPtr createScenegraph(void)
{
OSG::NodeRecPtr torus = OSG::makeTorus(1,5,8,16);
// create the terrain
OSG::ImageUnrecPtr height;
OSG::MaterialUnrecPtr mat;
mat = makeTexture("Default_TexMap.png");
height = OSG::ImageFileHandler::the()->read("Default_HeightMap.png");
terrain = OSG::QuadTreeTerrain::create();
terrain->setHeightData(height);
terrain->setMaterial(mat);
terrain->setVertexSpacing(30.0f/256.0f);
terrain->setHeightScale (5.0f);
terrain->setGeoMorphing(true);
terrain->setDetail (25.0f);
OSG::NodeRecPtr scenet = OSG::Node::create();
scenet->setCore(terrain);
terrainTransCore = OSG::Transform::create();
OSG::NodeRecPtr terrTrans = OSG::makeNodeFor(terrainTransCore);
torus->addChild(terrTrans);
OSG::Matrix terrainMat;
terrainMat.setTransform(OSG::Vec3f( 0, 0, 0),
OSG::Quaternion(OSG::Vec3f(0,1,0),0));
terrainTransCore->setMatrix(terrainMat);
terrTrans->addChild(scenet);
//create transformations & beacons for cameras & light
camBeacon = OSG::Node::create();
lightBeacon = OSG::Node::create();
OSG::TransformRecPtr lightTrans;
camTrans = OSG::Transform::create();
lightTrans = OSG::Transform::create();
OSG::Matrix camMat, lightM;
camMat.setIdentity();
lightM.setIdentity();
camTrans->setMatrix(camMat);
lightTrans->setMatrix(lightM);
camBeacon->setCore(camTrans);
lightBeacon->setCore(lightTrans );
//create the light source
OSG::DirectionalLightRecPtr dLight = OSG::DirectionalLight::create();
dLight->setDirection(OSG::Vec3f(0,1,2));
dLight->setDiffuse(OSG::Color4f(1,1,1,1));
dLight->setAmbient(OSG::Color4f(0.2f,0.2f,0.2f,1.f));
dLight->setSpecular(OSG::Color4f(1,1,1,1));
dLight->setBeacon(lightBeacon);
lightNode = OSG::Node::create();
lightNode->setCore(dLight);
lightNode->addChild(torus);
// now create the root and add all children
OSG::NodeRecPtr root = OSG::Node::create();
root->setCore(OSG::Group::create());
root->addChild(lightNode);
root->addChild(camBeacon);
root->addChild(lightBeacon);
return OSG::NodeTransitPtr(root);
}
int main(int argc, char **argv)
{
OSG::preloadSharedObject("OSGFileIO");
OSG::preloadSharedObject("OSGImageFileIO");
OSG::osgInit(argc,argv);
int winid = setupGLUT(&argc, argv);
scene = createScenegraph();
//create camera, background, viewport, render action, window
camera = OSG::PerspectiveCamera::create();
camera->setBeacon(camBeacon);
camera->setFov(OSG::osgDegree2Rad(90.0f));
camera->setNear(0.1f);
camera->setFar(100.f);
OSG::GradientBackgroundRecPtr bkg = OSG::GradientBackground::create();
bkg->addLine(OSG::Color3f(0.5f,0.5f,0.5f),0);
bkg->addLine(OSG::Color3f(1,1,1),1);
viewport = OSG::Viewport::create();
viewport->setCamera(camera);
viewport->setBackground(bkg);
viewport->setRoot(scene);
viewport->setSize(0,0,1,1);
renderAction = OSG::RenderAction::create();
OSG::GLUTWindowRecPtr gwin = OSG::GLUTWindow::create();
gwin->setGlutId(winid);
gwin->setSize(300,300);
window = gwin;
window->addPort(viewport);
window->init();
printf_s("Now moving terrain, camera is in 0,0,0\n");
OSG::commitChanges();
glutMainLoop();
return 0;
}
void reshape(int w, int h)
{
window->resize(w, h);
glutPostRedisplay();
}
void display(void)
{
OSG::commitChanges();
OSG::Matrix mat;
OSG::Quaternion q;
q.setValue(rx,ry,rz);
mat.setTransform(OSG::Vec3f(tx,ty,tz),q);
if(updateCameraPos)
camTrans->setMatrix(mat); // 15 30 15 -1.57
else
terrainTransCore->setMatrix(mat); // -15 15 -30 1.57
window->render(renderAction);
}
void mouse(int button, int state, int x, int y)
{
glutPostRedisplay();
}
void motion(int x, int y)
{
glutPostRedisplay();
}
void keyboard(unsigned char k, int x, int y)
{
switch(k)
{
case 27:
{
terrain = NULL;
terrainTransCore=NULL;
scene = NULL;
window = NULL;
camera = NULL;
viewport = NULL;
camBeacon = NULL;
lightBeacon = NULL;
lightNode = NULL;
renderAction= NULL;
camTrans = NULL;
OSG::osgExit();
exit(1);
}
break;
case 'a':
tx-=TRASL;
break;
case 'd':
tx+=TRASL;
break;
case 'w':
ty+=TRASL;
break;
case 's':
ty-=TRASL;
break;
case 'q':
tz+=TRASL;
break;
case 'e':
tz-=TRASL;
break;
case 'f':
rx-=ROT;
break;
case 'h':
rx+=ROT;
break;
case 't':
ry+=ROT;
break;
case 'g':
ry-=ROT;
break;
case 'r':
rz+=ROT;
break;
case 'y':
rz-=ROT;
break;
case '1': // move the terrain and put the camera in 0,0,0
{
tx=-15.f;
ty=15.f;
tz=-30.f;
rx=3.1415f/2.f;
ry=0.f;
rz=0.f;
updateCameraPos=false;
OSG::Matrix mat; mat.setIdentity();
camTrans->setMatrix(mat);
terrainTransCore->setMatrix(mat);
printf_s("Now moving terrain, camera is in 0,0,0\n");
}
break;
case '2': // move the camera and put the terrain in 0,0,0
{
tx=15.f;
ty=30.f;
tz=15.f;
rx=-3.1415f/2.f;
ry=0.f;
rz=0.f;
updateCameraPos=true;
OSG::Matrix mat; mat.setIdentity();
camTrans->setMatrix(mat);
terrainTransCore->setMatrix(mat);
printf_s("Now moving camera, terrain is in 0,0,0\n");
}
break;
case '0': // reset camera and terrain transformations
{
rx=ry=rz=tx=ty=tz=0.f;
OSG::Matrix mat; mat.setIdentity();
camTrans->setMatrix(mat);
terrainTransCore->setMatrix(mat);
}
break;
}
printf_s("%.1f %.1f %.1f %.1f %.1f %.1f\n", tx,ty,tz,rx,ry,rz);
}
int setupGLUT(int *argc, char *argv[])
{
glutInit(argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
int winid = glutCreateWindow("QuadTreeTerrain without SSM problem");
glutDisplayFunc(display);
glutMotionFunc(motion);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutIdleFunc(display);
return winid;
}
"
With the test project everything works, but when I tried to implement it
inside my project the terrain shows just some little parts of it (also with
wrong triangles, this one seems like an indexing problem).
After lot of trials, it seems to me that the quadtree algorithm does not
work properly when the terrain is not in the origin of the world
coordinates. In my project, the camera is fixed in the origin and the world
moves by the inverse of the camera "virtual" position (there is a transform
with the camera inverse position on top of the scene geometries).
To demonstrate the problem I created a small program by mixing the
"testQuadTreeTerrain" and the "11withoutSSM_complete" tests.
By pressing '1' the camera will be put in the origin and the terrain in a
convenient position to be shown; by pressing '2' the terrain will be in the
origin and the camera in the inverse of the case '1' camera position.
As you can see, in case '2' the terrain is correctly rendered, in case '1'
not.
You can use the button 'q,w,e,a,s,d' to change the position the and
'r,t,y,f,g,h' for rotations, in order to see how the terrain rendering
changes.
I also tried to use the 'terrain->setEyePoint()' and
'terrain->setEyePointValid()', but it works (again) only if the terrain is
in the origin.
What can I do to solve my problem? Thank you!
Christian Bar
Now the test code:
"
#include <OSGGLUT.h>
#include <OSGConfig.h>
#include <OSGSimpleGeometry.h>
#include <OSGGLUTWindow.h>
#include <OSGSolidBackground.h>
#include <OSGDirectionalLight.h>
#include <OSGPerspectiveCamera.h>
#include <OSGTransform.h>
#include <OSGRenderAction.h>
#include <OSGViewport.h>
#include <OSGGradientBackground.h>
#include <OSGTextureBackground.h>
#include <OSGTextureObjChunk.h>
#include <OSGImage.h>
#include <OSGImageForeground.h>
#include <OSGFileGrabForeground.h>
#include "OSGQuadTreeTerrain.h"
#include "OSGImageFileHandler.h"
#include "OSGChunkMaterial.h"
#include "OSGMaterialChunk.h"
#include "OSGTextureObjChunk.h"
#include "OSGTextureEnvChunk.h"
#define ROT 0.1f;
#define TRASL 1.f;
bool updateCameraPos=false;
float tx=-15.f;
float ty=15.f;
float tz=-30.f;
float rx=3.1415f/2.f;
float ry=0.f;
float rz=0.f;
OSG::TransformRecPtr terrainTransCore;
OSG::NodeRecPtr scene;
OSG::QuadTreeTerrainUnrecPtr terrain;
OSG::PerspectiveCameraRecPtr camera;
OSG::TransformRecPtr camTrans;
OSG::ViewportRecPtr viewport;
OSG::WindowRecPtr window;
OSG::NodeRecPtr camBeacon, lightBeacon, lightNode;
OSG::RenderActionRefPtr renderAction;
int setupGLUT(int *argc, char *argv[]);
OSG::MaterialTransitPtr makeTexture (const char* texname)
{
OSG::ImageUnrecPtr image = OSG::ImageFileHandler::the()->read(texname);
SLOG << "Create ChunkMaterial" << std::endl;
OSG::ChunkMaterialUnrecPtr texMatPtr = OSG::ChunkMaterial
::create();
OSG::TextureObjChunkUnrecPtr texChunkPtr =
OSG::TextureObjChunk::create();
OSG::TextureEnvChunkUnrecPtr texEnvChunkPtr =
OSG::TextureEnvChunk::create();
OSG::MaterialChunkUnrecPtr phongChunk = OSG::MaterialChunk
::create();
phongChunk->setDiffuse (OSG::Color4f(1.0f, 1.0f, 1.0f, 1.0f));
phongChunk->setAmbient (OSG::Color4f(0.1f, 0.1f, 0.1f, 1.0f));
phongChunk->setSpecular(OSG::Color4f(0.2f, 0.2f, 0.2f, 1.0f));
phongChunk->setShininess(6);
texChunkPtr->setImage ( image);
texChunkPtr->setWrapS ( GL_CLAMP );
texChunkPtr->setWrapT ( GL_CLAMP );
texChunkPtr->setWrapR ( GL_CLAMP );
texChunkPtr->setMinFilter ( GL_LINEAR );
texChunkPtr->setMagFilter ( GL_LINEAR );
texEnvChunkPtr->setEnvMode(GL_MODULATE);
texMatPtr->addChunk(texChunkPtr, 0);
texMatPtr->addChunk(texEnvChunkPtr, 0);
texMatPtr->addChunk(phongChunk);
return OSG::MaterialTransitPtr(texMatPtr);
}
OSG::NodeTransitPtr createScenegraph(void)
{
OSG::NodeRecPtr torus = OSG::makeTorus(1,5,8,16);
// create the terrain
OSG::ImageUnrecPtr height;
OSG::MaterialUnrecPtr mat;
mat = makeTexture("Default_TexMap.png");
height = OSG::ImageFileHandler::the()->read("Default_HeightMap.png");
terrain = OSG::QuadTreeTerrain::create();
terrain->setHeightData(height);
terrain->setMaterial(mat);
terrain->setVertexSpacing(30.0f/256.0f);
terrain->setHeightScale (5.0f);
terrain->setGeoMorphing(true);
terrain->setDetail (25.0f);
OSG::NodeRecPtr scenet = OSG::Node::create();
scenet->setCore(terrain);
terrainTransCore = OSG::Transform::create();
OSG::NodeRecPtr terrTrans = OSG::makeNodeFor(terrainTransCore);
torus->addChild(terrTrans);
OSG::Matrix terrainMat;
terrainMat.setTransform(OSG::Vec3f( 0, 0, 0),
OSG::Quaternion(OSG::Vec3f(0,1,0),0));
terrainTransCore->setMatrix(terrainMat);
terrTrans->addChild(scenet);
//create transformations & beacons for cameras & light
camBeacon = OSG::Node::create();
lightBeacon = OSG::Node::create();
OSG::TransformRecPtr lightTrans;
camTrans = OSG::Transform::create();
lightTrans = OSG::Transform::create();
OSG::Matrix camMat, lightM;
camMat.setIdentity();
lightM.setIdentity();
camTrans->setMatrix(camMat);
lightTrans->setMatrix(lightM);
camBeacon->setCore(camTrans);
lightBeacon->setCore(lightTrans );
//create the light source
OSG::DirectionalLightRecPtr dLight = OSG::DirectionalLight::create();
dLight->setDirection(OSG::Vec3f(0,1,2));
dLight->setDiffuse(OSG::Color4f(1,1,1,1));
dLight->setAmbient(OSG::Color4f(0.2f,0.2f,0.2f,1.f));
dLight->setSpecular(OSG::Color4f(1,1,1,1));
dLight->setBeacon(lightBeacon);
lightNode = OSG::Node::create();
lightNode->setCore(dLight);
lightNode->addChild(torus);
// now create the root and add all children
OSG::NodeRecPtr root = OSG::Node::create();
root->setCore(OSG::Group::create());
root->addChild(lightNode);
root->addChild(camBeacon);
root->addChild(lightBeacon);
return OSG::NodeTransitPtr(root);
}
int main(int argc, char **argv)
{
OSG::preloadSharedObject("OSGFileIO");
OSG::preloadSharedObject("OSGImageFileIO");
OSG::osgInit(argc,argv);
int winid = setupGLUT(&argc, argv);
scene = createScenegraph();
//create camera, background, viewport, render action, window
camera = OSG::PerspectiveCamera::create();
camera->setBeacon(camBeacon);
camera->setFov(OSG::osgDegree2Rad(90.0f));
camera->setNear(0.1f);
camera->setFar(100.f);
OSG::GradientBackgroundRecPtr bkg = OSG::GradientBackground::create();
bkg->addLine(OSG::Color3f(0.5f,0.5f,0.5f),0);
bkg->addLine(OSG::Color3f(1,1,1),1);
viewport = OSG::Viewport::create();
viewport->setCamera(camera);
viewport->setBackground(bkg);
viewport->setRoot(scene);
viewport->setSize(0,0,1,1);
renderAction = OSG::RenderAction::create();
OSG::GLUTWindowRecPtr gwin = OSG::GLUTWindow::create();
gwin->setGlutId(winid);
gwin->setSize(300,300);
window = gwin;
window->addPort(viewport);
window->init();
printf_s("Now moving terrain, camera is in 0,0,0\n");
OSG::commitChanges();
glutMainLoop();
return 0;
}
void reshape(int w, int h)
{
window->resize(w, h);
glutPostRedisplay();
}
void display(void)
{
OSG::commitChanges();
OSG::Matrix mat;
OSG::Quaternion q;
q.setValue(rx,ry,rz);
mat.setTransform(OSG::Vec3f(tx,ty,tz),q);
if(updateCameraPos)
camTrans->setMatrix(mat); // 15 30 15 -1.57
else
terrainTransCore->setMatrix(mat); // -15 15 -30 1.57
window->render(renderAction);
}
void mouse(int button, int state, int x, int y)
{
glutPostRedisplay();
}
void motion(int x, int y)
{
glutPostRedisplay();
}
void keyboard(unsigned char k, int x, int y)
{
switch(k)
{
case 27:
{
terrain = NULL;
terrainTransCore=NULL;
scene = NULL;
window = NULL;
camera = NULL;
viewport = NULL;
camBeacon = NULL;
lightBeacon = NULL;
lightNode = NULL;
renderAction= NULL;
camTrans = NULL;
OSG::osgExit();
exit(1);
}
break;
case 'a':
tx-=TRASL;
break;
case 'd':
tx+=TRASL;
break;
case 'w':
ty+=TRASL;
break;
case 's':
ty-=TRASL;
break;
case 'q':
tz+=TRASL;
break;
case 'e':
tz-=TRASL;
break;
case 'f':
rx-=ROT;
break;
case 'h':
rx+=ROT;
break;
case 't':
ry+=ROT;
break;
case 'g':
ry-=ROT;
break;
case 'r':
rz+=ROT;
break;
case 'y':
rz-=ROT;
break;
case '1': // move the terrain and put the camera in 0,0,0
{
tx=-15.f;
ty=15.f;
tz=-30.f;
rx=3.1415f/2.f;
ry=0.f;
rz=0.f;
updateCameraPos=false;
OSG::Matrix mat; mat.setIdentity();
camTrans->setMatrix(mat);
terrainTransCore->setMatrix(mat);
printf_s("Now moving terrain, camera is in 0,0,0\n");
}
break;
case '2': // move the camera and put the terrain in 0,0,0
{
tx=15.f;
ty=30.f;
tz=15.f;
rx=-3.1415f/2.f;
ry=0.f;
rz=0.f;
updateCameraPos=true;
OSG::Matrix mat; mat.setIdentity();
camTrans->setMatrix(mat);
terrainTransCore->setMatrix(mat);
printf_s("Now moving camera, terrain is in 0,0,0\n");
}
break;
case '0': // reset camera and terrain transformations
{
rx=ry=rz=tx=ty=tz=0.f;
OSG::Matrix mat; mat.setIdentity();
camTrans->setMatrix(mat);
terrainTransCore->setMatrix(mat);
}
break;
}
printf_s("%.1f %.1f %.1f %.1f %.1f %.1f\n", tx,ty,tz,rx,ry,rz);
}
int setupGLUT(int *argc, char *argv[])
{
glutInit(argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
int winid = glutCreateWindow("QuadTreeTerrain without SSM problem");
glutDisplayFunc(display);
glutMotionFunc(motion);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutIdleFunc(display);
return winid;
}
"