// react to keys
void keyboard(unsigned char k, int , int )
{
    switch(k)
    {
    case 27:    exit(1);
    case '0':   beginEditCP(particles, Particles::ModeFieldMask);
                particles->setMode(Particles::Points);
                endEditCP  (particles, Particles::ModeFieldMask);
                FLOG(("Particles switched to Points mode\n"));
                break;
    case '1':   beginEditCP(particles, Particles::ModeFieldMask);
                particles->setMode(Particles::Lines);
                endEditCP  (particles, Particles::ModeFieldMask);
                FLOG(("Particles switched to Lines mode\n"));
                break;
    case '2':   beginEditCP(particles, Particles::ModeFieldMask);
                particles->setMode(Particles::ViewDirQuads);
                endEditCP  (particles, Particles::ModeFieldMask);
                FLOG(("Particles switched to ViewDirQuads mode\n"));
                break;
    case '3':   beginEditCP(particles, Particles::ModeFieldMask);
                particles->setMode(Particles::ViewerQuads);
                endEditCP  (particles, Particles::ModeFieldMask);
                FLOG(("Particles switched to ViewerQuads mode\n"));
                break;
    case '4':   beginEditCP(particles, Particles::ModeFieldMask);
                particles->setMode(Particles::Arrows);
                endEditCP  (particles, Particles::ModeFieldMask);
                FLOG(("Particles switched to Arrows mode\n"));
                break;
    case '5':   beginEditCP(particles, Particles::ModeFieldMask);
                particles->setMode(Particles::ViewerArrows);
                endEditCP  (particles, Particles::ModeFieldMask);
                FLOG(("Particles switched to ViewerArrows mode\n"));
                break;
    case '6':   beginEditCP(particles, Particles::ModeFieldMask);
                particles->setMode(Particles::Rectangles);
                endEditCP  (particles, Particles::ModeFieldMask);
                FLOG(("Particles switched to Rectangles mode\n"));
                break;
    case 'q':   beginEditCP(particles, Particles::DrawOrderFieldMask);
                particles->setDrawOrder(Particles::BackToFront);
                endEditCP  (particles, Particles::DrawOrderFieldMask);
                FLOG(("Draw order switched to BackToFront mode\n"));
                break;
    case 'w':   beginEditCP(particles, Particles::DrawOrderFieldMask);
                particles->setDrawOrder(Particles::Any);
                endEditCP  (particles, Particles::DrawOrderFieldMask);
                FLOG(("Draw order switched to Any mode\n"));
                break;
    case 'a':   beginEditCP(particles, Particles::DynamicFieldMask);
                particles->setDynamic(!particles->getDynamic());
                endEditCP  (particles, Particles::DynamicFieldMask);
                FLOG(("Dynamic switched %s\n", particles->getDynamic()?"on":"off"));
                break;
    case ' ':   doMotion=!doMotion;
                FLOG(("Motion %s\n",doMotion?"started":"stopped"));
                break;
    case 'i':   doIndices=!doIndices;
                FLOG(("Indices %s\n",doIndices?"on":"off"));
                indices->resize(0);
                break;
    case 'b':   {
                ParticleBSPTree bsp;
                bsp.build(get_pointer(particles));
                bsp.dump();
                
                // ASCII
                std::string s;
                FieldDataTraits<ParticleBSPTree>::putToString(bsp,s);
                PLOG << s << std::endl;
                const Char8 *c=s.c_str();
                FieldDataTraits<ParticleBSPTree>::getFromString(bsp,c);
                bsp.dump();
                Pnt3f ref(0.5,0.5,0.5);
                UInt32 length = pnts->getSize();
                Int32 *order = bsp.traverse(ref,length);
                for(UInt32 i = 0; i < length; i++)
                {
                    std::cout << order[i] << " ";
                }
                std::cout << std::endl;
                delete [] order;
                
                // Bin
                std::cout << "BIN:" 
                     << FieldDataTraits<ParticleBSPTree>::getBinSize(bsp) 
                     << std::endl;
                
                FILE* wfile=fopen("binfile","w");
                TestHandler w(wfile);               
                FieldDataTraits<ParticleBSPTree>::copyToBin(w,bsp);
                w.flush();
                fclose(wfile);
                
                ParticleBSPTree bsp2;
                FILE *rfile=fopen("binfile","r");
                TestHandler r(rfile);
                FieldDataTraits<ParticleBSPTree>::copyFromBin(r,bsp2);
                fclose(rfile);
                
                bsp.dump();
                }
                break;
   }
}
// move the particles
void idle(void)
{
    if(doMotion)
    {    
        beginEditCP(pnts);
        beginEditCP(secpnts);

        MFPnt3f *p=pnts->editFieldPtr();
        MFPnt3f *sp=secpnts->editFieldPtr();

        for(UInt32 i=0; i<p->size(); ++i)
        {
            Pnt3f pos=(*p)[i];

            pos+=velocities[i];

            if(pos[0]<0 || pos[0]>1)
            {
                pos[0]-=velocities[i][0];
                velocities[i][0]=-velocities[i][0];
            }
            if(pos[1]<0 || pos[1]>1)
            {
                pos[1]-=velocities[i][1];
                velocities[i][1]=-velocities[i][1];
            }
            if(pos[2]<0 || pos[2]>1)
            {
                pos[2]-=velocities[i][2];
                velocities[i][2]=-velocities[i][2];
            }

            (*sp)[i] = pos;
        }

        endEditCP(pnts);
        endEditCP(secpnts);

        beginEditCP(particles,
                    Particles::PositionsFieldMask|Particles::SecPositionsFieldMask);
        particles->setPositions(secpnts);
        particles->setSecPositions(pnts);   
        endEditCP  (particles,
                    Particles::PositionsFieldMask|Particles::SecPositionsFieldMask);

        std::swap(pnts,secpnts);    
    }
    
    if(doIndices)
    {
        beginEditCP(particles, Particles::IndicesFieldMask);
        indices->resize(pnts->getSize() / 2);
        for(UInt32 i = 0; i < pnts->getSize() / 2; ++i)
        {
            (*indices)[i] = static_cast<UInt32>(osgrand() * 2 - 1) * pnts->getSize();
        }
        endEditCP  (particles, Particles::IndicesFieldMask);     
    }
     
    glutPostRedisplay();
}