/* This file is part of the graphics core library. Copyright (c) 2004, 2005 John Tsiombikas 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* fundamendal data structures for 3D graphics (inline definitions and templates) * * Author: John Tsiombikas 2004 * Modified: * Mihalis Georgoulopoulos 2004 * John Tsiombikas 2005 */ #include #include #ifdef USING_3DENGFX #include "3dengfx/3denginefx_types.hpp" SysCaps get_system_capabilities(); #endif // USING_3DENGFX #define INVALID_VBO 0 template GeometryArray::GeometryArray(bool dynamic) { data = 0; count = 0; buffer_object = INVALID_VBO; vbo_in_sync = false; set_dynamic(dynamic); } template GeometryArray::GeometryArray(const DataType *data, unsigned long count, bool dynamic) { this->data = 0; this->count = 0; buffer_object = INVALID_VBO; set_dynamic(dynamic); set_data(data, count); } template GeometryArray::GeometryArray(const GeometryArray &ga) { data = 0; count = 0; dynamic = ga.dynamic; buffer_object = INVALID_VBO; set_data(ga.data, ga.count); } template GeometryArray::~GeometryArray() { if(data) delete [] data; #ifdef USING_3DENGFX if(buffer_object != INVALID_VBO) { glext::glDeleteBuffers(1, &buffer_object); } #endif // USING_3DENGFX } template GeometryArray &GeometryArray::operator =(const GeometryArray &ga) { dynamic = ga.dynamic; if(data) delete [] data; set_data(ga.data, ga.count); return *this; } template void GeometryArray::sync_buffer_object() { #ifdef USING_3DENGFX if(dynamic) return; if(buffer_object == INVALID_VBO) { glext::glGenBuffers(1, &buffer_object); glext::glBindBuffer(GL_ARRAY_BUFFER_ARB, buffer_object); glext::glBufferData(GL_ARRAY_BUFFER_ARB, count * sizeof(DataType), data, GL_STATIC_DRAW_ARB); glext::glBindBuffer(GL_ARRAY_BUFFER_ARB, 0); } else { while(glGetError() != GL_NO_ERROR); glext::glBindBuffer(GL_ARRAY_BUFFER_ARB, buffer_object); glext::glBufferData(GL_ARRAY_BUFFER_ARB, count * sizeof(DataType), data, GL_STATIC_DRAW_ARB); glext::glBindBuffer(GL_ARRAY_BUFFER_ARB, 0); } #endif // USING_3DENGFX vbo_in_sync = true; } template inline void GeometryArray::set_data(const DataType *data, unsigned long count) { if(!data) return; if(!this->data || count != this->count) { if(this->data) { delete [] this->data; } this->data = new DataType[count]; } memcpy(this->data, data, count * sizeof(DataType)); this->count = count; #ifdef USING_3DENGFX if(!dynamic) { if(buffer_object != INVALID_VBO && count != this->count) { glext::glDeleteBuffers(1, &buffer_object); } sync_buffer_object(); vbo_in_sync = true; } #endif // USING_3DENGFX } template inline const DataType *GeometryArray::get_data() const { return data; } template inline DataType *GeometryArray::get_mod_data() { vbo_in_sync = false; return data; } template inline unsigned long GeometryArray::get_count() const { return count; } template void GeometryArray::set_dynamic(bool enable) { #ifdef USING_3DENGFX SysCaps sys_caps = get_system_capabilities(); dynamic = enable; if(!dynamic && !sys_caps.vertex_buffers) { dynamic = true; } #else dynamic = false; #endif // USING_3DENGFX } template inline bool GeometryArray::get_dynamic() const { return dynamic; } template inline unsigned int GeometryArray::get_buffer_object() const { if(!dynamic && !vbo_in_sync) { const_cast*>(this)->sync_buffer_object(); } return buffer_object; } // inline functions of specialization of GeometryArray inline const Index *GeometryArray::get_data() const { return data; } inline Index *GeometryArray::get_mod_data() { vbo_in_sync = false; return data; } inline unsigned long GeometryArray::get_count() const { return count; } inline void GeometryArray::set_dynamic(bool enable) { #ifdef USING_3DENGFX SysCaps sys_caps = get_system_capabilities(); dynamic = enable; if(!dynamic && !sys_caps.vertex_buffers) { dynamic = true; } #else dynamic = false; #endif // USING_3DENGFX } inline bool GeometryArray::get_dynamic() const { return dynamic; } inline unsigned int GeometryArray::get_buffer_object() const { if(!dynamic && !vbo_in_sync) { const_cast*>(this)->sync_buffer_object(); } return buffer_object; } ///////// Triangle Mesh Implementation (inline functions) ////////// inline const VertexArray *TriMesh::get_vertex_array() const { return &varray; } inline VertexArray *TriMesh::get_mod_vertex_array() { vertex_stats_valid = false; edges_valid = false; index_graph_valid = false; triangle_normals_valid = triangle_normals_normalized = false; return &varray; } inline const TriangleArray *TriMesh::get_triangle_array() const { return &tarray; } inline TriangleArray *TriMesh::get_mod_triangle_array() { indices_valid = false; edges_valid = false; index_graph_valid = false; triangle_normals_valid = triangle_normals_normalized = false; return &tarray; }