Exemple #1
0
  bool Mesh::load(const char * filename, bool computeTangents)
  {
    CTMcontext context = ctmNewContext(CTM_IMPORT);
    bool result = false;

    ctmLoad(context, filename);
    if (ctmGetError(context) == CTM_NONE)
    {
      result = true;

      const CTMuint triangleCount = ctmGetInteger(context, CTM_TRIANGLE_COUNT);
      const CTMuint vertCount = ctmGetInteger(context, CTM_VERTEX_COUNT);
      const CTMfloat * vertices = ctmGetFloatArray(context, CTM_VERTICES);
      const CTMfloat * normals = ctmGetFloatArray(context, CTM_NORMALS);
      const CTMfloat * texCoord0 = ctmGetFloatArray(context, CTM_UV_MAP_1);
      const CTMuint * indices = ctmGetIntegerArray(context, CTM_INDICES);

      begin();
      add(Mesh::VERTEX, GL_FLOAT, 3, vertices, sizeof(CTMfloat) * vertCount * 3);
      add(Mesh::NORMAL, GL_FLOAT, 3, normals, sizeof(CTMfloat) * vertCount * 3);
      add(Mesh::UV, GL_FLOAT, 3, texCoord0, sizeof(CTMfloat) * vertCount * 2);

      if (computeTangents)
      {

      }

      add(Mesh::INDICIES, 0, 0, indices, sizeof(CTMuint) * triangleCount);
      end(triangleCount);
    }

    ctmFreeContext(context);
    return result;
  }
Exemple #2
0
    void LoadMesh() {
        RenderContext& rc = GlobalRenderContext;

        // Open the CTM file:
        CTMcontext ctmContext = ctmNewContext(CTM_IMPORT);
        ctmLoad(ctmContext, "../demo/HeadlessGiant.ctm");
        // PezCheckCondition(ctmGetError(ctmContext) == CTM_NONE, "OpenCTM Issue");
        CTMuint vertexCount = ctmGetInteger(ctmContext, CTM_VERTEX_COUNT);
        rc.IndexCount = 3 * ctmGetInteger(ctmContext, CTM_TRIANGLE_COUNT);

        GLuint vao;
        glGenVertexArrays(1, &vao);
        glBindVertexArray(vao);

        // Create the VBO for positions:
        const CTMfloat* positions = ctmGetFloatArray(ctmContext, CTM_VERTICES);
        if (positions) {
            GLuint handle;
            GLsizeiptr size = vertexCount * sizeof(float) * 3;
            glGenBuffers(1, &handle);
            glBindBuffer(GL_ARRAY_BUFFER, handle);
            glBufferData(GL_ARRAY_BUFFER, size, positions, GL_STATIC_DRAW);
            glEnableVertexAttribArray(SlotPosition);
            glVertexAttribPointer(SlotPosition, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, 0);
        }

        // Create the VBO for normals:
        const CTMfloat* normals = ctmGetFloatArray(ctmContext, CTM_NORMALS);
        if (normals) {
            GLuint handle;
            GLsizeiptr size = vertexCount * sizeof(float) * 3;
            glGenBuffers(1, &handle);
            glBindBuffer(GL_ARRAY_BUFFER, handle);
            glBufferData(GL_ARRAY_BUFFER, size, normals, GL_STATIC_DRAW);
            glEnableVertexAttribArray(SlotNormal);
            glVertexAttribPointer(SlotNormal, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, 0);
        }

        // Create the VBO for indices:
        const CTMuint* indices = ctmGetIntegerArray(ctmContext, CTM_INDICES);
        if (indices) {
            GLuint handle;
            GLsizeiptr size = rc.IndexCount * sizeof(CTMuint);
            glGenBuffers(1, &handle);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle);
            glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, indices, GL_STATIC_DRAW);
        }

        ctmFreeContext(ctmContext);
    }
