1
/************************************************************************************
3
AstroMenace (Hardcore 3D space shooter with spaceship upgrade possibilities)
4
Copyright © 2006-2012 Michael Kurinnoy, Viewizard
7
AstroMenace is free software: you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation, either version 3 of the License, or
10
(at your option) any later version.
12
AstroMenace is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with AstroMenace. If not, see <http://www.gnu.org/licenses/>.
21
Web Site: http://www.viewizard.com/
22
Project: http://sourceforge.net/projects/openastromenace/
23
E-mail: viewizard@viewizard.com
25
*************************************************************************************/
28
#include "RendererInterface.h"
32
extern int tmpPrimCountGL;
33
extern PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTexture_ARB;
34
extern eDevCaps OpenGL_DevCaps;
41
//------------------------------------------------------------------------------------
42
// данный для индекс буфера
43
//------------------------------------------------------------------------------------
44
int VertexIndexCount = 0;
45
GLuint *VertexIndex = 0;
48
//------------------------------------------------------------------------------------
49
// Инициализация данных индекс буфера
50
//------------------------------------------------------------------------------------
51
void vw_Internal_InitializationIndexBufferData()
57
//------------------------------------------------------------------------------------
58
// Чистка памяти данных индекс буфера
59
//------------------------------------------------------------------------------------
60
void vw_Internal_ReleaseIndexBufferData()
62
if (VertexIndex != 0){delete [] VertexIndex; VertexIndex = 0;}
64
if (IndexVBO != 0){vw_DeleteVBO(*IndexVBO); delete IndexVBO; IndexVBO=0;}
71
//------------------------------------------------------------------------------------
72
// устанавливаем указатели, готовимся к прорисовке
73
//------------------------------------------------------------------------------------
74
GLuint *vw_SendVertices_EnableStatesAndPointers(int NumVertices, int DataFormat, void *Data, int Stride, unsigned int *VBO, unsigned int RangeStart, unsigned int *DataIndex, unsigned int *DataIndexVBO)
76
// если ничего не передали
77
if (Data == 0 && VBO == 0) return 0;
79
// флаг нужно ли с вбо делать
80
bool NeedVBO = OpenGL_DevCaps.VBOSupported;
81
if (VBO == 0) NeedVBO = false;
84
// обязательно в байты, т.к. делаем смещение в байтах!
85
BYTE *TMP = (BYTE *)Data;
87
// чтобы знать сколько отступать, кол-во ед. элементов, в нашем случае float
88
intptr_t AddStride = 0;
90
int TextQ = DataFormat & 0x000000F;
93
int TextCoordType = 1; // float
94
switch (DataFormat & 0x0F00000)
96
case 0x0100000: TextSize = 1; break;
97
case 0x0200000: TextSize = 2; break;
98
case 0x0300000: TextSize = 3; break;
99
case 0x0400000: TextSize = 4; break;
101
case 0x0500000: TextSize = 1; TextCoordType = 2; break;
102
case 0x0600000: TextSize = 2; TextCoordType = 2; break;
103
case 0x0700000: TextSize = 3; TextCoordType = 2; break;
104
case 0x0800000: TextSize = 4; TextCoordType = 2; break;
107
if (NeedVBO) vw_BindVBO(RI_ARRAY_BUFFER, *VBO);
110
// делаем установку поинтеров + ставим смещения для прорисовки
111
if ((DataFormat & 0x000F000) == RI_3f_XYZ)
113
glEnableClientState(GL_VERTEX_ARRAY);
115
glVertexPointer(3, GL_FLOAT, Stride, (intptr_t *)(AddStride));
117
glVertexPointer(3, GL_FLOAT, Stride, TMP + AddStride);
118
AddStride += 3*sizeof(GLfloat);
120
if ((DataFormat & 0x000F000) == RI_3i_XYZ)
122
glEnableClientState(GL_VERTEX_ARRAY);
124
glVertexPointer(3, GL_INT, Stride, (BYTE *)(AddStride));
126
glVertexPointer(3, GL_INT, Stride, TMP + AddStride);
127
AddStride += 3*sizeof(GLint);
129
if ((DataFormat & 0x000F000) == RI_3s_XYZ)
131
glEnableClientState(GL_VERTEX_ARRAY);
133
glVertexPointer(3, GL_SHORT, Stride, (BYTE *)(AddStride));
135
glVertexPointer(3, GL_SHORT, Stride, TMP + AddStride);
136
AddStride += 3*sizeof(GLshort);
139
if ((DataFormat & 0x000F000) == RI_2f_XY)
141
glEnableClientState(GL_VERTEX_ARRAY);
143
glVertexPointer(2, GL_FLOAT, Stride, (BYTE *)(AddStride));
145
glVertexPointer(2, GL_FLOAT, Stride, TMP + AddStride);
146
AddStride += 2*sizeof(GLfloat);
148
if ((DataFormat & 0x000F000) == RI_2s_XY)
150
glEnableClientState(GL_VERTEX_ARRAY);
152
glVertexPointer(2, GL_SHORT, Stride, (BYTE *)(AddStride));
154
glVertexPointer(2, GL_SHORT, Stride, TMP + AddStride);
155
AddStride += 2*sizeof(GLshort);
159
if ((DataFormat & 0x0000F00) == RI_3f_NORMAL)
161
glEnableClientState(GL_NORMAL_ARRAY);
163
glNormalPointer(GL_FLOAT, Stride, (BYTE *)(AddStride));
165
glNormalPointer(GL_FLOAT, Stride, TMP + AddStride);
166
AddStride += 3*sizeof(GLfloat);
170
if ((DataFormat & 0x00000F0) == RI_4f_COLOR)
172
glEnableClientState(GL_COLOR_ARRAY);
174
glColorPointer(4, GL_FLOAT, Stride, (BYTE *)(AddStride));
176
glColorPointer(4, GL_FLOAT, Stride, TMP + AddStride);
177
AddStride += 4*sizeof(GLfloat);
179
if ((DataFormat & 0x00000F0) == RI_4ub_COLOR)
181
glEnableClientState(GL_COLOR_ARRAY);
183
glColorPointer(4, GL_UNSIGNED_BYTE, Stride, (BYTE *)(AddStride));
185
glColorPointer(4, GL_UNSIGNED_BYTE, Stride, TMP + AddStride);
186
AddStride += 4*sizeof(GLubyte);
190
if (TextQ > 0)// текстурные коорд. есть...
192
for (int i=0; i<TextQ; i++)
194
if (glClientActiveTexture_ARB != 0) glClientActiveTexture_ARB(GL_TEXTURE0+i);
195
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
197
switch (TextCoordType)
202
glTexCoordPointer(TextSize, GL_FLOAT, Stride, (BYTE *)(AddStride));
204
glTexCoordPointer(TextSize, GL_FLOAT, Stride, TMP + AddStride);
205
if ((DataFormat & 0xF000000) == RI_SEPARATE_TEX_COORD) AddStride += TextSize*sizeof(GLfloat);
211
glTexCoordPointer(TextSize, GL_SHORT, Stride, (BYTE *)(AddStride));
213
glTexCoordPointer(TextSize, GL_SHORT, Stride, TMP + AddStride);
214
if ((DataFormat & 0xF000000) == RI_SEPARATE_TEX_COORD) AddStride += TextSize*sizeof(GLshort);
223
// указатель на смещение (в случае вбо) или на массив индексов
224
GLuint *VertexIndexPointer = 0;
225
// если нет своего, ставим общей массив индексов
226
if (DataIndexVBO == 0 && DataIndex == 0)
228
// собираем если нужно массив индексов
229
if ((unsigned int)VertexIndexCount < (unsigned int)(NumVertices+RangeStart))
231
if (VertexIndex != 0){delete [] VertexIndex; VertexIndex = 0;}
232
VertexIndexCount = 0;
234
VertexIndex = new GLuint[NumVertices+RangeStart]; if (VertexIndex == 0) return 0;
236
VertexIndexCount = NumVertices+RangeStart;
237
for (unsigned int i=0; i<NumVertices+RangeStart; i++) VertexIndex[i] = i;
239
// если держим VBO, все это один раз сразу запихиваем в видео память
240
if (OpenGL_DevCaps.VBOSupported)
242
// прежде всего удаляем старый буфер, если он был
243
if (IndexVBO != 0){vw_DeleteVBO(*IndexVBO); delete IndexVBO; IndexVBO=0;}
245
IndexVBO = new GLuint;
246
if (!vw_BuildIBO(VertexIndexCount, VertexIndex, IndexVBO))
248
delete IndexVBO; IndexVBO=0;
253
VertexIndexPointer = VertexIndex+RangeStart;
255
// собственно включаем индекс-вбо
256
if (OpenGL_DevCaps.VBOSupported)
259
vw_BindVBO(RI_ELEMENT_ARRAY_BUFFER, *IndexVBO);
260
VertexIndexPointer = NULL;
261
VertexIndexPointer = VertexIndexPointer+RangeStart;
265
{ // если массив или вбо индексов передали, просто подключаем их
266
VertexIndexPointer = DataIndex+RangeStart;
268
// собственно включаем индекс-вбо
269
if (OpenGL_DevCaps.VBOSupported)
270
if (DataIndexVBO != 0)
272
vw_BindVBO(RI_ELEMENT_ARRAY_BUFFER, *DataIndexVBO);
273
VertexIndexPointer = NULL;
274
VertexIndexPointer = VertexIndexPointer+RangeStart;
278
// возвращаем индексы основной программе
279
return VertexIndexPointer;
286
//------------------------------------------------------------------------------------
287
// выключаем все после прорисовки
288
//------------------------------------------------------------------------------------
289
void vw_SendVertices_DisableStatesAndPointers(int DataFormat, unsigned int *VBO, unsigned int *VAO)
291
// флаг нужно ли с вaо делать
292
bool NeedVAO = OpenGL_DevCaps.VAOSupported;
293
if (VAO == 0) NeedVAO = false;
301
// флаг нужно ли с вбо делать
302
bool NeedVBO = OpenGL_DevCaps.VBOSupported;
303
if (VBO == 0) NeedVBO = false;
306
if ((DataFormat & 0x0000F00) != 0) glDisableClientState(GL_NORMAL_ARRAY);
307
if ((DataFormat & 0x00000F0) != 0) glDisableClientState(GL_COLOR_ARRAY);
308
glDisableClientState(GL_VERTEX_ARRAY);
311
int TextQ = DataFormat & 0x000000F;
312
for (int i=TextQ-1; i>=0; i--)
314
if (glClientActiveTexture_ARB != 0) glClientActiveTexture_ARB(GL_TEXTURE0+i);
315
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
319
// сбрасываем индексный и вертексный буфера, если они были установлены
320
if (IndexVBO != 0) vw_BindVBO(RI_ELEMENT_ARRAY_BUFFER, 0);
321
if (NeedVBO) vw_BindVBO(RI_ARRAY_BUFFER, 0);
330
//------------------------------------------------------------------------------------
331
// Процедура передачи последовательности вертексов для прорисовки
332
//------------------------------------------------------------------------------------
333
void vw_SendVertices(int PrimitiveType, int NumVertices, int DataFormat, void *Data, int Stride, unsigned int *VBO, unsigned int RangeStart, unsigned int *DataIndex, unsigned int *DataIndexVBO, unsigned int *VAO)
335
// если ничего не передали
336
if (Data == 0 && VBO == 0 && VAO == 0) return;
337
// флаг нужно ли с вбо делать
338
bool NeedVBO = OpenGL_DevCaps.VBOSupported;
339
if (VBO == 0) NeedVBO = false;
340
// флаг нужно ли с вaо делать
341
bool NeedVAO = OpenGL_DevCaps.VAOSupported;
342
if (VAO == 0) NeedVAO = false;
345
// устанавливаем все необходимые указатели для прорисовки и получаем индексы
346
GLuint *VertexIndexPointer = 0;
353
VertexIndexPointer = vw_SendVertices_EnableStatesAndPointers(NumVertices, DataFormat, Data, Stride, VBO, RangeStart, DataIndex, DataIndexVBO);
356
// 1) Нельзя использовать short индексы (глючит в линуксе на картах нвидия, проверял на 97.55 драйвере)
357
// 2) Нельзя рисовать через glBegin-glEnd и glDrawArray - проблемы в линуксе у ati драйверов (на glDrawArray вообще сегфолтит)
358
// 3) С glDrawRangeElements могут быть неприятные сюрпризы на маках (интел+интел видео), сегфолты даже если учесть все ограничения (вертекс и индекс)
362
switch(PrimitiveType)
365
glDrawElements(GL_POINTS,NumVertices,GL_UNSIGNED_INT,VertexIndexPointer);
366
tmpPrimCountGL += NumVertices;
370
glDrawElements(GL_LINES,NumVertices,GL_UNSIGNED_INT,VertexIndexPointer);
371
tmpPrimCountGL += NumVertices/2;
375
glDrawElements(GL_TRIANGLES,NumVertices,GL_UNSIGNED_INT,VertexIndexPointer);
376
tmpPrimCountGL += NumVertices/3;
379
case RI_TRIANGLE_STRIP:
380
glDrawElements(GL_TRIANGLE_STRIP,NumVertices,GL_UNSIGNED_INT,VertexIndexPointer);
381
tmpPrimCountGL += NumVertices-2;
384
case RI_TRIANGLE_FAN:
385
glDrawElements(GL_TRIANGLE_FAN,NumVertices,GL_UNSIGNED_INT,VertexIndexPointer);
386
tmpPrimCountGL += NumVertices-2;
390
glDrawElements(GL_QUADS,NumVertices,GL_UNSIGNED_INT,VertexIndexPointer);
391
tmpPrimCountGL += NumVertices/4;
396
// выключаем все что включали
397
vw_SendVertices_DisableStatesAndPointers(DataFormat, VBO, VAO);