diff --git a/src/ogl/VBO_Vertex.cxx b/src/ogl/VBO_Vertex.cxx index fe399d1758..66418de488 100644 --- a/src/ogl/VBO_Vertex.cxx +++ b/src/ogl/VBO_Vertex.cxx @@ -23,17 +23,30 @@ GLuint VBO_Vertex::actVerts = 0; GLuint VBO_Vertex::actNorms = 0; GLuint VBO_Vertex::actTxcds = 0; GLuint VBO_Vertex::actColrs = 0; +GLuint VBO_Vertex::actIntrs = 0; GLuint VBO_Vertex::actBounded = 0; VBO_Vertex::VBO_Vertex( bool handleTexture_, bool handleNormal_, - bool handleColor_) : + bool handleColor_, + bool interlaced_) : VBO_Handler(), handleTexture(handleTexture_), handleNormal(handleNormal_), handleColor(handleColor_), verts(0), txcds(0), norms(0), colrs(0), - vbosReady(false) + vbosReady(false), interlaced(interlaced_) { + interlaced = false; + interlacedSize = 3; + strideTexture = interlacedSize; + if (handleTexture) + interlacedSize += 2; + strideNormal = interlacedSize; + if (handleNormal) + interlacedSize += 3; + strideColor = interlacedSize; + if (handleColor) + interlacedSize += 4; } void VBO_Vertex::resize() @@ -51,6 +64,8 @@ void VBO_Vertex::resize() hostedNormals.resize(3 * vboSize); if (!hostedColors.empty()) hostedColors.resize(4 * vboSize); + if (!hostedInterlaced.empty()) + hostedInterlaced.resize(interlacedSize * vboSize); if (!vbosReady) // Don't do anything on GL Context memory if not ready return; @@ -65,6 +80,9 @@ void VBO_Vertex::init() return; // GL Context is ready // Bind all buffers + if (interlaced) + glGenBuffers(1, &intrs); + else { glGenBuffers(1, &verts); if (handleTexture) @@ -76,6 +94,15 @@ void VBO_Vertex::init() } // Copy in memory buffer to GPU + if (interlaced) + { + bindBuffer(intrs); + glBufferData(GL_ARRAY_BUFFER, + vboSize * interlacedSize * sizeof(GLfloat), + hostedInterlaced.data(), + GL_DYNAMIC_DRAW); + } + else { bindBuffer(verts); glBufferData(GL_ARRAY_BUFFER, @@ -115,6 +142,9 @@ void VBO_Vertex::destroy() if (!vboSize) return; // drop all buffers + if (interlaced) + deleteBuffer(intrs); + else { deleteBuffer(verts); if (handleTexture) @@ -140,6 +170,20 @@ std::string VBO_Vertex::vboName() void VBO_Vertex::vertexData(int index, int size, const GLfloat vertices[]) { + if (interlaced) + { + if (hostedInterlaced.empty()) + hostedInterlaced.resize(interlacedSize * vboSize); + auto dataP = &hostedInterlaced[index * interlacedSize]; + auto vertP = vertices; + for (int i = 0; i < size; i++) + { + memcpy(dataP, vertP, sizeof(GLfloat[3])); + dataP += interlacedSize; + vertP += 3; + } + } + else { if (hostedVertices.empty()) hostedVertices.resize(3 * vboSize); @@ -149,6 +193,15 @@ void VBO_Vertex::vertexData(int index, int size, const GLfloat vertices[]) } if (!vbosReady) return; + if (interlaced) + { + bindBuffer(intrs); + glBufferSubData(GL_ARRAY_BUFFER, + index * interlacedSize * sizeof(GLfloat), + size * interlacedSize * sizeof(GLfloat), + &hostedInterlaced[index * interlacedSize]); + } + else { bindBuffer(verts); glBufferSubData(GL_ARRAY_BUFFER, @@ -162,6 +215,21 @@ void VBO_Vertex::textureData(int index, int size, const GLfloat textures[]) { if (!handleTexture) return; + if (interlaced) + { + if (hostedInterlaced.empty()) + hostedInterlaced.resize(interlacedSize * vboSize); + auto dataP = &hostedInterlaced[index * interlacedSize]; + auto textP = textures; + dataP += strideTexture; + for (int i = 0; i < size; i++) + { + memcpy(dataP, textP, sizeof(GLfloat[2])); + dataP += interlacedSize; + textP += 2; + } + } + else { if (hostedTextures.empty()) hostedTextures.resize(2 * vboSize); @@ -171,6 +239,15 @@ void VBO_Vertex::textureData(int index, int size, const GLfloat textures[]) } if (!vbosReady) return; + if (interlaced) + { + bindBuffer(intrs); + glBufferSubData(GL_ARRAY_BUFFER, + index * interlacedSize * sizeof(GLfloat), + size * interlacedSize * sizeof(GLfloat), + &hostedInterlaced[index * interlacedSize]); + } + else { bindBuffer(txcds); glBufferSubData(GL_ARRAY_BUFFER, @@ -184,6 +261,21 @@ void VBO_Vertex::normalData(int index, int size, const GLfloat normals[]) { if (!handleNormal) return; + if (interlaced) + { + if (hostedInterlaced.empty()) + hostedInterlaced.resize(interlacedSize * vboSize); + auto dataP = &hostedInterlaced[index * interlacedSize]; + auto normP = normals; + dataP += strideNormal; + for (int i = 0; i < size; i++) + { + memcpy(dataP, normP, sizeof(GLfloat[3])); + dataP += interlacedSize; + normP += 3; + } + } + else { if (hostedNormals.empty()) hostedNormals.resize(3 * vboSize); @@ -193,6 +285,15 @@ void VBO_Vertex::normalData(int index, int size, const GLfloat normals[]) } if (!vbosReady) return; + if (interlaced) + { + bindBuffer(intrs); + glBufferSubData(GL_ARRAY_BUFFER, + index * interlacedSize * sizeof(GLfloat), + size * interlacedSize * sizeof(GLfloat), + &hostedInterlaced[index * interlacedSize]); + } + else { bindBuffer(norms); glBufferSubData(GL_ARRAY_BUFFER, @@ -206,6 +307,21 @@ void VBO_Vertex::colorData(int index, int size, const GLfloat colors[]) { if (!handleColor) return; + if (interlaced) + { + if (hostedInterlaced.empty()) + hostedInterlaced.resize(interlacedSize * vboSize); + auto dataP = &hostedInterlaced[index * interlacedSize]; + auto coloP = colors; + dataP += strideColor; + for (int i = 0; i < size; i++) + { + memcpy(dataP, coloP, sizeof(GLfloat[4])); + dataP += interlacedSize; + coloP += 4; + } + } + else { if (hostedColors.empty()) hostedColors.resize(4 * vboSize); @@ -215,6 +331,15 @@ void VBO_Vertex::colorData(int index, int size, const GLfloat colors[]) } if (!vbosReady) return; + if (interlaced) + { + bindBuffer(intrs); + glBufferSubData(GL_ARRAY_BUFFER, + index * interlacedSize * sizeof(GLfloat), + size * interlacedSize * sizeof(GLfloat), + &hostedInterlaced[index * interlacedSize]); + } + else { bindBuffer(colrs); glBufferSubData(GL_ARRAY_BUFFER, @@ -256,6 +381,24 @@ void VBO_Vertex::enableVertexOnly() void VBO_Vertex::enableVertex() { + if (interlaced) + { + if (actIntrs == intrs) + return; + actIntrs = intrs; + bindBuffer(intrs); + glVertexPointer(3, GL_FLOAT, interlacedSize * sizeof(GLfloat), 0); + glTexCoordPointer(2, GL_FLOAT, + interlacedSize * sizeof(GLfloat), + (void *)(strideTexture * sizeof(GLfloat))); + glNormalPointer(GL_FLOAT, + interlacedSize * sizeof(GLfloat), + (void *)(strideNormal * sizeof(GLfloat))); + glColorPointer(4, GL_FLOAT, + interlacedSize * sizeof(GLfloat), + (void *)(strideColor * sizeof(GLfloat))); + } + else { if (actVerts == verts) return; @@ -282,6 +425,7 @@ void VBO_Vertex::enableTextures() if (actTxcds == txcds) return; actTxcds = txcds; + if (!interlaced) { bindBuffer(txcds); glTexCoordPointer(2, GL_FLOAT, 0, 0); @@ -305,6 +449,7 @@ void VBO_Vertex::enableNormals() if (actNorms == norms) return; actNorms = norms; + if (!interlaced) { bindBuffer(norms); glNormalPointer(GL_FLOAT, 0, 0); @@ -328,6 +473,7 @@ void VBO_Vertex::enableColors() if (actColrs == colrs) return; actColrs = colrs; + if (!interlaced) { bindBuffer(colrs); glColorPointer(4, GL_FLOAT, 0, 0); @@ -350,6 +496,12 @@ void VBO_Vertex::deleteBuffer(GLuint buffer) // tell that this buffer is not more bounded if (actBounded == buffer) actBounded = 0; + if (interlaced) + { + if (actIntrs == buffer) + actIntrs = 0; + } + else { if (actVerts == buffer) actVerts = 0; diff --git a/src/ogl/VBO_Vertex.h b/src/ogl/VBO_Vertex.h index 28f71cf4d5..77dfdba76f 100644 --- a/src/ogl/VBO_Vertex.h +++ b/src/ogl/VBO_Vertex.h @@ -34,7 +34,8 @@ class VBO_Vertex: public VBO_Handler VBO_Vertex( bool handleTexture, bool handleNormal, - bool handleColor); + bool handleColor, + bool interlaced); ~VBO_Vertex() = default; // This should be called when there is not enough space on the current @@ -76,6 +77,7 @@ class VBO_Vertex: public VBO_Handler static GLuint actTxcds; static GLuint actNorms; static GLuint actColrs; + static GLuint actIntrs; // Last bounded buffer static GLuint actBounded; @@ -91,6 +93,7 @@ class VBO_Vertex: public VBO_Handler GLuint txcds; GLuint norms; GLuint colrs; + GLuint intrs; // Bind vertex Buffer void enableVertex(); @@ -112,8 +115,15 @@ class VBO_Vertex: public VBO_Handler std::vector hostedTextures; std::vector hostedNormals; std::vector hostedColors; + std::vector hostedInterlaced; bool vbosReady; + + bool interlaced; + int interlacedSize; + int strideTexture; + int strideNormal; + int strideColor; }; // Local Variables: *** diff --git a/src/ogl/Vertex_Chunk.cxx b/src/ogl/Vertex_Chunk.cxx index 14521a3977..e09ed4c4f6 100644 --- a/src/ogl/Vertex_Chunk.cxx +++ b/src/ogl/Vertex_Chunk.cxx @@ -37,6 +37,7 @@ Vertex_Chunk::Vertex_Chunk(Component comp, unsigned int size) , indexSize(size) , myComp(comp) { + const bool interlaced = true; if (!size) { // Do nothing if size 0 @@ -55,25 +56,25 @@ Vertex_Chunk::Vertex_Chunk(Component comp, unsigned int size) switch (comp) { case Component::V: - myVBO = new VBO_Vertex(false, false, false); + myVBO = new VBO_Vertex(false, false, false, interlaced); break; case Component::VC: - myVBO = new VBO_Vertex(false, false, true); + myVBO = new VBO_Vertex(false, false, true, interlaced); break; case Component::VN: - myVBO = new VBO_Vertex(false, true, false); + myVBO = new VBO_Vertex(false, true, false, interlaced); break; case Component::VT: - myVBO = new VBO_Vertex(true, false, false); + myVBO = new VBO_Vertex(true, false, false, interlaced); break; case Component::VTC: - myVBO = new VBO_Vertex(true, false, true); + myVBO = new VBO_Vertex(true, false, true, interlaced); break; case Component::VTN: - myVBO = new VBO_Vertex(true, true, false); + myVBO = new VBO_Vertex(true, true, false, interlaced); break; case Component::VTNC: - myVBO = new VBO_Vertex(true, true, true); + myVBO = new VBO_Vertex(true, true, true, true); break; default: break;