Exemple #1
0
/*
 * @brief Allocates and populates static VBO's for the specified r_model_t.
 */
static void R_LoadVertexBuffers(r_model_t *mod) {

	if (!qglGenBuffers)
		return;

	if (IS_MESH_MODEL(mod) && mod->mesh->num_frames > 1) // animated models don't use VBO
		return;

	const GLsizei v = mod->num_verts * 3 * sizeof(GLfloat);
	const GLsizei st = mod->num_verts * 2 * sizeof(GLfloat);
	const GLsizei t = mod->num_verts * 4 * sizeof(GLfloat);

	// load the vertex buffer objects
	qglGenBuffers(1, &mod->vertex_buffer);
	qglBindBuffer(GL_ARRAY_BUFFER, mod->vertex_buffer);
	qglBufferData(GL_ARRAY_BUFFER, v, mod->verts, GL_STATIC_DRAW);

	qglGenBuffers(1, &mod->texcoord_buffer);
	qglBindBuffer(GL_ARRAY_BUFFER, mod->texcoord_buffer);
	qglBufferData(GL_ARRAY_BUFFER, st, mod->texcoords, GL_STATIC_DRAW);

	qglGenBuffers(1, &mod->normal_buffer);
	qglBindBuffer(GL_ARRAY_BUFFER, mod->normal_buffer);
	qglBufferData(GL_ARRAY_BUFFER, v, mod->normals, GL_STATIC_DRAW);

	qglGenBuffers(1, &mod->tangent_buffer);
	qglBindBuffer(GL_ARRAY_BUFFER, mod->tangent_buffer);
	qglBufferData(GL_ARRAY_BUFFER, t, mod->tangents, GL_STATIC_DRAW);

	if (mod->lightmap_texcoords) {
		qglGenBuffers(1, &mod->lightmap_texcoord_buffer);
		qglBindBuffer(GL_ARRAY_BUFFER, mod->lightmap_texcoord_buffer);
		qglBufferData(GL_ARRAY_BUFFER, st, mod->lightmap_texcoords, GL_STATIC_DRAW);
	}

	qglBindBuffer(GL_ARRAY_BUFFER, 0);

	R_GetError(mod->media.name);
}
Exemple #2
0
/*
 * R_LoadVertexBuffers
 */
static void R_LoadVertexBuffers(r_model_t *mod) {
	int v, st, t, c;

	if (!qglGenBuffers)
		return;

	if (mod->num_frames > 1) // animated models don't use VBO
		return;

	v = mod->num_verts * 3 * sizeof(GLfloat);
	st = mod->num_verts * 2 * sizeof(GLfloat);
	t = mod->num_verts * 4 * sizeof(GLfloat);
	c = mod->num_verts * 4 * sizeof(GLfloat);

	// load the vertex buffer objects
	qglGenBuffers(1, &mod->vertex_buffer);
	qglBindBuffer(GL_ARRAY_BUFFER, mod->vertex_buffer);
	qglBufferData(GL_ARRAY_BUFFER, v, mod->verts, GL_STATIC_DRAW);

	qglGenBuffers(1, &mod->texcoord_buffer);
	qglBindBuffer(GL_ARRAY_BUFFER, mod->texcoord_buffer);
	qglBufferData(GL_ARRAY_BUFFER, st, mod->texcoords, GL_STATIC_DRAW);

	qglGenBuffers(1, &mod->normal_buffer);
	qglBindBuffer(GL_ARRAY_BUFFER, mod->normal_buffer);
	qglBufferData(GL_ARRAY_BUFFER, v, mod->normals, GL_STATIC_DRAW);

	qglBindBuffer(GL_ARRAY_BUFFER, 0);

	if (mod->type != mod_bsp)
		return;

	// including lightmap coords, tangents, and colors for bsp
	qglGenBuffers(1, &mod->lmtexcoord_buffer);
	qglBindBuffer(GL_ARRAY_BUFFER, mod->lmtexcoord_buffer);
	qglBufferData(GL_ARRAY_BUFFER, st, mod->lmtexcoords, GL_STATIC_DRAW);

	qglGenBuffers(1, &mod->tangent_buffer);
	qglBindBuffer(GL_ARRAY_BUFFER, mod->tangent_buffer);
	qglBufferData(GL_ARRAY_BUFFER, t, mod->tangents, GL_STATIC_DRAW);

	qglGenBuffers(1, &mod->color_buffer);
	qglBindBuffer(GL_ARRAY_BUFFER, mod->color_buffer);
	qglBufferData(GL_ARRAY_BUFFER, c, mod->colors, GL_STATIC_DRAW);

	qglBindBuffer(GL_ARRAY_BUFFER, 0);
}
Exemple #3
0
/**
 * @brief Puts the map data into buffers
 * @sa R_ModAddMapTile
 * @note Shift the verts after the texcoords for diffuse and lightmap are loaded
 * @sa R_ModShiftTile
 * @todo Don't use the buffers from r_state here - they might overflow
 * @todo Decrease MAX_GL_ARRAY_LENGTH to 32768 again when this is fixed
 */
static void R_LoadBspVertexArrays (model_t *mod)
{
	int i, j;
	int vertind, coordind, tangind;
	float *vecShifted;
	float soff, toff, s, t;
	float *point, *sdir, *tdir;
	vec4_t tangent;
	vec3_t binormal;
	mBspSurface_t *surf;
	mBspVertex_t *vert;
	int vertexcount;

	vertind = coordind = tangind = vertexcount = 0;

	for (i = 0, surf = mod->bsp.surfaces; i < mod->bsp.numsurfaces; i++, surf++)
		for (j = 0; j < surf->numedges; j++)
			vertexcount++;

	surf = mod->bsp.surfaces;

	/* allocate the vertex arrays */
	mod->bsp.texcoords = (GLfloat *)Mem_PoolAlloc(vertexcount * 2 * sizeof(GLfloat), vid_modelPool, 0);
	mod->bsp.lmtexcoords = (GLfloat *)Mem_PoolAlloc(vertexcount * 2 * sizeof(GLfloat), vid_modelPool, 0);
	mod->bsp.verts = (GLfloat *)Mem_PoolAlloc(vertexcount * 3 * sizeof(GLfloat), vid_modelPool, 0);
	mod->bsp.normals = (GLfloat *)Mem_PoolAlloc(vertexcount * 3 * sizeof(GLfloat), vid_modelPool, 0);
	mod->bsp.tangents = (GLfloat *)Mem_PoolAlloc(vertexcount * 4 * sizeof(GLfloat), vid_modelPool, 0);

	for (i = 0; i < mod->bsp.numsurfaces; i++, surf++) {
		surf->index = vertind / 3;

		for (j = 0; j < surf->numedges; j++) {
			const float *normal;
			const int index = mod->bsp.surfedges[surf->firstedge + j];

			if (vertind >= MAX_GL_ARRAY_LENGTH * 3)
				Com_Error(ERR_DROP, "R_LoadBspVertexArrays: Exceeded MAX_GL_ARRAY_LENGTH %i", vertind);

			/* vertex */
			if (index > 0) {  /* negative indices to differentiate which end of the edge */
				const mBspEdge_t *edge = &mod->bsp.edges[index];
				vert = &mod->bsp.vertexes[edge->v[0]];
			} else {
				const mBspEdge_t *edge = &mod->bsp.edges[-index];
				vert = &mod->bsp.vertexes[edge->v[1]];
			}

			point = vert->position;

			/* shift it for assembled maps */
			vecShifted = &mod->bsp.verts[vertind];
			/* origin (func_door, func_rotating) bmodels must not have shifted vertices,
			 * they are translated by their entity origin value */
			if (surf->isOriginBrushModel)
				VectorCopy(point, vecShifted);
			else
				VectorAdd(point, shift, vecShifted);

			/* texture directional vectors and offsets */
			sdir = surf->texinfo->uv;
			soff = surf->texinfo->u_offset;

			tdir = surf->texinfo->vv;
			toff = surf->texinfo->v_offset;

			/* texture coordinates */
			s = DotProduct(point, sdir) + soff;
			s /= surf->texinfo->image->width;

			t = DotProduct(point, tdir) + toff;
			t /= surf->texinfo->image->height;

			mod->bsp.texcoords[coordind + 0] = s;
			mod->bsp.texcoords[coordind + 1] = t;

			if (surf->flags & MSURF_LIGHTMAP) {  /* lightmap coordinates */
				s = DotProduct(point, sdir) + soff;
				s -= surf->stmins[0];
				s += surf->light_s * surf->lightmap_scale;
				s += surf->lightmap_scale / 2.0;
				s /= r_lightmaps.size * surf->lightmap_scale;

				t = DotProduct(point, tdir) + toff;
				t -= surf->stmins[1];
				t += surf->light_t * surf->lightmap_scale;
				t += surf->lightmap_scale / 2.0;
				t /= r_lightmaps.size * surf->lightmap_scale;
			}

			mod->bsp.lmtexcoords[coordind + 0] = s;
			mod->bsp.lmtexcoords[coordind + 1] = t;

			/* normal vectors */
			if (surf->texinfo->flags & SURF_PHONG && VectorNotEmpty(vert->normal))
				normal = vert->normal; /* phong shaded */
			else
				normal = surf->normal; /* per plane */

			memcpy(&mod->bsp.normals[vertind], normal, sizeof(vec3_t));

			/* tangent vector */
			TangentVectors(normal, sdir, tdir, tangent, binormal);
			memcpy(&mod->bsp.tangents[tangind], tangent, sizeof(vec4_t));

			vertind += 3;
			coordind += 2;
			tangind += 4;
		}
	}

	if (qglBindBuffer) {
		/* and also the vertex buffer objects */
		qglGenBuffers(1, &mod->bsp.vertex_buffer);
		qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.vertex_buffer);
		qglBufferData(GL_ARRAY_BUFFER, vertind * sizeof(GLfloat), mod->bsp.verts, GL_STATIC_DRAW);

		qglGenBuffers(1, &mod->bsp.texcoord_buffer);
		qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.texcoord_buffer);
		qglBufferData(GL_ARRAY_BUFFER, coordind * sizeof(GLfloat), mod->bsp.texcoords, GL_STATIC_DRAW);

		qglGenBuffers(1, &mod->bsp.lmtexcoord_buffer);
		qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.lmtexcoord_buffer);
		qglBufferData(GL_ARRAY_BUFFER, coordind * sizeof(GLfloat), mod->bsp.lmtexcoords, GL_STATIC_DRAW);

		qglGenBuffers(1, &mod->bsp.normal_buffer);
		qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.normal_buffer);
		qglBufferData(GL_ARRAY_BUFFER, vertind * sizeof(GLfloat), mod->bsp.normals, GL_STATIC_DRAW);

		qglGenBuffers(1, &mod->bsp.tangent_buffer);
		qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.tangent_buffer);
		qglBufferData(GL_ARRAY_BUFFER, tangind * sizeof(GLfloat), mod->bsp.tangents, GL_STATIC_DRAW);

		qglBindBuffer(GL_ARRAY_BUFFER, 0);
	}
}
Exemple #4
0
/*
==============
RB_UpdateTessVao

Adapted from Tess_UpdateVBOs from xreal

Update the default VAO to replace the client side vertex arrays
==============
*/
void RB_UpdateTessVao(unsigned int attribBits)
{
	GLimp_LogComment("--- RB_UpdateTessVao ---\n");

	backEnd.pc.c_dynamicVaoDraws++;

	// update the default VAO
	if(tess.numVertexes > 0 && tess.numVertexes <= SHADER_MAX_VERTEXES && tess.numIndexes > 0 && tess.numIndexes <= SHADER_MAX_INDEXES)
	{
		int attribIndex;
		int attribUpload;

		R_BindVao(tess.vao);

		// orphan old vertex buffer so we don't stall on it
		qglBufferData(GL_ARRAY_BUFFER, tess.vao->vertexesSize, NULL, GL_DYNAMIC_DRAW);

		// if nothing to set, set everything
		if(!(attribBits & ATTR_BITS))
			attribBits = ATTR_BITS;

		attribUpload = attribBits;

		if((attribUpload & ATTR_TEXCOORD) || (attribUpload & ATTR_LIGHTCOORD))
		{
			// these are interleaved, so we update both if either need it
			// this translates to updating ATTR_TEXCOORD twice as large as it needs
			attribUpload &= ~ATTR_LIGHTCOORD;
			attribUpload |= ATTR_TEXCOORD;
		}

		for (attribIndex = 0; attribIndex < ATTR_INDEX_COUNT; attribIndex++)
		{
			uint32_t attribBit = 1 << attribIndex;
			vaoAttrib_t *vAtb = &tess.vao->attribs[attribIndex];

			if (attribUpload & attribBit)
			{
				// note: tess has a VBO where stride == size
				qglBufferSubData(GL_ARRAY_BUFFER, vAtb->offset, tess.numVertexes * vAtb->stride, tess.attribPointers[attribIndex]);
			}

			if (attribBits & attribBit)
			{
				if (!glRefConfig.vertexArrayObject)
					qglVertexAttribPointer(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset));

				if (!(glState.vertexAttribsEnabled & attribBit))
				{
					qglEnableVertexAttribArray(attribIndex);
					glState.vertexAttribsEnabled |= attribBit;
				}
			}
			else
			{
				if ((glState.vertexAttribsEnabled & attribBit))
				{
					qglDisableVertexAttribArray(attribIndex);
					glState.vertexAttribsEnabled &= ~attribBit;
				}
			}
		}

		// orphan old index buffer so we don't stall on it
		qglBufferData(GL_ELEMENT_ARRAY_BUFFER, tess.vao->indexesSize, NULL, GL_DYNAMIC_DRAW);

		qglBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, tess.numIndexes * sizeof(tess.indexes[0]), tess.indexes);
	}
}
Exemple #5
0
/*
============
R_CreateVao2
============
*/
vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int numIndexes, glIndex_t *indexes)
{
	vao_t          *vao;
	int             i;

	byte           *data;
	int             dataSize;
	int             dataOfs;

	int				glUsage = GL_STATIC_DRAW;

	if(!numVertexes || !numIndexes)
		return NULL;

	if(strlen(name) >= MAX_QPATH)
	{
		ri.Error(ERR_DROP, "R_CreateVao2: \"%s\" is too long", name);
	}

	if ( tr.numVaos == MAX_VAOS ) {
		ri.Error( ERR_DROP, "R_CreateVao2: MAX_VAOS hit");
	}

	R_IssuePendingRenderCommands();

	vao = tr.vaos[tr.numVaos] = ri.Hunk_Alloc(sizeof(*vao), h_low);
	tr.numVaos++;

	memset(vao, 0, sizeof(*vao));

	Q_strncpyz(vao->name, name, sizeof(vao->name));

	// since these vertex attributes are never altered, interleave them
	vao->attribs[ATTR_INDEX_POSITION      ].enabled = 1;
	vao->attribs[ATTR_INDEX_NORMAL        ].enabled = 1;
#ifdef USE_VERT_TANGENT_SPACE
	vao->attribs[ATTR_INDEX_TANGENT       ].enabled = 1;
#endif
	vao->attribs[ATTR_INDEX_TEXCOORD      ].enabled = 1;
	vao->attribs[ATTR_INDEX_LIGHTCOORD    ].enabled = 1;
	vao->attribs[ATTR_INDEX_COLOR         ].enabled = 1;
	vao->attribs[ATTR_INDEX_LIGHTDIRECTION].enabled = 1;

	vao->attribs[ATTR_INDEX_POSITION      ].count = 3;
	vao->attribs[ATTR_INDEX_NORMAL        ].count = 4;
	vao->attribs[ATTR_INDEX_TANGENT       ].count = 4;
	vao->attribs[ATTR_INDEX_TEXCOORD      ].count = 2;
	vao->attribs[ATTR_INDEX_LIGHTCOORD    ].count = 2;
	vao->attribs[ATTR_INDEX_COLOR         ].count = 4;
	vao->attribs[ATTR_INDEX_LIGHTDIRECTION].count = 4;

	vao->attribs[ATTR_INDEX_POSITION      ].type = GL_FLOAT;
	vao->attribs[ATTR_INDEX_NORMAL        ].type = glRefConfig.packedNormalDataType;
	vao->attribs[ATTR_INDEX_TANGENT       ].type = glRefConfig.packedNormalDataType;
	vao->attribs[ATTR_INDEX_TEXCOORD      ].type = glRefConfig.packedTexcoordDataType;
	vao->attribs[ATTR_INDEX_LIGHTCOORD    ].type = glRefConfig.packedTexcoordDataType;
	vao->attribs[ATTR_INDEX_COLOR         ].type = glRefConfig.packedColorDataType;
	vao->attribs[ATTR_INDEX_LIGHTDIRECTION].type = glRefConfig.packedNormalDataType;

	vao->attribs[ATTR_INDEX_POSITION      ].normalized = GL_FALSE;
	vao->attribs[ATTR_INDEX_NORMAL        ].normalized = GL_TRUE;
	vao->attribs[ATTR_INDEX_TANGENT       ].normalized = GL_TRUE;
	vao->attribs[ATTR_INDEX_TEXCOORD      ].normalized = GL_FALSE;
	vao->attribs[ATTR_INDEX_LIGHTCOORD    ].normalized = GL_FALSE;
	vao->attribs[ATTR_INDEX_COLOR         ].normalized = GL_FALSE;
	vao->attribs[ATTR_INDEX_LIGHTDIRECTION].normalized = GL_TRUE;

	vao->attribs[ATTR_INDEX_POSITION      ].offset = 0;        dataSize  = sizeof(verts[0].xyz);
	vao->attribs[ATTR_INDEX_NORMAL        ].offset = dataSize; dataSize += sizeof(uint32_t);
#ifdef USE_VERT_TANGENT_SPACE
	vao->attribs[ATTR_INDEX_TANGENT       ].offset = dataSize; dataSize += sizeof(uint32_t);
#endif
	vao->attribs[ATTR_INDEX_TEXCOORD      ].offset = dataSize; dataSize += glRefConfig.packedTexcoordDataSize;
	vao->attribs[ATTR_INDEX_LIGHTCOORD    ].offset = dataSize; dataSize += glRefConfig.packedTexcoordDataSize;
	vao->attribs[ATTR_INDEX_COLOR         ].offset = dataSize; dataSize += glRefConfig.packedColorDataSize;
	vao->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = dataSize; dataSize += sizeof(uint32_t);

	vao->attribs[ATTR_INDEX_POSITION      ].stride = dataSize;
	vao->attribs[ATTR_INDEX_NORMAL        ].stride = dataSize;
	vao->attribs[ATTR_INDEX_TANGENT       ].stride = dataSize;
	vao->attribs[ATTR_INDEX_TEXCOORD      ].stride = dataSize;
	vao->attribs[ATTR_INDEX_LIGHTCOORD    ].stride = dataSize;
	vao->attribs[ATTR_INDEX_COLOR         ].stride = dataSize;
	vao->attribs[ATTR_INDEX_LIGHTDIRECTION].stride = dataSize;


	if (glRefConfig.vertexArrayObject)
	{
		qglGenVertexArrays(1, &vao->vao);
		qglBindVertexArray(vao->vao);
	}


	// create VBO
	dataSize *= numVertexes;
	data = ri.Hunk_AllocateTempMemory(dataSize);
	dataOfs = 0;

	for (i = 0; i < numVertexes; i++)
	{
		// xyz
		memcpy(data + dataOfs, &verts[i].xyz, sizeof(verts[i].xyz));
		dataOfs += sizeof(verts[i].xyz);

		// normal
		dataOfs += R_VaoPackNormal(data + dataOfs, verts[i].normal);

#ifdef USE_VERT_TANGENT_SPACE
		// tangent
		dataOfs += R_VaoPackTangent(data + dataOfs, verts[i].tangent);
#endif

		// texcoords
		dataOfs += R_VaoPackTexCoord(data + dataOfs, verts[i].st);

		// lightmap texcoords
		dataOfs += R_VaoPackTexCoord(data + dataOfs, verts[i].lightmap);

		// colors
		dataOfs += R_VaoPackColors(data + dataOfs, verts[i].vertexColors);

		// light directions
		dataOfs += R_VaoPackNormal(data + dataOfs, verts[i].lightdir);
	}

	vao->vertexesSize = dataSize;

	qglGenBuffers(1, &vao->vertexesVBO);

	qglBindBuffer(GL_ARRAY_BUFFER, vao->vertexesVBO);
	qglBufferData(GL_ARRAY_BUFFER, vao->vertexesSize, data, glUsage);


	// create IBO
	vao->indexesSize = numIndexes * sizeof(glIndex_t);

	qglGenBuffers(1, &vao->indexesIBO);

	qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vao->indexesIBO);
	qglBufferData(GL_ELEMENT_ARRAY_BUFFER, vao->indexesSize, indexes, glUsage);


	Vao_SetVertexPointers(vao);


	glState.currentVao = vao;

	GL_CheckErrors();

	ri.Hunk_FreeTempMemory(data);

	return vao;
}
Exemple #6
0
/*
============
R_CreateVao
============
*/
vao_t *R_CreateVao(const char *name, byte *vertexes, int vertexesSize, byte *indexes, int indexesSize, vaoUsage_t usage)
{
	vao_t          *vao;
	int				glUsage;

	switch (usage)
	{
		case VAO_USAGE_STATIC:
			glUsage = GL_STATIC_DRAW;
			break;

		case VAO_USAGE_DYNAMIC:
			glUsage = GL_DYNAMIC_DRAW;
			break;

		default:
			Com_Error(ERR_FATAL, "bad vaoUsage_t given: %i", usage);
			return NULL;
	}

	if(strlen(name) >= MAX_QPATH)
	{
		ri.Error(ERR_DROP, "R_CreateVao: \"%s\" is too long", name);
	}

	if ( tr.numVaos == MAX_VAOS ) {
		ri.Error( ERR_DROP, "R_CreateVao: MAX_VAOS hit");
	}

	R_IssuePendingRenderCommands();

	vao = tr.vaos[tr.numVaos] = ri.Hunk_Alloc(sizeof(*vao), h_low);
	tr.numVaos++;

	memset(vao, 0, sizeof(*vao));

	Q_strncpyz(vao->name, name, sizeof(vao->name));


	if (glRefConfig.vertexArrayObject)
	{
		qglGenVertexArrays(1, &vao->vao);
		qglBindVertexArray(vao->vao);
	}


	vao->vertexesSize = vertexesSize;

	qglGenBuffers(1, &vao->vertexesVBO);

	qglBindBuffer(GL_ARRAY_BUFFER, vao->vertexesVBO);
	qglBufferData(GL_ARRAY_BUFFER, vertexesSize, vertexes, glUsage);


	vao->indexesSize = indexesSize;

	qglGenBuffers(1, &vao->indexesIBO);

	qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vao->indexesIBO);
	qglBufferData(GL_ELEMENT_ARRAY_BUFFER, indexesSize, indexes, glUsage);


	glState.currentVao = vao;

	GL_CheckErrors();

	return vao;
}
/**
 * @brief Puts the map data into buffers
 * @sa R_ModAddMapTile
 * @note Shift the verts after the texcoords for diffuse and lightmap are loaded
 * @sa R_ModShiftTile
 * @todo Don't use the buffers from r_state here - they might overflow
 * @todo Decrease MAX_GL_ARRAY_LENGTH to 32768 again when this is fixed
 */
static void R_LoadBspVertexArrays (model_t *mod)
{
	int i, j;
	int vertOfs, texCoordOfs, tangOfs;
	float *vecShifted;
	float soff, toff, s, t;
	float *point, *sdir, *tdir;
	vec4_t tangent;
	vec3_t binormal;
	mBspSurface_t *surf;
	mBspVertex_t *vert;
	int vertexCount, indexCount;

	vertOfs = texCoordOfs = tangOfs = 0;
	vertexCount = indexCount = 0;

	for (i = 0, surf = mod->bsp.surfaces; i < mod->bsp.numsurfaces; i++, surf++) {
		const int numedges = surf->numedges;
		vertexCount += numedges;
		if (numedges > 2) /* no triangles for degenerate polys */
			indexCount += (numedges - 2) * 3;
	}

	surf = mod->bsp.surfaces;

	/* allocate the vertex arrays */
	mod->bsp.texcoords   = Mem_PoolAllocTypeN(GLfloat, vertexCount * 2, vid_modelPool);
	mod->bsp.lmtexcoords = Mem_PoolAllocTypeN(GLfloat, vertexCount * 2, vid_modelPool);
	mod->bsp.verts       = Mem_PoolAllocTypeN(GLfloat, vertexCount * 3, vid_modelPool);
	mod->bsp.normals     = Mem_PoolAllocTypeN(GLfloat, vertexCount * 3, vid_modelPool);
	mod->bsp.tangents    = Mem_PoolAllocTypeN(GLfloat, vertexCount * 4, vid_modelPool);
	mod->bsp.indexes    = Mem_PoolAllocTypeN(GLint, indexCount, vid_modelPool); /* Will be filled at the end of map loading, after building surface lists */

	for (i = 0; i < mod->bsp.numsurfaces; i++, surf++) {
		surf->index = vertOfs / 3;
		surf->firstTriangle = -1; /* Mark as "no triangles generated yet" */

		for (j = 0; j < surf->numedges; j++) {
			const float *normal;
			const int index = mod->bsp.surfedges[surf->firstedge + j];

			/* vertex */
			if (index > 0) {  /* negative indices to differentiate which end of the edge */
				const mBspEdge_t *edge = &mod->bsp.edges[index];
				vert = &mod->bsp.vertexes[edge->v[0]];
			} else {
				const mBspEdge_t *edge = &mod->bsp.edges[-index];
				vert = &mod->bsp.vertexes[edge->v[1]];
			}

			point = vert->position;

			/* shift it for assembled maps */
			vecShifted = &mod->bsp.verts[vertOfs];
			/* origin (func_door, func_rotating) bmodels must not have shifted vertices,
			 * they are translated by their entity origin value */
			if (surf->isOriginBrushModel)
				VectorCopy(point, vecShifted);
			else
				VectorAdd(point, shift, vecShifted);

			/* texture directional vectors and offsets */
			sdir = surf->texinfo->uv;
			soff = surf->texinfo->u_offset;

			tdir = surf->texinfo->vv;
			toff = surf->texinfo->v_offset;

			/* texture coordinates */
			s = DotProduct(point, sdir) + soff;
			s /= surf->texinfo->image->width;

			t = DotProduct(point, tdir) + toff;
			t /= surf->texinfo->image->height;

			mod->bsp.texcoords[texCoordOfs + 0] = s;
			mod->bsp.texcoords[texCoordOfs + 1] = t;

			if (surf->flags & MSURF_LIGHTMAP) {  /* lightmap coordinates */
				s = DotProduct(point, sdir) + soff;
				s -= surf->stmins[0];
				s += surf->light_s * surf->lightmap_scale;
				s += surf->lightmap_scale / 2.0;
				s /= r_lightmaps.size * surf->lightmap_scale;

				t = DotProduct(point, tdir) + toff;
				t -= surf->stmins[1];
				t += surf->light_t * surf->lightmap_scale;
				t += surf->lightmap_scale / 2.0;
				t /= r_lightmaps.size * surf->lightmap_scale;
			}

			mod->bsp.lmtexcoords[texCoordOfs + 0] = s;
			mod->bsp.lmtexcoords[texCoordOfs + 1] = t;

			/* normal vectors */
			if ((surf->texinfo->flags & SURF_PHONG) && VectorNotEmpty(vert->normal))
				normal = vert->normal; /* phong shaded */
			else
				normal = surf->normal; /* per plane */

			memcpy(&mod->bsp.normals[vertOfs], normal, sizeof(vec3_t));

			/* tangent vector */
			TangentVectors(normal, sdir, tdir, tangent, binormal);
			memcpy(&mod->bsp.tangents[tangOfs], tangent, sizeof(vec4_t));

			vertOfs += 3;
			texCoordOfs += 2;
			tangOfs += 4;
		}
	}

	R_ReallocateStateArrays(vertOfs / 3);

	if (qglBindBuffer) {
		/* and also the vertex buffer objects */
		qglGenBuffers(1, &mod->bsp.vertex_buffer);
		qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.vertex_buffer);
		qglBufferData(GL_ARRAY_BUFFER, vertOfs * sizeof(GLfloat), mod->bsp.verts, GL_STATIC_DRAW);

		qglGenBuffers(1, &mod->bsp.texcoord_buffer);
		qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.texcoord_buffer);
		qglBufferData(GL_ARRAY_BUFFER, texCoordOfs * sizeof(GLfloat), mod->bsp.texcoords, GL_STATIC_DRAW);

		qglGenBuffers(1, &mod->bsp.lmtexcoord_buffer);
		qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.lmtexcoord_buffer);
		qglBufferData(GL_ARRAY_BUFFER, texCoordOfs * sizeof(GLfloat), mod->bsp.lmtexcoords, GL_STATIC_DRAW);

		qglGenBuffers(1, &mod->bsp.normal_buffer);
		qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.normal_buffer);
		qglBufferData(GL_ARRAY_BUFFER, vertOfs * sizeof(GLfloat), mod->bsp.normals, GL_STATIC_DRAW);

		qglGenBuffers(1, &mod->bsp.tangent_buffer);
		qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.tangent_buffer);
		qglBufferData(GL_ARRAY_BUFFER, tangOfs * sizeof(GLfloat), mod->bsp.tangents, GL_STATIC_DRAW);

		qglBindBuffer(GL_ARRAY_BUFFER, 0);
	}
}
Exemple #8
0
/**
 * @brief Re-initializes OpenGL state machine, all textures and renderer variables, this needed when application is put to background on Android.
 */
