Ejemplo n.º 1
0
int main()
{
	/* Procedura startowa:
	- Inicjalizacja biblioteki Allegro 5
	- Inicjalizacja dodatków dla Allegro 5
	- Rejestracja zdarzeñ Allegro 5
	- Uruchomienie g³ównej pêtli
	- Zamkniêcie biblioteki Allegro 5
	- Koniec programu
	*/
	ALLEGRO_DISPLAY *display = NULL;
	ALLEGRO_EVENT_QUEUE *event_queue = NULL;
	Init initializer;

	if(!initializer.initAllegro(display, event_queue, resolutionWidth, resolutionHeight))
	{
		return 1; // coœ posz³o nie tak, wychodzimy...
	}
	if(!initializer.initAddons())
	{
		return 1; // coœ posz³o nie tak, wychodzimy...
	}
	initializer.registerEvents(display, event_queue);
	gameLoop();
	initializer.closeAllegro(display, event_queue);

	return 0;
}
Ejemplo n.º 2
0
int main(int argc, char **argv)
{

   Init init;
   Game game(init.getWindow(), init.getGamepad());

   while(state != QUIT)
   {
      if(state == PLAY)
      {
         game.update();
         game.draw();
      }
      else if(state == PAUSE)
      {
         game.update();
      }
      else if(state == GAME_OVER)
      {
         game.update();
      }
      else if(state == RESTART)
      {
         game.restart();
      }
   }

   init.quit();
   return 0;
}
TreePatternNode *Pattern::ParseTreePattern(DagInit *Dag) {
  Record *Operator = Dag->getNodeType();

  if (Operator->isSubClassOf("ValueType")) {
    // If the operator is a ValueType, then this must be "type cast" of a leaf
    // node.
    if (Dag->getNumArgs() != 1)
      error("Type cast only valid for a leaf node!");
    
    Init *Arg = Dag->getArg(0);
    TreePatternNode *New;
    if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) {
      New = new TreePatternNode(DI);
      // If it's a regclass or something else known, set the type.
      New->setType(getIntrinsicType(DI->getDef()));
    } else if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
      New = ParseTreePattern(DI);
    } else {
      Arg->dump();
      error("Unknown leaf value for tree pattern!");
      return 0;
    }

    // Apply the type cast...
    New->updateNodeType(getValueType(Operator), TheRecord->getName());
    return New;
  }

  if (!ISE.getNodeTypes().count(Operator))
    error("Unrecognized node '" + Operator->getName() + "'!");

  std::vector<std::pair<TreePatternNode*, std::string> > Children;
  
  for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {
    Init *Arg = Dag->getArg(i);
    if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
      Children.push_back(std::make_pair(ParseTreePattern(DI),
                                        Dag->getArgName(i)));
    } else if (DefInit *DefI = dynamic_cast<DefInit*>(Arg)) {
      Record *R = DefI->getDef();
      // Direct reference to a leaf DagNode?  Turn it into a DagNode if its own.
      if (R->isSubClassOf("DagNode")) {
        Dag->setArg(i, new DagInit(R,
                                std::vector<std::pair<Init*, std::string> >()));
        --i;  // Revisit this node...
      } else {
        Children.push_back(std::make_pair(new TreePatternNode(DefI),
                                          Dag->getArgName(i)));
        // If it's a regclass or something else known, set the type.
        Children.back().first->setType(getIntrinsicType(R));
      }
    } else {
      Arg->dump();
      error("Unknown leaf value for tree pattern!");
    }
  }

  return new TreePatternNode(Operator, Children);
}
Ejemplo n.º 4
0
Record *MapTableEmitter::getInstrForColumn(Record *KeyInstr,
                                           ListInit *CurValueCol) {
  ListInit *RowFields = InstrMapDesc.getRowFields();
  std::vector<Init*> KeyValue;

  // Construct KeyValue using KeyInstr's values for RowFields.
  for (Init *RowField : RowFields->getValues()) {
    Init *KeyInstrVal = KeyInstr->getValue(RowField)->getValue();
    KeyValue.push_back(KeyInstrVal);
  }

  // Get all the instructions that share the same KeyValue as the KeyInstr
  // in RowInstrMap. We search through these instructions to find a match
  // for the current column, i.e., the instruction which has the same values
  // as CurValueCol for all the fields in ColFields.
  const std::vector<Record*> &RelatedInstrVec = RowInstrMap[KeyValue];

  ListInit *ColFields = InstrMapDesc.getColFields();
  Record *MatchInstr = nullptr;

  for (unsigned i = 0, e = RelatedInstrVec.size(); i < e; i++) {
    bool MatchFound = true;
    Record *CurInstr = RelatedInstrVec[i];
    for (unsigned j = 0, endCF = ColFields->size();
        (j < endCF) && MatchFound; j++) {
      Init *ColFieldJ = ColFields->getElement(j);
      Init *CurInstrInit = CurInstr->getValue(ColFieldJ)->getValue();
      std::string CurInstrVal = CurInstrInit->getAsUnquotedString();
      Init *ColFieldJVallue = CurValueCol->getElement(j);
      MatchFound = (CurInstrVal == ColFieldJVallue->getAsUnquotedString());
    }

    if (MatchFound) {
      if (MatchInstr) {
        // Already had a match
        // Error if multiple matches are found for a column.
        std::string KeyValueStr;
        for (Init *Value : KeyValue) {
          if (!KeyValueStr.empty())
            KeyValueStr += ", ";
          KeyValueStr += Value->getAsString();
        }

        PrintFatalError("Multiple matches found for `" + KeyInstr->getName() +
              "', for the relation `" + InstrMapDesc.getName() + "', row fields [" +
              KeyValueStr + "], column `" + CurValueCol->getAsString() + "'");
      }
      MatchInstr = CurInstr;
    }
  }
  return MatchInstr;
}
Ejemplo n.º 5
0
string dtype(Record* rec)
{
    Init* typeInit = rec->getValueInit("VT");
    if(!typeInit)
        return "";

    string type = typeInit->getAsString();

    if(type == "iPTR")
        return "void*";

    string vec = "";

    if(type[0] == 'v')
    {
        size_t i = 1;
        while(i != type.size() && type[i] <= '9' && type[i] >= '0')
            i++;

        vec = type.substr(1, i - 1);
        type = type.substr(i);
    }

    if(vec.size() > 0 && type.size() > 0)
    {
        int typeSize, vecElements;
        if(
            sscanf(vec.c_str(), "%d", &vecElements) == 1 &&
            sscanf(type.c_str() + 1, "%d", &typeSize) == 1 &&
            typeSize * vecElements > 256)
        {
            return "";
        }
    }

    if(type == "i8")
        return "byte" + vec;
    else if(type == "i16")
        return "short" + vec;
    else if(type == "i32")
        return "int" + vec;
    else if(type == "i64")
        return "long" + vec;
    else if(type == "f32")
        return "float" + vec;
    else if(type == "f64")
        return "double" + vec;
    else
        return "";
}
Ejemplo n.º 6
0
int main(int argc, char *argv[])
{
    	QCoreApplication a(argc, argv);
	Init i;


	switch(int pid = fork()) {
                case -1:
                        std::cout << "Error attempting to fork to background. Exiting" << std::endl;
                        return -1;
                        break;
                case 0:
                        setsid();
                        i.run();
                        break;
                default:
                        std::cout << argv[0] << " Running in background ("<< pid << ")" << std::endl;
                        fclose(stdout);
                        fclose(stdin);
                        fclose(stderr);
                        break;
        }
    	return a.exec();
}
Ejemplo n.º 7
0
json::Value JSONEmitter::translateInit(const Init &I) {

  // Init subclasses that we return as JSON primitive values of one
  // kind or another.

  if (isa<UnsetInit>(&I)) {
    return nullptr;
  } else if (auto *Bit = dyn_cast<BitInit>(&I)) {
    return Bit->getValue() ? 1 : 0;
  } else if (auto *Bits = dyn_cast<BitsInit>(&I)) {
    json::Array array;
    for (unsigned i = 0, limit = Bits->getNumBits(); i < limit; i++)
      array.push_back(translateInit(*Bits->getBit(i)));
    return std::move(array);
  } else if (auto *Int = dyn_cast<IntInit>(&I)) {
    return Int->getValue();
  } else if (auto *Str = dyn_cast<StringInit>(&I)) {
    return Str->getValue();
  } else if (auto *Code = dyn_cast<CodeInit>(&I)) {
    return Code->getValue();
  } else if (auto *List = dyn_cast<ListInit>(&I)) {
    json::Array array;
    for (auto val : *List)
      array.push_back(translateInit(*val));
    return std::move(array);
  }

  // Init subclasses that we return as JSON objects containing a
  // 'kind' discriminator. For these, we also provide the same
  // translation back into TableGen input syntax that -print-records
  // would give.

  json::Object obj;
  obj["printable"] = I.getAsString();

  if (auto *Def = dyn_cast<DefInit>(&I)) {
    obj["kind"] = "def";
    obj["def"] = Def->getDef()->getName();
    return std::move(obj);
  } else if (auto *Var = dyn_cast<VarInit>(&I)) {
    obj["kind"] = "var";
    obj["var"] = Var->getName();
    return std::move(obj);
  } else if (auto *VarBit = dyn_cast<VarBitInit>(&I)) {
    if (auto *Var = dyn_cast<VarInit>(VarBit->getBitVar())) {
      obj["kind"] = "varbit";
      obj["var"] = Var->getName();
      obj["index"] = VarBit->getBitNum();
      return std::move(obj);
    }
  } else if (auto *Dag = dyn_cast<DagInit>(&I)) {
    obj["kind"] = "dag";
    obj["operator"] = translateInit(*Dag->getOperator());
    if (auto name = Dag->getName())
      obj["name"] = name->getAsUnquotedString();
    json::Array args;
    for (unsigned i = 0, limit = Dag->getNumArgs(); i < limit; ++i) {
      json::Array arg;
      arg.push_back(translateInit(*Dag->getArg(i)));
      if (auto argname = Dag->getArgName(i))
        arg.push_back(argname->getAsUnquotedString());
      else
        arg.push_back(nullptr);
      args.push_back(std::move(arg));
    }
    obj["args"] = std::move(args);
    return std::move(obj);
  }

  // Final fallback: anything that gets past here is simply given a
  // kind field of 'complex', and the only other field is the standard
  // 'printable' representation.

  assert(!I.isConcrete());
  obj["kind"] = "complex";
  return std::move(obj);
}
Ejemplo n.º 8
0
/// ParseValue - Parse a tblgen value.  This returns null on error.
///
///   Value       ::= SimpleValue ValueSuffix*
///   ValueSuffix ::= '{' BitList '}'
///   ValueSuffix ::= '[' BitList ']'
///   ValueSuffix ::= '.' ID
///
Init *TGParser::ParseValue(Record *CurRec) {
  Init *Result = ParseSimpleValue(CurRec);
  if (Result == 0) return 0;
  
  // Parse the suffixes now if present.
  while (1) {
    switch (Lex.getCode()) {
    default: return Result;
    case tgtok::l_brace: {
      TGLoc CurlyLoc = Lex.getLoc();
      Lex.Lex(); // eat the '{'
      std::vector<unsigned> Ranges = ParseRangeList();
      if (Ranges.empty()) return 0;
      
      // Reverse the bitlist.
      std::reverse(Ranges.begin(), Ranges.end());
      Result = Result->convertInitializerBitRange(Ranges);
      if (Result == 0) {
        Error(CurlyLoc, "Invalid bit range for value");
        return 0;
      }
      
      // Eat the '}'.
      if (Lex.getCode() != tgtok::r_brace) {
        TokError("expected '}' at end of bit range list");
        return 0;
      }
      Lex.Lex();
      break;
    }
    case tgtok::l_square: {
      TGLoc SquareLoc = Lex.getLoc();
      Lex.Lex(); // eat the '['
      std::vector<unsigned> Ranges = ParseRangeList();
      if (Ranges.empty()) return 0;
      
      Result = Result->convertInitListSlice(Ranges);
      if (Result == 0) {
        Error(SquareLoc, "Invalid range for list slice");
        return 0;
      }
      
      // Eat the ']'.
      if (Lex.getCode() != tgtok::r_square) {
        TokError("expected ']' at end of list slice");
        return 0;
      }
      Lex.Lex();
      break;
    }
    case tgtok::period:
      if (Lex.Lex() != tgtok::Id) {  // eat the .
        TokError("expected field identifier after '.'");
        return 0;
      }
      if (!Result->getFieldType(Lex.getCurStrVal())) {
        TokError("Cannot access field '" + Lex.getCurStrVal() + "' of value '" +
                 Result->getAsString() + "'");
        return 0;
      }
      Result = new FieldInit(Result, Lex.getCurStrVal());
      Lex.Lex();  // eat field name
      break;
    }
  }
}
Ejemplo n.º 9
0
int main(void) {
    srand(time(NULL));

    //Create init object
    Init init = Init();

    //Initialize glfw
    init.glfw(4, 1);
    //Open a window
    GLFWwindow *window = init.window(400, 400);

    //Print window info
    init.printWindowInfo(window);

    //Make opened window current context
    glfwMakeContextCurrent(window);

    init.glew();

    int width, height;
    glfwGetFramebufferSize(window, &width, &height);
    glViewport(0, 0, width, height);

    glEnable(GL_CULL_FACE);


    // Nvidia cards require a vertex array to cooperate.
    GLuint VertexArrayID;
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);

    //Set up the initial state.
    unsigned int w = 32, h = 32, d = 32;
    State *prevState = new State(w, h, d);

    VelocityGrid *velocities = new VelocityGrid(w, h, d);
    prevState->setVelocityGrid(velocities);

    // init level set
    LevelSet *ls = factory::levelSet::ball(w, h, d);
    prevState->setLevelSet(ls);

    delete ls;

    // init simulator
    Simulator sim(*prevState, 0.1f);
    //    BubbleMaxExporter bubbleExporter;
    
    // Dark black background
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    //Load in shaders
    static ShaderProgram colorCubeProg("../vertShader.vert", "../colorCube.frag");
    static ShaderProgram rayCasterProg("../vertShader.vert", "../rayCaster.frag");
    static ShaderProgram bubbleProg("../bubbleVertShader.vert", "../bubbleFragShader.frag");

    static const GLfloat vertexBufferData[] = {
            -1.0f, -1.0f, -1.0f,
            1.0f, -1.0f, -1.0f,
            -1.0f, 1.0f, -1.0f,
            1.0f, 1.0f, -1.0f,
            -1.0f, -1.0f, 1.0f,
            1.0f, -1.0f, 1.0f,
            -1.0f, 1.0f, 1.0f,
            1.0f, 1.0f, 1.0f
    };

    static const GLuint triangleBufferData[] = {
            // xy plane (z = -1)
            0, 1, 3,
            3, 2, 0,
            // xz plane (y = -1)
            0, 5, 1,
            0, 4, 5,
            // yz plane (x = -1)
            0, 2, 4,
            2, 6, 4,
            // xy plane (z = 1)
            4, 7, 5,
            4, 6, 7,
            // xz plane (y = 1)
            2, 7, 6,
            2, 3, 7,
            // yz plane (x = 1)
            1, 5, 3,
            3, 5, 7
    };

    std::vector<GLfloat> g_bubble_buffer_data;

    //Create vertex buffer
    GLuint vertexbuffer;
    glGenBuffers(1, &vertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexBufferData), vertexBufferData, GL_STATIC_DRAW);



    GLuint triangleBuffer;
    glGenBuffers(1, &triangleBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, triangleBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(triangleBufferData), triangleBufferData, GL_STATIC_DRAW);

    // Create bubble buffer
    GLuint bubbleBuffer;
    glGenBuffers(1, &bubbleBuffer);

    // Create framebuffer
    FBO *framebuffer = new FBO(width, height);

    GLuint volumeTextureId;
    glGenTextures(1, &volumeTextureId);
    glBindTexture(GL_TEXTURE_3D, volumeTextureId);

    //Object which encapsulates a texture + The destruction of a texture.
    Texture3D tex3D(w, h, d);
    double lastTime = glfwGetTime();
    int nbFrames = 0;

    float deltaT = 0.1; //First time step

    glfwSwapInterval(1);
    int i = 0;
    do {


        framebuffer->activate();

        // common for both render passes.
        sim.step(deltaT);

        // deltaT = sim.getDeltaT();

        glm::mat4 matrix = glm::mat4(1.0f);
        matrix = glm::translate(matrix, glm::vec3(0.0f, 0.0f, 2.0f));
        matrix = glm::rotate(matrix, -3.1415926535f / 4.0f, glm::vec3(1.0f, 0.0f, 0.0f));
        matrix = glm::rotate(matrix, 0.1415926535f / 4.0f * (float) glfwGetTime(), glm::vec3(0.0f, 1.0f, 0.0f));

        // Render back face of the cube.
        colorCubeProg();
        glCullFace(GL_FRONT);

        {
            GLuint tLocation = glGetUniformLocation(colorCubeProg, "time");
            glUniform1f(tLocation, glfwGetTime());

            GLuint mvLocation = glGetUniformLocation(colorCubeProg, "mvMatrix");
            glUniformMatrix4fv(mvLocation, 1, false, glm::value_ptr(matrix));
        }

        glClear(GL_COLOR_BUFFER_BIT);
        glEnableVertexAttribArray(0);

        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, triangleBuffer);
    //Triangle coordinates
    glVertexAttribPointer(
            0,                  // Location 0
            3,                  // size
            GL_FLOAT,           // type
            GL_FALSE,           // normalized?
            0,                  // stride
            (void *) 0            // array buffer offset
    );

        glDrawElements(GL_TRIANGLES, 12 * 3, GL_UNSIGNED_INT, 0);
        glDisableVertexAttribArray(0);

        // Do the ray casting.
        glBindFramebuffer(GL_FRAMEBUFFER, 0); // bind the screen
        glCullFace(GL_BACK);
        rayCasterProg();

        {
            GLuint tLocation = glGetUniformLocation(rayCasterProg, "time");
            glUniform1f(tLocation, glfwGetTime());

            GLuint mvLocation = glGetUniformLocation(rayCasterProg, "mvMatrix");
            glUniformMatrix4fv(mvLocation, 1, false, glm::value_ptr(matrix));

            GLuint windowSizeLocation = glGetUniformLocation(rayCasterProg, "windowSize");
            glUniform2f(windowSizeLocation, width, height);
        }

        glClear(GL_COLOR_BUFFER_BIT);

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, *(framebuffer->getTexture()));

        GLuint textureLocation = glGetUniformLocation(rayCasterProg, "backfaceTexture");
        glUniform1i(textureLocation, 0);

        State *currentState = sim.getCurrentState();

        std::vector<glm::vec3> vertexList;
        std::vector<std::vector<int> > faceIndices;
        // copy desired quantities to texture
        for (unsigned int k = 0; k < d; ++k) {
            for (unsigned int j = 0; j < h; ++j) {
                for (unsigned int i = 0; i < w; ++i) {

                    // velocity
                    //tex3D.set(i,j,k,0, 0.5 + 0.5*currentState.getVelocityGrid()->u->get(i,j,k));
                    //tex3D.set(i,j,1, 0.5 + 0.5*currentState.getVelocityGrid()->v->get(i,j));
                    //tex3D.set(i,j,2, 0.5 + currentState.getCellTypeGrid()->get(i, j));
                    //tex3D.set(i,j,2, 0.5);
                    //tex3D.set(i,j,3, 1.0f);

                    // divergence
                    //tex3D.set(i,j,0, fabs(sim.getDivergenceGrid()->get(i,j)));
                    //tex3D.set(i,j,1, fabs(sim.getDivergenceGrid()->get(i,j)));
                    //tex3D.set(i,j,2, fabs(sim.getDivergenceGrid()->get(i,j)));
                    //tex3D.set(i,j,3, 1.0f);

                    // type
                    // tex3D.set(i,j,k, 0, currentState.getCellTypeGrid()->get(i,j, k) == CellType::FLUID ? 1.0 : 0.0);
                    // tex3D.set(i,j,k, 1, currentState.getCellTypeGrid()->get(i,j, k) == CellType::FLUID ? 1.0 : 0.0);
                    // tex3D.set(i,j,k, 2, currentState.getCellTypeGrid()->get(i,j, k) == CellType::SOLID ? 1.0 : 0.0);
                    // tex3D.set(i,j,k, 3, 1.0f);

                    if(currentState->getSignedDistanceGrid()->isValid(i+1,j,k) &&
                        currentState->getSignedDistanceGrid()->isValid(i,j+1,k) &&
                        currentState->getSignedDistanceGrid()->isValid(i+1,j+1,k) &&
                        currentState->getSignedDistanceGrid()->isValid(i,j,k+1) &&
                        currentState->getSignedDistanceGrid()->isValid(i+1,j,k+1) &&
                        currentState->getSignedDistanceGrid()->isValid(i,j+1,k+1) &&
                        currentState->getSignedDistanceGrid()->isValid(i+1,j+1,k+1)){

                        marchingCubes::GRIDCELL gridcell;
                        gridcell.p[0] = glm::vec3(i,j,k);
                        gridcell.p[1] = glm::vec3(i,j+1,k);
                        gridcell.p[2] = glm::vec3(i+1,j+1,k);
                        gridcell.p[3] = glm::vec3(i+1,j,k);
                        gridcell.p[4] = glm::vec3(i,j,k+1);
                        gridcell.p[5] = glm::vec3(i,j+1,k+1);
                        gridcell.p[6] = glm::vec3(i+1,j+1,k+1);
                        gridcell.p[7] = glm::vec3(i+1,j,k+1);

                        gridcell.val[0] = currentState->getSignedDistanceGrid()->get(i, j, k);
                        gridcell.val[1] = currentState->getSignedDistanceGrid()->get(i, j+1, k);
                        gridcell.val[2] = currentState->getSignedDistanceGrid()->get(i+1, j+1, k);
                        gridcell.val[3] = currentState->getSignedDistanceGrid()->get(i+1, j, k);
                        gridcell.val[4] = currentState->getSignedDistanceGrid()->get(i, j, k+1);
                        gridcell.val[5] = currentState->getSignedDistanceGrid()->get(i, j+1, k+1);
                        gridcell.val[6] = currentState->getSignedDistanceGrid()->get(i+1, j+1, k+1);
                        gridcell.val[7] = currentState->getSignedDistanceGrid()->get(i+1, j, k+1);

                        //std::cout << gridcell.val[0] << std::endl;

                        marchingCubes::TRIANGLE *triangles = new marchingCubes::TRIANGLE[5];
                        int numTriangles = marchingCubes::PolygoniseCube(gridcell, 0.0, triangles);
                        for(int i = 0; i < numTriangles; i++){
                            int startIndex = vertexList.size()+1;
                            for(int j = 0; j < 3; j++){
                                //std::cout << triangles[i].p[j].x << " " << triangles[i].p[j].y << " " << triangles[i].p[j].z << std::endl;
                            }
                            vertexList.push_back(triangles[i].p[0]);
                            vertexList.push_back(triangles[i].p[1]);
                            vertexList.push_back(triangles[i].p[2]);

                            std::vector<int> indices = {
                                    startIndex,
                                    startIndex+1,
                                    startIndex+2
                            };

                            faceIndices.push_back(indices);
                        }

                        delete[] triangles;
                    }
                    //signed dist
                    float dist = currentState->getSignedDistanceGrid()->get(i, j, k);
                    float solid = currentState->getCellTypeGrid()->get(i, j, k) == CellType::SOLID ? 1.0f : 0.0f;
                    dist = (glm::clamp(dist + solid, -1.0f, 1.0f) + 1) / 2;

                    tex3D.set(i, j, k, 0, solid);
                    tex3D.set(i, j, k, 1, 0.0f); // not used
                    tex3D.set(i, j, k, 2, dist);
                    tex3D.set(i, j, k, 3, 1.0f);
                    //closest point
                    // tex3D.set(i,j,0, currentState.getClosestPointGrid()->get(i,j).x / 70.0);
                    // tex3D.set(i,j,1, currentState.getClosestPointGrid()->get(i,j).y / 70.0);
                    // tex3D.set(i,j,2, 0.0f);
                    // tex3D.set(i,j,3, 1.0f);
                }
            }
        }

        printObjToFile("exported_" + std::to_string(i) + ".obj", vertexList, faceIndices);
        std::ofstream fileStream("exportedState_" + std::to_string(i) + ".pf", std::ios::binary);
        currentState->write(fileStream);
        fileStream.close();


        // activate and upload texture to gpu
        tex3D(GL_TEXTURE1);
        GLuint volumeTextureLocation = glGetUniformLocation(rayCasterProg, "volumeTexture");
        glUniform1i(volumeTextureLocation, 1);

        glEnableVertexAttribArray(0);
        glDrawElements(GL_TRIANGLES, 12 * 3, GL_UNSIGNED_INT, 0);
        glDisableVertexAttribArray(0);

        FBO::deactivate();

        

        ////////////////// Start drawing bubbles //////////////////////
        
        // Draw bubbles
        const std::vector<Bubble> bubbles = currentState->getBubbles();
        g_bubble_buffer_data.clear();
        std::cout << "frame=" << i << ", nBubbles=" << bubbles.size() << std::endl;
        for (int i = 0; i < bubbles.size(); i++) {
          Bubble b = bubbles.at(i);

          //          std::cout << "bubble pos " << b.position.x << ", " << b.position.y << std::endl << b.radius << std::endl;
            
          g_bubble_buffer_data.push_back(b.position.x / (float)w * 2.0 - 1.0);
          g_bubble_buffer_data.push_back(b.position.y / (float)h * 2.0 - 1.0);
          g_bubble_buffer_data.push_back(b.position.z / (float)d * 2.0 - 1.0);
          g_bubble_buffer_data.push_back(b.radius);
        }

           
        glBindBuffer(GL_ARRAY_BUFFER, bubbleBuffer);    
        glBufferData(GL_ARRAY_BUFFER, sizeof(float) * g_bubble_buffer_data.size(), &g_bubble_buffer_data[0], GL_DYNAMIC_DRAW);
        
                
        
        bubbleProg();
        glEnable(GL_PROGRAM_POINT_SIZE);

        {
            GLuint tLocation = glGetUniformLocation(colorCubeProg, "time");
            glUniform1f(tLocation, glfwGetTime());

            GLuint mvLocation = glGetUniformLocation(colorCubeProg, "mvMatrix");
            glUniformMatrix4fv(mvLocation, 1, false, glm::value_ptr(matrix));
        }

        //        glEnable (GL_BLEND);
        //        glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                
        glPointSize(4.0);
        
        if (g_bubble_buffer_data.size() > 0) {
          glEnable(GL_PROGRAM_POINT_SIZE);
          glEnableVertexAttribArray(0);
          glVertexAttribPointer(
                                0,                  //Location 0
                                4,                  // size
                                GL_FLOAT,           // type
                                GL_FALSE,           // normalized?
                                0,                  // stride
                                (void*)0            // array buffer offset
                                );
          
          glDrawArrays(GL_POINTS, 0, 4 * g_bubble_buffer_data.size()); // 3 indices starting at 0 -> 1 triangle
          glDisableVertexAttribArray(0);
        }
        ////////////////// End drawing bubbles //////////////////////
        




        glfwPollEvents();
        glfwSwapBuffers(window);
        double currentTime = glfwGetTime();
        nbFrames++;
        if (currentTime - lastTime >= 1.0) { // If last prinf() was more than 1 sec ago
            // printf and reset timer
            std::string title = std::to_string(1000.0 / double(nbFrames)) + "ms/frame        " + std::to_string(deltaT) + "  dt";
            glfwSetWindowTitle(window, title.c_str());
            nbFrames = 0;
            lastTime += 1.0;
        }
        i++;
        
        //        bubbleExporter.update(i, sim.getBubbleTracker());
        //        bubbleExporter.exportSnapshot(i, "bubbles_" + std::to_string(i) + ".mx");

        /*        if (i > 600) {
          bubbleExporter.exportBubbles("bubbles.mx");
          break;
          }*/
    } // Check if the ESC key was pressed or the window was closed
    while (!glfwWindowShouldClose(window));

    std::cout << "Cleaning up!" << std::endl;
    // Close OpenGL window and terminate GLFW
    glfwDestroyWindow(window);
    glfwTerminate();
    glDeleteBuffers(1, &vertexbuffer);

    glDeleteVertexArrays(1, &VertexArrayID);
    exit(EXIT_SUCCESS);
}