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; | ||
|  | } |