/* QGLView Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "glvbo.h" GLVBO::GLVBO(GLenum usage_) { buffer_ = 0; va_ = 0; usage = usage_; changed = true; } GLVBO::~GLVBO() { //destroy(); } void GLVBO::init() { if (!isIinit()) { //glGenVertexArrays(1, &va_); glGenBuffers(1, &buffer_); } changed = true; } void GLVBO::destroy() { deleteGLBuffer(buffer_); //deleteGLVertexArray(va_); } bool GLVBO::rebuffer(bool clear_) { QVector data; //data.clear(); data << vertices_; if (!normals_.isEmpty()) { data << normals_; has_normals = true; } else has_normals = false; if (!texcoords_.isEmpty()) { data << texcoords_; has_texcoords = true; } else has_texcoords = false; if (!colors_.isEmpty()) { data << colors_; has_colors = true; } else has_colors = false; //glBindVertexArray(va_); //qDebug() << "load buffer" << data.size() << buffer_; glBindBuffer(GL_ARRAY_BUFFER, buffer_); glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(GLfloat), data.constData(), usage); glBindBuffer(GL_ARRAY_BUFFER, 0); //glBindVertexArray(0); vert_count = vertices_.size() / 3; changed = false; //qDebug() << "rebuff" << buffer_ << vert_count; if (clear_) clear(); return !isEmpty(); } void GLVBO::draw(GLenum type, QGLShaderProgram * prog, bool simplest) { if (buffer_ == 0 || vert_count == 0) return; if (changed) rebuffer(); //qDebug() << "draw" << vert_count; void * offset = (void*)(vert_count * 3 * sizeof(GLfloat)); //glBindVertexArray(va_); void * offsets[3] = {0, 0, 0}; if (has_normals) { offsets[0] = offset; offset = (void*)(llong(offset) + vert_count * 3 * sizeof(GLfloat)); } if (has_texcoords) { offsets[1] = offset; offset = (void*)(llong(offset) + vert_count * 2 * sizeof(GLfloat)); } if (has_colors) { offsets[2] = offset; } glBindBuffer(GL_ARRAY_BUFFER, buffer_); if (prog) { glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_COLOR_ARRAY); int loc = prog->attributeLocation("_qgl_Vertex"); glEnableVertexAttribArray(loc); glVertexAttribPointer(loc, 3, GL_FLOAT, 0, 0, 0); loc = prog->attributeLocation("qgl_Normal"); if (has_normals) { glEnableVertexAttribArray(loc); glVertexAttribPointer(loc, 3, GL_FLOAT, 0, 0, offsets[0]); } else glDisableVertexAttribArray(loc); loc = prog->attributeLocation("qgl_Texture"); if (has_texcoords) { glEnableVertexAttribArray(loc); glVertexAttribPointer(loc, 2, GL_FLOAT, 0, 0, offsets[1]); } else glDisableVertexAttribArray(loc); loc = prog->attributeLocation("qgl_Color"); if (has_colors) { glEnableVertexAttribArray(loc); glVertexAttribPointer(loc, 4, GL_FLOAT, 0, 0, offsets[2]); } else glDisableVertexAttribArray(loc); } else { glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, 0); if (!simplest) { if (has_normals) { glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_FLOAT, 0, offset); offset = (void*)(llong(offset) + vert_count * 3 * sizeof(GLfloat)); } else glDisableClientState(GL_NORMAL_ARRAY); if (has_texcoords) { glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, offset); offset = (void*)(llong(offset) + vert_count * 2 * sizeof(GLfloat)); } else glDisableClientState(GL_TEXTURE_COORD_ARRAY); if (has_colors) { glEnableClientState(GL_COLOR_ARRAY); glColorPointer(4, GL_FLOAT, 0, offset); } else glDisableClientState(GL_COLOR_ARRAY); } } //qDebug() << "draw" << vert_count << buffer_ << offsets[0] << offsets[1] << offsets[3]; glDrawArrays(type, 0, vert_count); //qDebug() << "draw" << vert_count << buffer_ << "done"; glBindBuffer(GL_ARRAY_BUFFER, 0); } void GLVBO::clear() { vertices_.clear(); normals_.clear(); texcoords_.clear(); colors_.clear(); } bool GLVBO::saveToFile(const QString & filename) { if (filename.isEmpty()) return false; QFile f(filename); QByteArray ba; if (f.open(QFile::WriteOnly)) { QDataStream out(&ba, QFile::WriteOnly); out << vertices_ << normals_ << texcoords_ << colors_; ba = qCompress(ba); f.resize(0); f.write(ba); f.close(); return true; } return false; } bool GLVBO::loadFromFile(const QString & filename) { if (filename.isEmpty()) return false; QFile f(filename); QByteArray ba; if (f.open(QFile::ReadOnly)) { ba = f.readAll(); if (ba.isEmpty()) return false; ba = qUncompress(ba); QDataStream in(ba); in >> vertices_ >> normals_ >> texcoords_ >> colors_; changed = true; f.close(); return !isEmpty(); } return false; }