/* ============ R_InitVBOs ============ */ void R_InitVBOs(void) { int dataSize; int offset; ri.Printf(PRINT_ALL, "------- R_InitVBOs -------\n"); tr.numVBOs = 0; tr.numIBOs = 0; dataSize = sizeof(tess.xyz[0]); dataSize += sizeof(tess.normal[0]); #ifdef USE_VERT_TANGENT_SPACE dataSize += sizeof(tess.tangent[0]); dataSize += sizeof(tess.bitangent[0]); #endif dataSize += sizeof(tess.vertexColors[0]); dataSize += sizeof(tess.texCoords[0][0]) * 2; dataSize += sizeof(tess.lightdir[0]); dataSize *= SHADER_MAX_VERTEXES; tess.vbo = R_CreateVBO("tessVertexArray_VBO", NULL, dataSize, VBO_USAGE_DYNAMIC); offset = 0; tess.vbo->ofs_xyz = offset; offset += sizeof(tess.xyz[0]) * SHADER_MAX_VERTEXES; tess.vbo->ofs_normal = offset; offset += sizeof(tess.normal[0]) * SHADER_MAX_VERTEXES; #ifdef USE_VERT_TANGENT_SPACE tess.vbo->ofs_tangent = offset; offset += sizeof(tess.tangent[0]) * SHADER_MAX_VERTEXES; tess.vbo->ofs_bitangent = offset; offset += sizeof(tess.bitangent[0]) * SHADER_MAX_VERTEXES; #endif // these next two are actually interleaved tess.vbo->ofs_st = offset; tess.vbo->ofs_lightmap = offset + sizeof(tess.texCoords[0][0]); offset += sizeof(tess.texCoords[0][0]) * 2 * SHADER_MAX_VERTEXES; tess.vbo->ofs_vertexcolor = offset; offset += sizeof(tess.vertexColors[0]) * SHADER_MAX_VERTEXES; tess.vbo->ofs_lightdir = offset; tess.vbo->stride_xyz = sizeof(tess.xyz[0]); tess.vbo->stride_normal = sizeof(tess.normal[0]); #ifdef USE_VERT_TANGENT_SPACE tess.vbo->stride_tangent = sizeof(tess.tangent[0]); tess.vbo->stride_bitangent = sizeof(tess.bitangent[0]); #endif tess.vbo->stride_vertexcolor = sizeof(tess.vertexColors[0]); tess.vbo->stride_st = sizeof(tess.texCoords[0][0]) * 2; tess.vbo->stride_lightmap = sizeof(tess.texCoords[0][0]) * 2; tess.vbo->stride_lightdir = sizeof(tess.lightdir[0]); dataSize = sizeof(tess.indexes[0]) * SHADER_MAX_INDEXES; tess.ibo = R_CreateIBO("tessVertexArray_IBO", NULL, dataSize, VBO_USAGE_DYNAMIC); R_BindNullVBO(); R_BindNullIBO(); GL_CheckErrors(); }
/* ============ R_InitVBOs ============ */ void R_InitVBOs( void ) { int dataSize; ri.Printf( PRINT_DEVELOPER, "------- R_InitVBOs -------\n" ); Com_InitGrowList( &tr.vbos, 100 ); Com_InitGrowList( &tr.ibos, 100 ); #if !defined( COMPAT_Q3A ) && !defined( COMPAT_ET ) dataSize = sizeof( vec4_t ) * SHADER_MAX_VERTEXES * 11; #else dataSize = sizeof( vec4_t ) * SHADER_MAX_VERTEXES * 10; #endif tess.vbo = R_CreateVBO( "tessVertexArray_VBO", NULL, dataSize, VBO_USAGE_DYNAMIC ); tess.vbo->ofsXYZ = 0; tess.vbo->ofsTexCoords = tess.vbo->ofsXYZ + sizeof( tess.xyz ); tess.vbo->ofsLightCoords = tess.vbo->ofsTexCoords + sizeof( tess.texCoords ); tess.vbo->ofsTangents = tess.vbo->ofsLightCoords + sizeof( tess.lightCoords ); tess.vbo->ofsBinormals = tess.vbo->ofsTangents + sizeof( tess.tangents ); tess.vbo->ofsNormals = tess.vbo->ofsBinormals + sizeof( tess.binormals ); tess.vbo->ofsColors = tess.vbo->ofsNormals + sizeof( tess.normals ); #if !defined( COMPAT_Q3A ) && !defined( COMPAT_ET ) tess.vbo->ofsPaintColors = tess.vbo->ofsColors + sizeof( tess.colors ); tess.vbo->ofsAmbientLight = tess.vbo->ofsPaintColors + sizeof( tess.PaintColors ); #endif tess.vbo->ofsAmbientLight = tess.vbo->ofsColors + sizeof( tess.colors ); tess.vbo->ofsDirectedLight = tess.vbo->ofsAmbientLight + sizeof( tess.ambientLights ); tess.vbo->ofsLightDirections = tess.vbo->ofsDirectedLight + sizeof( tess.directedLights ); tess.vbo->sizeXYZ = sizeof( tess.xyz ); tess.vbo->sizeTangents = sizeof( tess.tangents ); tess.vbo->sizeBinormals = sizeof( tess.binormals ); tess.vbo->sizeNormals = sizeof( tess.normals ); dataSize = sizeof( tess.indexes ); tess.ibo = R_CreateIBO( "tessVertexArray_IBO", NULL, dataSize, VBO_USAGE_DYNAMIC ); R_InitUnitCubeVBO(); // allocate a PBO for color grade map transfers glGenBuffers( 1, &tr.colorGradePBO ); glBindBuffer( GL_PIXEL_PACK_BUFFER, tr.colorGradePBO ); glBufferData( GL_PIXEL_PACK_BUFFER, REF_COLORGRADEMAP_STORE_SIZE * sizeof(color4ub_t), NULL, GL_STREAM_COPY ); glBindBuffer( GL_PIXEL_PACK_BUFFER, 0 ); R_BindNullVBO(); R_BindNullIBO(); GL_CheckErrors(); }
/* ============ R_InitVBOs ============ */ void R_InitVBOs( void ) { int dataSize; byte *data; ri.Printf( PRINT_ALL, "------- R_InitVBOs -------\n" ); Com_InitGrowList( &tr.vbos, 100 ); Com_InitGrowList( &tr.ibos, 100 ); dataSize = sizeof( vec4_t ) * SHADER_MAX_VERTEXES * 11; data = Com_Allocate( dataSize ); memset( data, 0, dataSize ); tess.vbo = R_CreateVBO( "tessVertexArray_VBO", data, dataSize, VBO_USAGE_DYNAMIC ); tess.vbo->ofsXYZ = 0; tess.vbo->ofsTexCoords = tess.vbo->ofsXYZ + sizeof( tess.xyz ); tess.vbo->ofsLightCoords = tess.vbo->ofsTexCoords + sizeof( tess.texCoords ); tess.vbo->ofsTangents = tess.vbo->ofsLightCoords + sizeof( tess.lightCoords ); tess.vbo->ofsBinormals = tess.vbo->ofsTangents + sizeof( tess.tangents ); tess.vbo->ofsNormals = tess.vbo->ofsBinormals + sizeof( tess.binormals ); tess.vbo->ofsColors = tess.vbo->ofsNormals + sizeof( tess.normals ); #if !defined( COMPAT_Q3A ) && !defined( COMPAT_ET ) tess.vbo->ofsPaintColors = tess.vbo->ofsColors + sizeof( tess.colors ); tess.vbo->ofsLightDirections = tess.vbo->ofsPaintColors + sizeof( tess.paintColors ); #endif tess.vbo->sizeXYZ = sizeof( tess.xyz ); tess.vbo->sizeTangents = sizeof( tess.tangents ); tess.vbo->sizeBinormals = sizeof( tess.binormals ); tess.vbo->sizeNormals = sizeof( tess.normals ); Com_Dealloc( data ); dataSize = sizeof( tess.indexes ); data = Com_Allocate( dataSize ); memset( data, 0, dataSize ); tess.ibo = R_CreateIBO( "tessVertexArray_IBO", data, dataSize, VBO_USAGE_DYNAMIC ); Com_Dealloc( data ); R_InitUnitCubeVBO(); R_BindNullVBO(); R_BindNullIBO(); GL_CheckErrors(); }
/* ============ R_InitVBOs ============ */ void R_InitVBOs(void) { int dataSize; byte *data; Ren_Print("------- R_InitVBOs -------\n"); Com_InitGrowList(&tr.vbos, 100); Com_InitGrowList(&tr.ibos, 100); dataSize = sizeof(vec4_t) * SHADER_MAX_VERTEXES * 11; data = (byte *)Com_Allocate(dataSize); memset(data, 0, dataSize); tess.vbo = R_CreateVBO("tessVertexArray_VBO", data, dataSize, VBO_USAGE_DYNAMIC); tess.vbo->ofsXYZ = 0; tess.vbo->ofsTexCoords = tess.vbo->ofsXYZ + sizeof(tess.xyz); tess.vbo->ofsLightCoords = tess.vbo->ofsTexCoords + sizeof(tess.texCoords); tess.vbo->ofsTangents = tess.vbo->ofsLightCoords + sizeof(tess.lightCoords); tess.vbo->ofsBinormals = tess.vbo->ofsTangents + sizeof(tess.tangents); tess.vbo->ofsNormals = tess.vbo->ofsBinormals + sizeof(tess.binormals); tess.vbo->ofsColors = tess.vbo->ofsNormals + sizeof(tess.normals); tess.vbo->sizeXYZ = sizeof(tess.xyz); tess.vbo->sizeTangents = sizeof(tess.tangents); tess.vbo->sizeBinormals = sizeof(tess.binormals); tess.vbo->sizeNormals = sizeof(tess.normals); Com_Dealloc(data); dataSize = sizeof(tess.indexes); data = (byte *)Com_Allocate(dataSize); memset(data, 0, dataSize); tess.ibo = R_CreateIBO("tessVertexArray_IBO", data, dataSize, VBO_USAGE_DYNAMIC); Com_Dealloc(data); R_InitUnitCubeVBO(); R_BindNullVBO(); R_BindNullIBO(); GL_CheckErrors(); }
/* ================= R_LoadMDC ================= */ qboolean R_LoadMDC(model_t *mod, int lod, void *buffer, int bufferSize, const char *modName) { int i, j, k; mdcHeader_t *mdcModel = ( mdcHeader_t * ) buffer; md3Frame_t *mdcFrame; mdcSurface_t *mdcSurf; md3Shader_t *mdcShader; md3Triangle_t *mdcTri; md3St_t *mdcst; md3XyzNormal_t *mdcxyz; mdcXyzCompressed_t *mdcxyzComp; mdcTag_t *mdcTag; mdcTagName_t *mdcTagName; mdvModel_t *mdvModel; mdvFrame_t *frame; mdvSurface_t *surf; //, *surface; //unused srfTriangle_t *tri; mdvXyz_t *v; mdvSt_t *st; mdvTag_t *tag; mdvTagName_t *tagName; short *ps; int version; int size; version = LittleLong(mdcModel->version); if (version != MDC_VERSION) { Ren_Warning("R_LoadMD3: %s has wrong version (%i should be %i)\n", modName, version, MDC_VERSION); return qfalse; } mod->type = MOD_MESH; size = LittleLong(mdcModel->ofsEnd); mod->dataSize += size; mdvModel = mod->mdv[lod] = ri.Hunk_Alloc(sizeof(mdvModel_t), h_low); LL(mdcModel->ident); LL(mdcModel->version); LL(mdcModel->numFrames); LL(mdcModel->numTags); LL(mdcModel->numSurfaces); LL(mdcModel->ofsFrames); LL(mdcModel->ofsTags); LL(mdcModel->ofsSurfaces); LL(mdcModel->ofsEnd); LL(mdcModel->ofsEnd); LL(mdcModel->flags); LL(mdcModel->numSkins); if (mdcModel->numFrames < 1) { Ren_Warning("R_LoadMDC: '%s' has no frames\n", modName); return qfalse; } // swap all the frames mdvModel->numFrames = mdcModel->numFrames; mdvModel->frames = frame = ri.Hunk_Alloc(sizeof(*frame) * mdcModel->numFrames, h_low); mdcFrame = ( md3Frame_t * )(( byte * ) mdcModel + mdcModel->ofsFrames); for (i = 0; i < mdcModel->numFrames; i++, frame++, mdcFrame++) { #if 1 // ET HACK if (strstr(mod->name, "sherman") || strstr(mod->name, "mg42")) { frame->radius = 256; for (j = 0; j < 3; j++) { frame->bounds[0][j] = 128; frame->bounds[1][j] = -128; frame->localOrigin[j] = LittleFloat(mdcFrame->localOrigin[j]); } } else #endif { frame->radius = LittleFloat(mdcFrame->radius); for (j = 0; j < 3; j++) { frame->bounds[0][j] = LittleFloat(mdcFrame->bounds[0][j]); frame->bounds[1][j] = LittleFloat(mdcFrame->bounds[1][j]); frame->localOrigin[j] = LittleFloat(mdcFrame->localOrigin[j]); } } } // swap all the tags mdvModel->numTags = mdcModel->numTags; mdvModel->tags = tag = ri.Hunk_Alloc(sizeof(*tag) * (mdcModel->numTags * mdcModel->numFrames), h_low); mdcTag = ( mdcTag_t * )(( byte * ) mdcModel + mdcModel->ofsTags); for (i = 0; i < mdcModel->numTags * mdcModel->numFrames; i++, tag++, mdcTag++) { vec3_t angles; for (j = 0; j < 3; j++) { tag->origin[j] = ( float ) LittleShort(mdcTag->xyz[j]) * MD3_XYZ_SCALE; angles[j] = ( float ) LittleShort(mdcTag->angles[j]) * MDC_TAG_ANGLE_SCALE; } AnglesToAxis(angles, tag->axis); } mdvModel->tagNames = tagName = ri.Hunk_Alloc(sizeof(*tagName) * (mdcModel->numTags), h_low); mdcTagName = ( mdcTagName_t * )(( byte * ) mdcModel + mdcModel->ofsTagNames); for (i = 0; i < mdcModel->numTags; i++, tagName++, mdcTagName++) { Q_strncpyz(tagName->name, mdcTagName->name, sizeof(tagName->name)); } // swap all the surfaces mdvModel->numSurfaces = mdcModel->numSurfaces; mdvModel->surfaces = surf = ri.Hunk_Alloc(sizeof(*surf) * mdcModel->numSurfaces, h_low); mdcSurf = ( mdcSurface_t * )(( byte * ) mdcModel + mdcModel->ofsSurfaces); for (i = 0; i < mdcModel->numSurfaces; i++) { LL(mdcSurf->ident); LL(mdcSurf->flags); LL(mdcSurf->numBaseFrames); LL(mdcSurf->numCompFrames); LL(mdcSurf->numShaders); LL(mdcSurf->numTriangles); LL(mdcSurf->ofsTriangles); LL(mdcSurf->numVerts); LL(mdcSurf->ofsShaders); LL(mdcSurf->ofsSt); LL(mdcSurf->ofsXyzNormals); LL(mdcSurf->ofsXyzNormals); LL(mdcSurf->ofsXyzCompressed); LL(mdcSurf->ofsFrameBaseFrames); LL(mdcSurf->ofsFrameCompFrames); LL(mdcSurf->ofsEnd); if (mdcSurf->numVerts > SHADER_MAX_VERTEXES) { Ren_Drop("R_LoadMDC: %s has more than %i verts on a surface (%i)", modName, SHADER_MAX_VERTEXES, mdcSurf->numVerts); } if (mdcSurf->numTriangles > SHADER_MAX_TRIANGLES) { Ren_Drop("R_LoadMDC: %s has more than %i triangles on a surface (%i)", modName, SHADER_MAX_TRIANGLES, mdcSurf->numTriangles); } // change to surface identifier surf->surfaceType = SF_MDV; // give pointer to model for Tess_SurfaceMDX surf->model = mdvModel; // copy surface name Q_strncpyz(surf->name, mdcSurf->name, sizeof(surf->name)); // lowercase the surface name so skin compares are faster Q_strlwr(surf->name); // strip off a trailing _1 or _2 // this is a crutch for q3data being a mess j = strlen(surf->name); if (j > 2 && surf->name[j - 2] == '_') { surf->name[j - 2] = 0; } // register the shaders /* surf->numShaders = md3Surf->numShaders; surf->shaders = shader = ri.Hunk_Alloc(sizeof(*shader) * md3Surf->numShaders, h_low); md3Shader = (md3Shader_t *) ((byte *) md3Surf + md3Surf->ofsShaders); for(j = 0; j < md3Surf->numShaders; j++, shader++, md3Shader++) { shader_t *sh; sh = R_FindShader(md3Shader->name, SHADER_3D_DYNAMIC, RSF_DEFAULT); if(sh->defaultShader) { shader->shaderIndex = 0; } else { shader->shaderIndex = sh->index; } } */ // only consider the first shader mdcShader = ( md3Shader_t * )(( byte * ) mdcSurf + mdcSurf->ofsShaders); surf->shader = R_FindShader(mdcShader->name, SHADER_3D_DYNAMIC, qtrue); // swap all the triangles surf->numTriangles = mdcSurf->numTriangles; surf->triangles = tri = ri.Hunk_Alloc(sizeof(*tri) * mdcSurf->numTriangles, h_low); mdcTri = ( md3Triangle_t * )(( byte * ) mdcSurf + mdcSurf->ofsTriangles); for (j = 0; j < mdcSurf->numTriangles; j++, tri++, mdcTri++) { tri->indexes[0] = LittleLong(mdcTri->indexes[0]); tri->indexes[1] = LittleLong(mdcTri->indexes[1]); tri->indexes[2] = LittleLong(mdcTri->indexes[2]); } // swap all the XyzNormals mdcxyz = ( md3XyzNormal_t * )(( byte * ) mdcSurf + mdcSurf->ofsXyzNormals); for (j = 0; j < mdcSurf->numVerts * mdcSurf->numBaseFrames; j++, mdcxyz++) { mdcxyz->xyz[0] = LittleShort(mdcxyz->xyz[0]); mdcxyz->xyz[1] = LittleShort(mdcxyz->xyz[1]); mdcxyz->xyz[2] = LittleShort(mdcxyz->xyz[2]); mdcxyz->normal = LittleShort(mdcxyz->normal); } // swap all the XyzCompressed mdcxyzComp = ( mdcXyzCompressed_t * )(( byte * ) mdcSurf + mdcSurf->ofsXyzCompressed); for (j = 0; j < mdcSurf->numVerts * mdcSurf->numCompFrames; j++, mdcxyzComp++) { LL(mdcxyzComp->ofsVec); } // swap the frameBaseFrames ps = ( short * )(( byte * ) mdcSurf + mdcSurf->ofsFrameBaseFrames); for (j = 0; j < mdcModel->numFrames; j++, ps++) { *ps = LittleShort(*ps); } // swap the frameCompFrames ps = ( short * )(( byte * ) mdcSurf + mdcSurf->ofsFrameCompFrames); for (j = 0; j < mdcModel->numFrames; j++, ps++) { *ps = LittleShort(*ps); } surf->numVerts = mdcSurf->numVerts; surf->verts = v = ri.Hunk_Alloc(sizeof(*v) * (mdcSurf->numVerts * mdcModel->numFrames), h_low); for (j = 0; j < mdcModel->numFrames; j++) { int baseFrame; int compFrame = 0; baseFrame = ( int ) *(( short * )(( byte * ) mdcSurf + mdcSurf->ofsFrameBaseFrames) + j); mdcxyz = ( md3XyzNormal_t * )(( byte * ) mdcSurf + mdcSurf->ofsXyzNormals + baseFrame * mdcSurf->numVerts * sizeof(md3XyzNormal_t)); if (mdcSurf->numCompFrames > 0) { compFrame = ( int ) *(( short * )(( byte * ) mdcSurf + mdcSurf->ofsFrameCompFrames) + j); if (compFrame >= 0) { mdcxyzComp = ( mdcXyzCompressed_t * )(( byte * ) mdcSurf + mdcSurf->ofsXyzCompressed + compFrame * mdcSurf->numVerts * sizeof(mdcXyzCompressed_t)); } } for (k = 0; k < mdcSurf->numVerts; k++, v++, mdcxyz++) { v->xyz[0] = LittleShort(mdcxyz->xyz[0]) * MD3_XYZ_SCALE; v->xyz[1] = LittleShort(mdcxyz->xyz[1]) * MD3_XYZ_SCALE; v->xyz[2] = LittleShort(mdcxyz->xyz[2]) * MD3_XYZ_SCALE; if (mdcSurf->numCompFrames > 0 && compFrame >= 0) { vec3_t ofsVec; R_MDC_DecodeXyzCompressed2(LittleShort(mdcxyzComp->ofsVec), ofsVec); VectorAdd(v->xyz, ofsVec, v->xyz); mdcxyzComp++; } } } // swap all the ST surf->st = st = ri.Hunk_Alloc(sizeof(*st) * mdcSurf->numVerts, h_low); mdcst = ( md3St_t * )(( byte * ) mdcSurf + mdcSurf->ofsSt); for (j = 0; j < mdcSurf->numVerts; j++, mdcst++, st++) { st->st[0] = LittleFloat(mdcst->st[0]); st->st[1] = LittleFloat(mdcst->st[1]); } // find the next surface mdcSurf = ( mdcSurface_t * )(( byte * ) mdcSurf + mdcSurf->ofsEnd); surf++; } #if 1 // create VBO surfaces from md3 surfaces { mdvNormTanBi_t *vertexes; mdvNormTanBi_t *vert; growList_t vboSurfaces; srfVBOMDVMesh_t *vboSurf; byte *data; int dataSize; int dataOfs; vec4_t tmp; GLuint ofsTexCoords; GLuint ofsTangents; GLuint ofsBinormals; GLuint ofsNormals; GLuint sizeXYZ = 0; GLuint sizeTangents = 0; GLuint sizeBinormals = 0; GLuint sizeNormals = 0; int vertexesNum; int f; Com_InitGrowList(&vboSurfaces, 10); for (i = 0, surf = mdvModel->surfaces; i < mdvModel->numSurfaces; i++, surf++) { //allocate temp memory for vertex data vertexes = (mdvNormTanBi_t *)ri.Hunk_AllocateTempMemory(sizeof(*vertexes) * surf->numVerts * mdvModel->numFrames); // calc tangent spaces { const float *v0, *v1, *v2; const float *t0, *t1, *t2; vec3_t tangent; vec3_t binormal; vec3_t normal; for (j = 0, vert = vertexes; j < (surf->numVerts * mdvModel->numFrames); j++, vert++) { VectorClear(vert->tangent); VectorClear(vert->binormal); VectorClear(vert->normal); } for (f = 0; f < mdvModel->numFrames; f++) { for (j = 0, tri = surf->triangles; j < surf->numTriangles; j++, tri++) { v0 = surf->verts[surf->numVerts * f + tri->indexes[0]].xyz; v1 = surf->verts[surf->numVerts * f + tri->indexes[1]].xyz; v2 = surf->verts[surf->numVerts * f + tri->indexes[2]].xyz; t0 = surf->st[tri->indexes[0]].st; t1 = surf->st[tri->indexes[1]].st; t2 = surf->st[tri->indexes[2]].st; #if 1 R_CalcTangentSpace(tangent, binormal, normal, v0, v1, v2, t0, t1, t2); #else R_CalcNormalForTriangle(normal, v0, v1, v2); R_CalcTangentsForTriangle(tangent, binormal, v0, v1, v2, t0, t1, t2); #endif for (k = 0; k < 3; k++) { float *v; v = vertexes[surf->numVerts * f + tri->indexes[k]].tangent; VectorAdd(v, tangent, v); v = vertexes[surf->numVerts * f + tri->indexes[k]].binormal; VectorAdd(v, binormal, v); v = vertexes[surf->numVerts * f + tri->indexes[k]].normal; VectorAdd(v, normal, v); } } } for (j = 0, vert = vertexes; j < (surf->numVerts * mdvModel->numFrames); j++, vert++) { VectorNormalize(vert->tangent); VectorNormalize(vert->binormal); VectorNormalize(vert->normal); } } //Ren_Print("...calculating MDC mesh VBOs ( '%s', %i verts %i tris )\n", surf->name, surf->numVerts, surf->numTriangles); // create surface vboSurf = ri.Hunk_Alloc(sizeof(*vboSurf), h_low); Com_AddToGrowList(&vboSurfaces, vboSurf); vboSurf->surfaceType = SF_VBO_MDVMESH; vboSurf->mdvModel = mdvModel; vboSurf->mdvSurface = surf; vboSurf->numIndexes = surf->numTriangles * 3; vboSurf->numVerts = surf->numVerts; /* vboSurf->vbo = R_CreateVBO2(va("staticWorldMesh_vertices %i", vboSurfaces.currentElements), numVerts, optimizedVerts, ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BINORMAL | ATTR_NORMAL | ATTR_COLOR); */ vboSurf->ibo = R_CreateIBO2(va("staticMDCMesh_IBO %s", surf->name), surf->numTriangles, surf->triangles, VBO_USAGE_STATIC); // create VBO vertexesNum = surf->numVerts; dataSize = (surf->numVerts * mdvModel->numFrames * sizeof(vec4_t) * 4) + // xyz, tangent, binormal, normal (surf->numVerts * sizeof(vec4_t)); // texcoords data = ri.Hunk_AllocateTempMemory(dataSize); dataOfs = 0; // feed vertex XYZ for (f = 0; f < mdvModel->numFrames; f++) { for (j = 0; j < vertexesNum; j++) { for (k = 0; k < 3; k++) { tmp[k] = surf->verts[f * vertexesNum + j].xyz[k]; } tmp[3] = 1; Com_Memcpy(data + dataOfs, ( vec_t * ) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } if (f == 0) { sizeXYZ = dataOfs; } } // feed vertex texcoords ofsTexCoords = dataOfs; for (j = 0; j < vertexesNum; j++) { for (k = 0; k < 2; k++) { tmp[k] = surf->st[j].st[k]; } tmp[2] = 0; tmp[3] = 1; Com_Memcpy(data + dataOfs, ( vec_t * ) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } // feed vertex tangents ofsTangents = dataOfs; for (f = 0; f < mdvModel->numFrames; f++) { for (j = 0; j < vertexesNum; j++) { for (k = 0; k < 3; k++) { tmp[k] = vertexes[f * vertexesNum + j].tangent[k]; } tmp[3] = 1; Com_Memcpy(data + dataOfs, ( vec_t * ) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } if (f == 0) { sizeTangents = dataOfs - ofsTangents; } } // feed vertex binormals ofsBinormals = dataOfs; for (f = 0; f < mdvModel->numFrames; f++) { for (j = 0; j < vertexesNum; j++) { for (k = 0; k < 3; k++) { tmp[k] = vertexes[f * vertexesNum + j].binormal[k]; } tmp[3] = 1; Com_Memcpy(data + dataOfs, ( vec_t * ) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } if (f == 0) { sizeBinormals = dataOfs - ofsBinormals; } } // feed vertex normals ofsNormals = dataOfs; for (f = 0; f < mdvModel->numFrames; f++) { for (j = 0; j < vertexesNum; j++) { for (k = 0; k < 3; k++) { tmp[k] = vertexes[f * vertexesNum + j].normal[k]; } tmp[3] = 1; Com_Memcpy(data + dataOfs, ( vec_t * ) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } if (f == 0) { sizeNormals = dataOfs - ofsNormals; } } vboSurf->vbo = R_CreateVBO(va("staticMDCMesh_VBO '%s'", surf->name), data, dataSize, VBO_USAGE_STATIC); vboSurf->vbo->ofsXYZ = 0; vboSurf->vbo->ofsTexCoords = ofsTexCoords; vboSurf->vbo->ofsLightCoords = ofsTexCoords; vboSurf->vbo->ofsTangents = ofsTangents; vboSurf->vbo->ofsBinormals = ofsBinormals; vboSurf->vbo->ofsNormals = ofsNormals; vboSurf->vbo->sizeXYZ = sizeXYZ; vboSurf->vbo->sizeTangents = sizeTangents; vboSurf->vbo->sizeBinormals = sizeBinormals; vboSurf->vbo->sizeNormals = sizeNormals; ri.Hunk_FreeTempMemory(data); ri.Hunk_FreeTempMemory(vertexes); } // move VBO surfaces list to hunk mdvModel->numVBOSurfaces = vboSurfaces.currentElements; mdvModel->vboSurfaces = ri.Hunk_Alloc(mdvModel->numVBOSurfaces * sizeof(*mdvModel->vboSurfaces), h_low); for (i = 0; i < mdvModel->numVBOSurfaces; i++) { mdvModel->vboSurfaces[i] = ( srfVBOMDVMesh_t * ) Com_GrowListElement(&vboSurfaces, i); } Com_DestroyGrowList(&vboSurfaces); } #endif return qtrue; }
void AddSurfaceToVBOSurfacesList2(growList_t *vboSurfaces, growList_t *vboTriangles, growList_t *vboVertexes, md5Model_t *md5, int skinIndex, const char *materialName, int numBoneReferences, int boneReferences[MAX_BONES]) { int j, k; int vertexesNum; byte *data; int dataSize; int dataOfs; GLuint ofsTexCoords; GLuint ofsTangents; GLuint ofsBinormals; GLuint ofsNormals; GLuint ofsBoneIndexes; GLuint ofsBoneWeights; int indexesNum; byte *indexes; int indexesSize; int indexesOfs; skelTriangle_t *tri; vec4_t tmp; int index; srfVBOMD5Mesh_t *vboSurf; md5Vertex_t *v; shader_t *shader; int shaderIndex; vertexesNum = vboVertexes->currentElements; indexesNum = vboTriangles->currentElements * 3; // create surface vboSurf = ri.Hunk_Alloc(sizeof(*vboSurf), h_low); Com_AddToGrowList(vboSurfaces, vboSurf); vboSurf->surfaceType = SF_VBO_MD5MESH; vboSurf->md5Model = md5; ri.Printf(PRINT_ALL, "AddSurfaceToVBOSurfacesList2: loading shader '%s'\n", materialName); shader = R_FindShader(materialName, SHADER_3D_DYNAMIC, qtrue); if (shader->defaultShader) { shaderIndex = 0; } else { shaderIndex = shader->index; } vboSurf->shader = R_GetShaderByHandle(shaderIndex); vboSurf->skinIndex = skinIndex; vboSurf->numIndexes = indexesNum; vboSurf->numVerts = vertexesNum; dataSize = vertexesNum * (sizeof(vec4_t) * 8); data = ri.Hunk_AllocateTempMemory(dataSize); dataOfs = 0; indexesSize = indexesNum * sizeof(int); indexes = ri.Hunk_AllocateTempMemory(indexesSize); indexesOfs = 0; //ri.Printf(PRINT_ALL, "AddSurfaceToVBOSurfacesList( %i verts, %i tris )\n", surf->numVerts, vboTriangles->currentElements); vboSurf->numBoneRemap = 0; Com_Memset(vboSurf->boneRemap, 0, sizeof(vboSurf->boneRemap)); Com_Memset(vboSurf->boneRemapInverse, 0, sizeof(vboSurf->boneRemapInverse)); //ri.Printf(PRINT_ALL, "referenced bones: "); for (j = 0; j < MAX_BONES; j++) { if (boneReferences[j] > 0) { vboSurf->boneRemap[j] = vboSurf->numBoneRemap; vboSurf->boneRemapInverse[vboSurf->numBoneRemap] = j; vboSurf->numBoneRemap++; //ri.Printf(PRINT_ALL, "(%i -> %i) ", j, vboSurf->boneRemap[j]); } } //ri.Printf(PRINT_ALL, "\n"); //for(j = 0, tri = surf->triangles; j < surf->numTriangles; j++, tri++) for (j = 0; j < vboTriangles->currentElements; j++) { tri = Com_GrowListElement(vboTriangles, j); for (k = 0; k < 3; k++) { index = tri->indexes[k]; Com_Memcpy(indexes + indexesOfs, &index, sizeof(int)); indexesOfs += sizeof(int); } } // feed vertex XYZ for (j = 0; j < vertexesNum; j++) { v = Com_GrowListElement(vboVertexes, j); for (k = 0; k < 3; k++) { tmp[k] = v->position[k]; } tmp[3] = 1; Com_Memcpy(data + dataOfs, ( vec_t * ) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } // feed vertex texcoords ofsTexCoords = dataOfs; for (j = 0; j < vertexesNum; j++) { v = Com_GrowListElement(vboVertexes, j); for (k = 0; k < 2; k++) { tmp[k] = v->texCoords[k]; } tmp[2] = 0; tmp[3] = 1; Com_Memcpy(data + dataOfs, ( vec_t * ) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } // feed vertex tangents ofsTangents = dataOfs; for (j = 0; j < vertexesNum; j++) { v = Com_GrowListElement(vboVertexes, j); for (k = 0; k < 3; k++) { tmp[k] = v->tangent[k]; } tmp[3] = 1; Com_Memcpy(data + dataOfs, ( vec_t * ) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } // feed vertex binormals ofsBinormals = dataOfs; for (j = 0; j < vertexesNum; j++) { v = Com_GrowListElement(vboVertexes, j); for (k = 0; k < 3; k++) { tmp[k] = v->binormal[k]; } tmp[3] = 1; Com_Memcpy(data + dataOfs, ( vec_t * ) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } // feed vertex normals ofsNormals = dataOfs; for (j = 0; j < vertexesNum; j++) { v = Com_GrowListElement(vboVertexes, j); for (k = 0; k < 3; k++) { tmp[k] = v->normal[k]; } tmp[3] = 1; Com_Memcpy(data + dataOfs, ( vec_t * ) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } // feed bone indices ofsBoneIndexes = dataOfs; for (j = 0; j < vertexesNum; j++) { v = Com_GrowListElement(vboVertexes, j); for (k = 0; k < MAX_WEIGHTS; k++) { if (k < v->numWeights) { index = vboSurf->boneRemap[v->weights[k]->boneIndex]; } else { index = 0; } Com_Memcpy(data + dataOfs, &index, sizeof(int)); dataOfs += sizeof(int); } } // feed bone weights ofsBoneWeights = dataOfs; for (j = 0; j < vertexesNum; j++) { v = Com_GrowListElement(vboVertexes, j); for (k = 0; k < MAX_WEIGHTS; k++) { if (k < v->numWeights) { tmp[k] = v->weights[k]->boneWeight; } else { tmp[k] = 0; } } Com_Memcpy(data + dataOfs, ( vec_t * ) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } vboSurf->vbo = R_CreateVBO(va("staticMD5Mesh_VBO %i", vboSurfaces->currentElements), data, dataSize, VBO_USAGE_STATIC); vboSurf->vbo->ofsXYZ = 0; vboSurf->vbo->ofsTexCoords = ofsTexCoords; vboSurf->vbo->ofsLightCoords = ofsTexCoords; vboSurf->vbo->ofsTangents = ofsTangents; vboSurf->vbo->ofsBinormals = ofsBinormals; vboSurf->vbo->ofsNormals = ofsNormals; vboSurf->vbo->ofsBoneIndexes = ofsBoneIndexes; vboSurf->vbo->ofsBoneWeights = ofsBoneWeights; vboSurf->ibo = R_CreateIBO(va("staticMD5Mesh_IBO %i", vboSurfaces->currentElements), indexes, indexesSize, VBO_USAGE_STATIC); ri.Hunk_FreeTempMemory(indexes); ri.Hunk_FreeTempMemory(data); // megs /* ri.Printf(PRINT_ALL, "md5 mesh data VBO size: %d.%02d MB\n", dataSize / (1024 * 1024), (dataSize % (1024 * 1024)) * 100 / (1024 * 1024)); ri.Printf(PRINT_ALL, "md5 mesh tris VBO size: %d.%02d MB\n", indexesSize / (1024 * 1024), (indexesSize % (1024 * 1024)) * 100 / (1024 * 1024)); */ ri.Printf(PRINT_ALL, "created VBO surface %i with %i vertices and %i triangles\n", vboSurfaces->currentElements, vboSurf->numVerts, vboSurf->numIndexes / 3); }
static void AddSurfaceToVBOSurfacesListMDM( growList_t *vboSurfaces, growList_t *vboTriangles, mdmModel_t *mdm, mdmSurfaceIntern_t *surf, int skinIndex, int numBoneReferences, int boneReferences[ MAX_BONES ] ) { int j, k, lod; int vertexesNum; byte *data; int dataSize; int dataOfs; GLuint ofsTexCoords; GLuint ofsTangents; GLuint ofsBinormals; GLuint ofsNormals; GLuint ofsBoneIndexes; GLuint ofsBoneWeights; int indexesNum; byte *indexes; int indexesSize; int indexesOfs; skelTriangle_t *tri; vec4_t tmp; int index; srfVBOMDMMesh_t *vboSurf; md5Vertex_t *v; // vec4_t tmpColor = { 1, 1, 1, 1 }; static int32_t collapse[ MDM_MAX_VERTS ]; vertexesNum = surf->numVerts; indexesNum = vboTriangles->currentElements * 3; // create surface vboSurf = ri.Hunk_Alloc( sizeof( *vboSurf ), h_low ); Com_AddToGrowList( vboSurfaces, vboSurf ); vboSurf->surfaceType = SF_VBO_MDMMESH; vboSurf->mdmModel = mdm; vboSurf->mdmSurface = surf; vboSurf->shader = R_GetShaderByHandle( surf->shaderIndex ); vboSurf->skinIndex = skinIndex; vboSurf->numIndexes = indexesNum; vboSurf->numVerts = vertexesNum; dataSize = vertexesNum * ( sizeof( vec4_t ) * 7 ); data = ri.Hunk_AllocateTempMemory( dataSize ); dataOfs = 0; //ri.Printf(PRINT_ALL, "AddSurfaceToVBOSurfacesList( %i verts, %i tris )\n", surf->numVerts, vboTriangles->currentElements); vboSurf->numBoneRemap = 0; Com_Memset( vboSurf->boneRemap, 0, sizeof( vboSurf->boneRemap ) ); Com_Memset( vboSurf->boneRemapInverse, 0, sizeof( vboSurf->boneRemapInverse ) ); //ri.Printf(PRINT_ALL, "original referenced bones: [ "); //for(j = 0; j < surf->numBoneReferences; j++) //{ // ri.Printf(PRINT_ALL, "%i, ", surf->boneReferences[j]); //} //ri.Printf(PRINT_ALL, "]\n"); //ri.Printf(PRINT_ALL, "new referenced bones: "); for ( j = 0; j < MAX_BONES; j++ ) { if ( boneReferences[ j ] > 0 ) { vboSurf->boneRemap[ j ] = vboSurf->numBoneRemap; vboSurf->boneRemapInverse[ vboSurf->numBoneRemap ] = j; vboSurf->numBoneRemap++; //ri.Printf(PRINT_ALL, "(%i -> %i) ", j, vboSurf->boneRemap[j]); } } //ri.Printf(PRINT_ALL, "\n"); // feed vertex XYZ for ( j = 0; j < vertexesNum; j++ ) { for ( k = 0; k < 3; k++ ) { tmp[ k ] = surf->verts[ j ].position[ k ]; } tmp[ 3 ] = 1; Com_Memcpy( data + dataOfs, ( vec_t * ) tmp, sizeof( vec4_t ) ); dataOfs += sizeof( vec4_t ); } // feed vertex texcoords ofsTexCoords = dataOfs; for ( j = 0; j < vertexesNum; j++ ) { for ( k = 0; k < 2; k++ ) { tmp[ k ] = surf->verts[ j ].texCoords[ k ]; } tmp[ 2 ] = 0; tmp[ 3 ] = 1; Com_Memcpy( data + dataOfs, ( vec_t * ) tmp, sizeof( vec4_t ) ); dataOfs += sizeof( vec4_t ); } // feed vertex tangents ofsTangents = dataOfs; for ( j = 0; j < vertexesNum; j++ ) { for ( k = 0; k < 3; k++ ) { tmp[ k ] = surf->verts[ j ].tangent[ k ]; } tmp[ 3 ] = 1; Com_Memcpy( data + dataOfs, ( vec_t * ) tmp, sizeof( vec4_t ) ); dataOfs += sizeof( vec4_t ); } // feed vertex binormals ofsBinormals = dataOfs; for ( j = 0; j < vertexesNum; j++ ) { for ( k = 0; k < 3; k++ ) { tmp[ k ] = surf->verts[ j ].binormal[ k ]; } tmp[ 3 ] = 1; Com_Memcpy( data + dataOfs, ( vec_t * ) tmp, sizeof( vec4_t ) ); dataOfs += sizeof( vec4_t ); } // feed vertex normals ofsNormals = dataOfs; for ( j = 0; j < vertexesNum; j++ ) { for ( k = 0; k < 3; k++ ) { tmp[ k ] = surf->verts[ j ].normal[ k ]; } tmp[ 3 ] = 1; Com_Memcpy( data + dataOfs, ( vec_t * ) tmp, sizeof( vec4_t ) ); dataOfs += sizeof( vec4_t ); } // feed bone indices ofsBoneIndexes = dataOfs; for ( j = 0, v = surf->verts; j < surf->numVerts; j++, v++ ) { for ( k = 0; k < MAX_WEIGHTS; k++ ) { if ( k < v->numWeights ) { index = vboSurf->boneRemap[ v->weights[ k ]->boneIndex ]; } else { index = 0; } Com_Memcpy( data + dataOfs, &index, sizeof( int ) ); dataOfs += sizeof( int ); } } // feed bone weights ofsBoneWeights = dataOfs; for ( j = 0, v = surf->verts; j < surf->numVerts; j++, v++ ) { for ( k = 0; k < MAX_WEIGHTS; k++ ) { if ( k < v->numWeights ) { tmp[ k ] = v->weights[ k ]->boneWeight; } else { tmp[ k ] = 0; } } Com_Memcpy( data + dataOfs, ( vec_t * ) tmp, sizeof( vec4_t ) ); dataOfs += sizeof( vec4_t ); } vboSurf->vbo = R_CreateVBO( va( "staticMDMMesh_VBO %i", vboSurfaces->currentElements ), data, dataSize, VBO_USAGE_STATIC ); vboSurf->vbo->ofsXYZ = 0; vboSurf->vbo->ofsTexCoords = ofsTexCoords; vboSurf->vbo->ofsLightCoords = ofsTexCoords; vboSurf->vbo->ofsTangents = ofsTangents; vboSurf->vbo->ofsBinormals = ofsBinormals; vboSurf->vbo->ofsNormals = ofsNormals; vboSurf->vbo->ofsColors = ofsNormals; vboSurf->vbo->ofsLightCoords = 0; // not required anyway vboSurf->vbo->ofsLightDirections = 0; // not required anyway vboSurf->vbo->ofsBoneIndexes = ofsBoneIndexes; vboSurf->vbo->ofsBoneWeights = ofsBoneWeights; // calculate LOD IBOs lod = 0; do { float flod; int renderCount; flod = mdmLODResolutions[ lod ]; renderCount = MIN( ( int )( ( float ) surf->numVerts * flod ), surf->numVerts ); if ( renderCount < surf->minLod ) { renderCount = surf->minLod; flod = ( float ) renderCount / surf->numVerts; } if ( renderCount == surf->numVerts ) { indexesNum = vboTriangles->currentElements * 3; indexesSize = indexesNum * sizeof( int ); indexes = ri.Hunk_AllocateTempMemory( indexesSize ); indexesOfs = 0; for ( j = 0; j < vboTriangles->currentElements; j++ ) { tri = Com_GrowListElement( vboTriangles, j ); for ( k = 0; k < 3; k++ ) { index = tri->indexes[ k ]; Com_Memcpy( indexes + indexesOfs, &index, sizeof( int ) ); indexesOfs += sizeof( int ); } } } else { int ci[ 3 ]; int32_t *pCollapseMap; int32_t *pCollapse; pCollapse = collapse; for ( j = 0; j < renderCount; pCollapse++, j++ ) { *pCollapse = j; } pCollapseMap = &surf->collapseMap[ renderCount ]; for ( j = renderCount; j < surf->numVerts; j++, pCollapse++, pCollapseMap++ ) { int32_t collapseValue = *pCollapseMap; *pCollapse = collapse[ collapseValue ]; } indexesNum = 0; for ( j = 0; j < vboTriangles->currentElements; j++ ) { tri = Com_GrowListElement( vboTriangles, j ); ci[ 0 ] = collapse[ tri->indexes[ 0 ] ]; ci[ 1 ] = collapse[ tri->indexes[ 1 ] ]; ci[ 2 ] = collapse[ tri->indexes[ 2 ] ]; // FIXME // note: serious optimization opportunity here, // by sorting the triangles the following "continue" // could have been made into a "break" statement. if ( ci[ 0 ] == ci[ 1 ] || ci[ 1 ] == ci[ 2 ] || ci[ 2 ] == ci[ 0 ] ) { continue; } indexesNum += 3; } indexesSize = indexesNum * sizeof( int ); indexes = ri.Hunk_AllocateTempMemory( indexesSize ); indexesOfs = 0; for ( j = 0; j < vboTriangles->currentElements; j++ ) { tri = Com_GrowListElement( vboTriangles, j ); ci[ 0 ] = collapse[ tri->indexes[ 0 ] ]; ci[ 1 ] = collapse[ tri->indexes[ 1 ] ]; ci[ 2 ] = collapse[ tri->indexes[ 2 ] ]; // FIXME // note: serious optimization opportunity here, // by sorting the triangles the following "continue" // could have been made into a "break" statement. if ( ci[ 0 ] == ci[ 1 ] || ci[ 1 ] == ci[ 2 ] || ci[ 2 ] == ci[ 0 ] ) { continue; } for ( k = 0; k < 3; k++ ) { index = ci[ k ]; Com_Memcpy( indexes + indexesOfs, &index, sizeof( int ) ); indexesOfs += sizeof( int ); } } } vboSurf->ibo[ lod ] = R_CreateIBO( va( "staticMDMMesh_IBO_LOD_%f %i", flod, indexesNum / 3 ), indexes, indexesSize, VBO_USAGE_STATIC ); vboSurf->ibo[ lod ]->indexesNum = indexesNum; ri.Hunk_FreeTempMemory( indexes ); if ( vboTriangles->currentElements != surf->numTriangles ) { ri.Printf( PRINT_WARNING, "Can't calculate LOD IBOs\n" ); break; } lod++; } while ( lod < MD3_MAX_LODS ); ri.Hunk_FreeTempMemory( data ); // megs /* ri.Printf(PRINT_ALL, "md5 mesh data VBO size: %d.%02d MB\n", dataSize / (1024 * 1024), (dataSize % (1024 * 1024)) * 100 / (1024 * 1024)); ri.Printf(PRINT_ALL, "md5 mesh tris VBO size: %d.%02d MB\n", indexesSize / (1024 * 1024), (indexesSize % (1024 * 1024)) * 100 / (1024 * 1024)); */ }
void AddSurfaceToVBOSurfacesList(growList_t * vboSurfaces, growList_t * vboTriangles, md5Model_t * md5, md5Surface_t * surf, int skinIndex, int numBoneReferences, int boneReferences[MAX_BONES]) { int j, k; int vertexesNum; byte *data; int dataSize; int dataOfs; GLuint ofsTexCoords; GLuint ofsTangents; GLuint ofsBinormals; GLuint ofsNormals; GLuint ofsColors; GLuint ofsBoneIndexes; GLuint ofsBoneWeights; int indexesNum; byte *indexes; int indexesSize; int indexesOfs; skelTriangle_t *tri; vec4_t tmp; int index; srfVBOMD5Mesh_t *vboSurf; md5Vertex_t *v; vec4_t tmpColor = { 1, 1, 1, 1 }; vertexesNum = surf->numVerts; indexesNum = vboTriangles->currentElements * 3; // create surface vboSurf = ri.Hunk_Alloc(sizeof(*vboSurf), h_low); Com_AddToGrowList(vboSurfaces, vboSurf); vboSurf->surfaceType = SF_VBO_MD5MESH; vboSurf->md5Model = md5; vboSurf->shader = R_GetShaderByHandle(surf->shaderIndex); vboSurf->skinIndex = skinIndex; vboSurf->numIndexes = indexesNum; vboSurf->numVerts = vertexesNum; dataSize = vertexesNum * (sizeof(vec4_t) * 8); data = ri.Hunk_AllocateTempMemory(dataSize); dataOfs = 0; indexesSize = indexesNum * sizeof(int); indexes = ri.Hunk_AllocateTempMemory(indexesSize); indexesOfs = 0; //ri.Printf(PRINT_ALL, "AddSurfaceToVBOSurfacesList( %i verts, %i tris )\n", surf->numVerts, vboTriangles->currentElements); vboSurf->numBoneRemap = 0; Com_Memset(vboSurf->boneRemap, 0, sizeof(vboSurf->boneRemap)); Com_Memset(vboSurf->boneRemapInverse, 0, sizeof(vboSurf->boneRemapInverse)); //ri.Printf(PRINT_ALL, "referenced bones: "); for(j = 0; j < MAX_BONES; j++) { if(boneReferences[j] > 0) { vboSurf->boneRemap[j] = vboSurf->numBoneRemap; vboSurf->boneRemapInverse[vboSurf->numBoneRemap] = j; vboSurf->numBoneRemap++; //ri.Printf(PRINT_ALL, "(%i -> %i) ", j, vboSurf->boneRemap[j]); } } //ri.Printf(PRINT_ALL, "\n"); //for(j = 0, tri = surf->triangles; j < surf->numTriangles; j++, tri++) for(j = 0; j < vboTriangles->currentElements; j++) { tri = Com_GrowListElement(vboTriangles, j); for(k = 0; k < 3; k++) { index = tri->indexes[k]; Com_Memcpy(indexes + indexesOfs, &index, sizeof(int)); indexesOfs += sizeof(int); } } // feed vertex XYZ for(j = 0; j < vertexesNum; j++) { for(k = 0; k < 3; k++) { tmp[k] = surf->verts[j].position[k]; } tmp[3] = 1; Com_Memcpy(data + dataOfs, (vec_t *) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } // feed vertex texcoords ofsTexCoords = dataOfs; for(j = 0; j < vertexesNum; j++) { for(k = 0; k < 2; k++) { tmp[k] = surf->verts[j].texCoords[k]; } tmp[2] = 0; tmp[3] = 1; Com_Memcpy(data + dataOfs, (vec_t *) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } // feed vertex tangents ofsTangents = dataOfs; for(j = 0; j < vertexesNum; j++) { for(k = 0; k < 3; k++) { tmp[k] = surf->verts[j].tangent[k]; } tmp[3] = 1; Com_Memcpy(data + dataOfs, (vec_t *) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } // feed vertex binormals ofsBinormals = dataOfs; for(j = 0; j < vertexesNum; j++) { for(k = 0; k < 3; k++) { tmp[k] = surf->verts[j].binormal[k]; } tmp[3] = 1; Com_Memcpy(data + dataOfs, (vec_t *) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } // feed vertex normals ofsNormals = dataOfs; for(j = 0; j < vertexesNum; j++) { for(k = 0; k < 3; k++) { tmp[k] = surf->verts[j].normal[k]; } tmp[3] = 1; Com_Memcpy(data + dataOfs, (vec_t *) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } // feed vertex colors ofsColors = dataOfs; for(j = 0; j < vertexesNum; j++) { Com_Memcpy(data + dataOfs, tmpColor, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } // feed bone indices ofsBoneIndexes = dataOfs; for(j = 0, v = surf->verts; j < surf->numVerts; j++, v++) { for(k = 0; k < MAX_WEIGHTS; k++) { if(k < v->numWeights) index = vboSurf->boneRemap[v->weights[k]->boneIndex]; else index = 0; Com_Memcpy(data + dataOfs, &index, sizeof(int)); dataOfs += sizeof(int); } } // feed bone weights ofsBoneWeights = dataOfs; for(j = 0, v = surf->verts; j < surf->numVerts; j++, v++) { for(k = 0; k < MAX_WEIGHTS; k++) { if(k < v->numWeights) tmp[k] = v->weights[k]->boneWeight; else tmp[k] = 0; } Com_Memcpy(data + dataOfs, (vec_t *) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } vboSurf->vbo = R_CreateVBO(va("staticMD5Mesh_VBO %i", vboSurfaces->currentElements), data, dataSize, VBO_USAGE_STATIC); vboSurf->vbo->ofsXYZ = 0; vboSurf->vbo->ofsTexCoords = ofsTexCoords; vboSurf->vbo->ofsLightCoords = ofsTexCoords; vboSurf->vbo->ofsTangents = ofsTangents; vboSurf->vbo->ofsBinormals = ofsBinormals; vboSurf->vbo->ofsNormals = ofsNormals; vboSurf->vbo->ofsColors = ofsColors; vboSurf->vbo->ofsLightCoords = ofsColors; // not required anyway vboSurf->vbo->ofsLightDirections = ofsColors; // not required anyway vboSurf->vbo->ofsBoneIndexes = ofsBoneIndexes; vboSurf->vbo->ofsBoneWeights = ofsBoneWeights; vboSurf->ibo = R_CreateIBO(va("staticMD5Mesh_IBO %i", vboSurfaces->currentElements), indexes, indexesSize, VBO_USAGE_STATIC); ri.Hunk_FreeTempMemory(indexes); ri.Hunk_FreeTempMemory(data); // megs /* ri.Printf(PRINT_ALL, "md5 mesh data VBO size: %d.%02d MB\n", dataSize / (1024 * 1024), (dataSize % (1024 * 1024)) * 100 / (1024 * 1024)); ri.Printf(PRINT_ALL, "md5 mesh tris VBO size: %d.%02d MB\n", indexesSize / (1024 * 1024), (indexesSize % (1024 * 1024)) * 100 / (1024 * 1024)); */ }