246 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			246 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								#include "VertexBufferImpl.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <Kore/Graphics3/Graphics.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "ShaderImpl.h"
							 | 
						||
| 
								 | 
							
								#include "ogl.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <assert.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								using namespace Kore;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Graphics3::VertexBuffer *VertexBufferImpl::current = nullptr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								VertexBufferImpl::VertexBufferImpl(int count, int instanceDataStepRate) : myCount(count), instanceDataStepRate(instanceDataStepRate) {
							 | 
						||
| 
								 | 
							
								#ifndef NDEBUG
							 | 
						||
| 
								 | 
							
									initialized = false;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Graphics3::VertexBuffer::VertexBuffer(int vertexCount, const Graphics4::VertexStructure &structure, Usage usage, int instanceDataStepRate)
							 | 
						||
| 
								 | 
							
								    : VertexBufferImpl(vertexCount, instanceDataStepRate) {
							 | 
						||
| 
								 | 
							
									myStride = 0;
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < structure.size; ++i) {
							 | 
						||
| 
								 | 
							
										Graphics4::VertexElement element = structure.elements[i];
							 | 
						||
| 
								 | 
							
										switch (element.data) {
							 | 
						||
| 
								 | 
							
										case Graphics4::ColorVertexData:
							 | 
						||
| 
								 | 
							
											myStride += 1 * 4;
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case Graphics4::Float1VertexData:
							 | 
						||
| 
								 | 
							
											myStride += 1 * 4;
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case Graphics4::Float2VertexData:
							 | 
						||
| 
								 | 
							
											myStride += 2 * 4;
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case Graphics4::Float3VertexData:
							 | 
						||
| 
								 | 
							
											myStride += 3 * 4;
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case Graphics4::Float4VertexData:
							 | 
						||
| 
								 | 
							
											myStride += 4 * 4;
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case Graphics4::Float4x4VertexData:
							 | 
						||
| 
								 | 
							
											myStride += 4 * 4 * 4;
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									this->structure = structure;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									glGenBuffers(1, &bufferId);
							 | 
						||
| 
								 | 
							
									glCheckErrors();
							 | 
						||
| 
								 | 
							
									data = new float[vertexCount * myStride / 4];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Graphics3::VertexBuffer::~VertexBuffer() {
							 | 
						||
| 
								 | 
							
									unset();
							 | 
						||
| 
								 | 
							
									delete[] data;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								float *Graphics3::VertexBuffer::lock() {
							 | 
						||
| 
								 | 
							
									return data;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								// TODO: FIXME!
							 | 
						||
| 
								 | 
							
								float* VertexBuffer::lock(int start, int count) {
							 | 
						||
| 
								 | 
							
								    myCount = count;
							 | 
						||
| 
								 | 
							
								    return nullptr;//&buffer[start * 9];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Graphics3::VertexBuffer::unlock() {
							 | 
						||
| 
								 | 
							
									glBindBuffer(GL_ARRAY_BUFFER, bufferId);
							 | 
						||
| 
								 | 
							
									glCheckErrors();
							 | 
						||
| 
								 | 
							
									glBufferData(GL_ARRAY_BUFFER, myStride * myCount, data, GL_STATIC_DRAW);
							 | 
						||
| 
								 | 
							
									glCheckErrors();
							 | 
						||
| 
								 | 
							
								#ifndef NDEBUG
							 | 
						||
| 
								 | 
							
									initialized = true;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int Graphics3::VertexBuffer::_set(int offset) {
							 | 
						||
| 
								 | 
							
									assert(initialized); // Vertex Buffer is used before lock/unlock was called
							 | 
						||
| 
								 | 
							
									int offsetoffset = setVertexAttributes(offset);
							 | 
						||
| 
								 | 
							
									if (IndexBuffer::current != nullptr)
							 | 
						||
| 
								 | 
							
										IndexBuffer::current->_set();
							 | 
						||
| 
								 | 
							
									return offsetoffset;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void VertexBufferImpl::unset() {
							 | 
						||
| 
								 | 
							
									if ((void *)current == (void *)this)
							 | 
						||
| 
								 | 
							
										current = nullptr;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int Graphics3::VertexBuffer::count() {
							 | 
						||
| 
								 | 
							
									return myCount;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int Graphics3::VertexBuffer::stride() {
							 | 
						||
| 
								 | 
							
									return myStride;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int VertexBufferImpl::setVertexAttributes(int offset) {
							 | 
						||
| 
								 | 
							
									glBindBuffer(GL_ARRAY_BUFFER, bufferId);
							 | 
						||
| 
								 | 
							
									glCheckErrors();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Enable vertex attributes
							 | 
						||
| 
								 | 
							
									unsigned int usedAttribsMask = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int internaloffset = 0;
							 | 
						||
| 
								 | 
							
									int actualIndex = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for (int index = 0; index < structure.size; ++index) {
							 | 
						||
| 
								 | 
							
										Graphics4::VertexElement element = structure.elements[index];
							 | 
						||
| 
								 | 
							
										int size = 0;
							 | 
						||
| 
								 | 
							
										GLenum type = GL_FLOAT;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										switch (element.data) {
							 | 
						||
| 
								 | 
							
										case Graphics4::ColorVertexData:
							 | 
						||
| 
								 | 
							
											size = 4;
							 | 
						||
| 
								 | 
							
											type = GL_UNSIGNED_BYTE;
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case Graphics4::Float1VertexData:
							 | 
						||
| 
								 | 
							
											size = 1;
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case Graphics4::Float2VertexData:
							 | 
						||
| 
								 | 
							
											size = 2;
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case Graphics4::Float3VertexData:
							 | 
						||
| 
								 | 
							
											size = 3;
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case Graphics4::Float4VertexData:
							 | 
						||
| 
								 | 
							
											size = 4;
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case Graphics4::Float4x4VertexData:
							 | 
						||
| 
								 | 
							
											size = 16;
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										switch (element.attribute) {
							 | 
						||
| 
								 | 
							
										case Graphics4::VertexCoord:
							 | 
						||
| 
								 | 
							
											assert(size >= 2 && size <= 4);
							 | 
						||
| 
								 | 
							
											glEnableClientState(GL_VERTEX_ARRAY);
							 | 
						||
| 
								 | 
							
											glVertexPointer(size, type, myStride, reinterpret_cast<const void *>(internaloffset));
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										case Graphics4::VertexNormal:
							 | 
						||
| 
								 | 
							
											assert(size == 3);
							 | 
						||
| 
								 | 
							
											glEnableClientState(GL_NORMAL_ARRAY);
							 | 
						||
| 
								 | 
							
											glNormalPointer(type, myStride, reinterpret_cast<const void *>(internaloffset));
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										case Graphics4::VertexColor0:
							 | 
						||
| 
								 | 
							
											assert(size >= 3 && size <= 4);
							 | 
						||
| 
								 | 
							
											glEnableClientState(GL_COLOR_ARRAY);
							 | 
						||
| 
								 | 
							
											glColorPointer(size, type, myStride, reinterpret_cast<const void *>(internaloffset));
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										case Graphics4::VertexColor1:
							 | 
						||
| 
								 | 
							
											assert(size == 3);
							 | 
						||
| 
								 | 
							
											glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
							 | 
						||
| 
								 | 
							
											glSecondaryColorPointer(size, type, myStride, reinterpret_cast<const void *>(internaloffset));
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										case Graphics4::VertexTexCoord0:
							 | 
						||
| 
								 | 
							
										case Graphics4::VertexTexCoord1:
							 | 
						||
| 
								 | 
							
										case Graphics4::VertexTexCoord2:
							 | 
						||
| 
								 | 
							
										case Graphics4::VertexTexCoord3:
							 | 
						||
| 
								 | 
							
										case Graphics4::VertexTexCoord4:
							 | 
						||
| 
								 | 
							
										case Graphics4::VertexTexCoord5:
							 | 
						||
| 
								 | 
							
										case Graphics4::VertexTexCoord6:
							 | 
						||
| 
								 | 
							
										case Graphics4::VertexTexCoord7:
							 | 
						||
| 
								 | 
							
											assert(size >= 1 && size <= 4);
							 | 
						||
| 
								 | 
							
											glClientActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(element.attribute - Graphics4::VertexTexCoord0));
							 | 
						||
| 
								 | 
							
											glEnableClientState(GL_TEXTURE_COORD_ARRAY);
							 | 
						||
| 
								 | 
							
											glTexCoordPointer(size, type, myStride, reinterpret_cast<const void *>(internaloffset));
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										default:
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										usedAttribsMask |= (1u << element.attribute);
							 | 
						||
| 
								 | 
							
										++actualIndex;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										switch (element.data) {
							 | 
						||
| 
								 | 
							
										case Graphics4::ColorVertexData:
							 | 
						||
| 
								 | 
							
											internaloffset += 4 * 1;
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case Graphics4::Float1VertexData:
							 | 
						||
| 
								 | 
							
											internaloffset += 4 * 1;
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case Graphics4::Float2VertexData:
							 | 
						||
| 
								 | 
							
											internaloffset += 4 * 2;
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case Graphics4::Float3VertexData:
							 | 
						||
| 
								 | 
							
											internaloffset += 4 * 3;
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case Graphics4::Float4VertexData:
							 | 
						||
| 
								 | 
							
											internaloffset += 4 * 4;
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case Graphics4::Float4x4VertexData:
							 | 
						||
| 
								 | 
							
											internaloffset += 4 * 4 * 4;
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Disable unused vertex attributes
							 | 
						||
| 
								 | 
							
									for (int attrib = Graphics4::VertexCoord; attrib <= Graphics4::VertexTexCoord7; ++attrib) {
							 | 
						||
| 
								 | 
							
										if ((usedAttribsMask & (1u << attrib)) == 0) {
							 | 
						||
| 
								 | 
							
											switch (attrib) {
							 | 
						||
| 
								 | 
							
											case Graphics4::VertexCoord:
							 | 
						||
| 
								 | 
							
												glDisableClientState(GL_VERTEX_ARRAY);
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											case Graphics4::VertexNormal:
							 | 
						||
| 
								 | 
							
												glDisableClientState(GL_NORMAL_ARRAY);
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											case Graphics4::VertexColor0:
							 | 
						||
| 
								 | 
							
												glDisableClientState(GL_COLOR_ARRAY);
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											case Graphics4::VertexColor1:
							 | 
						||
| 
								 | 
							
												glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											case Graphics4::VertexTexCoord0:
							 | 
						||
| 
								 | 
							
											case Graphics4::VertexTexCoord1:
							 | 
						||
| 
								 | 
							
											case Graphics4::VertexTexCoord2:
							 | 
						||
| 
								 | 
							
											case Graphics4::VertexTexCoord3:
							 | 
						||
| 
								 | 
							
											case Graphics4::VertexTexCoord4:
							 | 
						||
| 
								 | 
							
											case Graphics4::VertexTexCoord5:
							 | 
						||
| 
								 | 
							
											case Graphics4::VertexTexCoord6:
							 | 
						||
| 
								 | 
							
											case Graphics4::VertexTexCoord7:
							 | 
						||
| 
								 | 
							
												glClientActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(attrib - Graphics4::VertexTexCoord0));
							 | 
						||
| 
								 | 
							
												glDisableClientState(GL_TEXTURE_COORD_ARRAY);
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											default:
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										glCheckErrors();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return actualIndex;
							 | 
						||
| 
								 | 
							
								}
							 |