Hi,
I have a question on how to addChild/subChild a Slices node correctly.
We have an application adding and subtracting Slices nodes/creating materials
for Slice nodes often
and its leaking memory.
In the attachment you find a modified version of testSlices.cpp, reproducing
this behaviour.
Is the destructor and the changed-method of Slices correct?
In Geometry the destructor and the changed-method contains a
subRefCP(_sfMaterial.getValue());
Thanks for your help,
Christoph
/*---------------------------------------------------------------------------*\
* OpenSG *
* *
* *
* Copyright (C) 2000-2002 by the OpenSG Forum *
* *
* www.opensg.org *
* *
* contact: [EMAIL PROTECTED], [EMAIL PROTECTED], [EMAIL PROTECTED] *
* *
\*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*\
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Library General Public License as published *
* by the Free Software Foundation, version 2. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*\
* Changes *
* *
* *
* *
* *
* *
* *
\*---------------------------------------------------------------------------*/
#include <OSGConfig.h>
#include <iostream>
#include <OSGGLUT.h>
#include <OSGFieldContainerFactory.h>
#include <OSGSFSysTypes.h>
#include <OSGVector.h>
#include <OSGQuaternion.h>
#include <OSGMatrix.h>
#include <OSGMatrixUtility.h>
#include <OSGBoxVolume.h>
#include <OSGNode.h>
#include <OSGGroup.h>
#include <OSGThread.h>
#include <OSGTransform.h>
#include <OSGAttachment.h>
#include <OSGMFVecTypes.h>
#include <OSGAction.h>
#include <OSGDrawAction.h>
#include <OSGSimpleGeometry.h>
#include <OSGSimpleMaterial.h>
#include <OSGChunkMaterial.h>
#include <OSGTextureChunk.h>
#include <OSGBlendChunk.h>
#include <OSGDirectionalLight.h>
#include "OSGViewport.h"
#include "OSGCamera.h"
#include "OSGWindow.h"
#include "OSGGLUTWindow.h"
#include "OSGCamera.h"
#include "OSGPerspectiveCamera.h"
#include "OSGSolidBackground.h"
#include "OSGOSGWriter.h"
#include "OSGImage.h"
#include "OSGSlices.h"
//#include "OSGUniformBackground.h"
#include "OSGTrackball.h"
#include "OSGNavigator.h"
/**---added
stuff------------------------------------------------------------------*/
/**---end of added
stuff-----------------------------------------------------------*/
using namespace OSG;
DrawAction * ract;
NodePtr root;
Vec3f size;
PerspectiveCameraPtr cam;
ViewportPtr vp;
WindowPtr win;
SlicesPtr slicesCore;
TransformPtr cam_trans;
unsigned numberOfSlices;
Navigator navigator;
int mouseb = 0;
int lastx=0, lasty=0;
bool cullFace = true;
bool buttonPressed;
void
display(void)
{
Matrix m1, m2, m3;
if ( buttonPressed ) navigator.moveTo(lastx,lasty);
m1=navigator.getMatrix();
// m1.transpose();
// m2.setTranslate(0,0,8);
// m1.mult(m2);
cam_trans->getSFMatrix()->setValue( m1 );
win->draw( ract );
}
void reshape( int w, int h )
{
std::cerr << "Reshape: " << w << "," << h << std::endl;
win->resize( w, h );
}
void
animate(void)
{
glutPostRedisplay();
}
// tballall stuff
void
motion(int x, int y)
{
/* Real32 w = win->getWidth(), h = win->getHeight();
Real32 a = 2. * ( lastx / w - .5 ),
b = 2. * ( .5 - lasty / h ),
c = 2. * ( x / w - .5 ),
d = 2. * ( .5 - y / h );
if ( mouseb & ( 1 << GLUT_LEFT_BUTTON ) )
{
tball.updateRotation( a, b, c, d );
}
else if ( mouseb & ( 1 << GLUT_MIDDLE_BUTTON ) )
{
tball.updatePosition( a, b, c, d );
}
else if ( mouseb & ( 1 << GLUT_RIGHT_BUTTON ) )
{
tball.updatePositionNeg( a, b, c, d );
}*/
lastx = x;
lasty = y;
if ( buttonPressed ) navigator.moveTo(x,y);
}
void
mouse(int button, int state, int x, int y)
{
if ( state == 0 )
{
switch ( button )
{
case GLUT_LEFT_BUTTON:
navigator.buttonPress(Navigator::LEFT_MOUSE,x,y);
break;
case
GLUT_MIDDLE_BUTTON:navigator.buttonPress(Navigator::MIDDLE_MOUSE,x,y);
break;
case GLUT_RIGHT_BUTTON:
navigator.buttonPress(Navigator::RIGHT_MOUSE,x,y);
break;
case 3:
navigator.buttonPress(Navigator::UP_MOUSE,x,y);
break;
case 4:
navigator.buttonPress(Navigator::DOWN_MOUSE,x,y);
break;
}
mouseb |= 1 << button;
buttonPressed=true;
}
else if ( state == 1 )
{
switch ( button )
{
case GLUT_LEFT_BUTTON:
navigator.buttonRelease(Navigator::LEFT_MOUSE,x,y);
break;
case
GLUT_MIDDLE_BUTTON:navigator.buttonRelease(Navigator::MIDDLE_MOUSE,x,y);
break;
case GLUT_RIGHT_BUTTON:
navigator.buttonRelease(Navigator::RIGHT_MOUSE,x,y);
break;
}
mouseb &= ~(1 << button);
buttonPressed=false;
}
lastx = x;
lasty = y;
}
void
vis(int visible)
{
if (visible == GLUT_VISIBLE)
{
glutIdleFunc(animate);
}
else
{
glutIdleFunc(NULL);
}
}
void key(unsigned char key, int x, int y)
{
switch ( key )
{
case 27: osgExit(); exit(0);
case 'b':
cullFace = !cullFace;
if (cullFace)
glEnable(GL_CULL_FACE);
else
glDisable(GL_CULL_FACE);
std::cout << "cullFace: " << cullFace << std::endl;
break;
case 's':
case 'S':
{
float f = (key == 's') ? 0.9 : 1.1;
numberOfSlices = unsigned(f * numberOfSlices) + 1;
beginEditCP(slicesCore);
{
slicesCore->setNumberOfSlices(numberOfSlices);
}
endEditCP(slicesCore);
std::cout << numberOfSlices << std::endl;
}
break;
case 'q':
beginEditCP(slicesCore);
{
Real32 s = size.length();
slicesCore->setSize(Vec3f(s,s,s));
}
endEditCP(slicesCore);
break;
case 'w':
beginEditCP(slicesCore);
{
slicesCore->setSize(size);
}
endEditCP(slicesCore);
break;
case 'p': {
std::ofstream outFileStream( "test.osg" );
OSGWriter writer( outFileStream, 2 );
writer.write( root );
std::cerr << "File dumped." << std::endl;
}
break;
case 'L': glDisable( GL_LIGHTING );
std::cerr << "Lighting disabled." << std::endl;
break;
case 'l': glEnable( GL_LIGHTING );
std::cerr << "Lighting enabled." << std::endl;
break;
case 'z': glPolygonMode( GL_FRONT_AND_BACK, GL_POINT);
std::cerr << "PolygonMode: Point." << std::endl;
break;
case 'x': glPolygonMode( GL_FRONT_AND_BACK, GL_LINE);
std::cerr << "PolygonMode: Line." << std::endl;
break;
case 'c': glPolygonMode( GL_FRONT_AND_BACK, GL_FILL);
std::cerr << "PolygonMode: Fill." << std::endl;
break;
case 'r': std::cerr << "Sending ray through " << x << "," << y <<
std::endl;
Line l;
cam->calcViewRay( l, x, y, *vp );
std::cerr << "From " << l.getPosition() << ", dir " << l.getDirection()
<< std::endl;
break;
}
}
int main (int argc, char **argv)
{
osgInit(argc,argv);
// GLUT init
glutInit(&argc, argv);
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
int winid = glutCreateWindow("OpenSG");
glutKeyboardFunc(key);
glutVisibilityFunc(vis);
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutIdleFunc(display);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutIdleFunc(display);
// glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
glEnable( GL_DEPTH_TEST );
glEnable( GL_LIGHTING );
glEnable( GL_LIGHT0 );
// OSG
// create the graph
// beacon for camera and light
NodePtr b1n = Node::create();
GroupPtr b1 = Group::create();
beginEditCP(b1n);
b1n->setCore( b1 );
endEditCP(b1n);
// transformation
NodePtr t1n = Node::create();
TransformPtr t1 = Transform::create();
beginEditCP(t1n);
t1n->setCore( t1 );
t1n->addChild( b1n );
endEditCP(t1n);
cam_trans = t1;
// light
NodePtr dlight = Node::create();
DirectionalLightPtr dl = DirectionalLight::create();
beginEditCP(dlight);
dlight->setCore( dl );
endEditCP(dlight);
beginEditCP(dl);
dl->setAmbient( .3, .3, .3, 1 );
dl->setDiffuse( 1, 1, 1, 1 );
dl->setDirection(0,0,1);
dl->setBeacon( b1n);
endEditCP(dl);
// root
root = Node::create();
GroupPtr gr1 = Group::create();
beginEditCP(root);
root->setCore( gr1 );
root->addChild( t1n );
root->addChild( dlight );
endEditCP(root);
Vec3f min,max;
// forever create and delete slices
while (true) {
// create the slice node...
slicesCore = Slices::create();
NodePtr slicesNode = Node::create();
beginEditCP(slicesNode);
slicesNode->setCore(slicesCore);
endEditCP(slicesNode);
ImagePtr imageP = NullFC;
if (argc > 1)
{
imageP = Image::create();
if (imageP->read(argv[1]))
{
if (imageP->getFrameCount() > 1)
imageP->flipDepthFrameData();
size.setValues( imageP->getWidth(),
imageP->getHeight(),
imageP->getDepth() );
imageP->dump();
imageP->scaleNextPower2();
if (imageP->hasAlphaChannel() == false) {
switch (imageP->getPixelFormat()) {
case Image::OSG_L_PF:
imageP->reformat(Image::OSG_LA_PF);
break;
case Image::OSG_RGB_PF:
imageP->reformat(Image::OSG_RGBA_PF);
break;
default:
std::cerr << "Can not reformat image\n" << std::endl;
break;
}
}
imageP->dump();
}
else
{
FFATAL (("Can not read \'%s\'\n", argv[1]));
subRefCP(imageP);
imageP = NullFC;
return -1;
}
}
MaterialPtr matPtr;
if (imageP!=NullFC)
{
std::cout << "Create ChunkMaterial" << std::endl;
ChunkMaterialPtr texMatPtr = ChunkMaterial::create();
TextureChunkPtr texChunkPtr = TextureChunk::create();
BlendChunkPtr blendChunkPtr = BlendChunk::create();
beginEditCP (texChunkPtr);
{
texChunkPtr->setImage ( imageP);
texChunkPtr->setWrapS ( GL_CLAMP );
texChunkPtr->setWrapT ( GL_CLAMP );
texChunkPtr->setWrapR ( GL_CLAMP );
texChunkPtr->setMinFilter ( GL_LINEAR );
texChunkPtr->setMagFilter ( GL_LINEAR );
//texChunkPtr->setMinFilter ( GL_NEAREST );
//texChunkPtr->setMagFilter ( GL_NEAREST );
}
endEditCP (texChunkPtr);
beginEditCP (blendChunkPtr);
{
blendChunkPtr->setSrcFactor ( GL_SRC_ALPHA );
blendChunkPtr->setDestFactor ( GL_ONE_MINUS_SRC_ALPHA );
}
endEditCP (blendChunkPtr);
beginEditCP (texMatPtr);
{
texMatPtr->addChunk(texChunkPtr);
texMatPtr->addChunk(blendChunkPtr);
}
endEditCP (texMatPtr);
matPtr = texMatPtr;
//numberOfSlices = unsigned((size.x() + size.y() + size.z()) / 3);
numberOfSlices = unsigned(size.length());
size.normalize();
}
else
{
std::cout << "Create SimpleMaterial" << std::endl;
SimpleMaterialPtr colMatPtr = SimpleMaterial::create();
beginEditCP (colMatPtr);
{
colMatPtr->setDiffuse( Color3f( 1,0,0 ) );
colMatPtr->setAmbient( Color3f( 1,0,0 ) );
colMatPtr->setSpecular( Color3f( 1,1,1 ) );
colMatPtr->setShininess( 10 );
}
endEditCP (colMatPtr);
matPtr = colMatPtr;
size.setValues(1,1,1);
numberOfSlices = 10;
}
std::cout << size << std::endl;
std::cout << numberOfSlices << std::endl;
beginEditCP(slicesCore);
{
slicesCore->setMaterial (matPtr);
slicesCore->setSize (size);
slicesCore->setNumberOfSlices (numberOfSlices);
}
endEditCP(slicesCore);
slicesNode->updateVolume();
slicesNode->getVolume().getBounds( min, max );
std::cout << "Volume: from " << min << " to " << max << std::endl;
beginEditCP(dlight);
dlight->addChild( slicesNode );
endEditCP(dlight);
// ...and delete it
beginEditCP(dlight);
dlight->subChild( slicesNode );
endEditCP(dlight);
}
// Camera
cam = PerspectiveCamera::create();
cam->setBeacon( b1n );
cam->setFov( deg2rad( 45 ) );
cam->setNear( 0.1 );
cam->setFar( 10000 );
// Background
SolidBackgroundPtr bkgnd = SolidBackground::create();
// Viewport
vp = Viewport::create();
vp->setCamera( cam );
vp->setBackground( bkgnd );
vp->setRoot( root );
vp->setSize( 0,0, 1,1 );
// Window
std::cout << "GLUT winid: " << winid << std::endl;
GLUTWindowPtr gwin;
GLint glvp[4];
glGetIntegerv( GL_VIEWPORT, glvp );
glCullFace (GL_BACK);
gwin = GLUTWindow::create();
gwin->setId(winid);
gwin->setSize( glvp[2], glvp[3] );
win = gwin;
win->addPort( vp );
win->init();
// Action
ract = DrawAction::create();
// tball
// navigation speed
Vec3f dim(max - min);
std::cout << "dim: " << dim.length() << std::endl;
navigator.set( Pnt3f ( dim.length() * 2, 0, 0),
Pnt3f ( 0,0,0),
Vec3f ( 0,1,0) );
navigator.setMotionFactor ( dim.length() * 0.1 );
navigator.setMode(Navigator::TRACKBALL);
navigator.setViewport(vp);
// run...
glutMainLoop();
return 0;
}