/* ============ R_CreateVBO2 ============ */ VBO_t *R_CreateVBO2( const char *name, int numVertexes, srfVert_t *verts, unsigned int stateBits, vboUsage_t usage ) { VBO_t *vbo; int i, j; byte *data; int dataSize; int dataOfs; int glUsage; switch ( usage ) { case VBO_USAGE_STATIC: glUsage = GL_STATIC_DRAW; break; case VBO_USAGE_DYNAMIC: glUsage = GL_DYNAMIC_DRAW; break; default: glUsage = 0; Com_Error( ERR_FATAL, "bad vboUsage_t given: %i", usage ); } if ( !numVertexes ) { return NULL; } if ( strlen( name ) >= MAX_QPATH ) { ri.Error( ERR_DROP, "R_CreateVBO2: \"%s\" is too long", name ); } // make sure the render thread is stopped R_SyncRenderThread(); vbo = ri.Hunk_Alloc( sizeof( *vbo ), h_low ); Com_AddToGrowList( &tr.vbos, vbo ); Q_strncpyz( vbo->name, name, sizeof( vbo->name ) ); vbo->ofsXYZ = 0; vbo->ofsTexCoords = 0; vbo->ofsLightCoords = 0; vbo->ofsBinormals = 0; vbo->ofsTangents = 0; vbo->ofsNormals = 0; vbo->ofsColors = 0; vbo->ofsPaintColors = 0; vbo->ofsLightDirections = 0; vbo->ofsBoneIndexes = 0; vbo->ofsBoneWeights = 0; vbo->sizeXYZ = 0; vbo->sizeTangents = 0; vbo->sizeBinormals = 0; vbo->sizeNormals = 0; // create VBO dataSize = numVertexes * ( sizeof( vec4_t ) * 9 ); data = ri.Hunk_AllocateTempMemory( dataSize ); dataOfs = 0; // since this is all float, point tmp directly into data // 2-entry -> { memb[0], memb[1], 0, 1 } // 3-entry -> { memb[0], memb[1], memb[2], 1 } #define VERTEXCOPY(memb) \ do { \ vec_t *tmp = (vec_t *) ( data + dataOfs ); \ for ( i = 0; i < numVertexes; i++ ) \ { \ for ( j = 0; j < ARRAY_LEN( verts->memb ); j++ ) { *tmp++ = verts[ i ].memb[ j ]; } \ if ( ARRAY_LEN( verts->memb ) < 3 ) { *tmp++ = 0; } \ if ( ARRAY_LEN( verts->memb ) < 4 ) { *tmp++ = 1; } \ } \ dataOfs += i * sizeof( vec4_t ); \ } while ( 0 ) // set up xyz array VERTEXCOPY( xyz ); // feed vertex texcoords if ( stateBits & ATTR_TEXCOORD ) { vbo->ofsTexCoords = dataOfs; VERTEXCOPY( st ); } // feed vertex lightmap texcoords if ( stateBits & ATTR_LIGHTCOORD ) { vbo->ofsLightCoords = dataOfs; VERTEXCOPY( lightmap ); } // feed vertex tangents if ( stateBits & ATTR_TANGENT ) { vbo->ofsTangents = dataOfs; VERTEXCOPY( tangent ); } // feed vertex binormals if ( stateBits & ATTR_BINORMAL ) { vbo->ofsBinormals = dataOfs; VERTEXCOPY( binormal ); } // feed vertex normals if ( stateBits & ATTR_NORMAL ) { vbo->ofsNormals = dataOfs; VERTEXCOPY( normal ); } // feed vertex colors if ( stateBits & ATTR_COLOR ) { vbo->ofsColors = dataOfs; VERTEXCOPY( lightColor ); } #if !defined( COMPAT_Q3A ) && !defined( COMPAT_ET ) // feed vertex paint colors if ( stateBits & ATTR_PAINTCOLOR ) { vbo->ofsPaintColors = dataOfs; VERTEXCOPY( paintColor ); } // feed vertex light directions if ( stateBits & ATTR_LIGHTDIRECTION ) { vbo->ofsLightDirections = dataOfs; VERTEXCOPY( lightDirection ); } #endif vbo->vertexesSize = dataSize; vbo->vertexesNum = numVertexes; glGenBuffers( 1, &vbo->vertexesVBO ); glBindBuffer( GL_ARRAY_BUFFER, vbo->vertexesVBO ); glBufferData( GL_ARRAY_BUFFER, dataSize, data, glUsage ); glBindBuffer( GL_ARRAY_BUFFER, 0 ); GL_CheckErrors(); ri.Hunk_FreeTempMemory( data ); return vbo; }
/* ============ R_CreateVBO2 ============ */ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t *verts, unsigned int stateBits, vboUsage_t usage) { VBO_t *vbo; int i, j; byte *data; int dataSize; int dataOfs; int glUsage; unsigned int bits; switch (usage) { case VBO_USAGE_STATIC: glUsage = GL_STATIC_DRAW; break; case VBO_USAGE_DYNAMIC: glUsage = GL_DYNAMIC_DRAW; break; default: glUsage = 0; Ren_Fatal("bad vboUsage_t given: %i", usage); break; } if (!numVertexes) { return NULL; } if (strlen(name) >= MAX_QPATH) { Ren_Drop("R_CreateVBO2: \"%s\" is too long\n", name); } // make sure the render thread is stopped R_IssuePendingRenderCommands(); vbo = (VBO_t *)ri.Hunk_Alloc(sizeof(*vbo), h_low); Com_AddToGrowList(&tr.vbos, vbo); Q_strncpyz(vbo->name, name, sizeof(vbo->name)); vbo->ofsXYZ = 0; vbo->ofsTexCoords = 0; vbo->ofsLightCoords = 0; vbo->ofsBinormals = 0; vbo->ofsTangents = 0; vbo->ofsNormals = 0; vbo->ofsColors = 0; vbo->ofsPaintColors = 0; vbo->ofsLightDirections = 0; vbo->ofsBoneIndexes = 0; vbo->ofsBoneWeights = 0; vbo->sizeXYZ = 0; vbo->sizeTangents = 0; vbo->sizeBinormals = 0; vbo->sizeNormals = 0; // size VBO dataSize = 0; bits = stateBits; while (bits) { if (bits & 1) { dataSize += sizeof(vec4_t); } bits >>= 1; } dataSize *= numVertexes; data = (byte *)ri.Hunk_AllocateTempMemory(dataSize); dataOfs = 0; // since this is all float, point tmp directly into data // 2-entry -> { memb[0], memb[1], 0, 1 } // 3-entry -> { memb[0], memb[1], memb[2], 1 } #define VERTEXSIZE(memb) (sizeof(verts->memb) / sizeof(verts->memb[0])) #define VERTEXCOPY(memb) \ do { \ vec_t *tmp = (vec_t *) (data + dataOfs); \ for (i = 0; i < numVertexes; i++) \ { \ for (j = 0; j < VERTEXSIZE(memb); j++) { *tmp++ = verts[i].memb[j]; } \ if (VERTEXSIZE(memb) < 3) { *tmp++ = 0; } \ if (VERTEXSIZE(memb) < 4) { *tmp++ = 1; } \ } \ dataOfs += i * sizeof(vec4_t); \ } while (0) if (stateBits & ATTR_POSITION) { vbo->ofsXYZ = dataOfs; VERTEXCOPY(xyz); } // feed vertex texcoords if (stateBits & ATTR_TEXCOORD) { vbo->ofsTexCoords = dataOfs; VERTEXCOPY(st); } // feed vertex lightmap texcoords if (stateBits & ATTR_LIGHTCOORD) { vbo->ofsLightCoords = dataOfs; VERTEXCOPY(lightmap); } // feed vertex tangents if (stateBits & ATTR_TANGENT) { vbo->ofsTangents = dataOfs; VERTEXCOPY(tangent); } // feed vertex binormals if (stateBits & ATTR_BINORMAL) { vbo->ofsBinormals = dataOfs; VERTEXCOPY(binormal); } // feed vertex normals if (stateBits & ATTR_NORMAL) { vbo->ofsNormals = dataOfs; VERTEXCOPY(normal); } // feed vertex colors if (stateBits & ATTR_COLOR) { vbo->ofsColors = dataOfs; VERTEXCOPY(lightColor); } vbo->vertexesSize = dataSize; vbo->vertexesNum = numVertexes; glGenBuffers(1, &vbo->vertexesVBO); glBindBuffer(GL_ARRAY_BUFFER, vbo->vertexesVBO); glBufferData(GL_ARRAY_BUFFER, dataSize, data, glUsage); glBindBuffer(GL_ARRAY_BUFFER, 0); GL_CheckErrors(); ri.Hunk_FreeTempMemory(data); return vbo; }