added 3dengfx into the repo, probably not the correct version for this
[summerhack] / src / 3dengfx / src / gfx / 3dgeom.inl
1 /*
2 This file is part of the graphics core library.
3
4 Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 /* fundamendal data structures for 3D graphics (inline definitions and templates)
22  *
23  * Author: John Tsiombikas 2004
24  * Modified: 
25  *              Mihalis Georgoulopoulos 2004
26  *              John Tsiombikas 2005
27  */
28
29 #include <iostream>
30 #include <cstring>
31
32 #ifdef USING_3DENGFX
33 #include "3dengfx/3denginefx_types.hpp"
34
35 SysCaps get_system_capabilities();
36 #endif  // USING_3DENGFX
37
38 #define INVALID_VBO             0
39
40 template <class DataType>
41 GeometryArray<DataType>::GeometryArray(bool dynamic) {
42         data = 0;
43         count = 0;
44         buffer_object = INVALID_VBO;
45         vbo_in_sync = false;
46
47         set_dynamic(dynamic);
48 }
49
50 template <class DataType>
51 GeometryArray<DataType>::GeometryArray(const DataType *data, unsigned long count, bool dynamic) {
52         this->data = 0;
53         this->count = 0;
54         buffer_object = INVALID_VBO;
55         set_dynamic(dynamic);
56
57         set_data(data, count);
58 }
59
60 template <class DataType>
61 GeometryArray<DataType>::GeometryArray(const GeometryArray<DataType> &ga) {
62         data = 0;
63         count = 0;
64         dynamic = ga.dynamic;
65         buffer_object = INVALID_VBO;
66
67         set_data(ga.data, ga.count);
68 }
69
70 template <class DataType>
71 GeometryArray<DataType>::~GeometryArray() {
72         if(data) delete [] data;
73 #ifdef USING_3DENGFX
74         if(buffer_object != INVALID_VBO) {
75                 glext::glDeleteBuffers(1, &buffer_object);
76         }
77 #endif  // USING_3DENGFX
78 }
79
80 template <class DataType>
81 GeometryArray<DataType> &GeometryArray<DataType>::operator =(const GeometryArray<DataType> &ga) {
82         dynamic = ga.dynamic;
83         if(data) delete [] data;
84
85         set_data(ga.data, ga.count);
86         
87         return *this;
88 }
89
90 template <class DataType>
91 void GeometryArray<DataType>::sync_buffer_object() {
92 #ifdef USING_3DENGFX
93         if(dynamic) return;
94
95         if(buffer_object == INVALID_VBO) {
96                 glext::glGenBuffers(1, &buffer_object);
97                 glext::glBindBuffer(GL_ARRAY_BUFFER_ARB, buffer_object);
98                 glext::glBufferData(GL_ARRAY_BUFFER_ARB, count * sizeof(DataType), data, GL_STATIC_DRAW_ARB);
99                 glext::glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
100         } else {
101
102                 while(glGetError() != GL_NO_ERROR);
103                 glext::glBindBuffer(GL_ARRAY_BUFFER_ARB, buffer_object);
104
105                 glext::glBufferData(GL_ARRAY_BUFFER_ARB, count * sizeof(DataType), data, GL_STATIC_DRAW_ARB);
106                 glext::glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
107         }
108 #endif  // USING_3DENGFX
109         vbo_in_sync = true;
110 }
111
112
113 template <class DataType>
114 inline void GeometryArray<DataType>::set_data(const DataType *data, unsigned long count) {
115         if(!data) return;
116         if(!this->data || count != this->count) {
117                 if(this->data) {
118                         delete [] this->data;
119                 }
120                 this->data = new DataType[count];
121         }
122         
123         memcpy(this->data, data, count * sizeof(DataType));
124         this->count = count;
125
126 #ifdef USING_3DENGFX
127         if(!dynamic) {
128                 if(buffer_object != INVALID_VBO && count != this->count) {
129                         glext::glDeleteBuffers(1, &buffer_object);
130                 }
131                 sync_buffer_object();
132                 vbo_in_sync = true;
133         }
134 #endif  // USING_3DENGFX
135 }
136
137 template <class DataType>
138 inline const DataType *GeometryArray<DataType>::get_data() const {
139         return data;
140 }
141
142 template <class DataType>
143 inline DataType *GeometryArray<DataType>::get_mod_data() {
144         vbo_in_sync = false;
145         return data;
146 }
147
148 template <class DataType>
149 inline unsigned long GeometryArray<DataType>::get_count() const {
150         return count;
151 }
152
153 template <class DataType>
154 void GeometryArray<DataType>::set_dynamic(bool enable) {
155 #ifdef USING_3DENGFX
156         SysCaps sys_caps = get_system_capabilities();
157         dynamic = enable;
158
159         if(!dynamic && !sys_caps.vertex_buffers) {
160                 dynamic = true;
161         }
162 #else
163         dynamic = false;
164 #endif  // USING_3DENGFX
165 }
166
167 template <class DataType>
168 inline bool GeometryArray<DataType>::get_dynamic() const {
169         return dynamic;
170 }
171
172 template <class DataType>
173 inline unsigned int GeometryArray<DataType>::get_buffer_object() const {
174         if(!dynamic && !vbo_in_sync) {
175                 const_cast<GeometryArray<DataType>*>(this)->sync_buffer_object();
176         }
177                 
178         return buffer_object;
179 }
180
181 // inline functions of <index> specialization of GeometryArray
182
183 inline const Index *GeometryArray<Index>::get_data() const {
184         return data;
185 }
186
187 inline Index *GeometryArray<Index>::get_mod_data() {
188         vbo_in_sync = false;
189         return data;
190 }
191
192 inline unsigned long GeometryArray<Index>::get_count() const {
193         return count;
194 }
195
196 inline void GeometryArray<Index>::set_dynamic(bool enable) {
197 #ifdef USING_3DENGFX
198         SysCaps sys_caps = get_system_capabilities();
199         dynamic = enable;
200
201         if(!dynamic && !sys_caps.vertex_buffers) {
202                 dynamic = true;
203         }
204 #else
205         dynamic = false;
206 #endif  // USING_3DENGFX
207 }
208
209 inline bool GeometryArray<Index>::get_dynamic() const {
210         return dynamic;
211 }
212
213 inline unsigned int GeometryArray<Index>::get_buffer_object() const {
214         if(!dynamic && !vbo_in_sync) {
215                 const_cast<GeometryArray<Index>*>(this)->sync_buffer_object();
216         }
217
218         return buffer_object;
219 }
220
221
222 ///////// Triangle Mesh Implementation (inline functions) //////////
223 inline const VertexArray *TriMesh::get_vertex_array() const {
224         return &varray;
225 }
226
227 inline VertexArray *TriMesh::get_mod_vertex_array() {
228         vertex_stats_valid = false;
229         edges_valid = false;
230         index_graph_valid = false;
231         triangle_normals_valid = triangle_normals_normalized = false;
232         return &varray;
233 }
234
235 inline const TriangleArray *TriMesh::get_triangle_array() const {
236         return &tarray;
237 }
238
239 inline TriangleArray *TriMesh::get_mod_triangle_array() {
240         indices_valid = false;
241         edges_valid = false;
242         index_graph_valid = false;
243         triangle_normals_valid = triangle_normals_normalized = false;
244         return &tarray;
245 }