Exemple #3
0
Mesh CreateMesh(const char* ctmFile, float totalScale, float lengthScale)
{
    Mesh mesh = {0};
    
    char qualifiedPath[256] = {0};
    strcpy(qualifiedPath, PezResourcePath());
    strcat(qualifiedPath, "/\0");
    strcat(qualifiedPath, ctmFile);
    
    // Open the CTM file:
    CTMcontext ctmContext = ctmNewContext(CTM_IMPORT);
    ctmLoad(ctmContext, qualifiedPath);
    PezCheckCondition(ctmGetError(ctmContext) == CTM_NONE, "OpenCTM issue with loading %s", qualifiedPath);
    CTMuint vertexCount = ctmGetInteger(ctmContext, CTM_VERTEX_COUNT);
    CTMuint faceCount = ctmGetInteger(ctmContext, CTM_TRIANGLE_COUNT);

    // Create the VBO for positions:
    const CTMfloat* positions = ctmGetFloatArray(ctmContext, CTM_VERTICES);
    if (positions) {
    
        // Find bounding box
        float m = 99999.0f;
        Point3 minCorner = P3MakeFromElems(m, m, m);
        Point3 maxCorner = P3MakeFromElems(-m, -m, -m);
        const CTMfloat* pSrc = positions;
        CTMuint remainingVerts = vertexCount;
        while (remainingVerts--)
        {
            float x = *pSrc++;
            float y = *pSrc++;
            float z = *pSrc++;
            Point3 p = P3MakeFromElems(x, y, z);
            minCorner = P3MinPerElem(p, minCorner);
            maxCorner = P3MaxPerElem(p, maxCorner);
        }
		
        // Scale such that the Z extent is 'scale'
        // The X and Y scales are computed according to the aspect ratio.
        // The model is centered at (+0.5, +0.5, +0.5).
        float xratio = (maxCorner.x - minCorner.x) / (maxCorner.z - minCorner.z);
        float yratio = (maxCorner.y - minCorner.y) / (maxCorner.z - minCorner.z);

        float sx = lengthScale * totalScale * xratio / (maxCorner.x - minCorner.x);
        float sy = totalScale * yratio / (maxCorner.y - minCorner.y);
        float sz = totalScale / (maxCorner.z - minCorner.z);
        pSrc = positions;
        remainingVerts = vertexCount;
        CTMfloat* pDest = (CTMfloat*) positions;
        while (remainingVerts--)
        {
            float x = *pSrc++;
            float y = *pSrc++;
            float z = *pSrc++;
            *pDest++ = (x - minCorner.x) * sx - totalScale * xratio / 2;
            *pDest++ = (y - minCorner.y) * sy - totalScale * yratio / 2;
            *pDest++ = (z - minCorner.z) * sz - totalScale / 2;
        }

        GLuint handle;
        GLsizeiptr size = vertexCount * sizeof(float) * 3;
        glGenBuffers(1, &handle);
        glBindBuffer(GL_ARRAY_BUFFER, handle);
        glBufferData(GL_ARRAY_BUFFER, size, positions, GL_STATIC_DRAW);
        mesh.Positions = handle;
    }
    
    // Create the VBO for normals:
    const CTMfloat* normals = ctmGetFloatArray(ctmContext, CTM_NORMALS);
    if (normals) {
        GLuint handle;
        GLsizeiptr size = vertexCount * sizeof(float) * 3;
        glGenBuffers(1, &handle);
        glBindBuffer(GL_ARRAY_BUFFER, handle);
        glBufferData(GL_ARRAY_BUFFER, size, normals, GL_STATIC_DRAW);
        mesh.Normals = handle;
    }
    
    // Create the VBO for indices:
    const CTMuint* indices = ctmGetIntegerArray(ctmContext, CTM_INDICES);
    if (indices) {
        
        GLsizeiptr bufferSize = faceCount * 3 * sizeof(GLuint);
        
        GLuint handle;
        glGenBuffers(1, &handle);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferSize, indices, GL_STATIC_DRAW);
        mesh.Faces = handle;
    }
    
    ctmFreeContext(ctmContext);

    mesh.FaceCount = faceCount;
    mesh.VertexCount = vertexCount;

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    return mesh;
}
Exemple #4
0
Mesh CreateMesh(const char* ctmFile)
{
    Mesh mesh = {0, 0, 0, 0};
    
    char qualifiedPath[256] = {0};
    strcpy(qualifiedPath, PezResourcePath());
    strcat(qualifiedPath, "/\0");
    strcat(qualifiedPath, ctmFile);
    
    // Open the CTM file:
    CTMcontext ctmContext = ctmNewContext(CTM_IMPORT);
    ctmLoad(ctmContext, qualifiedPath);
    PezCheckCondition(ctmGetError(ctmContext) == CTM_NONE, "OpenCTM issue with loading %s", qualifiedPath);
    CTMuint vertexCount = ctmGetInteger(ctmContext, CTM_VERTEX_COUNT);
    CTMuint faceCount = ctmGetInteger(ctmContext, CTM_TRIANGLE_COUNT);
    
    // Create the VBO for positions:
    const CTMfloat* positions = ctmGetFloatArray(ctmContext, CTM_VERTICES);
    if (positions) {
        GLuint handle;
        GLsizeiptr size = vertexCount * sizeof(float) * 3;
        glGenBuffers(1, &handle);
        glBindBuffer(GL_ARRAY_BUFFER, handle);
        glBufferData(GL_ARRAY_BUFFER, size, positions, GL_STATIC_DRAW);
        mesh.Positions = handle;
    }
    
    // Create the VBO for normals:
    const CTMfloat* normals = ctmGetFloatArray(ctmContext, CTM_NORMALS);
    if (normals) {
        GLuint handle;
        GLsizeiptr size = vertexCount * sizeof(float) * 3;
        glGenBuffers(1, &handle);
        glBindBuffer(GL_ARRAY_BUFFER, handle);
        glBufferData(GL_ARRAY_BUFFER, size, normals, GL_STATIC_DRAW);
        mesh.Normals = handle;
    }
    
    // Create the VBO for indices:
    const CTMuint* indices = ctmGetIntegerArray(ctmContext, CTM_INDICES);
    if (indices) {
        
        GLsizeiptr bufferSize = faceCount * 3 * sizeof(unsigned short);
        
        // Convert indices from 32-bit to 16-bit:
        unsigned short* faceBuffer = (unsigned short*) malloc(bufferSize);
        unsigned short* pDest = faceBuffer;
        const CTMuint* pSrc = indices;
        unsigned int remainingFaces = faceCount;
        while (remainingFaces--)
        {
            *pDest++ = (unsigned short) *pSrc++;
            *pDest++ = (unsigned short) *pSrc++;
            *pDest++ = (unsigned short) *pSrc++;
        }
        
        GLuint handle;
        glGenBuffers(1, &handle);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferSize, faceBuffer, GL_STATIC_DRAW);
        mesh.Faces = handle;
        
        free(faceBuffer);
    }
    
    ctmFreeContext(ctmContext);

    mesh.FaceCount = faceCount;

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    return mesh;
}
Exemple #5
0
/* Import OpenCTM file */
int dlImportOCTM( dlObject* object, const char *file, int bAnimated )
{
   FILE *f;
   CTMcontext context;
   CTMuint  vertCount, triCount, uvCount, attribCount;
   const CTMuint *indices;
   const CTMfloat *vertices, *normals, *coords, *attribs;
   CTMenum  error;
   unsigned int i, i2; /* the god of iterators, and his child */
   const char *textureFilename, *comment, *attribName;
   char *texturePath = NULL;

   LOGINFOP("Attempt to load: %s", file);

   /* obiviously we need a import context
    * HEY! Maybe CTM_EXPORT would work!? */
   context = ctmNewContext( CTM_IMPORT );

   /* check if we fail at context creation */
   if(!context)
   {
      LOGERR("I suck at context creation");

      RET("%d", RETURN_FAIL);
      return( RETURN_FAIL );
   }

   /* Yush! Open the file */
   f = fopen( (char*)file, "rb" );
   if(!f)
   {
      LOGERRP("File: %s, could not open", file);

      RET("%d", RETURN_FAIL);
      return( RETURN_FAIL );
   }

   /* I think, i fell love with this API */
   ctmLoadCustom( context, (CTMreadfn)readOCTMFile, f );

   /* What's the magic word to close it? */
   fclose(f);

   /* lets just hope that it does not have any errors */
   if((error = ctmGetError(context)) != CTM_NONE)
   {
      /* Go! Pikachu! Use the printf! */
      LOGERRP("%s", ctmErrorString( error ));
      ctmFreeContext(context);

      RET("%d", RETURN_FAIL);
      return( RETURN_FAIL );
   }

   /* so far all good, lets do this! */
   vertCount   = ctmGetInteger( context, CTM_VERTEX_COUNT );
   vertices    = ctmGetFloatArray( context, CTM_VERTICES );
   triCount    = ctmGetInteger( context, CTM_TRIANGLE_COUNT );
   indices     = ctmGetIntegerArray( context, CTM_INDICES );
   uvCount     = ctmGetInteger( context, CTM_UV_MAP_COUNT );
   attribCount = ctmGetInteger( context, CTM_ATTRIB_MAP_COUNT );

   comment   = ctmGetString( context, CTM_FILE_COMMENT );
   if( comment )
      dlPuts(comment);

   /* ok, we go the info..
    * now.. how to deal with it? */
   dlResetVertexBuffer( object->vbo, vertCount );
   dlResetIndexBuffer( object->ibo, triCount * 3 );

   /* indices */
   i = 0;
   for(; i != triCount * 3; ++i)
      dlInsertIndex( object->ibo,
                     indices[i]  );

   /* vertices */
   i = 0;
   for(; i != vertCount; ++i)
      dlInsertVertex( object->vbo,
                      vertices[ i * 3 ],
                      vertices[ i * 3 + 1 ],
                      vertices[ i * 3 + 2 ]  );

   /* texture coords */
   i = 0;
   while( i != uvCount )
   {
      coords = ctmGetFloatArray( context, CTM_UV_MAP_1 + i );
      dlResetCoordBuffer( object->vbo, i, vertCount );

      /* get texture filename */
      textureFilename = ctmGetUVMapString( context, CTM_UV_MAP_1 + i, CTM_FILE_NAME );
      if(!textureFilename)
         textureFilename = ctmGetUVMapString( context, CTM_UV_MAP_1 + i, CTM_NAME );

      /* check path */
      if(textureFilename)
         texturePath = dlImportTexturePath( textureFilename,
                                            file );

      /* load if exists */
      if(texturePath)
      {
         if(object->material) dlFreeMaterial(object->material);
         object->material = dlNewMaterialFromImage( texturePath, SOIL_FLAG_DEFAULTS );
         free( texturePath );
      }

      i2 = 0;
      for(; i2 != vertCount; ++i2)
      {
         dlInsertCoord( object->vbo, i,
                        coords[ i2 * 2 ],
                        coords[ i2 * 2 + 1 ] );
      }

      ++i;
   }

   /* normals */
   if(ctmGetInteger(context, CTM_HAS_NORMALS) == CTM_TRUE)
   {
       dlResetNormalBuffer( object->vbo, vertCount );
       normals = ctmGetFloatArray( context, CTM_NORMALS );

       i = 0;
       for(; i != vertCount; ++i)
          dlInsertNormal( object->vbo,
                          normals[ i * 3 ],
                          normals[ i * 3 + 1 ],
                          normals[ i * 3 + 2 ]  );
   }

   /* custom attribs, only for vertex colors atm */
   i = 0;
   for(; i != attribCount; ++i)
   {
      attribName = ctmGetAttribMapString( context, CTM_ATTRIB_MAP_1 + i, CTM_NAME );
      attribs     = ctmGetFloatArray( context, CTM_ATTRIB_MAP_1 + i );

      if(attribName)
         LOGINFO(attribName);

#if VERTEX_COLOR
      if( strcmp( attribName, COLOR_ATTRIB ) == 0 )
      {
         dlResetColorBuffer( object->vbo, vertCount );

         i2 = 0;
         for(; i2 != vertCount; ++i2)
            dlInsertColor( object->vbo,
                           attribs[ i2 * 4 ],
                           attribs[ i2 * 4 + 1 ],
                           attribs[ i2 * 4 + 2 ],
                           attribs[ i2 * 4 + 3 ]  );
      }
#endif
   }


   /* this is now GL_TRIANGLES object
    * maybe add tristripper option? */
   object->primitive_type = GL_TRIANGLES;

   /* free the bird */
   ctmFreeContext(context);

   RET("%d", RETURN_OK);
   return( RETURN_OK );
}
int main(int argc, const char *argv[])
{
    if(argc != 3) {
        std::cout << "Usage: #> ./osg_openctm_sqlite inputdb row\n";
        std::cout << "* draw an openctm mesh stored as a row in an sqlite db with osg\n";
        return 0;
    }

    Kompex::SQLiteDatabase *pDatabase = new Kompex::SQLiteDatabase(argv[1],SQLITE_OPEN_READWRITE,0);
    Kompex::SQLiteStatement *pStmt = new Kompex::SQLiteStatement(pDatabase);

    int cRow = 0;
    int rowId = 0;
    int dbRow = 2;
    bool isEmpty = false;

    std::string rowFileKey;
    pStmt->Sql("SELECT rowid,filekey,empty FROM grid_mesh;");
    while(pStmt->FetchRow())   {
        if(cRow == dbRow)   {
            // row file key
            rowId = pStmt->GetColumnInt(0);
            rowFileKey = pStmt->GetColumnString(1);
            isEmpty = pStmt->GetColumnBool(2);
        }
        cRow++;
    }
    pStmt->FreeQuery();
    Kompex::SQLiteBlob *pKompexBlob;

    if(!isEmpty)   {
        // read in ctm blob to memory
        pKompexBlob=new Kompex::SQLiteBlob(pDatabase,"main","grid_mesh","mesh",1);
        size = pKompexBlob->GetBlobSize();
        memblock = new char[size];
        pKompexBlob->ReadBlob(memblock,size);
        delete pKompexBlob;
        std::cout << "# Read in " << rowFileKey << " (" << size << " bytes)\n";

        // uncompress ctm
        CTMcontext context;
        CTMuint    vertCount, triCount;
        CTMuint const* indices;
        CTMfloat   const * vertices;

        context = ctmNewContext(CTM_IMPORT);

        g_pos = 0;
        ctmLoadCustom(context,ctmReadBlob,(void*)memblock);
        if(ctmGetError(context) == CTM_NONE)
        {
            // access the mesh data
            vertCount = ctmGetInteger(context, CTM_VERTEX_COUNT);
            vertices = ctmGetFloatArray(context, CTM_VERTICES);
            triCount = ctmGetInteger(context, CTM_TRIANGLE_COUNT);
            indices = ctmGetIntegerArray(context, CTM_INDICES);

            std::cout << "# Mesh has " << vertCount << " vertices\n";
            std::cout << "# Mesh has " << triCount << " triangles\n";

            // build up openscenegraph geometry
            osg::ref_ptr<osg::Vec3Array> listVxArray = new osg::Vec3Array(vertCount);
            unsigned int vxIdx=0;
            for(int i=0; i < listVxArray->size(); i++)   {
                osg::Vec3 vertex;
                vertex.x() = vertices[vxIdx]; vxIdx++;
                vertex.y() = vertices[vxIdx]; vxIdx++;
                vertex.z() = vertices[vxIdx]; vxIdx++;
                listVxArray->at(i) = vertex;
            }

            osg::ref_ptr<osg::DrawElementsUInt> listIdxs =
                    new osg::DrawElementsUInt(GL_TRIANGLES,triCount*3);
            for(int i=0; i < listIdxs->size(); i++)   {
                listIdxs->at(i) = indices[i];
            }

            osg::ref_ptr<osg::Geometry> geomMesh = new osg::Geometry;
            geomMesh->setVertexArray(listVxArray.get());
            geomMesh->setNormalArray(listVxArray.get());
            geomMesh->addPrimitiveSet(listIdxs.get());

            osg::ref_ptr<osg::Geode> geodeMesh = new osg::Geode;
            geodeMesh->addDrawable(geomMesh.get());

            osg::ref_ptr<osg::Group> groupRoot = new osg::Group;
            groupRoot->addChild(geodeMesh.get());

            // free ctm memory
            ctmFreeContext(context);

            // start viewer
            osgViewer::Viewer viewer;
            viewer.setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
            viewer.setUpViewInWindow(100,100,800,480);
            viewer.setSceneData(groupRoot.get());
            return viewer.run();
        }
        else
        {
            std::cout << "# Fatal error reading in mesh file! Exiting...\n";
            ctmFreeContext(context);
            return 0;
        }



//        // stuff
        delete[] memblock;
//        delete pStmt;
//        delete pDatabase;
        return 0;
    }
    else   {
        std::cout << "# Row " << rowId << " was empty! Exiting...\n";
        delete pStmt;
        delete pDatabase;
        return 0;
    }
}
Exemple #7
0
int main(int argc, char *argv[]) {
    int rc;
    int exit_application = 0;

    //Create a screen context that will be used to create an EGL surface to to receive libscreen events
    screen_create_context(&screen_cxt, 0);

    //Initialize BPS library
    bps_initialize();

    //Use utility code to initialize EGL for rendering with GL ES 2.0
    if (EXIT_SUCCESS != bbutil_init_egl(screen_cxt)) {
        fprintf(stderr, "bbutil_init_egl failed\n");
        bbutil_terminate();
        screen_destroy_context(screen_cxt);
        return 0;
    }

    //Initialize application logic
    osg::setNotifyLevel(osg::DEBUG_INFO);

    // node: interesting geometry
    CTMcontext cContext;
    CTMuint vertCount,triCount;
    CTMuint const * indices;
    CTMfloat const * vertices;
    CTMfloat const * normals;

    cContext = ctmNewContext(CTM_IMPORT);
    ctmLoad(cContext,"app/native/models/cow.ctm");
    if(ctmGetError(cContext) == CTM_NONE)
    {
        // access the mesh data
        vertCount = ctmGetInteger(cContext, CTM_VERTEX_COUNT);
        vertices = ctmGetFloatArray(cContext, CTM_VERTICES);
        triCount = ctmGetInteger(cContext, CTM_TRIANGLE_COUNT);
        indices = ctmGetIntegerArray(cContext, CTM_INDICES);

        std::cout << "# Mesh has " << vertCount << " vertices\n";
        std::cout << "# Mesh has " << triCount << " triangles\n";
    }
    else
    {
        std::cout << "Error Reading CTM File!" << std::endl;
        return -1;
    }

    // build up openscenegraph geometry
    osg::ref_ptr<osg::Vec3Array> listVxArray = new osg::Vec3Array(vertCount);
    unsigned int vxIdx=0;
    for(int i=0; i < listVxArray->size(); i++)   {
        osg::Vec3 vertex;
        vertex.x() = vertices[vxIdx]; vxIdx++;
        vertex.y() = vertices[vxIdx]; vxIdx++;
        vertex.z() = vertices[vxIdx]; vxIdx++;
        listVxArray->at(i) = vertex;
    }

    osg::ref_ptr<osg::DrawElementsUInt> listIdxs =
            new osg::DrawElementsUInt(GL_TRIANGLES,triCount*3);
    for(int i=0; i < listIdxs->size(); i++)   {
        listIdxs->at(i) = indices[i];
    }

    osg::ref_ptr<osg::Geometry> geomMesh = new osg::Geometry;
    geomMesh->setVertexArray(listVxArray.get());
    geomMesh->addPrimitiveSet(listIdxs.get());
    osgUtil::SmoothingVisitor::smooth(*geomMesh);

    osg::ref_ptr<osg::Geode> geodeMesh = new osg::Geode;
    geodeMesh->addDrawable(geomMesh.get());

    osg::ref_ptr<osg::Group> groupRoot = new osg::Group;
    groupRoot->addChild(geodeMesh.get());

    // free ctm memory
    ctmFreeContext(cContext);

    // shader
    osg::StateSet *ss = geodeMesh->getOrCreateStateSet();
    osg::ref_ptr<osg::Program> program = new osg::Program;
    program->setName( "simpleshader" );
    program->addShader( new osg::Shader( osg::Shader::VERTEX, gVertexShader ) );
    program->addShader( new osg::Shader( osg::Shader::FRAGMENT, gFragmentShader ) );
    ss->setAttributeAndModes(program, osg::StateAttribute::ON);
//    ss->setMode(GL_DEPTH_TEST,osg::StateAttribute::ON);
//    ss->setAttributeAndModes(new osg::CullFace(osg::CullFace::FRONT), osg::StateAttribute::OFF);
//    ss->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK), osg::StateAttribute::ON);

    // rotate that cube
    osg::ref_ptr<osg::MatrixTransform> nodeSpin = new osg::MatrixTransform;
    nodeSpin->addChild(geodeMesh.get());
    nodeSpin->addUpdateCallback(new osg::AnimationPathCallback(osg::Vec3(0,0,0),
                                                               osg::Y_AXIS,
                                                               osg::inDegrees(45.0f)));
    // node: root
    osg::ref_ptr<osg::Group> nodeRoot = new osg::Group;
    nodeRoot->addChild(nodeSpin.get());

    // center point
    osg::BoundingBox modelBounds = geodeMesh->getBoundingBox();

    // viewer
    osgViewer::Viewer myViewer;
    myViewer.setSceneData(nodeRoot.get());
    myViewer.getCamera()->setViewMatrixAsLookAt(osg::Vec3((modelBounds.xMax()-modelBounds.xMin())*2,
                                                          (modelBounds.yMax()-modelBounds.yMin())*2,
                                                          (modelBounds.zMax()-modelBounds.zMin())*2),
                                                modelBounds.center(),
                                                osg::Vec3(0,1,0));

    // graphics window embedded
    osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> myWindow =
            new osgViewer::GraphicsWindowEmbedded(0,0,1024,600);
    myWindow->getState()->setUseModelViewAndProjectionUniforms(true);
    myWindow->getState()->setUseVertexAttributeAliasing(true);

    // setup viewer
    myViewer.getCamera()->setViewport(new osg::Viewport(0,0,1024,600));
    myViewer.getCamera()->setGraphicsContext(myWindow.get());
    myViewer.setThreadingModel(osgViewer::Viewer::SingleThreaded);

    //Signal BPS library that navigator and screen events will be requested
    if (BPS_SUCCESS != screen_request_events(screen_cxt)) {
        fprintf(stderr, "screen_request_events failed\n");
        bbutil_terminate();
        screen_destroy_context(screen_cxt);
        bps_shutdown();
        return 0;
    }

    if (BPS_SUCCESS != navigator_request_events(0)) {
        fprintf(stderr, "navigator_request_events failed\n");
        bbutil_terminate();
        screen_destroy_context(screen_cxt);
        bps_shutdown();
        return 0;
    }

    //Signal BPS library that navigator orientation is not to be locked
    if (BPS_SUCCESS != navigator_rotation_lock(false)) {
        fprintf(stderr, "navigator_rotation_lock failed\n");
        bbutil_terminate();
        screen_destroy_context(screen_cxt);
        bps_shutdown();
        return 0;
    }

    while (!exit_application) {
        //Request and process all available BPS events
        bps_event_t *event = NULL;

        for(;;) {
            rc = bps_get_event(&event, 0);
            assert(rc == BPS_SUCCESS);

            if (event) {
                int domain = bps_event_get_domain(event);

                if (domain == screen_get_domain()) {
                    handleScreenEvent(event);
                } else if ((domain == navigator_get_domain())
                        && (NAVIGATOR_EXIT == bps_event_get_code(event))) {
                    exit_application = 1;
                }
            } else {
                break;
            }
        }
        myViewer.frame();
        bbutil_swap();
    }

    //Stop requesting events from libscreen
    screen_stop_events(screen_cxt);

    //Shut down BPS library for this process
    bps_shutdown();

    //Use utility code to terminate EGL setup
    bbutil_terminate();

    //Destroy libscreen context
    screen_destroy_context(screen_cxt);
    return 0;
}