Hi again.
I wrote a little test program to show where my problems are, please have
a look at the code.
There are two threads (t0, the torus, on aspect 0, t1, the box, on
aspect1) in this program.
Things, that I find strange:
* Obviously, there is a difference if I add something to the graph (B)
in the in the main thread or in the newly started (A). Why? Is there a
way to add geometry outside of the main thread for aspect 0 _and_ 1?!
* Oli writes in his tutorial: "Every thread has its own ChangeList" Is
it possible, that this is wrong? If not, how can it be, that the changes
done in t0 (working on aspect 0) are visible, even if I do nothing with
the changelist?
* I haven't tried it with a cluster / server setup, but I fear that
there are differences (B1 vs. B2). Why?
* Is there a way to check which aspect a thread uses from the main
thread? getAspect returns 0 for t0 (ok) and t1 (Bug or fetaure?) in the
app thread.
This is very confusing. Is there a way to simplify / generalize this, so
that it just works for all aspects and setups (GLUT and client /
server)?! A helper function in ThreadManager or similar? Something like
ThreadManager::the()->applyAndMergeToAppAndClearAllOthers(); //Maybe
with a better name ;)
mgr->draw();
Thread::getCurrentChangeList()->clear();
Thanks & regards,
Dominik
#include <OpenSG/OSGGLUT.h>
#include <OpenSG/OSGConfig.h>
#include <OpenSG/OSGSimpleGeometry.h>
#include <OpenSG/OSGGLUTWindow.h>
#include <OpenSG/OSGSimpleSceneManager.h>
#include <OSGThread.h>
#include <OSGBarrier.h>
#include <OSGCoredNodePtr.h>
#include <OSGComponentTransform.h>
#include <iostream>
#include <GL/glut.h>
OSG_USING_NAMESPACE
using namespace std;
SimpleSceneManager *mgr;
int setupGLUT( int *argc, char *argv[] );
Real32 t;
Thread *t0,*t1;
Barrier *barrier0,*barrier1;
CoredNodePtr<Group> scene;
CoredNodePtr<ComponentTransform> transTorus;
CoredNodePtr<ComponentTransform> transBox;
void addTorus();
void addBox();
void funcAspect0(void *no){
//A:
//addTorus();
while(true){
Quaternion q(Vec3f(0,1,0),t/1000.);
beginEditCP(transTorus.core());
transTorus.core()->setRotation(q);
endEditCP(transTorus.core());
barrier0->enter(2);
barrier0->enter(2);
}
}
void funcAspect1(void *no){
//A:
//addBox();
while(true){
Quaternion q(Vec3f(0,1,0),-t/1000.);
beginEditCP(transBox.core());
transBox.core()->setRotation(q);
endEditCP(transBox.core());
barrier1->enter(2);
barrier1->enter(2);
}
}
void applyAndClear(Thread* t){
t->getChangeList()->applyAndClear();
}
void apply(Thread* t){
t->getChangeList()->apply();
}
void clear(Thread* t){
t->getChangeList()->clearAll();
}
void merge(Thread* t){
OSG::Thread::getCurrentChangeList()->merge(*(t->getChangeList()));
}
void mergeAndClear(Thread* t){
merge(t);
clear(t);
}
void display(void){
t = glutGet(GLUT_ELAPSED_TIME );
barrier0->enter(2);barrier1->enter(2);
/*B: addBox/addTorus in main()=appThread*/
//B2: Torus and box rotating
mergeAndClear(t0); // AFAIK this is needed for Cluster/Server setup
applyAndClear(t1);
//B1: Torus and Box rotating
//applyAndClear(t1);
//t0 noop
//B0: torus rotates
//t0 noop
//t1 noop
/*A: addBox/addTorus in thread functions*/
//A10 box visible
//apply(t1);
//merge(t0);
//A9:box visible
//merge(t0);
//apply(t1);
//A8: torus visible
//merge(t0);
//merge(t1);
//A7: box visible
//apply(t1);
//apply(t0);
//A6 box visible
//applyAndClear(t1);
//applyAndClear(t0);
//A5:box visible
//merge(t0);
//applyAndClear(t1);
//A4: box visible
//applyAndClear(t1);//t0 noop
//A3: torus visible
//mergeAndClear(t1);//t0 noop
//A2: torus visible
//applyAndClear(t0);//t1 noop
//A1: torus visible
//mergeAndClear(t0);//t1 noop
//A0: torus visible
//t0 noop t1 noop
mgr->redraw();
barrier0->enter(2);barrier1->enter(2);
Thread::getCurrentChangeList()->clearAll();
}
int main(int argc, char **argv){
ChangeList::setReadWriteDefault();
osgInit(argc,argv);
int winid = setupGLUT(&argc, argv);
GLUTWindowPtr gwin= GLUTWindow::create();
gwin->setId(winid);
gwin->init();
scene = CoredNodePtr<Group>::create();
//B:
addTorus();
addBox();
barrier0=Barrier::create();
barrier1=Barrier::create();
t0=dynamic_cast<Thread*>(ThreadManager::the()->getThread("A0"));
t0->runFunction(&funcAspect0,0,0);
t1=dynamic_cast<Thread*>(ThreadManager::the()->getThread("A1"));
t1->runFunction(&funcAspect1,1,0);
mgr = new SimpleSceneManager;
mgr->setWindow(gwin );
mgr->setRoot (scene.node());
mgr->showAll();
glutMainLoop();
return 0;
}
void addTorus(){
NodePtr torus = makeTorus(.25, 1, 16, 16);
transTorus = CoredNodePtr<ComponentTransform>::create();
beginEditCP(transTorus.node(),Node::ChildrenFieldMask );
transTorus.node()->addChild(torus);
endEditCP (transTorus.node(),Node::ChildrenFieldMask );
beginEditCP(scene.node(),Node::ChildrenFieldMask );
scene.node()->addChild(transTorus.node());
endEditCP (scene.node(),Node::ChildrenFieldMask );
}
void addBox(){
NodePtr box = makeBox(0.5,0.5,0.1,1,1,1);
transBox = CoredNodePtr<ComponentTransform>::create();
beginEditCP(transBox.node(),Node::ChildrenFieldMask );
transBox.node()->addChild(box);
endEditCP (transBox.node(),Node::ChildrenFieldMask );
beginEditCP(scene.node(),Node::ChildrenFieldMask );
scene.node()->addChild(transBox.node());
endEditCP (scene.node(),Node::ChildrenFieldMask );
}
void reshape(int w, int h){
mgr->resize(w, h);
glutPostRedisplay();
}
void mouse(int button, int state, int x, int y){
if (state)mgr->mouseButtonRelease(button, x, y);
else mgr->mouseButtonPress(button, x, y);
glutPostRedisplay();
}
void motion(int x, int y){
mgr->mouseMove(x, y);
glutPostRedisplay();
}
void keyboard(unsigned char k, int x, int y){
switch(k){
case 27:{
OSG::osgExit();
exit(0);
}
break;
}
}
int setupGLUT(int *argc, char *argv[])
{
glutInit(argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
int winid = glutCreateWindow("OpenSG");
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutIdleFunc(display);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutKeyboardFunc(keyboard);
return winid;
}