//////////////////////////////////////////////////////////////////////////////// // Scorched3D (c) 2000-2003 // // This file is part of Scorched3D. // // Scorched3D 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 2 of the License, or // (at your option) any later version. // // Scorched3D 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 Scorched3D; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include // ************ NOTE VBO TURNED OFF FOR NOW ************** // GLVertexArray::GLVertexArray(GLenum prim, int noTris, unsigned int type, GLTexture *texture) : prim_(prim), noTris_(noTris), setup_(false), verticesVBO_(0), colorsVBO_(0), textureVBO_(0), texture_(texture), secondTexture_(false), useVBO_(true), listNo_(0) { if (type & typeVertex) { vertices_ = (GLVertexArrayVertex *) malloc(sizeof(GLVertexArrayVertex) * noTris); } else vertices_ = 0; if (type & typeColor) { colors_ = (GLVertexArrayColor *) malloc(sizeof(GLVertexArrayColor) * noTris); } else colors_ = 0; if (type & typeTexture) { texCoord_ = (GLVertexArrayTexCoord*) malloc(sizeof(GLVertexArrayTexCoord) * noTris); } else texCoord_ = 0; } GLVertexArray::~GLVertexArray() { if (colors_) free(colors_); if (vertices_) free(vertices_); if (texCoord_) free(texCoord_); if (verticesVBO_) GLStateExtension::glDeleteBuffersARB()(1, &verticesVBO_); if (colorsVBO_) GLStateExtension::glDeleteBuffersARB()(1, &colorsVBO_); if (textureVBO_) GLStateExtension::glDeleteBuffersARB()(1, &textureVBO_); if (glIsList(listNo_)) glDeleteLists(listNo_, 1); } void GLVertexArray::setVertex(int offset, GLfloat x, GLfloat y, GLfloat z) { DIALOG_ASSERT(vertices_); DIALOG_ASSERT(offset < noTris_); GLVertexArrayVertex newVertex = { x ,y ,z }; vertices_[offset] = newVertex; } void GLVertexArray::setColor(int offset, GLfloat r, GLfloat g, GLfloat b) { DIALOG_ASSERT(colors_); DIALOG_ASSERT(offset < noTris_); GLVertexArrayColor newColor = { r ,g ,b }; colors_[offset] = newColor; } void GLVertexArray::setTexCoord(int offset, GLfloat a, GLfloat b) { DIALOG_ASSERT(texCoord_); DIALOG_ASSERT(offset < noTris_); GLVertexArrayTexCoord newTexCoord = { a, b }; texCoord_[offset] = newTexCoord; } void GLVertexArray::setup() { // ************ NOTE VBO TURNED OFF FOR NOW ************** // useVBO_ = false; if (useVBO_ && GLStateExtension::glGenBuffersARB()) { useVBO_ = true; if (vertices_) { GLStateExtension::glGenBuffersARB()(1, &verticesVBO_); GLStateExtension::glBindBufferARB()(GL_ARRAY_BUFFER_ARB, verticesVBO_); GLStateExtension::glBufferDataARB()(GL_ARRAY_BUFFER_ARB, sizeof(GLVertexArrayVertex) * noTris_, vertices_, GL_STATIC_DRAW_ARB); if (glGetError() == GL_OUT_OF_MEMORY) useVBO_ = false; } if (colors_) { GLStateExtension::glGenBuffersARB()(1, &colorsVBO_); GLStateExtension::glBindBufferARB()(GL_ARRAY_BUFFER_ARB, colorsVBO_); GLStateExtension::glBufferDataARB()(GL_ARRAY_BUFFER_ARB, sizeof(GLVertexArrayColor) * noTris_, colors_, GL_STATIC_DRAW_ARB); if (glGetError() == GL_OUT_OF_MEMORY) useVBO_ = false; } if (texCoord_) { GLStateExtension::glGenBuffersARB()(1, &textureVBO_); GLStateExtension::glBindBufferARB()(GL_ARRAY_BUFFER_ARB, textureVBO_); GLStateExtension::glBufferDataARB()(GL_ARRAY_BUFFER_ARB, sizeof(GLVertexArrayTexCoord) * noTris_, texCoord_, GL_STATIC_DRAW_ARB); if (glGetError() == GL_OUT_OF_MEMORY) useVBO_ = false; } } else { useVBO_ = false; } } int GLVertexArray::getNoTris() { if (prim_ == GL_TRIANGLES) return noTris_ / 3; if (prim_ == GL_TRIANGLE_STRIP) return noTris_ - 2; if (prim_ == GL_QUAD_STRIP) return noTris_ - 2; if (prim_ == GL_QUADS) return noTris_ / 4; DIALOG_ASSERT(0); return 0; } void GLVertexArray::draw() { unsigned int requiredState = 0; if (texCoord_) { requiredState = GLState::TEXTURE_ON; if (texture_ && texture_->getTexFormat() == GL_RGBA) { requiredState |= GLState::BLEND_ON; } } GLState textureState(requiredState); if (texCoord_ && texture_) texture_->draw(); if (listNo_ == 0) { makeList(); } if (listNo_ != 0) { glCallList(listNo_); } GLInfo::addNoTriangles(getNoTris()); } void GLVertexArray::makeList() { if (!setup_) { setup(); setup_ = true; } if (!useVBO_) { if (vertices_) { glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, &vertices_[0].x); } if (colors_) { glEnableClientState(GL_COLOR_ARRAY); glColorPointer(3, GL_FLOAT, 0, &colors_[0].r); } if (texCoord_) { glEnableClientState(GL_TEXTURE_COORD_ARRAY); if (secondTexture_) GLStateExtension::glClientActiveTextureARB()(GL_TEXTURE1_ARB); glTexCoordPointer(2, GL_FLOAT, 0, &texCoord_[0].a); } } else { if (vertices_) { glEnableClientState(GL_VERTEX_ARRAY); GLStateExtension::glBindBufferARB()(GL_ARRAY_BUFFER_ARB, verticesVBO_); glVertexPointer(3, GL_FLOAT, 0, 0); } if (colors_) { glEnableClientState(GL_COLOR_ARRAY); GLStateExtension::glBindBufferARB()(GL_ARRAY_BUFFER_ARB, colorsVBO_); glColorPointer(3, GL_FLOAT, 0, 0); } if (texCoord_) { glEnableClientState(GL_TEXTURE_COORD_ARRAY); if (secondTexture_) GLStateExtension::glClientActiveTextureARB()(GL_TEXTURE1_ARB); GLStateExtension::glBindBufferARB()(GL_ARRAY_BUFFER_ARB, textureVBO_); glTexCoordPointer(2, GL_FLOAT, 0, 0); } } if (!useVBO_) glNewList(listNo_ = glGenLists(1), GL_COMPILE); glDrawArrays(prim_, 0, noTris_); if (!useVBO_) glEndList(); if (vertices_) glDisableClientState(GL_VERTEX_ARRAY); if (colors_) glDisableClientState(GL_COLOR_ARRAY); if (texCoord_) { if (secondTexture_) GLStateExtension::glClientActiveTextureARB()(GL_TEXTURE0_ARB); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } }