Example #1
0
/*
* RB_UploadQuadIndicesToStream
*/
static void RB_UploadStaticQuadIndices( void )
{
	int leftVerts, numVerts, numElems;
	int vertsOffset, elemsOffset;
	mesh_t mesh;
	mesh_vbo_t *vbo = rb.streamVBOs[-RB_VBO_STREAM_QUAD - 1];

	assert( MAX_BATCH_VERTS < MAX_STREAM_VBO_VERTS );

	vertsOffset = 0;
	elemsOffset = 0;
	
	memset( &mesh, 0, sizeof( mesh ) );

	for( leftVerts = MAX_STREAM_VBO_VERTS; leftVerts > 0; leftVerts -= numVerts ) {
		numVerts = min( MAX_BATCH_VERTS, leftVerts );
		numElems = numVerts/4*6;

		mesh.numElems = numElems;
		mesh.numVerts = numVerts;

		R_UploadVBOElemData( vbo, vertsOffset, elemsOffset, &mesh, VBO_HINT_ELEMS_QUAD );
		vertsOffset += numVerts;
		elemsOffset += numElems;
	}
}
Example #2
0
/*
* Mod_SkeletalBuildStaticVBOForMesh
* 
* Builds a static vertex buffer object for given skeletal model mesh
*/
static void Mod_SkeletalBuildStaticVBOForMesh( mskmesh_t *mesh )
{
	mesh_t skmmesh;
	vattribmask_t vattribs;
	
	vattribs = VATTRIB_POSITION_BIT | VATTRIB_TEXCOORDS_BIT | VATTRIB_NORMAL_BIT | VATTRIB_SVECTOR_BIT;
	vattribs |= VATTRIB_BONES_BITS;
	vattribs |= mesh->skin.shader->vattribs;

	mesh->vbo = R_CreateMeshVBO( ( void * )mesh, 
		mesh->numverts, mesh->numtris * 3, 0, vattribs, VBO_TAG_MODEL, vattribs );

	if( !mesh->vbo ) {
		return;
	}

	memset( &skmmesh, 0, sizeof( skmmesh ) );

	skmmesh.elems = mesh->elems;
	skmmesh.numElems = mesh->numtris * 3;
	skmmesh.numVerts = mesh->numverts;

	skmmesh.xyzArray = mesh->xyzArray;
	skmmesh.stArray = mesh->stArray;
	skmmesh.normalsArray = mesh->normalsArray;
	skmmesh.sVectorsArray = mesh->sVectorsArray;

	R_UploadVBOVertexData( mesh->vbo, 0, vattribs, &skmmesh, VBO_HINT_NONE ); 
	R_UploadVBOElemData( mesh->vbo, 0, 0, &skmmesh, VBO_HINT_NONE );
	if( glConfig.maxGLSLBones > 0 ) {
	    R_UploadVBOBonesData( mesh->vbo, 0, mesh->numverts, mesh->blendIndices, mesh->blendWeights );
	}
}
Example #3
0
/*
* Mod_AliasBuildStaticVBOForMesh
* 
* Builds a static vertex buffer object for given alias model mesh
*/
static void Mod_AliasBuildStaticVBOForMesh( maliasmesh_t *mesh )
{
	int i;
	mesh_t aliasmesh;
	vattribmask_t vattribs;
	
	vattribs = VATTRIB_TEXCOORDS_BIT | VATTRIB_NORMAL_BIT | VATTRIB_SVECTOR_BIT;
	for( i = 0; i < mesh->numskins; i++ ) {
		vattribs |= mesh->skins[i].shader->vattribs;
	}

	mesh->vbo = R_CreateMeshVBO( ( void * )mesh, 
		mesh->numverts, mesh->numtris * 3, 0, vattribs, VBO_TAG_MODEL );

	if( !mesh->vbo ) {
		return;
	}

	memset( &aliasmesh, 0, sizeof( aliasmesh ) );

	aliasmesh.elems = mesh->elems;
	aliasmesh.numElems = mesh->numtris * 3;
	aliasmesh.numVerts = mesh->numverts;

	aliasmesh.xyzArray = mesh->xyzArray;
	aliasmesh.stArray = mesh->stArray;
	aliasmesh.normalsArray = mesh->normalsArray;
	aliasmesh.sVectorsArray = mesh->sVectorsArray;

	R_UploadVBOVertexData( mesh->vbo, 0, vattribs, &aliasmesh, VBO_HINT_NONE );
	R_UploadVBOElemData( mesh->vbo, 0, 0, &aliasmesh, VBO_HINT_NONE );
}
Example #4
0
/*
* Mod_AliasBuildStaticVBOForMesh
* 
* Builds a static vertex buffer object for given alias model mesh
*/
static void Mod_AliasBuildStaticVBOForMesh( maliasmesh_t *mesh )
{
	mesh_t aliasmesh;

	mesh->vbo = R_CreateStaticMeshVBO( ( void * )mesh, 
		mesh->numverts, mesh->numtris * 3, MF_STCOORDS | (mesh->sVectorsArray ? MF_SVECTORS : 0), VBO_TAG_MODEL );
	if( !mesh->vbo ) {
		return;
	}

	aliasmesh.elems = mesh->elems;
	aliasmesh.numElems = mesh->numtris * 3;
	aliasmesh.numVerts = mesh->numverts;

	aliasmesh.xyzArray = mesh->xyzArray;
	aliasmesh.stArray = mesh->stArray;
	aliasmesh.normalsArray = mesh->normalsArray;
	aliasmesh.sVectorsArray = mesh->sVectorsArray;

	R_UploadVBOVertexData( mesh->vbo, 0, &aliasmesh ); 
	R_UploadVBOElemData( mesh->vbo, 0, 0, &aliasmesh );
}
Example #5
0
/*
* RB_FlushDynamicMeshes
*/
void RB_FlushDynamicMeshes( void )
{
    int i, numDraws = rb.numDynamicDraws;
    rbDynamicStream_t *stream;
    rbDynamicDraw_t *draw;
    int sx, sy, sw, sh;
    float offsetx = 0.0f, offsety = 0.0f, transx, transy;
    mat4_t m;

    if( !numDraws ) {
        return;
    }

    for( i = 0; i < RB_VBO_NUM_STREAMS; i++ ) {
        stream = &rb.dynamicStreams[i];

        // R_UploadVBO* are going to rebind buffer arrays for upload
        // so update our local VBO state cache by calling RB_BindVBO
        RB_BindVBO( -i - 1, GL_TRIANGLES ); // dummy value for primitive here

        // because of firstVert, upload elems first
        if( stream->drawElements.numElems ) {
            mesh_t elemMesh;
            memset( &elemMesh, 0, sizeof( elemMesh ) );
            elemMesh.elems = dynamicStreamElems[i] + stream->drawElements.firstElem;
            elemMesh.numElems = stream->drawElements.numElems;
            R_UploadVBOElemData( stream->vbo, 0, stream->drawElements.firstElem, &elemMesh );
            stream->drawElements.firstElem += stream->drawElements.numElems;
            stream->drawElements.numElems = 0;
        }

        if( stream->drawElements.numVerts ) {
            R_UploadVBOVertexRawData( stream->vbo, stream->drawElements.firstVert, stream->drawElements.numVerts,
                                      stream->vertexData + stream->drawElements.firstVert * stream->vbo->vertexSize );
            stream->drawElements.firstVert += stream->drawElements.numVerts;
            stream->drawElements.numVerts = 0;
        }
    }

    RB_GetScissor( &sx, &sy, &sw, &sh );

    Matrix4_Copy( rb.objectMatrix, m );
    transx = m[12];
    transy = m[13];

    for( i = 0, draw = rb.dynamicDraws; i < numDraws; i++, draw++ ) {
        RB_BindShader( draw->entity, draw->shader, draw->fog );
        RB_BindVBO( draw->streamId, draw->primitive );
        RB_SetPortalSurface( draw->portalSurface );
        RB_SetShadowBits( draw->shadowBits );
        RB_Scissor( draw->scissor[0], draw->scissor[1], draw->scissor[2], draw->scissor[3] );

        // translate the mesh in 2D
        if( ( offsetx != draw->offset[0] ) || ( offsety != draw->offset[1] ) ) {
            offsetx = draw->offset[0];
            offsety = draw->offset[1];
            m[12] = transx + offsetx;
            m[13] = transy + offsety;
            RB_LoadObjectMatrix( m );
        }

        RB_DrawElements(
            draw->drawElements.firstVert, draw->drawElements.numVerts,
            draw->drawElements.firstElem, draw->drawElements.numElems,
            draw->drawElements.firstVert, draw->drawElements.numVerts,
            draw->drawElements.firstElem, draw->drawElements.numElems );
    }

    rb.numDynamicDraws = 0;

    RB_Scissor( sx, sy, sw, sh );

    // restore the original translation in the object matrix if it has been changed
    if( offsetx || offsety ) {
        m[12] = transx;
        m[13] = transy;
        RB_LoadObjectMatrix( m );
    }
}
Example #6
0
/*
* RB_UploadMesh
*/
void RB_UploadMesh( const mesh_t *mesh )
{
	int stream;
	mesh_vbo_t *vbo;
	vboSlice_t *offset;
	vbo_hint_t vbo_hint = VBO_HINT_NONE;
	int numVerts = mesh->numVerts, numElems = mesh->numElems;

	assert( rb.currentVBOId < RB_VBO_NONE );
	if( rb.currentVBOId >= RB_VBO_NONE ) {
		return;
	}
	
	if( rb.currentVBOId == RB_VBO_STREAM_QUAD ) {
		numElems = numVerts/4*6;
	} else if( !numElems && rb.currentVBOId == RB_VBO_STREAM ) {
		numElems = (max(numVerts, 2) - 2) * 3;
	}

	if( !numVerts || !numElems ) {
		return;
	}

	vbo = rb.currentVBO;
	stream = -rb.currentVBOId - 1;
	offset = &rb.streamOffset[stream];

	if( offset->firstVert+offset->numVerts+numVerts > MAX_STREAM_VBO_VERTS || 
		offset->firstElem+offset->numVerts+numElems > MAX_STREAM_VBO_ELEMENTS ) {

		RB_DrawElements( offset->firstVert, offset->numVerts, 
			offset->firstElem, offset->numElems );

		R_DiscardVBOVertexData( vbo );
		if( rb.currentVBOId != RB_VBO_STREAM_QUAD ) {
			R_DiscardVBOElemData( vbo );
		}

		offset->firstVert = 0;
		offset->firstElem = 0;
		offset->numVerts = 0;
		offset->numElems = 0;
	}

	if( numVerts > MAX_STREAM_VBO_VERTS ||
		numElems > MAX_STREAM_VBO_ELEMENTS ) {
		// FIXME: do something about this?
		return;
	}

	if( rb.currentVBOId == RB_VBO_STREAM_QUAD ) {
		vbo_hint = VBO_HINT_ELEMS_QUAD;

		// quad indices are stored in a static vbo, don't call R_UploadVBOElemData
	} else {
		if( mesh->elems ) {
			vbo_hint = VBO_HINT_NONE;
		} else if( rb.currentVBOId == RB_VBO_STREAM ) {
			vbo_hint = VBO_HINT_ELEMS_TRIFAN;
		} else {
			assert( 0 );
		}
		R_UploadVBOElemData( vbo, offset->firstVert + offset->numVerts, 
			offset->firstElem + offset->numElems, mesh, vbo_hint );
	}

	R_UploadVBOVertexData( vbo, offset->firstVert + offset->numVerts, 
		rb.currentVAttribs, mesh, vbo_hint );

	offset->numElems += numElems;
	offset->numVerts += numVerts;
}
Example #7
0
/*
* Gen_BoxSide
*
* I don't know exactly what Q3A does for skybox texturing, but
* this is at least fairly close.  We tile the texture onto the
* inside of a large sphere, and put the camera near the top of
* the sphere. We place the box around the camera, and cast rays
* through the box verts to the sphere to find the texture coordinates.
*/
static void Gen_BoxSide( skydome_t *skydome, int side, vec3_t orig, vec3_t drow, vec3_t dcol ) {
	vec3_t pos, w, row, norm;
	float *v, *n, *st = NULL, *st2;
	int r, c;
	float t, d, d2, b, b2, q[2], s;
	elem_t *elem;
	mesh_t *mesh = &( skydome->meshes[side] );

	s = 1.0 / ( SIDE_SIZE - 1 );
	d = EYE_RAD; // sphere center to camera distance
	d2 = d * d;
	b = SPHERE_RAD; // sphere radius
	b2 = b * b;
	q[0] = 1.0 / ( 2.0 * SCALE_S );
	q[1] = 1.0 / ( 2.0 * SCALE_T );

	v = mesh->xyzArray[0];
	n = mesh->normalsArray[0];
	if( side != 5 ) {
		st = skydome->sphereStCoords[side][0];
	}
	st2 = skydome->linearStCoords[side][0];

	VectorCopy( orig, row );

//	CrossProduct( dcol, drow, norm );
//	VectorNormalize( norm );
	VectorClear( norm );

	for( r = 0; r < SIDE_SIZE; r++ ) {
		VectorCopy( row, pos );
		for( c = 0; c < SIDE_SIZE; c++ ) {
			// pos points from eye to vertex on box
			VectorCopy( pos, v );
			VectorCopy( pos, w );

			// Normalize pos -> w
			VectorNormalize( w );

			// Find distance along w to sphere
			t = sqrt( d2 * ( w[2] * w[2] - 1.0 ) + b2 ) - d * w[2];
			w[0] *= t;
			w[1] *= t;

			if( st ) {
				// use x and y on sphere as s and t
				// minus is here so skies scoll in correct (Q3A's) direction
				st[0] = -w[0] * q[0];
				st[1] = -w[1] * q[1];

				// avoid bilerp seam
				st[0] = ( bound( -1, st[0], 1 ) + 1.0 ) * 0.5;
				st[1] = ( bound( -1, st[1], 1 ) + 1.0 ) * 0.5;
			}

			st2[0] = c * s;
			st2[1] = 1.0 - r * s;

			VectorAdd( pos, dcol, pos );
			VectorCopy( norm, n );

			v[3] = 0; // set w-coordinate to 0 for infinite farclip
			n[3] = 0;

			v += 4;
			n += 4;
			if( st ) {
				st += 2;
			}
			st2 += 2;
		}

		VectorAdd( row, drow, row );
	}

	// elements in tristrip order
	elem = mesh->elems;
	for( r = 0; r < SIDE_SIZE - 1; r++ ) {
		for( c = 0; c < SIDE_SIZE - 1; c++ ) {
			elem[0] = r * SIDE_SIZE + c;
			elem[1] = elem[4] = elem[0] + SIDE_SIZE;
			elem[2] = elem[3] = elem[0] + 1;
			elem[5] = elem[1] + 1;
			elem += 6;
		}
	}

	// upload two static VBO's for each side except for the bottom one
	// which only has 1 side for skybox
	if( side != 5 ) {
		mesh->stArray = skydome->sphereStCoords[side];
		R_UploadVBOVertexData( skydome->sphereVbos[side], 0, SKYDOME_VATTRIBS, mesh );
		R_UploadVBOElemData( skydome->sphereVbos[side], 0, 0, mesh );
	}

	skydome->meshes[side].stArray = skydome->linearStCoords[side];
	R_UploadVBOVertexData( skydome->linearVbos[side], 0, SKYDOME_VATTRIBS, mesh );
	R_UploadVBOElemData( skydome->linearVbos[side], 0, 0, mesh );
}