forked from bartvdbraak/blender
239 lines
6.6 KiB
C++
239 lines
6.6 KiB
C++
/*
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
*
|
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
* All rights reserved.
|
|
*
|
|
* The Original Code is: all of this file.
|
|
*
|
|
* Contributor(s): none yet.
|
|
*
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
*/
|
|
|
|
#include "RAS_StorageVBO.h"
|
|
#include "RAS_MeshObject.h"
|
|
|
|
#include "GL/glew.h"
|
|
|
|
VBO::VBO(RAS_DisplayArray *data, unsigned int indices)
|
|
{
|
|
this->data = data;
|
|
this->size = data->m_vertex.size();
|
|
this->indices = indices;
|
|
this->stride = sizeof(RAS_TexVert);
|
|
|
|
// Determine drawmode
|
|
if (data->m_type == data->QUAD)
|
|
this->mode = GL_QUADS;
|
|
else if (data->m_type == data->TRIANGLE)
|
|
this->mode = GL_TRIANGLES;
|
|
else
|
|
this->mode = GL_LINE;
|
|
|
|
// Generate Buffers
|
|
glGenBuffersARB(1, &this->ibo);
|
|
glGenBuffersARB(1, &this->vbo_id);
|
|
|
|
// Fill the buffers with initial data
|
|
UpdateIndices();
|
|
UpdateData();
|
|
|
|
// Establish offsets
|
|
this->vertex_offset = (void*)(((RAS_TexVert*)0)->getXYZ());
|
|
this->normal_offset = (void*)(((RAS_TexVert*)0)->getNormal());
|
|
this->tangent_offset = (void*)(((RAS_TexVert*)0)->getTangent());
|
|
this->color_offset = (void*)(((RAS_TexVert*)0)->getRGBA());;
|
|
this->uv_offset = (void*)(((RAS_TexVert*)0)->getUV(0));
|
|
}
|
|
|
|
VBO::~VBO()
|
|
{
|
|
glDeleteBuffersARB(1, &this->ibo);
|
|
glDeleteBuffersARB(1, &this->vbo_id);
|
|
}
|
|
|
|
void VBO::UpdateData()
|
|
{
|
|
glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vbo_id);
|
|
glBufferData(GL_ARRAY_BUFFER, this->stride*this->size, &this->data->m_vertex[0], GL_STATIC_DRAW);
|
|
}
|
|
|
|
void VBO::UpdateIndices()
|
|
{
|
|
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, this->ibo);
|
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, data->m_index.size() * sizeof(GLushort),
|
|
&data->m_index[0], GL_STATIC_DRAW);
|
|
}
|
|
|
|
void VBO::Draw(int texco_num, RAS_IRasterizer::TexCoGen* texco, int attrib_num, RAS_IRasterizer::TexCoGen* attrib, int *attrib_layer, bool multi)
|
|
{
|
|
int unit;
|
|
|
|
// Bind buffers
|
|
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, this->ibo);
|
|
glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vbo_id);
|
|
|
|
// Vertexes
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
glVertexPointer(3, GL_FLOAT, this->stride, this->vertex_offset);
|
|
|
|
// Normals
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
glNormalPointer(GL_FLOAT, this->stride, this->normal_offset);
|
|
|
|
// Colors
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
|
glColorPointer(4, GL_UNSIGNED_BYTE, this->stride, this->color_offset);
|
|
|
|
if (multi)
|
|
{
|
|
for (unit = 0; unit < texco_num; ++unit)
|
|
{
|
|
glClientActiveTexture(GL_TEXTURE0_ARB + unit);
|
|
switch (texco[unit]) {
|
|
case RAS_IRasterizer::RAS_TEXCO_ORCO:
|
|
case RAS_IRasterizer::RAS_TEXCO_GLOB:
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
glTexCoordPointer(3, GL_FLOAT, this->stride, this->vertex_offset);
|
|
break;
|
|
case RAS_IRasterizer::RAS_TEXCO_UV:
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
glTexCoordPointer(2, GL_FLOAT, this->stride, (void*)((intptr_t)this->uv_offset+(sizeof(GLfloat)*2*unit)));
|
|
break;
|
|
case RAS_IRasterizer::RAS_TEXCO_NORM:
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
glTexCoordPointer(3, GL_FLOAT, this->stride, this->normal_offset);
|
|
break;
|
|
case RAS_IRasterizer::RAS_TEXTANGENT:
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
glTexCoordPointer(4, GL_FLOAT, this->stride, this->tangent_offset);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
glClientActiveTextureARB(GL_TEXTURE0_ARB);
|
|
}
|
|
else //TexFace
|
|
{
|
|
glClientActiveTextureARB(GL_TEXTURE0_ARB);
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
glTexCoordPointer(2, GL_FLOAT, this->stride, this->uv_offset);
|
|
}
|
|
|
|
if (GLEW_ARB_vertex_program)
|
|
{
|
|
for (unit = 0; unit < attrib_num; ++unit)
|
|
{
|
|
switch (attrib[unit]) {
|
|
case RAS_IRasterizer::RAS_TEXCO_ORCO:
|
|
case RAS_IRasterizer::RAS_TEXCO_GLOB:
|
|
glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, this->stride, this->vertex_offset);
|
|
glEnableVertexAttribArrayARB(unit);
|
|
break;
|
|
case RAS_IRasterizer::RAS_TEXCO_UV:
|
|
glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, this->stride, (void*)((intptr_t)this->uv_offset+attrib_layer[unit]*sizeof(GLfloat)*2));
|
|
glEnableVertexAttribArrayARB(unit);
|
|
break;
|
|
case RAS_IRasterizer::RAS_TEXCO_NORM:
|
|
glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, stride, this->normal_offset);
|
|
glEnableVertexAttribArrayARB(unit);
|
|
break;
|
|
case RAS_IRasterizer::RAS_TEXTANGENT:
|
|
glVertexAttribPointerARB(unit, 4, GL_FLOAT, GL_FALSE, this->stride, this->tangent_offset);
|
|
glEnableVertexAttribArrayARB(unit);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
glDrawElements(this->mode, this->indices, GL_UNSIGNED_SHORT, 0);
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
glDisableClientState(GL_NORMAL_ARRAY);
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
if (GLEW_ARB_vertex_program)
|
|
{
|
|
for (int i = 0; i < attrib_num; ++i)
|
|
glDisableVertexAttribArrayARB(i);
|
|
}
|
|
|
|
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
|
|
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
|
|
}
|
|
|
|
RAS_StorageVBO::RAS_StorageVBO(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib, int *attrib_layer):
|
|
m_drawingmode(RAS_IRasterizer::KX_TEXTURED),
|
|
m_texco_num(texco_num),
|
|
m_attrib_num(attrib_num),
|
|
m_texco(texco),
|
|
m_attrib(attrib),
|
|
m_attrib_layer(attrib_layer)
|
|
{
|
|
}
|
|
|
|
RAS_StorageVBO::~RAS_StorageVBO()
|
|
{
|
|
}
|
|
|
|
bool RAS_StorageVBO::Init()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
void RAS_StorageVBO::Exit()
|
|
{
|
|
m_vbo_lookup.clear();
|
|
}
|
|
|
|
void RAS_StorageVBO::IndexPrimitives(RAS_MeshSlot& ms)
|
|
{
|
|
IndexPrimitivesInternal(ms, false);
|
|
}
|
|
|
|
void RAS_StorageVBO::IndexPrimitivesMulti(RAS_MeshSlot& ms)
|
|
{
|
|
IndexPrimitivesInternal(ms, true);
|
|
}
|
|
|
|
void RAS_StorageVBO::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
|
|
{
|
|
RAS_MeshSlot::iterator it;
|
|
VBO *vbo;
|
|
|
|
for (ms.begin(it); !ms.end(it); ms.next(it))
|
|
{
|
|
vbo = m_vbo_lookup[it.array];
|
|
|
|
if (vbo == 0)
|
|
m_vbo_lookup[it.array] = vbo = new VBO(it.array, it.totindex);
|
|
|
|
// Update the vbo
|
|
if (ms.m_mesh->MeshModified())
|
|
{
|
|
vbo->UpdateData();
|
|
}
|
|
|
|
vbo->Draw(*m_texco_num, m_texco, *m_attrib_num, m_attrib, m_attrib_layer, multi);
|
|
}
|
|
}
|