AbstractChart2D::AbstractChart2D() : mTickCount(9), mTickSize(10), mLeftMargin(64), mRightMargin(10), mTopMargin(10), mBottomMargin(32), mXMax(1), mXMin(0), mYMax(1), mYMin(0), mDecorVBO(0), mBorderProgram(0), mSpriteProgram(0) { /* load font Vera font for chart text * renderings, below function actually returns a constant * reference to font object used by Chart objects, we are * calling it here just to make sure required font glyphs * are loaded into the shared Font object */ getChartFont(); mBorderProgram = initShaders(gChartVertexShaderSrc, gChartFragmentShaderSrc); mSpriteProgram = initShaders(gChartVertexShaderSrc, gChartSpriteFragmentShaderSrc); mBorderPointIndex = glGetAttribLocation (mBorderProgram, "point"); mBorderColorIndex = glGetUniformLocation(mBorderProgram, "color"); mBorderMatIndex = glGetUniformLocation(mBorderProgram, "transform"); mSpriteTickcolorIndex = glGetUniformLocation(mSpriteProgram, "tick_color"); mSpriteMatIndex = glGetUniformLocation(mSpriteProgram, "transform"); mSpriteTickaxisIndex = glGetUniformLocation(mSpriteProgram, "isYAxis"); /* the following function sets the member variable * mTickCount and creates VBO to hold tick marks and the corresponding * text markers for those ticks on the axes */ setTickCount(mTickCount); }
void AbstractChart::renderTickLabels(int pWindowId, unsigned w, unsigned h, std::vector<std::string> &texts, glm::mat4 &transformation, int coor_offset, bool useZoffset) { auto &fonter = getChartFont(); fonter->setOthro2D(int(w), int(h)); float pos[2]; for (StringIter it = texts.begin(); it!=texts.end(); ++it) { int idx = int(it - texts.begin()); glm::vec4 p = glm::vec4(mTickTextX[idx+coor_offset], mTickTextY[idx+coor_offset], (useZoffset ? mTickTextZ[idx+coor_offset] : 0), 1); glm::vec4 res = transformation * p; /* convert text position from [-1,1] range to * [0, 1) range and then offset horizontally * to compensate for margins and ticksize */ pos[0] = w*(res.x/res.w+1.0f)/2.0f; pos[1] = h*(res.y/res.w+1.0f)/2.0f; /* offset based on text size to align * text center with tick mark position */ if(coor_offset < mTickCount) { pos[0] -= ((CHART2D_FONT_SIZE*it->length()/2.0f)); }else if(coor_offset >= mTickCount && coor_offset < 2*mTickCount) { pos[1] -= ((CHART2D_FONT_SIZE)); }else { pos[0] -= ((CHART2D_FONT_SIZE*it->length()/2.0f)); pos[1] -= ((CHART2D_FONT_SIZE)); } fonter->render(pWindowId, pos, WHITE, it->c_str(), CHART2D_FONT_SIZE); } }
AbstractChart::AbstractChart(int pLeftMargin, int pRightMargin, int pTopMargin, int pBottomMargin) : mTickCount(9), mTickSize(10), mLeftMargin(pLeftMargin), mRightMargin(pRightMargin), mTopMargin(pTopMargin), mBottomMargin(pBottomMargin), mXMax(1), mXMin(0), mYMax(1), mYMin(0), mZMax(1), mZMin(0), mXTitle("X-Axis"), mYTitle("Y-Axis"), mZTitle("Z-Axis"), mDecorVBO(-1), mBorderProgram(-1), mSpriteProgram(-1), mBorderAttribPointIndex(-1), mBorderUniformColorIndex(-1), mBorderUniformMatIndex(-1), mSpriteUniformMatIndex(-1), mSpriteUniformTickcolorIndex(-1), mSpriteUniformTickaxisIndex(-1) { CheckGL("Begin AbstractChart::AbstractChart"); /* load font Vera font for chart text * renderings, below function actually returns a constant * reference to font object used by Chart objects, we are * calling it here just to make sure required font glyphs * are loaded into the shared Font object */ getChartFont(); mBorderProgram = initShaders(gChartVertexShaderSrc, gChartFragmentShaderSrc); mSpriteProgram = initShaders(gChartVertexShaderSrc, gChartSpriteFragmentShaderSrc); mBorderAttribPointIndex = glGetAttribLocation (mBorderProgram, "point"); mBorderUniformColorIndex = glGetUniformLocation(mBorderProgram, "color"); mBorderUniformMatIndex = glGetUniformLocation(mBorderProgram, "transform"); mSpriteUniformTickcolorIndex = glGetUniformLocation(mSpriteProgram, "tick_color"); mSpriteUniformMatIndex = glGetUniformLocation(mSpriteProgram, "transform"); mSpriteUniformTickaxisIndex = glGetUniformLocation(mSpriteProgram, "isYAxis"); CheckGL("End AbstractChart::AbstractChart"); }
void AbstractChart2D::renderChart(const void* pWnd, int pX, int pY, int pVPW, int pVPH) { float w = float(pVPW - (mLeftMargin + mRightMargin + mTickSize)); float h = float(pVPH - (mTopMargin + mBottomMargin + mTickSize)); float offset_x = (1.9f * (mLeftMargin+mTickSize) + (w - pVPW)) / pVPW; float offset_y = (1.9f * (mBottomMargin+mTickSize) + (h - pVPH)) / pVPH; float scale_x = w / pVPW; float scale_y = h / pVPH; CheckGL("Begin Chart::render"); bindResources(pWnd); /* bind the plotting shader program */ glUseProgram(mBorderProgram); /* set uniform attributes of shader * for drawing the plot borders */ glm::mat4 trans = glm::scale(glm::translate(glm::mat4(1), glm::vec3(offset_x, offset_y, 0)), glm::vec3(scale_x, scale_y, 1)); glUniformMatrix4fv(mBorderMatIndex, 1, GL_FALSE, glm::value_ptr(trans)); glUniform4fv(mBorderColorIndex, 1, WHITE); /* Draw borders */ glDrawArrays(GL_LINE_LOOP, 0, 4); /* reset shader program binding */ glUseProgram(0); /* bind the sprite shader program to * draw ticks on x and y axes */ glPointSize((GLfloat)mTickSize); glUseProgram(mSpriteProgram); glUniform4fv(mSpriteTickcolorIndex, 1, WHITE); glUniformMatrix4fv(mSpriteMatIndex, 1, GL_FALSE, glm::value_ptr(trans)); /* Draw tick marks on y axis */ glUniform1i(mSpriteTickaxisIndex, 1); glDrawArrays(GL_POINTS, 4, mTickCount); /* Draw tick marks on x axis */ glUniform1i(mSpriteTickaxisIndex, 0); glDrawArrays(GL_POINTS, 4+mTickCount, mTickCount); glUseProgram(0); glPointSize(1); unbindResources(); auto &fonter = getChartFont(); fonter->setOthro2D(int(w), int(h)); float pos[2]; /* render tick marker texts for y axis */ for (StringIter it = mYText.begin(); it!=mYText.end(); ++it) { int idx = int(it - mYText.begin()); glm::vec4 res = trans * glm::vec4(mTickTextX[idx], mTickTextY[idx], 0, 1); /* convert text position from [-1,1] range to * [0, 1) range and then offset horizontally * to compensate for margins and ticksize */ pos[0] = w*(res.x+1.0f)/2.0f; pos[1] = h*(res.y+1.0f)/2.0f; pos[0] -= (pVPW-w)*0.60f; fonter->render(pWnd, pos, WHITE, it->c_str(), CHART2D_FONT_SIZE); } /* render tick marker texts for x axis */ for (StringIter it = mXText.begin(); it!=mXText.end(); ++it) { int idx = int(it - mXText.begin()); /* mTickCount offset is needed while reading point coordinates for * x axis tick marks */ glm::vec4 res = trans * glm::vec4(mTickTextX[idx+mTickCount], mTickTextY[idx+mTickCount], 0, 1); /* convert text position from [-1,1] range to * [0, 1) range and then offset vertically * to compensate for margins and ticksize */ pos[0] = w*(res.x+1.0f)/2.0f; pos[1] = h*(res.y+1.0f)/2.0f; pos[1] -= (pVPH-h)*0.34f; /* offset horizontally based on text size to align * text center with tick mark position */ pos[0] -= (CHART2D_FONT_SIZE*(it->length()-2)/2.0f); fonter->render(pWnd, pos, WHITE, it->c_str(), CHART2D_FONT_SIZE); } /* render chart axes titles */ if (!mYTitle.empty()) { glm::vec4 res = trans * glm::vec4(-1.0f, 0.0f, 0.0f, 1.0f); pos[0] = w*(res.x+1.0f)/2.0f; pos[1] = h*(res.y+1.0f)/2.0f; pos[0] -= (pVPW-w)*0.76; fonter->render(pWnd, pos, WHITE, mYTitle.c_str(), CHART2D_FONT_SIZE, true); } if (!mXTitle.empty()) { glm::vec4 res = trans * glm::vec4(0.0f, -1.0f, 0.0f, 1.0f); pos[0] = w*(res.x+1.0f)/2.0f; pos[1] = h*(res.y+1.0f)/2.0f; pos[1] -= (pVPH-h)*0.66; fonter->render(pWnd, pos, WHITE, mXTitle.c_str(), CHART2D_FONT_SIZE); } CheckGL("End Chart::render"); }
void AbstractChart2D::renderChart(int pX, int pY, int pVPW, int pVPH) const { float w = float(pVPW - (mLeftMargin + mRightMargin + mTickSize)); float h = float(pVPH - (mTopMargin + mBottomMargin + mTickSize)); float offset_x = (2.0f * (mLeftMargin+mTickSize) + (w - pVPW)) / pVPW; float offset_y = (2.0f * (mBottomMargin+mTickSize) + (h - pVPH)) / pVPH; float scale_x = w / pVPW; float scale_y = h / pVPH; CheckGL("Begin Chart::render"); glEnableVertexAttribArray(mBorderPointIndex); glBindBuffer(GL_ARRAY_BUFFER, mDecorVBO); glVertexAttribPointer(mBorderPointIndex, 2, GL_FLOAT, GL_FALSE, 0, 0); /* bind the plotting shader program */ glUseProgram(mBorderProgram); /* set uniform attributes of shader * for drawing the plot borders */ glm::mat4 trans = glm::scale(glm::translate(glm::mat4(1), glm::vec3(offset_x, offset_y, 0)), glm::vec3(scale_x, scale_y, 1)); glUniformMatrix4fv(mBorderMatIndex, 1, GL_FALSE, glm::value_ptr(trans)); glUniform4fv(mBorderColorIndex, 1, WHITE); /* Draw borders */ glDrawArrays(GL_LINE_LOOP, 0, 4); /* reset shader program binding */ glUseProgram(0); /* bind the sprite shader program to * draw ticks on x and y axes */ glPointSize((GLfloat)mTickSize); /* Following line is required for opengl compatibility profile */ glEnable(GL_POINT_SPRITE); glUseProgram(mSpriteProgram); glUniform4fv(mSpriteTickcolorIndex, 1, WHITE); glUniformMatrix4fv(mSpriteMatIndex, 1, GL_FALSE, glm::value_ptr(trans)); /* Draw tick marks on y axis */ glUniform1i(mSpriteTickaxisIndex, 1); glDrawArrays(GL_POINTS, 4, mTickCount); /* Draw tick marks on x axis */ glUniform1i(mSpriteTickaxisIndex, 0); glDrawArrays(GL_POINTS, 4+mTickCount, mTickCount); glUseProgram(0); glPointSize(1); glDisableVertexAttribArray(mBorderPointIndex); glBindBuffer(GL_ARRAY_BUFFER, 0); /* Following line is required for opengl compatibility profile */ glDisable(GL_POINT_SPRITE); auto &fonter = getChartFont(); fonter.setOthro2D(int(w), int(h)); float pos[2]; /* render tick marker texts for y axis */ for (StringIter it = mYText.begin(); it!=mYText.end(); ++it) { int idx = int(it - mYText.begin()); glm::vec4 res = trans * glm::vec4(mTickTextX[idx], mTickTextY[idx], 0, 1); pos[0] = w*(res.x+1.0f)/2.0f; pos[1] = h*(res.y+1.0f)/2.0f; pos[0] -= (pVPW-w)*0.50f; fonter.render(pos, WHITE, it->c_str(), 15); } /* render tick marker texts for x axis */ for (StringIter it = mXText.begin(); it!=mXText.end(); ++it) { int idx = int(it - mXText.begin()); /* mTickCount offset is needed while reading point coordinates for * x axis tick marks */ glm::vec4 res = trans * glm::vec4(mTickTextX[idx+mTickCount], mTickTextY[idx+mTickCount], 0, 1); pos[0] = w*(res.x+1.0f)/2.0f; pos[1] = h*(res.y+1.0f)/2.0f; pos[1] -= (pVPH-h)*0.32f; fonter.render(pos, WHITE, it->c_str(), 15); } /* render chart axes titles */ if (!mYTitle.empty()) { glm::vec4 res = trans * glm::vec4(-1.0f, 0.0f, 0.0f, 1.0f); pos[0] = w*(res.x+1.0f)/2.0f; pos[1] = h*(res.y+1.0f)/2.0f; pos[0] -= (pVPW-w)*0.70f; fonter.render(pos, WHITE, mYTitle.c_str(), 15, true); } if (!mXTitle.empty()) { glm::vec4 res = trans * glm::vec4(0.0f, -1.0f, 0.0f, 1.0f); pos[0] = w*(res.x+1.0f)/2.0f; pos[1] = h*(res.y+1.0f)/2.0f; pos[1] -= (pVPH-h)*0.70f; fonter.render(pos, WHITE, mXTitle.c_str(), 15); } CheckGL("End Chart::render"); }
void Chart3D::renderChart(int pWindowId, int pX, int pY, int pVPW, int pVPH) { CheckGL("Being Chart3D::renderChart"); float w = float(pVPW - (mLeftMargin + mRightMargin + mTickSize)); float h = float(pVPH - (mTopMargin + mBottomMargin + mTickSize)); Chart3D::bindResources(pWindowId); /* bind the plotting shader program */ glUseProgram(mBorderProgram); /* set uniform attributes of shader * for drawing the plot borders */ glm::mat4 model = glm::rotate(glm::mat4(1.0f), -glm::radians(90.f), glm::vec3(0,1,0)) * glm::rotate(glm::mat4(1.0f), -glm::radians(90.f), glm::vec3(1,0,0)) * glm::scale(glm::mat4(1.f), glm::vec3(1.0f, 1.0f, 1.0f)); glm::mat4 view = glm::lookAt(glm::vec3(-1,0.5f,1.0f), glm::vec3(1,-1,-1),glm::vec3(0,1,0)); glm::mat4 projection = glm::ortho(-2.f, 2.f, -2.f, 2.f, -1.1f, 10.f); glm::mat4 mvp = projection * view * model; glm::mat4 trans = mvp; glUniformMatrix4fv(mBorderUniformMatIndex, 1, GL_FALSE, glm::value_ptr(trans)); glUniform4fv(mBorderUniformColorIndex, 1, WHITE); /* Draw borders */ glDrawArrays(GL_LINES, 0, 6); /* reset shader program binding */ glUseProgram(0); /* bind the sprite shader program to * draw ticks on x and y axes */ glEnable(GL_PROGRAM_POINT_SIZE); glPointSize((GLfloat)mTickSize); glUseProgram(mSpriteProgram); glUniform4fv(mSpriteUniformTickcolorIndex, 1, WHITE); glUniformMatrix4fv(mSpriteUniformMatIndex, 1, GL_FALSE, glm::value_ptr(trans)); /* Draw tick marks on z axis */ glUniform1i(mSpriteUniformTickaxisIndex, 1); glDrawArrays(GL_POINTS, 6, mTickCount); /* Draw tick marks on y axis */ glUniform1i(mSpriteUniformTickaxisIndex, 0); glDrawArrays(GL_POINTS, 6 + mTickCount, mTickCount); /* Draw tick marks on x axis */ glUniform1i(mSpriteUniformTickaxisIndex, 0); glDrawArrays(GL_POINTS, 6 + (2*mTickCount), mTickCount); glUseProgram(0); glPointSize(1); glDisable(GL_PROGRAM_POINT_SIZE); Chart3D::unbindResources(); renderTickLabels(pWindowId, w, h, mZText, trans, 0); renderTickLabels(pWindowId, w, h, mYText, trans, mTickCount); renderTickLabels(pWindowId, w, h, mXText, trans, 2*mTickCount); auto &fonter = getChartFont(); fonter->setOthro2D(int(w), int(h)); float pos[2]; /* render chart axes titles */ if (!mZTitle.empty()) { glm::vec4 res = trans * glm::vec4(-1.0f, -1.0f, 0.0f, 1.0f); pos[0] = w*(res.x/res.w+1.0f)/2.0f; pos[1] = h*(res.y/res.w+1.0f)/2.0f; pos[0] -= 6*(mTickSize * (w/pVPW)); pos[1] += mZTitle.length()/2 * CHART2D_FONT_SIZE; fonter->render(pWindowId, pos, WHITE, mZTitle.c_str(), CHART2D_FONT_SIZE, true); } if (!mYTitle.empty()) { glm::vec4 res = trans * glm::vec4(1.0f, 0.0f, -1.0f, 1.0f); pos[0] = w*(res.x/res.w+1.0f)/2.0f; pos[1] = h*(res.y/res.w+1.0f)/2.0f; pos[0] += 0.5 * ((mTickSize * (w/pVPW)) + mYTitle.length()/2 * CHART2D_FONT_SIZE); pos[1] -= 4*(mTickSize * (h/pVPH)); fonter->render(pWindowId, pos, WHITE, mYTitle.c_str(), CHART2D_FONT_SIZE); } if (!mXTitle.empty()) { glm::vec4 res = trans * glm::vec4(0.0f, -1.0f, -1.0f, 1.0f); pos[0] = w*(res.x/res.w+1.0f)/2.0f; pos[1] = h*(res.y/res.w+1.0f)/2.0f; pos[0] -= (mTickSize * (w/pVPW)) + mXTitle.length()/2 * CHART2D_FONT_SIZE; pos[1] -= 4*(mTickSize * (h/pVPH)); fonter->render(pWindowId, pos, WHITE, mXTitle.c_str(), CHART2D_FONT_SIZE); } CheckGL("End Chart3D::renderChart"); }
void Chart2D::renderChart(int pWindowId, int pX, int pY, int pVPW, int pVPH) { CheckGL("Begin Chart2D::renderChart"); float w = float(pVPW - (mLeftMargin + mRightMargin + mTickSize)); float h = float(pVPH - (mTopMargin + mBottomMargin + mTickSize)); float offset_x = (2.0f * (mLeftMargin+mTickSize) + (w - pVPW)) / pVPW; float offset_y = (2.0f * (mBottomMargin+mTickSize) + (h - pVPH)) / pVPH; float scale_x = w / pVPW; float scale_y = h / pVPH; Chart2D::bindResources(pWindowId); /* bind the plotting shader program */ glUseProgram(mBorderProgram); /* set uniform attributes of shader * for drawing the plot borders */ glm::mat4 trans = glm::translate(glm::scale(glm::mat4(1), glm::vec3(scale_x, scale_y, 1)), glm::vec3(offset_x, offset_y, 0)); glUniformMatrix4fv(mBorderUniformMatIndex, 1, GL_FALSE, glm::value_ptr(trans)); glUniform4fv(mBorderUniformColorIndex, 1, WHITE); /* Draw borders */ glDrawArrays(GL_LINE_LOOP, 0, 4); /* reset shader program binding */ glUseProgram(0); /* bind the sprite shader program to * draw ticks on x and y axes */ glPointSize((GLfloat)mTickSize); glUseProgram(mSpriteProgram); glUniform4fv(mSpriteUniformTickcolorIndex, 1, WHITE); glUniformMatrix4fv(mSpriteUniformMatIndex, 1, GL_FALSE, glm::value_ptr(trans)); /* Draw tick marks on y axis */ glUniform1i(mSpriteUniformTickaxisIndex, 1); glDrawArrays(GL_POINTS, 4, mTickCount); /* Draw tick marks on x axis */ glUniform1i(mSpriteUniformTickaxisIndex, 0); glDrawArrays(GL_POINTS, 4+mTickCount, mTickCount); glUseProgram(0); glPointSize(1); Chart2D::unbindResources(); renderTickLabels(pWindowId, int(w), int(h), mYText, trans, 0, false); renderTickLabels(pWindowId, int(w), int(h), mXText, trans, mTickCount, false); auto &fonter = getChartFont(); fonter->setOthro2D(int(w), int(h)); float pos[2]; /* render chart axes titles */ if (!mYTitle.empty()) { glm::vec4 res = trans * glm::vec4(-1.0f, 0.0f, 0.0f, 1.0f); pos[0] = w*(res.x+1.0f)/2.0f; pos[1] = h*(res.y+1.0f)/2.0f; pos[0] += (mTickSize * (w/pVPW)); fonter->render(pWindowId, pos, WHITE, mYTitle.c_str(), CHART2D_FONT_SIZE, true); } if (!mXTitle.empty()) { glm::vec4 res = trans * glm::vec4(0.0f, -1.0f, 0.0f, 1.0f); pos[0] = w*(res.x+1.0f)/2.0f; pos[1] = h*(res.y+1.0f)/2.0f; pos[1] += (mTickSize * (h/pVPH)); fonter->render(pWindowId, pos, WHITE, mXTitle.c_str(), CHART2D_FONT_SIZE); } CheckGL("End Chart2D::renderChart"); }