void R_ReinitOpenglContext (void)
{
	/* De-allocate old GL state, these functinos will call glDeleteTexture(), so they should go before everything else */
	R_FontCleanCache();
	R_ShutdownFBObjects();
	R_ShutdownPrograms();
	R_BeginBuildingLightmaps(); /* This function will also call glDeleteTexture() */
	/* Re-initialize GL state */
	R_SetDefaultState();
	R_InitPrograms();
	/* Re-upload all textures */
	R_InitMiscTexture();
	R_ReloadImages();
	/* Re-upload other GL stuff */
	R_InitFBObjects();
	R_UpdateDefaultMaterial("", "", "", NULL);

	/* Re-upload the battlescape terrain geometry */
	if (!qglBindBuffer)
		return;

	for (int tile = 0; tile < r_numMapTiles; tile++) {
		model_t *mod = r_mapTiles[tile];

		int vertind = 0, coordind = 0, tangind = 0;
		mBspSurface_t *surf = mod->bsp.surfaces;

		for (int i = 0; i < mod->bsp.numsurfaces; i++, surf++) {
			vertind += 3 * surf->numedges;
			coordind += 2 * surf->numedges;
			tangind += 4 * surf->numedges;
		}

		qglGenBuffers(1, &mod->bsp.vertex_buffer);
		qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.vertex_buffer);
		qglBufferData(GL_ARRAY_BUFFER, vertind * sizeof(GLfloat), mod->bsp.verts, GL_STATIC_DRAW);

		qglGenBuffers(1, &mod->bsp.texcoord_buffer);
		qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.texcoord_buffer);
		qglBufferData(GL_ARRAY_BUFFER, coordind * sizeof(GLfloat), mod->bsp.texcoords, GL_STATIC_DRAW);

		qglGenBuffers(1, &mod->bsp.lmtexcoord_buffer);
		qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.lmtexcoord_buffer);
		qglBufferData(GL_ARRAY_BUFFER, coordind * sizeof(GLfloat), mod->bsp.lmtexcoords, GL_STATIC_DRAW);

		qglGenBuffers(1, &mod->bsp.normal_buffer);
		qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.normal_buffer);
		qglBufferData(GL_ARRAY_BUFFER, vertind * sizeof(GLfloat), mod->bsp.normals, GL_STATIC_DRAW);

		qglGenBuffers(1, &mod->bsp.tangent_buffer);
		qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.tangent_buffer);
		qglBufferData(GL_ARRAY_BUFFER, tangind * sizeof(GLfloat), mod->bsp.tangents, GL_STATIC_DRAW);

		qglGenBuffers(1, &mod->bsp.index_buffer);
		qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mod->bsp.index_buffer);
		qglBufferData(GL_ELEMENT_ARRAY_BUFFER, mod->bsp.numIndexes * sizeof(GLushort), mod->bsp.indexes, GL_STATIC_DRAW);
		qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

		for (int i = 0; i < mod->bsp.numsurfaces; i++)
			R_CreateSurfaceLightmap(&mod->bsp.surfaces[i]);
	}

	R_EndBuildingLightmaps();
	qglBindBuffer(GL_ARRAY_BUFFER, 0);
}