Beispiel #1
0
/*
=============
GL_DrawAliasFrameLerp

interpolates between two frames and origins
FIXME: batch lerp all vertexes
=============
*/
void GL_DrawAliasFrameLerp (dmdl_t *paliashdr, float backlerp)
{
    float 	l;
    daliasframe_t	*frame, *oldframe;
    dtrivertx_t	*v, *ov, *verts;
    int		*order;
    int		count;
    float	frontlerp;
    float	alpha;
    vec3_t	move, delta, vectors[3];
    vec3_t	frontv, backv;
    int		i;
    int		index_xyz;
    float	*lerp;

    frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
                              + currententity->frame * paliashdr->framesize);
    verts = v = frame->verts;

    oldframe = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
                                 + currententity->oldframe * paliashdr->framesize);
    ov = oldframe->verts;

    order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds);

//	glTranslatef (frame->translate[0], frame->translate[1], frame->translate[2]);
//	glScalef (frame->scale[0], frame->scale[1], frame->scale[2]);

    if (currententity->flags & RF_TRANSLUCENT)
        alpha = currententity->alpha;
    else
        alpha = 1.0;

    // PMM - added double shell
    if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
        qglDisable( GL_TEXTURE_2D );

    frontlerp = 1.0 - backlerp;

    // move should be the delta back to the previous frame * backlerp
    VectorSubtract (currententity->oldorigin, currententity->origin, delta);
    AngleVectors (currententity->angles, vectors[0], vectors[1], vectors[2]);

    move[0] = DotProduct (delta, vectors[0]);	// forward
    move[1] = -DotProduct (delta, vectors[1]);	// left
    move[2] = DotProduct (delta, vectors[2]);	// up

    VectorAdd (move, oldframe->translate, move);

    for (i=0 ; i<3 ; i++)
    {
        move[i] = backlerp*move[i] + frontlerp*frame->translate[i];
    }

    for (i=0 ; i<3 ; i++)
    {
        frontv[i] = frontlerp*frame->scale[i];
        backv[i] = backlerp*oldframe->scale[i];
    }

    lerp = s_lerped[0];

    GL_LerpVerts( paliashdr->num_xyz, v, ov, verts, lerp, move, frontv, backv );

    if ( gl_vertex_arrays->value )
    {
        float colorArray[MAX_VERTS*4];

        qglEnableClientState( GL_VERTEX_ARRAY );
        qglVertexPointer( 3, GL_FLOAT, 16, s_lerped );	// padded for SIMD

//		if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) )
        // PMM - added double damage shell
        if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
        {
            qglColor4f( shadelight[0], shadelight[1], shadelight[2], alpha );
        }
        else
        {
            qglEnableClientState( GL_COLOR_ARRAY );
            qglColorPointer( 3, GL_FLOAT, 0, colorArray );

            //
            // pre light everything
            //
            for ( i = 0; i < paliashdr->num_xyz; i++ )
            {
                float l = shadedots[verts[i].lightnormalindex];

                colorArray[i*3+0] = l * shadelight[0];
                colorArray[i*3+1] = l * shadelight[1];
                colorArray[i*3+2] = l * shadelight[2];
            }
        }

        if ( qglLockArraysEXT != 0 )
            qglLockArraysEXT( 0, paliashdr->num_xyz );

        while (1)
        {
            // get the vertex count and primitive type
            count = *order++;
            if (!count)
                break;		// done
            if (count < 0)
            {
                count = -count;
                qglBegin (GL_TRIANGLE_FAN);
            }
            else
            {
                qglBegin (GL_TRIANGLE_STRIP);
            }

            // PMM - added double damage shell
            if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
            {
                do
                {
                    index_xyz = order[2];
                    order += 3;

                    qglVertex3fv( s_lerped[index_xyz] );

                } while (--count);
            }
            else
            {
                do
                {
                    // texture coordinates come from the draw list
                    qglTexCoord2f (((float *)order)[0], ((float *)order)[1]);
                    index_xyz = order[2];

                    order += 3;

                    // normals and vertexes come from the frame list
//					l = shadedots[verts[index_xyz].lightnormalindex];

//					qglColor4f (l* shadelight[0], l*shadelight[1], l*shadelight[2], alpha);
                    qglArrayElement( index_xyz );

                } while (--count);
            }
            qglEnd ();
        }

        if ( qglUnlockArraysEXT != 0 )
            qglUnlockArraysEXT();
    }
    else
    {
        while (1)
        {
            // get the vertex count and primitive type
            count = *order++;
            if (!count)
                break;		// done
            if (count < 0)
            {
                count = -count;
                qglBegin (GL_TRIANGLE_FAN);
            }
            else
            {
                qglBegin (GL_TRIANGLE_STRIP);
            }

            if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) )
            {
                do
                {
                    index_xyz = order[2];
                    order += 3;

                    qglColor4f( shadelight[0], shadelight[1], shadelight[2], alpha);
                    qglVertex3fv (s_lerped[index_xyz]);

                } while (--count);
            }
            else
            {
                do
                {
                    // texture coordinates come from the draw list
                    qglTexCoord2f (((float *)order)[0], ((float *)order)[1]);
                    index_xyz = order[2];
                    order += 3;

                    // normals and vertexes come from the frame list
                    l = shadedots[verts[index_xyz].lightnormalindex];

                    qglColor4f (l* shadelight[0], l*shadelight[1], l*shadelight[2], alpha);
                    qglVertex3fv (s_lerped[index_xyz]);
                } while (--count);
            }

            qglEnd ();
        }
    }

//	if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) )
    // PMM - added double damage shell
    if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
        qglEnable( GL_TEXTURE_2D );
}
Beispiel #2
0
/*
=================
RB_ShadowFinish

Darken everything that is is a shadow volume.
We have to delay this until everything has been shadowed,
because otherwise shadows from different body parts would
overlap and double darken.
=================
*/
void RB_ShadowFinish( void ) {
	if ( r_shadows->integer != 2 ) {
		return;
	}
	if ( glConfig.stencilBits < 4 ) {
		return;
	}

#ifdef _DEBUG_STENCIL_SHADOWS
	return;
#endif

	qglEnable( GL_STENCIL_TEST );
	qglStencilFunc( GL_NOTEQUAL, 0, 255 );

	qglStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );

	bool planeZeroBack = false;
	if (qglIsEnabled(GL_CLIP_PLANE0))
	{
		planeZeroBack = true;
		qglDisable (GL_CLIP_PLANE0);
	}
	GL_Cull(CT_TWO_SIDED);
	//qglDisable (GL_CULL_FACE);

	GL_Bind( tr.whiteImage );

	qglPushMatrix();
    qglLoadIdentity ();

//	qglColor3f( 0.6f, 0.6f, 0.6f );
//	GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO );

//	qglColor3f( 1, 0, 0 );
//	GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );

	qglColor4f( 0.0f, 0.0f, 0.0f, 0.5f );
	//GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
	GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );

#ifdef HAVE_GLES
	static GLfloat vtx[] = {
		-100.0f,  100.0f, -10.0f,
		100.0f,  100.0f, -10.0f,
		100.0f, -100.0f, -10.0f,
		-100.0f, -100.0f, -10.0f
	};
	GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
	GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
	if (text)
		qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
	if (glcol)
		qglDisableClientState(GL_COLOR_ARRAY);
	qglVertexPointer(3, GL_FLOAT, 0, vtx);
	qglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
	if (text)
		qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
	if (glcol)
		qglEnableClientState(GL_COLOR_ARRAY);
#else
	qglBegin( GL_QUADS );
	qglVertex3f( -100.0f, 100.0f, -10.0f);
	qglVertex3f( 100.0f, 100.0f, -10.0f);
	qglVertex3f( 100.0f, -100.0f, -10.0f);
	qglVertex3f( -100.0f, -100.0f, -10.0f);
	qglEnd();
#endif

	qglColor4f(1,1,1,1);
	qglDisable( GL_STENCIL_TEST );
	if (planeZeroBack)
	{
		qglEnable (GL_CLIP_PLANE0);
	}
	qglPopMatrix();
}
Beispiel #3
0
void RB_DistortionFill(void)
{
	float alpha = tr_distortionAlpha;
	float spost = 0.0f;
	float spost2 = 0.0f;

	if ( glConfig.stencilBits < 4 )
	{
		return;
	}

	//ok, cap the stupid thing now I guess
	if (!tr_distortionPrePost)
	{
		RB_CaptureScreenImage();
	}

	qglEnable(GL_STENCIL_TEST);
	qglStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF);
	qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

	qglDisable (GL_CLIP_PLANE0);
	GL_Cull( CT_TWO_SIDED );

	//reset the view matrices and go into ortho mode
	qglMatrixMode(GL_PROJECTION);
	qglPushMatrix();
	qglLoadIdentity();
	qglOrtho(0, glConfig.vidWidth, glConfig.vidHeight, 32, -1, 1);
	qglMatrixMode(GL_MODELVIEW);
	qglPushMatrix();
	qglLoadIdentity();

	if (tr_distortionStretch)
	{ //override
		spost = tr_distortionStretch;
		spost2 = tr_distortionStretch;
	}
	else
	{ //do slow stretchy effect
		spost = sin(tr.refdef.time * 0.0005 + tr.refdef.timeFraction * 0.0005);
		if (spost < 0.0f)
		{
			spost = -spost;
		}
		spost *= 0.2f;

		spost2 = sin(tr.refdef.time * 0.0005 + tr.refdef.timeFraction * 0.0005);
		if (spost2 < 0.0f)
		{
			spost2 = -spost2;
		}
		spost2 *= 0.08f;
	}

	if (alpha != 1.0f)
	{ //blend
		GL_State(GLS_SRCBLEND_SRC_ALPHA|GLS_DSTBLEND_SRC_ALPHA);
	}
	else
	{ //be sure to reset the draw state
		GL_State(0);
	}


#ifdef HAVE_GLES
	qglColor4f(1.0f, 1.0f, 1.0f, alpha);
	GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
	GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
	if (!text)
		qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
	if (glcol)
		qglDisableClientState(GL_COLOR_ARRAY);
	GLfloat tex[] = {
		0 + spost2, 1 - spost,
		0 + spost2, 0 + spost,
		1 - spost2, 0 + spost,
		1 - spost2, 1 - spost
	};
	GLfloat vtx[] = {
		0, 0,
		0, glConfig.vidHeight,
		glConfig.vidWidth, glConfig.vidHeight,
		glConfig.vidWidth, 0
	};
	qglTexCoordPointer(2, GL_FLOAT, 0, tex);
	qglVertexPointer(2, GL_FLOAT, 0, vtx);
	qglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
	/*	if (glcol)
	qglEnableClientState( GL_COLOR_ARRAY );
	if (!text)
	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );*/
#else
	qglBegin(GL_QUADS);
		qglColor4f(1.0f, 1.0f, 1.0f, alpha);
		qglTexCoord2f(0+spost2, 1-spost);
		qglVertex2f(0, 0);

		qglTexCoord2f(0+spost2, 0+spost);
		qglVertex2f(0, glConfig.vidHeight);

		qglTexCoord2f(1-spost2, 0+spost);
		qglVertex2f(glConfig.vidWidth, glConfig.vidHeight);

		qglTexCoord2f(1-spost2, 1-spost);
		qglVertex2f(glConfig.vidWidth, 0);
	qglEnd();
#endif

	if (tr_distortionAlpha == 1.0f && tr_distortionStretch == 0.0f)
	{ //no overrides
		if (tr_distortionNegate)
		{ //probably the crazy alternate saber trail
			alpha = 0.8f;
			GL_State(GLS_SRCBLEND_ZERO|GLS_DSTBLEND_ONE_MINUS_SRC_COLOR);
		}
		else
		{
			alpha = 0.5f;
			GL_State(GLS_SRCBLEND_SRC_ALPHA|GLS_DSTBLEND_SRC_ALPHA);
		}

		spost = sin(tr.refdef.time * 0.0008 + tr.refdef.timeFraction * 0.0008);
		if (spost < 0.0f)
		{
			spost = -spost;
		}
		spost *= 0.08f;

		spost2 = sin(tr.refdef.time * 0.0008 + tr.refdef.timeFraction * 0.0008);
		if (spost2 < 0.0f)
		{
			spost2 = -spost2;
		}
		spost2 *= 0.2f;


#ifdef HAVE_GLES
		qglColor4f(1.0f, 1.0f, 1.0f, alpha);
		/*		GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
		GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
		if (!text)
		qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
		if (glcol)
		qglDisableClientState( GL_COLOR_ARRAY );*/
		GLfloat tex[] = {
			0 + spost2, 1 - spost,
			0 + spost2, 0 + spost,
			1 - spost2, 0 + spost,
			1 - spost2, 1 - spost
		};
		GLfloat vtx[] = {
			0, 0,
			0, glConfig.vidHeight,
			glConfig.vidWidth, glConfig.vidHeight,
			glConfig.vidWidth, 0
		};
		qglTexCoordPointer(2, GL_FLOAT, 0, tex);
		qglVertexPointer(2, GL_FLOAT, 0, vtx);
		qglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
#else
		qglBegin(GL_QUADS);
			qglColor4f(1.0f, 1.0f, 1.0f, alpha);
			qglTexCoord2f(0+spost2, 1-spost);
			qglVertex2f(0, 0);

			qglTexCoord2f(0+spost2, 0+spost);
			qglVertex2f(0, glConfig.vidHeight);

			qglTexCoord2f(1-spost2, 0+spost);
			qglVertex2f(glConfig.vidWidth, glConfig.vidHeight);

			qglTexCoord2f(1-spost2, 1-spost);
			qglVertex2f(glConfig.vidWidth, 0);
		qglEnd();
#endif
	}
#ifdef HAVE_GLES
	if (glcol)
		qglEnableClientState(GL_COLOR_ARRAY);
	if (!text)
		qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
#endif

	//pop the view matrices back
	qglMatrixMode(GL_PROJECTION);
	qglPopMatrix();
	qglMatrixMode(GL_MODELVIEW);
	qglPopMatrix();

	qglDisable( GL_STENCIL_TEST );
}
Beispiel #4
0
void idSplineList::draw(bool editMode)
{
	int i;
	idVec4 yellow(1, 1, 0, 1);

	if(controlPoints.Num() == 0)
	{
		return;
	}

	if(dirty)
	{
		buildSpline();
	}


	qglColor3fv(controlColor);
	qglPointSize(5);

	qglBegin(GL_POINTS);

	for(i = 0; i < controlPoints.Num(); i++)
	{
		qglVertex3fv(*controlPoints[i]);
	}

	qglEnd();

	if(editMode)
	{
		for(i = 0; i < controlPoints.Num(); i++)
		{
			glBox(activeColor, *controlPoints[i], 4);
		}
	}

	//Draw the curve
	qglColor3fv(pathColor);
	qglBegin(GL_LINE_STRIP);
	int count = splinePoints.Num();

	for(i = 0; i < count; i++)
	{
		qglVertex3fv(*splinePoints[i]);
	}

	qglEnd();

	if(editMode)
	{
		qglColor3fv(segmentColor);
		qglPointSize(3);
		qglBegin(GL_POINTS);

		for(i = 0; i < count; i++)
		{
			qglVertex3fv(*splinePoints[i]);
		}

		qglEnd();
	}

	if(count > 0)
	{
		//assert(activeSegment >=0 && activeSegment < count);
		if(activeSegment >= 0 && activeSegment < count)
		{
			glBox(activeColor, *splinePoints[activeSegment], 6);
			glBox(yellow, *splinePoints[activeSegment], 8);
		}
	}

}
Beispiel #5
0
void
R_DrawAliasShadow ( dmdl_t *paliashdr, int posenum )
{
#if defined(VERTEX_ARRAYS)
    uint16_t total;
    GLenum type;
#endif
	int     *order;
	vec3_t point;
	float height, lheight;
	int count;

	lheight = currententity->origin [ 2 ] - lightspot [ 2 ];
	height = 0;
	order = (int *) ( (byte *) paliashdr + paliashdr->ofs_glcmds );
	height = -lheight + 0.1f;

	/* stencilbuffer shadows */
	if ( have_stencil && gl_stencilshadow->value )
	{
		qglEnable( GL_STENCIL_TEST );
		qglStencilFunc( GL_EQUAL, 1, 2 );
		qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
	}

	while ( 1 )
	{
		/* get the vertex count and primitive type */
		count = *order++;

		if ( !count )
		{
			break; /* done */
		}

		if ( count < 0 )
		{
			count = -count;
#if defined(VERTEX_ARRAYS)
            type = GL_TRIANGLE_FAN;
#else
			qglBegin( GL_TRIANGLE_FAN );
#endif
		}
		else
		{
#if defined(VERTEX_ARRAYS)
            type = GL_TRIANGLE_STRIP;
#else
			qglBegin( GL_TRIANGLE_STRIP );
#endif
		}

#if defined(VERTEX_ARRAYS)
        total = count;
        GLfloat vtx[3*total];
        uint32_t index_vtx = 0;
#endif

		do
		{
			/* normals and vertexes come from the frame list */
			memcpy( point, s_lerped [ order [ 2 ] ], sizeof ( point )  );

			point [ 0 ] -= shadevector [ 0 ] * ( point [ 2 ] + lheight );
			point [ 1 ] -= shadevector [ 1 ] * ( point [ 2 ] + lheight );
			point [ 2 ] = height;

#if defined(VERTEX_ARRAYS)
            vtx[index_vtx++] = point [ 0 ];
            vtx[index_vtx++] = point [ 1 ];
            vtx[index_vtx++] = point [ 2 ];
#else
			qglVertex3fv( point );
#endif

			order += 3;
		}
		while ( --count );

#if defined(VERTEX_ARRAYS)
        qglEnableClientState( GL_VERTEX_ARRAY );

        qglVertexPointer( 3, GL_FLOAT, 0, vtx );
        qglDrawArrays( type, 0, total );

        qglDisableClientState( GL_VERTEX_ARRAY );
#else
		qglEnd();
#endif
	}

	/* stencilbuffer shadows */
	if ( have_stencil && gl_stencilshadow->value )
	{
		qglDisable( GL_STENCIL_TEST );
	}
}
Beispiel #6
0
/*
=============
RE_StretchRaw

FIXME: not exactly backend
Stretches a raw 32 bit power of 2 bitmap image over the given screen rectangle.
Used for cinematics.
=============
*/
void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
	int			i, j;
	int			start, end;
#ifdef VCMODS_OPENGLES
	vec2_t		texcoords[4];
	vec2_t		verts[4];
	glIndex_t	indicies[6] = {0, 1, 2, 0, 3, 2};
#endif

	if ( !tr.registered ) {
		return;
	}
	R_SyncRenderThread();

	// we definately want to sync every frame for the cinematics
	qglFinish();

	start = end = 0;
	if ( r_speeds->integer ) {
		start = ri.Milliseconds();
	}

	// make sure rows and cols are powers of 2
	for ( i = 0 ; ( 1 << i ) < cols ; i++ ) {
	}
	for ( j = 0 ; ( 1 << j ) < rows ; j++ ) {
	}
	if ( ( 1 << i ) != cols || ( 1 << j ) != rows) {
		ri.Error (ERR_DROP, "Draw_StretchRaw: size not a power of 2: %i by %i", cols, rows);
	}

	GL_Bind( tr.scratchImage[client] );

	// if the scratchImage isn't in the format we want, specify it as a new texture
	if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) {
		tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
		tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
#ifdef VCMODS_OPENGLES
      //don't do qglTexImage2D as this may end up doing a compressed image
      //on which we are not allowed to do further sub images
		glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
#else
		qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
#endif
		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
	} else {
		if (dirty) {
			// otherwise, just subimage upload it so that drivers can tell we are going to be changing
			// it and don't try and do a texture compression
			qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
		}
	}

	if ( r_speeds->integer ) {
		end = ri.Milliseconds();
		ri.Printf( PRINT_ALL, "qglTexSubImage2D %i, %i: %i msec\n", cols, rows, end - start );
	}

	RB_SetGL2D();

#ifdef VCMODS_OPENGLES
	qglColor4f( tr.identityLight, tr.identityLight, tr.identityLight, 1.0f );

	verts[0][0] = x;  verts[0][1] = y;
	verts[1][0] = x+w;  verts[1][1] = y;
	verts[2][0] = x+w;  verts[2][1] = y+h;
	verts[3][0] = x;  verts[3][1] = y+h;

	texcoords[0][0] = 0.5f/cols;      texcoords[0][1] = 0.5f/rows;
	texcoords[1][0] = (cols-0.5f)/cols;   texcoords[1][1] = 0.5f/rows;
	texcoords[2][0] = (cols-0.5f)/cols;   texcoords[2][1] = (rows-0.5f)/rows;
	texcoords[3][0] = 0.5f/cols;      texcoords[3][1] = (rows-0.5f)/rows;

	qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
	qglTexCoordPointer( 2, GL_FLOAT, 0, texcoords );
	qglVertexPointer  ( 2, GL_FLOAT, 0, verts );
	qglDrawElements( GL_TRIANGLE_STRIP, 6, GL_INDEX_TYPE, indicies );
	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
#else
	qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight );

	qglBegin (GL_QUADS);
	qglTexCoord2f ( 0.5f / cols,  0.5f / rows );
	qglVertex2f (x, y);
	qglTexCoord2f ( ( cols - 0.5f ) / cols ,  0.5f / rows );
	qglVertex2f (x+w, y);
	qglTexCoord2f ( ( cols - 0.5f ) / cols, ( rows - 0.5f ) / rows );
	qglVertex2f (x+w, y+h);
	qglTexCoord2f ( 0.5f / cols, ( rows - 0.5f ) / rows );
	qglVertex2f (x, y+h);
	qglEnd ();
#endif
}
Beispiel #7
0
void R_RenderShadowEdges( void ) {
	int		i;

#if 0
	int		numTris;

	// dumb way -- render every triangle's edges
	numTris = tess.numIndexes / 3;

	for ( i = 0 ; i < numTris ; i++ ) {
		int		i1, i2, i3;

		if ( !facing[i] ) {
			continue;
		}

		i1 = tess.indexes[ i*3 + 0 ];
		i2 = tess.indexes[ i*3 + 1 ];
		i3 = tess.indexes[ i*3 + 2 ];

		qglBegin( GL_TRIANGLE_STRIP );
		qglVertex3fv( tess.xyz[ i1 ] );
		qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] );
		qglVertex3fv( tess.xyz[ i2 ] );
		qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
		qglVertex3fv( tess.xyz[ i3 ] );
		qglVertex3fv( tess.xyz[ i3 + tess.numVertexes ] );
		qglVertex3fv( tess.xyz[ i1 ] );
		qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] );
		qglEnd();
	}
#else
	int		c, c2;
	int		j, k;
	int		i2;
	int		c_edges, c_rejected;
	int		hit[2];

	// an edge is NOT a silhouette edge if its face doesn't face the light,
	// or if it has a reverse paired edge that also faces the light.
	// A well behaved polyhedron would have exactly two faces for each edge,
	// but lots of models have dangling edges or overfanned edges
	c_edges = 0;
	c_rejected = 0;

	for ( i = 0 ; i < tess.numVertexes ; i++ ) {
		c = numEdgeDefs[ i ];
		for ( j = 0 ; j < c ; j++ ) {
			if ( !edgeDefs[ i ][ j ].facing ) {
				continue;
			}

			hit[0] = 0;
			hit[1] = 0;

			i2 = edgeDefs[ i ][ j ].i2;
			c2 = numEdgeDefs[ i2 ];
			for ( k = 0 ; k < c2 ; k++ ) {
				if ( edgeDefs[ i2 ][ k ].i2 == i ) {
					hit[ edgeDefs[ i2 ][ k ].facing ]++;
				}
			}

			// if it doesn't share the edge with another front facing
			// triangle, it is a sil edge
			if ( hit[ 1 ] == 0 ) {
				qglBegin( GL_TRIANGLE_STRIP );
				qglVertex3fv( tess.xyz[ i ] );
				qglVertex3fv( tess.xyz[ i + tess.numVertexes ] );
				qglVertex3fv( tess.xyz[ i2 ] );
				qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
				qglEnd();
				c_edges++;
			} else {
				c_rejected++;
			}
		}
	}
#endif
}
Beispiel #8
0
void R_DrawSkyBox (void)
{
	int		i;

#if 0
qglEnable (GL_BLEND);
GL_TexEnv( GL_MODULATE );
qglColor4f (1,1,1,0.5);
qglDisable (GL_DEPTH_TEST);
#endif

	// jkrige - skybox
	qglDisable (GL_DEPTH_TEST);
	/*if (skyrotate)
	{	// check for no sky at all
		for (i=0 ; i<6 ; i++)
			if (skymins[0][i] < skymaxs[0][i]
			&& skymins[1][i] < skymaxs[1][i])
				break;
		if (i == 6)
			return;		// nothing visible
	}*/
	// jkrige - skybox

qglPushMatrix ();
qglTranslatef (r_origin[0], r_origin[1], r_origin[2]);
qglRotatef (r_newrefdef.time * skyrotate, skyaxis[0], skyaxis[1], skyaxis[2]);

	for (i=0 ; i<6 ; i++)
	{
		// jkrige - skybox
		/*if (skyrotate)
		{	// hack, forces full sky to draw when rotating
			skymins[0][i] = -1;
			skymins[1][i] = -1;
			skymaxs[0][i] = 1;
			skymaxs[1][i] = 1;
		}

		if (skymins[0][i] >= skymaxs[0][i]
		|| skymins[1][i] >= skymaxs[1][i])
			continue;*/
		// jkrige - skybox

		GL_Bind (sky_images[skytexorder[i]]->texnum);

		qglBegin (GL_QUADS);
		// jkrige - skybox
		MakeSkyVec (-1, -1, i);
		MakeSkyVec (-1, 1, i);
		MakeSkyVec (1, 1, i);
		MakeSkyVec (1, -1, i);
		//MakeSkyVec (skymins[0][i], skymins[1][i], i);
		//MakeSkyVec (skymins[0][i], skymaxs[1][i], i);
		//MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i);
		//MakeSkyVec (skymaxs[0][i], skymins[1][i], i);
		// jkrige - skybox
		qglEnd ();
	}
qglPopMatrix ();
#if 0
glDisable (GL_BLEND);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glColor4f (1,1,1,0.5);
glEnable (GL_DEPTH_TEST);
#endif

	// jkrige - skybox
	qglEnable (GL_DEPTH_TEST);
	// jkrige - skybox
}
/*
=============
RE_StretchRaw

FIXME: not exactly backend
Stretches a raw 32 bit power of 2 bitmap image over the given screen rectangle.
Used for cinematics.
=============
*/
void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
	int			i, j;
	int			start, end;

	if ( !tr.registered ) {
		return;
	}
	R_SyncRenderThread();

#ifdef FRAMEBUFFER_AND_GLSL_SUPPORT
	// Needed here to support cinematics
	R_FrameBuffer_EndFrame();
#endif

	// we definately want to sync every frame for the cinematics
	qglFinish();

	start = end = 0;
	if ( r_speeds->integer ) {
		start = ri.Milliseconds();
	}

	// make sure rows and cols are powers of 2
	for ( i = 0 ; ( 1 << i ) < cols ; i++ ) {
	}
	for ( j = 0 ; ( 1 << j ) < rows ; j++ ) {
	}
	if ( ( 1 << i ) != cols || ( 1 << j ) != rows) {
		ri.Error (ERR_DROP, "Draw_StretchRaw: size not a power of 2: %i by %i", cols, rows);
	}

	GL_Bind( tr.scratchImage[client] );

	// if the scratchImage isn't in the format we want, specify it as a new texture
	if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) {
		tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
		tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
		qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );	
	} else {
		if (dirty) {
			// otherwise, just subimage upload it so that drivers can tell we are going to be changing
			// it and don't try and do a texture compression
			qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
		}
	}

	if ( r_speeds->integer ) {
		end = ri.Milliseconds();
		ri.Printf( PRINT_ALL, "qglTexSubImage2D %i, %i: %i msec\n", cols, rows, end - start );
	}

	RB_SetGL2D();

	qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight );

	qglBegin (GL_QUADS);
	qglTexCoord2f ( 0.5f / cols,  0.5f / rows );
	qglVertex2f (x, y);
	qglTexCoord2f ( ( cols - 0.5f ) / cols ,  0.5f / rows );
	qglVertex2f (x+w, y);
	qglTexCoord2f ( ( cols - 0.5f ) / cols, ( rows - 0.5f ) / rows );
	qglVertex2f (x+w, y+h);
	qglTexCoord2f ( 0.5f / cols, ( rows - 0.5f ) / rows );
	qglVertex2f (x, y+h);
	qglEnd ();
}
Beispiel #10
0
/*
===============
DrawRuledSurface
===============
*/
void DrawRuledSurface (face_t *cf, float ctrl[2][3][5] ) {
	int			j, k, l;
	vec5_t		curve[2][CBLOCK_SUBDIVISIONS+1];
	//float		u;
	float		*v;

	if (curveFile) {
		fprintf (curveFile, "RULED {\n");
		fprintf (curveFile, "textures/%s\n", cf->texdef.name);
		Write3DMatrix (curveFile, 2, 3, 5, (float *)ctrl);
		fprintf (curveFile, "}\n");
		return;
	}

	for (j = 0 ; j < 2 ; j++) {
		for (l = 0 ; l < 5 ; l++) {
			float	a, b, c;
			float	qA, qB, qC;
			float	f;
			int		k;

			a = ctrl[j][0][l];
			b = ctrl[j][1][l];
			c = ctrl[j][2][l];
			qA = a - 2 * b + c;
			qB = 2 * b - 2 * a;
			qC = a;

			for (k = 0 ; k <= CBLOCK_SUBDIVISIONS ; k++) {
				f = (float)k / CBLOCK_SUBDIVISIONS;
				curve[j][k][l] = qA*f*f + qB*f + qC;
			}
		}
	}

	if ( bevelBrush ) {
		face_t	*f;

		for (k = 0 ; k < CBLOCK_SUBDIVISIONS ; k++) {
			f = Face_Clone( bevelBrush->brush_faces );
			f->texdef.flags |= SURF_CURVE_FAKE;
			f->next = bevelBrush->brush_faces;
			bevelBrush->brush_faces = f;

			VectorCopy( curve[0][k], f->planepts[0] );
			VectorCopy( curve[1][k], f->planepts[1] );
			VectorCopy( curve[0][k+1], f->planepts[2] );
			Brush_MakeFacePlane( f );
		}
		return;
	}



	qglBindTexture (GL_TEXTURE_2D, cf->d_texture->texture_number);

  float fColor[3];
  SetColor(cf, fColor);

	qglBegin (GL_QUAD_STRIP);
	for (k = 0 ; k <= CBLOCK_SUBDIVISIONS ; k++) {
		v = curve[0][k];
		qglTexCoord2fv( v + 3 );
		qglVertex3fv( v );

		v = curve[1][k];
		qglTexCoord2fv( v + 3 );
		qglVertex3fv( v );
	}


	qglEnd ();
}
Beispiel #11
0
/*
===================
DrawPatch
===================
*/
void DrawPatch (face_t *cf, float ctrl[3][3][5]) {
	int		i, j;
	float	u, v;
	vec5_t	verts[CBLOCK_SUBDIVISIONS+1][CBLOCK_SUBDIVISIONS+1];

	if (curveFile) {
		fprintf (curveFile, "PATCH {\n");
		fprintf (curveFile, "textures/%s\n", cf->texdef.name);
		Write3DMatrix (curveFile, 3, 3, 5, (float *)ctrl);
		fprintf (curveFile, "}\n");
		return;
	}

	for (i = 0 ; i <= CBLOCK_SUBDIVISIONS ; i++) {
		for (j = 0 ; j <= CBLOCK_SUBDIVISIONS ; j++) {
			u = (float)i / CBLOCK_SUBDIVISIONS;
			v = (float)j / CBLOCK_SUBDIVISIONS;
			SamplePatch (ctrl, u, v, verts[i][j]);
		}
	}

	if ( bevelBrush ) {
		face_t		*f;
		vec3_t		v0, v1, v2;
		vec3_t		d1, d2, cross;

		for (i = 0 ; i < CBLOCK_SUBDIVISIONS ; i++) {
			for (j = 0 ; j < CBLOCK_SUBDIVISIONS ; j++) {
				VectorCopy( verts[i][j], v0 );
				VectorCopy( verts[i][j+1], v1 );
				VectorCopy( verts[i+1][j], v2 );

				VectorSubtract( v0, v1, d1 );
				VectorSubtract( v2, v1, d2 );
				CrossProduct( d1, d2, cross );
				if ( VectorLength( cross ) == 0 ) {
					continue;	// degenerate
				}
				f = Face_Clone( bevelBrush->brush_faces );
				f->texdef.flags |= SURF_CURVE_FAKE;
				VectorCopy( v0, f->planepts[0] );
				VectorCopy( v1, f->planepts[1] );
				VectorCopy( v2, f->planepts[2] );
				Brush_MakeFacePlane( f );
				f->next = bevelBrush->brush_faces;
				bevelBrush->brush_faces = f;
			}
		}
		return;
	}



	qglBindTexture (GL_TEXTURE_2D, cf->d_texture->texture_number);

  float fColor[3];
  SetColor(cf, fColor);


	for (i = 0 ; i < CBLOCK_SUBDIVISIONS ; i++) {
		qglBegin (GL_QUAD_STRIP);
		for (j = 0 ; j <= CBLOCK_SUBDIVISIONS ; j++) {
			qglTexCoord2fv( verts[i+1][j] + 3 );
			qglVertex3fv( verts[i+1][j] );
			qglTexCoord2fv( verts[i][j] + 3 );
			qglVertex3fv( verts[i][j] );
      DecColor(fColor);
		}
		qglEnd ();
	}
}
Beispiel #12
0
/*
===============
DrawCurveFan

Draws a curve as part of a flat surface
===============
*/
void DrawCurveFan (face_t *cf, vec5_t opposite, vec5_t prev, vec5_t peak, vec5_t next) {
	int			i, k, l;
	float		coef[5][3];

	// write it out
	if (curveFile) {
		vec5_t	vecs[4];

		for ( i = 0 ; i < 5 ; i++ ) {
			vecs[0][i] = opposite[i];
			vecs[1][i] = prev[i];
			vecs[2][i] = peak[i];
			vecs[3][i] = next[i];
		}
		fprintf (curveFile, "CURVEFAN {\n");
		fprintf (curveFile, "textures/%s\n", cf->texdef.name);
		Write2DMatrix (curveFile, 4, 5, (float *)vecs);
		fprintf (curveFile, "}\n");
		return;
	}

	// calculate the coefficients
	for (l = 0 ; l < 5 ; l++) {
		float	a, b, c;

		a = prev[l];
		b = peak[l];
		c = next[l];
		coef[l][0] = a;
		coef[l][1] = 2 * b - 2 * a;
		coef[l][2] = a - 2 * b + c;
	}


	// draw it
	qglBindTexture (GL_TEXTURE_2D, cf->d_texture->texture_number);


  float fColor[3];
  SetColor(cf, fColor);


	qglBegin (GL_TRIANGLE_FAN);

	qglTexCoord2fv( opposite + 3 );
	qglVertex3fv( opposite );

	for ( k = 0 ; k <= CBLOCK_SUBDIVISIONS ; k++ ) {
		vec5_t		curve;
		float		f;

		f = (float)k / CBLOCK_SUBDIVISIONS;
		for ( l = 0 ; l < 5 ; l++ ) {
			curve[l] = coef[l][2]*f*f + coef[l][1]*f + coef[l][0];
		}

		qglTexCoord2fv( curve + 3 );
		qglVertex3fv( curve );
    DecColor(fColor);
	}

	qglEnd ();
}
Beispiel #13
0
void RB_ColorCorrect( void ) {
	GLint loc;
	GLenum target;
	int width, height;
	int shift;
	float mul;

	if ( !r_enablePostProcess->integer || !r_enableColorCorrect->integer || !glsl ) {
		return;
	}

	GL_SelectTexture(0);
	qglDisable(GL_TEXTURE_2D);
	qglEnable(GL_TEXTURE_RECTANGLE_ARB);

	target = GL_TEXTURE_RECTANGLE_ARB;

	width = glConfig.vidWidth;
	height = glConfig.vidHeight;

	qglBindTexture(target, tr.backBufferTexture);
	qglCopyTexSubImage2D(target, 0, 0, 0, 0, 0, glConfig.vidWidth, glConfig.vidHeight);

	qglMatrixMode(GL_PROJECTION);
	qglLoadIdentity();
	qglMatrixMode(GL_MODELVIEW);
	qglLoadIdentity();

	RB_SetGL2D();
	GL_State( GLS_DEPTHTEST_DISABLE );

    qglUseProgramObjectARB(tr.colorCorrectSp);
	loc = qglGetUniformLocationARB(tr.colorCorrectSp, "p_gammaRecip");
	if (loc < 0) {
		Com_Error(ERR_DROP, "%s() couldn't get p_gammaRecip", __FUNCTION__);
	}
	qglUniform1fARB(loc, (GLfloat)(1.0 / r_gamma->value));

	//mul = r_overBrightBitsValue->value;
	mul = r_overBrightBits->value;
	if (mul < 0.0) {
		mul = 0.0;
	}
	shift = tr.overbrightBits;

	loc = qglGetUniformLocationARB(tr.colorCorrectSp, "p_overbright");
	if (loc < 0) {
		Com_Error(ERR_DROP, "%s() couldn't get p_overbright", __FUNCTION__);
	}
	qglUniform1fARB(loc, (GLfloat)((float)(1 << shift) * mul));

	loc = qglGetUniformLocationARB(tr.colorCorrectSp, "p_contrast");
	if (loc < 0) {
		Com_Error(ERR_DROP, "%s() couldn't get p_contrast", __FUNCTION__);
	}
	qglUniform1fARB(loc, (GLfloat)r_contrast->value);

	loc = qglGetUniformLocationARB(tr.colorCorrectSp, "backBufferTex");
	if (loc < 0) {
		Com_Error(ERR_DROP, "%s() couldn't get backBufferTex", __FUNCTION__);
	}
	qglUniform1iARB(loc, 0);

	qglBegin(GL_QUADS);

	qglTexCoord2i(0, 0);
	qglVertex2i(0, height);

	qglTexCoord2i(width, 0);
	qglVertex2i(width, height);

	qglTexCoord2i(width, height);
	qglVertex2i(width, 0);

	qglTexCoord2i(0, height);
	qglVertex2i(0, 0);

	qglEnd();

	qglUseProgramObjectARB(0);

	qglDisable(GL_TEXTURE_RECTANGLE_ARB);
	qglEnable(GL_TEXTURE_2D);
}
Beispiel #14
0
static void RB_BloomCombine( void ) {
	GLenum target;
	int width, height;
	GLint loc;

	GL_SelectTexture(0);
	qglDisable(GL_TEXTURE_2D);
	qglEnable(GL_TEXTURE_RECTANGLE_ARB);
	target = GL_TEXTURE_RECTANGLE_ARB;

	width = tr.bloomWidth;
	height = tr.bloomHeight;

	qglBindTexture(target, tr.bloomTexture);
	qglCopyTexSubImage2D(target, 0, 0, 0, 0, glConfig.vidHeight - height, width, height);

	qglUseProgramObjectARB(tr.combineSp);

	qglBindTexture(target, tr.backBufferTexture);
	loc = qglGetUniformLocationARB(tr.combineSp, "backBufferTex");
	if (loc < 0) {
		Com_Error(ERR_DROP, "%s() couldn't get backBufferTex", __FUNCTION__);
	}
	qglUniform1iARB(loc, 0);

	GL_SelectTexture(1);
	qglDisable(GL_TEXTURE_2D);
	qglEnable(GL_TEXTURE_RECTANGLE_ARB);

	qglBindTexture(target, tr.bloomTexture);
	loc = qglGetUniformLocationARB(tr.combineSp, "bloomTex");
	if (loc < 0) {
		Com_Error(ERR_DROP, "%s() couldn't get bloomTex", __FUNCTION__);
	}
	qglUniform1iARB(loc, 1);

	loc = qglGetUniformLocationARB(tr.combineSp, "p_bloomsaturation");
	if (loc < 0) {
		Com_Error(ERR_DROP, "%s() couldn't get p_bloomsaturation", __FUNCTION__);
	}
	qglUniform1fARB(loc, (GLfloat)r_BloomSaturation->value);

	loc = qglGetUniformLocationARB(tr.combineSp, "p_scenesaturation");
	if (loc < 0) {
		Com_Error(ERR_DROP, "%s() couldn't get p_scenesaturation", __FUNCTION__);
	}
	qglUniform1fARB(loc, (GLfloat)r_BloomSceneSaturation->value);

	loc = qglGetUniformLocationARB(tr.combineSp, "p_bloomintensity");
	if (loc < 0) {
		Com_Error(ERR_DROP, "%s() couldn't get p_bloomintensity", __FUNCTION__);
	}
	qglUniform1fARB(loc, (GLfloat)r_BloomIntensity->value);

	loc = qglGetUniformLocationARB(tr.combineSp, "p_sceneintensity");
	if (loc < 0) {
		Com_Error(ERR_DROP, "%s() couldn't get p_sceneintensity", __FUNCTION__);
	}
	qglUniform1fARB(loc, (GLfloat)r_BloomSceneIntensity->value);


	width = glConfig.vidWidth;
	height = glConfig.vidHeight;

    qglBegin(GL_QUADS);

	qglMultiTexCoord2iARB(GL_TEXTURE0_ARB, 0, 0);
	qglMultiTexCoord2iARB(GL_TEXTURE1_ARB, 0, 0);
	qglVertex2i(0, height);

	qglMultiTexCoord2iARB(GL_TEXTURE0_ARB, width, 0);
	qglMultiTexCoord2iARB(GL_TEXTURE1_ARB, tr.bloomWidth, 0);
	qglVertex2i(width, height);

	qglMultiTexCoord2iARB(GL_TEXTURE0_ARB, width, height);
	qglMultiTexCoord2iARB(GL_TEXTURE1_ARB, tr.bloomWidth, tr.bloomHeight);
	qglVertex2i(width, 0);

	qglMultiTexCoord2iARB(GL_TEXTURE0_ARB, 0, height);
	qglMultiTexCoord2iARB(GL_TEXTURE1_ARB, 0, tr.bloomHeight);
	qglVertex2i(0, 0);

	qglEnd();

	qglUseProgramObjectARB(0);

	GL_SelectTexture(1);
	qglDisable(GL_TEXTURE_RECTANGLE_ARB);
	qglDisable(GL_TEXTURE_2D);

	GL_SelectTexture(0);
	qglDisable(GL_TEXTURE_RECTANGLE_ARB);
	qglEnable(GL_TEXTURE_2D);
}
Beispiel #15
0
/*
===============
CreateOptTri
===============
*/
static void CreateOptTri( optVertex_t *first, optEdge_t *e1, optEdge_t *e2, optIsland_t *island ) {
	optEdge_t		*opposite;
	optVertex_t		*second, *third;
	optTri_t		*optTri;
	mapTri_t		*tri;

	if ( e1->v1 == first ) {
		second = e1->v2;
	} else if ( e1->v2 == first ) {
		second = e1->v1;
	} else {
		common->Error( "CreateOptTri: mislinked edge" );
		return;
	}

	if ( e2->v1 == first ) {
		third = e2->v2;
	} else if ( e2->v2 == first ) {
		third = e2->v1;
	} else {
		common->Error( "CreateOptTri: mislinked edge" );
		return;
	}

	if ( !IsTriangleValid( first, second, third ) ) {
		common->Error( "CreateOptTri: invalid" );
		return;
	}

//DrawEdges( island );

		// identify the third edge
	if ( dmapGlobals.drawflag ) {
		qglColor3f(1,1,0);
		qglBegin( GL_LINES );
		qglVertex3fv( e1->v1->pv.ToFloatPtr() );
		qglVertex3fv( e1->v2->pv.ToFloatPtr() );
		qglEnd();
		qglFlush();
		qglColor3f(0,1,1);
		qglBegin( GL_LINES );
		qglVertex3fv( e2->v1->pv.ToFloatPtr() );
		qglVertex3fv( e2->v2->pv.ToFloatPtr() );
		qglEnd();
		qglFlush();
	}

	for ( opposite = second->edges ; opposite ; ) {
		if ( opposite != e1 && ( opposite->v1 == third || opposite->v2 == third ) ) {
			break;
		}
		if ( opposite->v1 == second ) {
			opposite = opposite->v1link;
		} else if ( opposite->v2 == second ) {
			opposite = opposite->v2link;
		} else {
			common->Error( "BuildOptTriangles: mislinked edge" );
			return;
		}
	}

	if ( !opposite ) {
		common->Printf( "Warning: BuildOptTriangles: couldn't locate opposite\n" );
		return;
	}

	if ( dmapGlobals.drawflag ) {
		qglColor3f(1,0,1);
		qglBegin( GL_LINES );
		qglVertex3fv( opposite->v1->pv.ToFloatPtr() );
		qglVertex3fv( opposite->v2->pv.ToFloatPtr() );
		qglEnd();
		qglFlush();
	}

	// create new triangle
	optTri = (optTri_t *)Mem_Alloc( sizeof( *optTri ), TAG_DMAP );
	optTri->v[0] = first;
	optTri->v[1] = second;
	optTri->v[2] = third;
	optTri->midpoint = ( optTri->v[0]->pv + optTri->v[1]->pv + optTri->v[2]->pv ) * ( 1.0f / 3.0f );
	optTri->next = island->tris;
	island->tris = optTri;

	if ( dmapGlobals.drawflag ) {
		qglColor3f( 1, 1, 1 );
		qglPointSize( 4 );
		qglBegin( GL_POINTS );
		qglVertex3fv( optTri->midpoint.ToFloatPtr() );
		qglEnd();
		qglFlush();
	}

	// find the midpoint, and scan through all the original triangles to
	// see if it is inside any of them
	for ( tri = island->group->triList ; tri ; tri = tri->next ) {
		if ( PointInTri( optTri->midpoint, tri, island ) ) {
			break;
		}
	}
	if ( tri ) {
		optTri->filled = true;
	} else {
		optTri->filled = false;
	}
	if ( dmapGlobals.drawflag ) {
		if ( optTri->filled ) {
			qglColor3f( ( 128 + orandom.RandomInt( 127 ) )/ 255.0, 0, 0 );
		} else {
			qglColor3f( 0, ( 128 + orandom.RandomInt( 127 ) ) / 255.0, 0 );
		}
		qglBegin( GL_TRIANGLES );
		qglVertex3fv( optTri->v[0]->pv.ToFloatPtr() );
		qglVertex3fv( optTri->v[1]->pv.ToFloatPtr() );
		qglVertex3fv( optTri->v[2]->pv.ToFloatPtr() );
		qglEnd();
		qglColor3f( 1, 1, 1 );
		qglBegin( GL_LINE_LOOP );
		qglVertex3fv( optTri->v[0]->pv.ToFloatPtr() );
		qglVertex3fv( optTri->v[1]->pv.ToFloatPtr() );
		qglVertex3fv( optTri->v[2]->pv.ToFloatPtr() );
		qglEnd();
		qglFlush();
	}

	// link the triangle to it's edges
	LinkTriToEdge( optTri, e1 );
	LinkTriToEdge( optTri, e2 );
	LinkTriToEdge( optTri, opposite );
}
Beispiel #16
0
/*
===============
RB_ShowImages

Draw all the images to the screen, on top of whatever
was there.  This is used to test for texture thrashing.

Also called by RE_EndRegistration
===============
*/
void RB_ShowImages( void ) {
	int i;
	image_t *image;
	float x, y, w, h;
	int start, end;

	if ( !backEnd.projection2D ) {
		RB_SetGL2D();
	}

	qglClear( GL_COLOR_BUFFER_BIT );

	qglFinish();


	start = ri.Milliseconds();

	for ( i = 0 ; i < tr.numImages ; i++ ) {
		image = tr.images[i];

		w = glConfig.vidWidth / 40;
		h = glConfig.vidHeight / 30;

		x = i % 40 * w;
		y = i / 30 * h;

		// show in proportional size in mode 2
		if ( r_showImages->integer == 2 ) {
			w *= image->uploadWidth / 512.0f;
			h *= image->uploadHeight / 512.0f;
		}

#ifdef USE_OPENGLES
		GLfloat tex[] = {
		 0, 0, 
		 1, 0,
		 1, 1, 
		 0, 1 };
		GLfloat vtx[] = {
		 x, y,
		 x + w, y,
		 x + w, y + h,
		 x, y + h };
		GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
		GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
		if (glcol)
			qglDisableClientState(GL_COLOR_ARRAY);
		if (!text)
			qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
		qglTexCoordPointer( 2, GL_FLOAT, 0, tex );
		qglVertexPointer  ( 2, GL_FLOAT, 0, vtx );
		qglDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
		if (glcol)
			qglEnableClientState(GL_COLOR_ARRAY);
		if (!text)
			qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
#else
		GL_Bind( image );
		qglBegin( GL_QUADS );
		qglTexCoord2f( 0, 0 );
		qglVertex2f( x, y );
		qglTexCoord2f( 1, 0 );
		qglVertex2f( x + w, y );
		qglTexCoord2f( 1, 1 );
		qglVertex2f( x + w, y + h );
		qglTexCoord2f( 0, 1 );
		qglVertex2f( x, y + h );
		qglEnd();
#endif
	}

	qglFinish();

	end = ri.Milliseconds();
	ri.Printf( PRINT_ALL, "%i msec to draw all images\n", end - start );

}
Beispiel #17
0
/*
===============
RB_ShowImages

Draw all the images to the screen, on top of whatever
was there.  This is used to test for texture thrashing.

Also called by RE_EndRegistration
===============
*/
void RB_ShowImages( void ) {
	int		i;
	image_t	*image;
	float	x, y, w, h;
	int		start, end;
#ifdef VCMODS_OPENGLES
	vec2_t  texcoords[4] = { {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f} };
	vec2_t  verts[4];
	glIndex_t indicies[6] = { 0, 1, 2, 0, 3, 2};
#endif

	if ( !backEnd.projection2D ) {
		RB_SetGL2D();
	}

	qglClear( GL_COLOR_BUFFER_BIT );

	qglFinish();

	start = ri.Milliseconds();
#ifdef VCMODS_OPENGLES
	qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
#endif

	for ( i=0 ; i<tr.numImages ; i++ ) {
		image = tr.images[i];

		w = glConfig.vidWidth / 20;
		h = glConfig.vidHeight / 15;
		x = i % 20 * w;
		y = i / 20 * h;

		// show in proportional size in mode 2
		if ( r_showImages->integer == 2 ) {
			w *= image->uploadWidth / 512.0f;
			h *= image->uploadHeight / 512.0f;
		}

#ifdef VCMODS_OPENGLES
		verts[0][0] = x;  verts[0][1] = y;
		verts[1][0] = x+w;  verts[1][1] = y;
		verts[2][0] = x+w;  verts[2][1] = y+h;
		verts[3][0] = x;  verts[3][1] = y+h;

		qglTexCoordPointer( 2, GL_FLOAT, 0, texcoords );
		qglVertexPointer  ( 2, GL_FLOAT, 0, verts );
		qglDrawElements( GL_TRIANGLE_STRIP, 6, GL_INDEX_TYPE, indicies );
#else
		GL_Bind( image );
		qglBegin (GL_QUADS);
		qglTexCoord2f( 0, 0 );
		qglVertex2f( x, y );
		qglTexCoord2f( 1, 0 );
		qglVertex2f( x + w, y );
		qglTexCoord2f( 1, 1 );
		qglVertex2f( x + w, y + h );
		qglTexCoord2f( 0, 1 );
		qglVertex2f( x, y + h );
		qglEnd();
#endif
	}

#ifdef VCMODS_OPENGLES
	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
#endif
	qglFinish();

	end = ri.Milliseconds();
	ri.Printf( PRINT_ALL, "%i msec to draw all images\n", end - start );

}
Beispiel #18
0
/*
=============
RE_StretchRaw

FIXME: not exactly backend
Stretches a raw 32 bit power of 2 bitmap image over the given screen rectangle.
Used for cinematics.
=============
*/
void RE_StretchRaw( int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty ) {
	int i, j;
	int start, end;

	if ( !tr.registered ) {
		return;
	}
	R_IssuePendingRenderCommands();

	if ( tess.numIndexes ) {
		RB_EndSurface();
	}

	// we definately want to sync every frame for the cinematics
	qglFinish();

	start = 0;
	if ( r_speeds->integer ) {
		start = ri.Milliseconds();
	}

	// make sure rows and cols are powers of 2
	for ( i = 0 ; ( 1 << i ) < cols ; i++ ) {
	}
	for ( j = 0 ; ( 1 << j ) < rows ; j++ ) {
	}
	if ( ( 1 << i ) != cols || ( 1 << j ) != rows ) {
		ri.Error( ERR_DROP, "Draw_StretchRaw: size not a power of 2: %i by %i", cols, rows );
	}

	GL_Bind( tr.scratchImage[client] );

	// if the scratchImage isn't in the format we want, specify it as a new texture
	if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) {
		tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
		tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
#ifdef USE_OPENGLES
		qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
#else
		qglTexImage2D( GL_TEXTURE_2D, 0, 3, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
#endif
		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
	} else {
		if ( dirty ) {
			// otherwise, just subimage upload it so that drivers can tell we are going to be changing
			// it and don't try and do a texture compression
			qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
		}
	}

	if ( r_speeds->integer ) {
		end = ri.Milliseconds();
		ri.Printf( PRINT_ALL, "qglTexSubImage2D %i, %i: %i msec\n", cols, rows, end - start );
	}

	RB_SetGL2D();

	qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight );

#ifdef USE_OPENGLES
	GLfloat tex[] = {
	 0.5f / cols,  0.5f / rows,
	 ( cols - 0.5f ) / cols ,  0.5f / rows,
	 ( cols - 0.5f ) / cols, ( rows - 0.5f ) / rows,
	 0.5f / cols, ( rows - 0.5f ) / rows };
	GLfloat vtx[] = {
	 x, y,
	 x+w, y,
	 x+w, y+h,
	 x, y+h };
	GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
	GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
	if (glcol)
		qglDisableClientState(GL_COLOR_ARRAY);
	if (!text)
		qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
	qglTexCoordPointer( 2, GL_FLOAT, 0, tex );
	qglVertexPointer  ( 2, GL_FLOAT, 0, vtx );
	qglDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
	if (!text)
		qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
	if (glcol)
		qglEnableClientState(GL_COLOR_ARRAY);
#else
	qglBegin( GL_QUADS );
	qglTexCoord2f( 0.5f / cols,  0.5f / rows );
	qglVertex2f( x, y );
	qglTexCoord2f( ( cols - 0.5f ) / cols,  0.5f / rows );
	qglVertex2f( x + w, y );
	qglTexCoord2f( ( cols - 0.5f ) / cols, ( rows - 0.5f ) / rows );
	qglVertex2f( x + w, y + h );
	qglTexCoord2f( 0.5f / cols, ( rows - 0.5f ) / rows );
	qglVertex2f( x, y + h );
	qglEnd();
#endif
}
Beispiel #19
0
/*
==============
R_CalcBones

    The list of bones[] should only be built and modified from within here
==============
*/
void R_CalcBones(mdsHeader_t *header, const refEntity_t *refent, int *boneList, int numBones)
{
	int   i;
	int   *boneRefs;
	float torsoWeight;

	// if the entity has changed since the last time the bones were built, reset them
	if (memcmp(&lastBoneEntity, refent, sizeof(refEntity_t)))
	{
		// different, cached bones are not valid
		memset(validBones, 0, header->numBones);
		lastBoneEntity = *refent;

		// (SA) also reset these counter statics
		//----(SA)	print stats for the complete model (not per-surface)
		if (r_bonesDebug->integer == 4 && totalrt)
		{
			Ren_Print("Lod %.2f  verts %4d/%4d  tris %4d/%4d  (%.2f%%)\n",
			          lodScale,
			          totalrv,
			          totalv,
			          totalrt,
			          totalt,
			          ( float )(100.0 * totalrt) / (float) totalt);
		}
		totalrv = totalrt = totalv = totalt = 0;
	}

	memset(newBones, 0, header->numBones);

	if (refent->oldframe == refent->frame)
	{
		backlerp  = 0;
		frontlerp = 1;
	}
	else
	{
		backlerp  = refent->backlerp;
		frontlerp = 1.0f - backlerp;
	}

	if (refent->oldTorsoFrame == refent->torsoFrame)
	{
		torsoBacklerp  = 0;
		torsoFrontlerp = 1;
	}
	else
	{
		torsoBacklerp  = refent->torsoBacklerp;
		torsoFrontlerp = 1.0f - torsoBacklerp;
	}

	frameSize = (int) (sizeof(mdsFrame_t) + (header->numBones - 1) * sizeof(mdsBoneFrameCompressed_t));

	frame = ( mdsFrame_t * )((byte *)header + header->ofsFrames +
	                         refent->frame * frameSize);
	torsoFrame = ( mdsFrame_t * )((byte *)header + header->ofsFrames +
	                              refent->torsoFrame * frameSize);
	oldFrame = ( mdsFrame_t * )((byte *)header + header->ofsFrames +
	                            refent->oldframe * frameSize);
	oldTorsoFrame = ( mdsFrame_t * )((byte *)header + header->ofsFrames +
	                                 refent->oldTorsoFrame * frameSize);

	// lerp all the needed bones (torsoParent is always the first bone in the list)
	cBoneList      = frame->bones;
	cBoneListTorso = torsoFrame->bones;

	boneInfo = ( mdsBoneInfo_t * )((byte *)header + header->ofsBones);
	boneRefs = boneList;
	//
	Matrix3Transpose(refent->torsoAxis, torsoAxis);

#ifdef HIGH_PRECISION_BONES
	if (qtrue)
	{
#else
	if (!backlerp && !torsoBacklerp)
	{
#endif
		for (i = 0; i < numBones; i++, boneRefs++)
		{
			if (validBones[*boneRefs])
			{
				// this bone is still in the cache
				bones[*boneRefs] = rawBones[*boneRefs];
				continue;
			}

			// find our parent, and make sure it has been calculated
			if ((boneInfo[*boneRefs].parent >= 0) && (!validBones[boneInfo[*boneRefs].parent] && !newBones[boneInfo[*boneRefs].parent]))
			{
				R_CalcBone(header, refent, boneInfo[*boneRefs].parent);
			}

			R_CalcBone(header, refent, *boneRefs);
		}
	}
	else        // interpolated
	{
		cOldBoneList      = oldFrame->bones;
		cOldBoneListTorso = oldTorsoFrame->bones;

		for (i = 0; i < numBones; i++, boneRefs++)
		{
			if (validBones[*boneRefs])
			{
				// this bone is still in the cache
				bones[*boneRefs] = rawBones[*boneRefs];
				continue;
			}

			// find our parent, and make sure it has been calculated
			if ((boneInfo[*boneRefs].parent >= 0) && (!validBones[boneInfo[*boneRefs].parent] && !newBones[boneInfo[*boneRefs].parent]))
			{
				R_CalcBoneLerp(header, refent, boneInfo[*boneRefs].parent);
			}

			R_CalcBoneLerp(header, refent, *boneRefs);
		}
	}

	// adjust for torso rotations
	torsoWeight = 0;
	boneRefs    = boneList;
	for (i = 0; i < numBones; i++, boneRefs++)
	{
		thisBoneInfo = &boneInfo[*boneRefs];
		bonePtr      = &bones[*boneRefs];
		// add torso rotation
		if (thisBoneInfo->torsoWeight > 0)
		{
			if (!newBones[*boneRefs])
			{
				// just copy it back from the previous calc
				bones[*boneRefs] = oldBones[*boneRefs];
				continue;
			}

			if (!(thisBoneInfo->flags & BONEFLAG_TAG))
			{
				// 1st multiply with the bone->matrix
				// 2nd translation for rotation relative to bone around torso parent offset
				VectorSubtract(bonePtr->translation, torsoParentOffset, t);
				Matrix4FromAxisPlusTranslation(bonePtr->matrix, t, m1);
				// 3rd scaled rotation
				// 4th translate back to torso parent offset
				// use previously created matrix if available for the same weight
				if (torsoWeight != thisBoneInfo->torsoWeight)
				{
					Matrix4FromScaledAxisPlusTranslation(torsoAxis, thisBoneInfo->torsoWeight, torsoParentOffset, m2);
					torsoWeight = thisBoneInfo->torsoWeight;
				}
				// multiply matrices to create one matrix to do all calculations
				Matrix4MultiplyInto3x3AndTranslation(m2, m1, bonePtr->matrix, bonePtr->translation);

			}
			else        // tag's require special handling
			{   // rotate each of the axis by the torsoAngles
				LocalScaledMatrixTransformVector(bonePtr->matrix[0], thisBoneInfo->torsoWeight, torsoAxis, tmpAxis[0]);
				LocalScaledMatrixTransformVector(bonePtr->matrix[1], thisBoneInfo->torsoWeight, torsoAxis, tmpAxis[1]);
				LocalScaledMatrixTransformVector(bonePtr->matrix[2], thisBoneInfo->torsoWeight, torsoAxis, tmpAxis[2]);
				memcpy(bonePtr->matrix, tmpAxis, sizeof(tmpAxis));

				// rotate the translation around the torsoParent
				VectorSubtract(bonePtr->translation, torsoParentOffset, t);
				LocalScaledMatrixTransformVector(t, thisBoneInfo->torsoWeight, torsoAxis, bonePtr->translation);
				VectorAdd(bonePtr->translation, torsoParentOffset, bonePtr->translation);
			}
		}
	}

	// backup the final bones
	memcpy(oldBones, bones, sizeof(bones[0]) * header->numBones);
}

#ifdef DBG_PROFILE_BONES
#define DBG_SHOWTIME    Ren_Print("%i: %i, ", di++, (dt = ri.Milliseconds()) - ldt); ldt = dt;
#else
#define DBG_SHOWTIME    ;
#endif

/*
==============
RB_SurfaceAnim
==============
*/
void RB_SurfaceAnim(mdsSurface_t *surface)
{
	int         j, k;
	refEntity_t *refent;
	int         *boneList;
	mdsHeader_t *header;

#ifdef DBG_PROFILE_BONES
	int di = 0, dt, ldt;

	dt  = ri.Milliseconds();
	ldt = dt;
#endif

	refent   = &backEnd.currentEntity->e;
	boneList = ( int * )((byte *)surface + surface->ofsBoneReferences);
	header   = ( mdsHeader_t * )((byte *)surface + surface->ofsHeader);

	R_CalcBones(header, (const refEntity_t *)refent, boneList, surface->numBoneReferences);

	DBG_SHOWTIME

	// calculate LOD
	// TODO: lerp the radius and origin
	VectorAdd(refent->origin, frame->localOrigin, vec);
	lodRadius = frame->radius;
	lodScale  = RB_CalcMDSLod(refent, vec, lodRadius, header->lodBias, header->lodScale);


//DBG_SHOWTIME

	// modification to allow dead skeletal bodies to go below minlod (experiment)
	if (refent->reFlags & REFLAG_DEAD_LOD)
	{
		if (lodScale < 0.35)       // allow dead to lod down to 35% (even if below surf->minLod) (%35 is arbitrary and probably not good generally.  worked for the blackguard/infantry as a test though)
		{
			lodScale = 0.35;
		}
		render_count = ROUND_INT(surface->numVerts * lodScale);

	}
	else
	{
		render_count = ROUND_INT(surface->numVerts * lodScale);
		if (render_count < surface->minLod)
		{
			if (!(refent->reFlags & REFLAG_DEAD_LOD))
			{
				render_count = surface->minLod;
			}
		}
	}

	if (render_count > surface->numVerts)
	{
		render_count = surface->numVerts;
	}

	RB_CheckOverflow(render_count, surface->numTriangles);

//DBG_SHOWTIME

	// setup triangle list
	RB_CheckOverflow(surface->numVerts, surface->numTriangles * 3);

//DBG_SHOWTIME

	collapse_map = ( int * )(( byte * )surface + surface->ofsCollapseMap);
	triangles    = ( int * )((byte *)surface + surface->ofsTriangles);
	indexes      = surface->numTriangles * 3;
	baseIndex    = tess.numIndexes;
	baseVertex   = tess.numVertexes;
	oldIndexes   = baseIndex;

	tess.numVertexes += render_count;

	pIndexes = &tess.indexes[baseIndex];

//DBG_SHOWTIME

	if (render_count == surface->numVerts)
	{
		memcpy(pIndexes, triangles, sizeof(triangles[0]) * indexes);
		if (baseVertex)
		{
			glIndex_t *indexesEnd;
			for (indexesEnd = pIndexes + indexes ; pIndexes < indexesEnd ; pIndexes++)
			{
				*pIndexes += baseVertex;
			}
		}
		tess.numIndexes += indexes;
	}
	else
	{
		int *collapseEnd;

		pCollapse = collapse;
		for (j = 0; j < render_count; pCollapse++, j++)
		{
			*pCollapse = j;
		}

		pCollapseMap = &collapse_map[render_count];
		for (collapseEnd = collapse + surface->numVerts ; pCollapse < collapseEnd; pCollapse++, pCollapseMap++)
		{
			*pCollapse = collapse[*pCollapseMap];
		}

		for (j = 0 ; j < indexes ; j += 3)
		{
			p0 = collapse[*(triangles++)];
			p1 = collapse[*(triangles++)];
			p2 = collapse[*(triangles++)];

			// FIXME
			// note:  serious optimization opportunity here,
			//  by sorting the triangles the following "continue"
			//  could have been made into a "break" statement.
			if (p0 == p1 || p1 == p2 || p2 == p0)
			{
				continue;
			}

			*(pIndexes++)    = baseVertex + p0;
			*(pIndexes++)    = baseVertex + p1;
			*(pIndexes++)    = baseVertex + p2;
			tess.numIndexes += 3;
		}

		baseIndex = tess.numIndexes;
	}

//DBG_SHOWTIME

	// deform the vertexes by the lerped bones

	numVerts   = surface->numVerts;
	v          = ( mdsVertex_t * )((byte *)surface + surface->ofsVerts);
	tempVert   = ( float * )(tess.xyz + baseVertex);
	tempNormal = ( float * )(tess.normal + baseVertex);
	for (j = 0; j < render_count; j++, tempVert += 4, tempNormal += 4)
	{
		mdsWeight_t *w;

		VectorClear(tempVert);

		w = v->weights;
		for (k = 0 ; k < v->numWeights ; k++, w++)
		{
			bone = &bones[w->boneIndex];
			LocalAddScaledMatrixTransformVectorTranslate(w->offset, w->boneWeight, bone->matrix, bone->translation, tempVert);
		}

		LocalMatrixTransformVector(v->normal, bones[v->weights[0].boneIndex].matrix, tempNormal);

		tess.texCoords0[baseVertex + j].v[0] = v->texCoords[0];
		tess.texCoords0[baseVertex + j].v[1] = v->texCoords[1];

		v = (mdsVertex_t *)&v->weights[v->numWeights];
	}

	DBG_SHOWTIME

	if (r_bonesDebug->integer)
	{
		if (r_bonesDebug->integer < 3)
		{
			int i;

			// DEBUG: show the bones as a stick figure with axis at each bone
			boneRefs = ( int * )((byte *)surface + surface->ofsBoneReferences);
			for (i = 0; i < surface->numBoneReferences; i++, boneRefs++)
			{
				bonePtr = &bones[*boneRefs];

				GL_Bind(tr.whiteImage);
				qglLineWidth(1);
				qglBegin(GL_LINES);
				for (j = 0; j < 3; j++)
				{
					VectorClear(vec);
					vec[j] = 1;
					qglColor3fv(vec);
					qglVertex3fv(bonePtr->translation);
					VectorMA(bonePtr->translation, 5, bonePtr->matrix[j], vec);
					qglVertex3fv(vec);
				}
				qglEnd();

				// connect to our parent if it's valid
				if (validBones[boneInfo[*boneRefs].parent])
				{
					qglLineWidth(2);
					qglBegin(GL_LINES);
					qglColor3f(.6, .6, .6);
					qglVertex3fv(bonePtr->translation);
					qglVertex3fv(bones[boneInfo[*boneRefs].parent].translation);
					qglEnd();
				}

				qglLineWidth(1);
			}
		}

		if (r_bonesDebug->integer == 3 || r_bonesDebug->integer == 4)
		{
			int render_indexes = (tess.numIndexes - oldIndexes);

			// show mesh edges
			tempVert   = ( float * )(tess.xyz + baseVertex);
			tempNormal = ( float * )(tess.normal + baseVertex);

			GL_Bind(tr.whiteImage);
			qglLineWidth(1);
			qglBegin(GL_LINES);
			qglColor3f(.0, .0, .8);

			pIndexes = &tess.indexes[oldIndexes];
			for (j = 0; j < render_indexes / 3; j++, pIndexes += 3)
			{
				qglVertex3fv(tempVert + 4 * pIndexes[0]);
				qglVertex3fv(tempVert + 4 * pIndexes[1]);

				qglVertex3fv(tempVert + 4 * pIndexes[1]);
				qglVertex3fv(tempVert + 4 * pIndexes[2]);

				qglVertex3fv(tempVert + 4 * pIndexes[2]);
				qglVertex3fv(tempVert + 4 * pIndexes[0]);
			}

			qglEnd();

			// track debug stats
			if (r_bonesDebug->integer == 4)
			{
				totalrv += render_count;
				totalrt += render_indexes / 3;
				totalv  += surface->numVerts;
				totalt  += surface->numTriangles;
			}

			if (r_bonesDebug->integer == 3)
			{
				Ren_Print("Lod %.2f  verts %4d/%4d  tris %4d/%4d  (%.2f%%)\n", lodScale, render_count, surface->numVerts, render_indexes / 3, surface->numTriangles,
				          ( float )(100.0 * render_indexes / 3) / (float) surface->numTriangles);
			}
		}
	}

	if (r_bonesDebug->integer > 1)
	{
		// dont draw the actual surface
		tess.numIndexes  = oldIndexes;
		tess.numVertexes = baseVertex;
		return;
	}

#ifdef DBG_PROFILE_BONES
	Ren_Print("\n");
#endif
}
Beispiel #20
0
static inline void RB_BlurGlowTexture()
{
	qglDisable (GL_CLIP_PLANE0);
	GL_Cull( CT_TWO_SIDED );

	// Go into orthographic 2d mode.
	qglMatrixMode(GL_PROJECTION);
	qglPushMatrix();
	qglLoadIdentity();
	qglOrtho(0, backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight, 0, -1, 1);
	qglMatrixMode(GL_MODELVIEW);
	qglPushMatrix();
	qglLoadIdentity();

	GL_State(GLS_DEPTHTEST_DISABLE);

	/////////////////////////////////////////////////////////
	// Setup vertex and pixel programs.
	/////////////////////////////////////////////////////////

	// NOTE: The 0.25 is because we're blending 4 textures (so = 1.0) and we want a relatively normalized pixel
	// intensity distribution, but this won't happen anyways if intensity is higher than 1.0.
	float fBlurDistribution = r_DynamicGlowIntensity->value * 0.25f;
	float fBlurWeight[4] = { fBlurDistribution, fBlurDistribution, fBlurDistribution, 1.0f };

	// Enable and set the Vertex Program.
	qglEnable( GL_VERTEX_PROGRAM_ARB );
	qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, tr.glowVShader );

	// Apply Pixel Shaders.
	if ( qglCombinerParameterfvNV )
	{
		BeginPixelShader( GL_REGISTER_COMBINERS_NV, tr.glowPShader );

		// Pass the blur weight to the regcom.
		qglCombinerParameterfvNV( GL_CONSTANT_COLOR0_NV, (float*)&fBlurWeight );
	}
	else if ( qglProgramEnvParameter4fARB )
	{
		BeginPixelShader( GL_FRAGMENT_PROGRAM_ARB, tr.glowPShader );

		// Pass the blur weight to the Fragment Program.
		qglProgramEnvParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 0, fBlurWeight[0], fBlurWeight[1], fBlurWeight[2], fBlurWeight[3] );
	}

	/////////////////////////////////////////////////////////
	// Set the blur texture to the 4 texture stages.
	/////////////////////////////////////////////////////////

	// How much to offset each texel by.
	float fTexelWidthOffset = 0.1f, fTexelHeightOffset = 0.1f;

	GLuint uiTex = tr.screenGlow;  

	qglActiveTextureARB( GL_TEXTURE3_ARB );  
	qglEnable( GL_TEXTURE_RECTANGLE_EXT ); 
	qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, uiTex );
	
	qglActiveTextureARB( GL_TEXTURE2_ARB ); 
	qglEnable( GL_TEXTURE_RECTANGLE_EXT );
	qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, uiTex );

	qglActiveTextureARB( GL_TEXTURE1_ARB );
	qglEnable( GL_TEXTURE_RECTANGLE_EXT );
	qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, uiTex );

	qglActiveTextureARB(GL_TEXTURE0_ARB );
	qglDisable( GL_TEXTURE_2D );  
	qglEnable( GL_TEXTURE_RECTANGLE_EXT );
	qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, uiTex ); 
	
	/////////////////////////////////////////////////////////
	// Draw the blur passes (each pass blurs it more, increasing the blur radius ).
	/////////////////////////////////////////////////////////
	
	//int iTexWidth = backEnd.viewParms.viewportWidth, iTexHeight = backEnd.viewParms.viewportHeight;
	int iTexWidth = glConfig.vidWidth, iTexHeight = glConfig.vidHeight; 
	
	for ( int iNumBlurPasses = 0; iNumBlurPasses < r_DynamicGlowPasses->integer; iNumBlurPasses++ )       
	{
		// Load the Texel Offsets into the Vertex Program.
		qglProgramEnvParameter4fARB( GL_VERTEX_PROGRAM_ARB, 0, -fTexelWidthOffset, -fTexelWidthOffset, 0.0f, 0.0f );
		qglProgramEnvParameter4fARB( GL_VERTEX_PROGRAM_ARB, 1, -fTexelWidthOffset, fTexelWidthOffset, 0.0f, 0.0f );
		qglProgramEnvParameter4fARB( GL_VERTEX_PROGRAM_ARB, 2, fTexelWidthOffset, -fTexelWidthOffset, 0.0f, 0.0f );
		qglProgramEnvParameter4fARB( GL_VERTEX_PROGRAM_ARB, 3, fTexelWidthOffset, fTexelWidthOffset, 0.0f, 0.0f );

		// After first pass put the tex coords to the viewport size.
		if ( iNumBlurPasses == 1 )
		{
			if ( !g_bTextureRectangleHack ) 
			{
				iTexWidth = backEnd.viewParms.viewportWidth;
				iTexHeight = backEnd.viewParms.viewportHeight;
			}

			uiTex = tr.blurImage;
			qglActiveTextureARB( GL_TEXTURE3_ARB );  
			qglDisable( GL_TEXTURE_2D );
			qglEnable( GL_TEXTURE_RECTANGLE_EXT ); 
			qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, uiTex );
			qglActiveTextureARB( GL_TEXTURE2_ARB ); 
			qglDisable( GL_TEXTURE_2D );
			qglEnable( GL_TEXTURE_RECTANGLE_EXT );
			qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, uiTex );			
			qglActiveTextureARB( GL_TEXTURE1_ARB );
			qglDisable( GL_TEXTURE_2D );
			qglEnable( GL_TEXTURE_RECTANGLE_EXT );
			qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, uiTex );
			qglActiveTextureARB(GL_TEXTURE0_ARB );
			qglDisable( GL_TEXTURE_2D );
			qglEnable( GL_TEXTURE_RECTANGLE_EXT );
			qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, uiTex ); 

			// Copy the current image over.
			qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, uiTex );     
			qglCopyTexSubImage2D( GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, 0, 0, backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight );
		}

		// Draw the fullscreen quad.
		qglBegin( GL_QUADS ); 
			qglMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0, iTexHeight );  
			qglVertex2f( 0, 0 );

			qglMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0, 0 );
			qglVertex2f( 0, backEnd.viewParms.viewportHeight );

			qglMultiTexCoord2fARB( GL_TEXTURE0_ARB, iTexWidth, 0 ); 
			qglVertex2f( backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight );

			qglMultiTexCoord2fARB( GL_TEXTURE0_ARB, iTexWidth, iTexHeight );
			qglVertex2f( backEnd.viewParms.viewportWidth, 0 ); 
		qglEnd();

		qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, tr.blurImage );       
		qglCopyTexSubImage2D( GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, 0, 0, backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight );    

		// Increase the texel offsets.
		// NOTE: This is possibly the most important input to the effect. Even by using an exponential function I've been able to
		// make it look better (at a much higher cost of course). This is cheap though and still looks pretty great. In the future 
		// I might want to use an actual gaussian equation to correctly calculate the pixel coefficients and attenuates, texel
		// offsets, gaussian amplitude and radius...
		fTexelWidthOffset += r_DynamicGlowDelta->value;
		fTexelHeightOffset += r_DynamicGlowDelta->value;
	}

	// Disable multi-texturing.
	qglActiveTextureARB( GL_TEXTURE3_ARB );   
	qglDisable( GL_TEXTURE_RECTANGLE_EXT );

	qglActiveTextureARB( GL_TEXTURE2_ARB );
	qglDisable( GL_TEXTURE_RECTANGLE_EXT );

	qglActiveTextureARB( GL_TEXTURE1_ARB );
	qglDisable( GL_TEXTURE_RECTANGLE_EXT );

	qglActiveTextureARB(GL_TEXTURE0_ARB );
	qglDisable( GL_TEXTURE_RECTANGLE_EXT );
	qglEnable( GL_TEXTURE_2D );

	qglDisable( GL_VERTEX_PROGRAM_ARB );
	EndPixelShader();
	
	qglMatrixMode(GL_PROJECTION);
	qglPopMatrix();
	qglMatrixMode(GL_MODELVIEW);
	qglPopMatrix();

	qglDisable( GL_BLEND );
	glState.currenttmu = 0;	//this matches the last one we activated
}
Beispiel #21
0
/**
 * @brief Stretches a raw 32 bit power of 2 bitmap image over the given screen rectangle.
 * Used for cinematics.
 *
 * @param[in] x
 * @param[in] y
 * @param[in] w
 * @param[in] h
 * @param[in] cols
 * @param[in] rows
 * @param[in] data
 * @param[in] client
 * @param[in] dirty
 *
 * @todo FIXME: not exactly backend
 */
void RE_StretchRaw(int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty)
{
	int i, j;
	int start;

	if (!tr.registered)
	{
		return;
	}
	R_IssuePendingRenderCommands();

	// we definately want to sync every frame for the cinematics
	qglFinish();

	start = 0;
	if (r_speeds->integer)
	{
		start = ri.Milliseconds();
	}

	if (!GL_ARB_texture_non_power_of_two)
	{
		// make sure rows and cols are powers of 2
		for (i = 0; (1 << i) < cols; i++)
		{
		}
		for (j = 0; (1 << j) < rows; j++)
		{
		}
		if ((1 << i) != cols || (1 << j) != rows)
		{
			Ren_Drop("Draw_StretchRaw: size not a power of 2: %i by %i", cols, rows);
		}
	}

	GL_Bind(tr.scratchImage[client]);

	// if the scratchImage isn't in the format we want, specify it as a new texture
	if (cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height)
	{
		tr.scratchImage[client]->width  = tr.scratchImage[client]->uploadWidth = cols;
		tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
		qglTexImage2D(GL_TEXTURE_2D, 0, 3, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	}
	else
	{
		if (dirty)
		{
			// otherwise, just subimage upload it so that drivers can tell we are going to be changing
			// it and don't try and do a texture compression
			qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data);
		}
	}

	if (r_speeds->integer)
	{
		int end = ri.Milliseconds();

		Ren_Print("qglTexSubImage2D %i, %i: %i msec\n", cols, rows, end - start);
	}

	RB_SetGL2D();

	qglColor3f(tr.identityLight, tr.identityLight, tr.identityLight);

	qglBegin(GL_QUADS);
	qglTexCoord2f(0.5f / cols, 0.5f / rows);
	qglVertex2f(x, y);
	qglTexCoord2f((cols - 0.5f) / cols, 0.5f / rows);
	qglVertex2f(x + w, y);
	qglTexCoord2f((cols - 0.5f) / cols, (rows - 0.5f) / rows);
	qglVertex2f(x + w, y + h);
	qglTexCoord2f(0.5f / cols, (rows - 0.5f) / rows);
	qglVertex2f(x, y + h);
	qglEnd();
}
Beispiel #22
0
// Draw the glow blur over the screen additively.
static inline void RB_DrawGlowOverlay()
{
	qglDisable (GL_CLIP_PLANE0);
	GL_Cull( CT_TWO_SIDED );

	// Go into orthographic 2d mode.
	qglMatrixMode(GL_PROJECTION);
	qglPushMatrix();
	qglLoadIdentity();
	qglOrtho(0, glConfig.vidWidth, glConfig.vidHeight, 0, -1, 1);
	qglMatrixMode(GL_MODELVIEW);
	qglPushMatrix();
	qglLoadIdentity();

	GL_State(GLS_DEPTHTEST_DISABLE);

	qglDisable( GL_TEXTURE_2D );
	qglEnable( GL_TEXTURE_RECTANGLE_EXT );

	// For debug purposes.
	if ( r_DynamicGlow->integer != 2 )
	{
		// Render the normal scene texture.
		qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, tr.sceneImage ); 
		qglBegin(GL_QUADS);    
			qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
			qglTexCoord2f( 0, glConfig.vidHeight ); 
			qglVertex2f( 0, 0 );

			qglTexCoord2f( 0, 0 );
			qglVertex2f( 0, glConfig.vidHeight );

			qglTexCoord2f( glConfig.vidWidth, 0 );
			qglVertex2f( glConfig.vidWidth, glConfig.vidHeight );

			qglTexCoord2f( glConfig.vidWidth, glConfig.vidHeight );
			qglVertex2f( glConfig.vidWidth, 0 );
		qglEnd();
	}

	// One and Inverse Src Color give a very soft addition, while one one is a bit stronger. With one one we can
	// use additive blending through multitexture though.
	if ( r_DynamicGlowSoft->integer )
	{
		qglBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_COLOR );
	}
	else
	{
		qglBlendFunc( GL_ONE, GL_ONE );
	}
	qglEnable( GL_BLEND );  

	// Now additively render the glow texture.
	qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, tr.blurImage );     
	qglBegin(GL_QUADS);    
		qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );  
		qglTexCoord2f( 0, r_DynamicGlowHeight->integer ); 
		qglVertex2f( 0, 0 );

		qglTexCoord2f( 0, 0 );
		qglVertex2f( 0, glConfig.vidHeight );

		qglTexCoord2f( r_DynamicGlowWidth->integer, 0 );
		qglVertex2f( glConfig.vidWidth, glConfig.vidHeight );

		qglTexCoord2f( r_DynamicGlowWidth->integer, r_DynamicGlowHeight->integer );
		qglVertex2f( glConfig.vidWidth, 0 );
	qglEnd();

	qglDisable( GL_TEXTURE_RECTANGLE_EXT );
	qglEnable( GL_TEXTURE_2D );
	qglBlendFunc( GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR );
	qglDisable( GL_BLEND );

	qglMatrixMode(GL_PROJECTION);
	qglPopMatrix();
	qglMatrixMode(GL_MODELVIEW);
	qglPopMatrix();
}
/*
==================
RB_STD_LightScale

Perform extra blending passes to multiply the entire buffer by
a floating point value
==================
*/
void RB_STD_LightScale(void)
{
	float	v, f;

	if (backEnd.overBright == 1.0f) {
		return;
	}

	if (r_skipLightScale.GetBool()) {
		return;
	}

	RB_LogComment("---------- RB_STD_LightScale ----------\n");

	// the scissor may be smaller than the viewport for subviews
	if (r_useScissor.GetBool()) {
		qglScissor(backEnd.viewDef->viewport.x1 + backEnd.viewDef->scissor.x1,
		           backEnd.viewDef->viewport.y1 + backEnd.viewDef->scissor.y1,
		           backEnd.viewDef->scissor.x2 - backEnd.viewDef->scissor.x1 + 1,
		           backEnd.viewDef->scissor.y2 - backEnd.viewDef->scissor.y1 + 1);
		backEnd.currentScissor = backEnd.viewDef->scissor;
	}

	// full screen blends
	qglLoadIdentity();
	qglMatrixMode(GL_PROJECTION);
	qglPushMatrix();
	qglLoadIdentity();
	qglOrtho(0, 1, 0, 1, -1, 1);

	GL_State(GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_SRC_COLOR);
	GL_Cull(CT_TWO_SIDED);	// so mirror views also get it
	globalImages->BindNull();
	qglDisable(GL_DEPTH_TEST);
	qglDisable(GL_STENCIL_TEST);

	v = 1;

	while (idMath::Fabs(v - backEnd.overBright) > 0.01) {	// a little extra slop
		f = backEnd.overBright / v;
		f /= 2;

		if (f > 1) {
			f = 1;
		}

		qglColor3f(f, f, f);
		v = v * f * 2;

		qglBegin(GL_QUADS);
		qglVertex2f(0,0);
		qglVertex2f(0,1);
		qglVertex2f(1,1);
		qglVertex2f(1,0);
		qglEnd();
	}


	qglPopMatrix();
	qglEnable(GL_DEPTH_TEST);
	qglMatrixMode(GL_MODELVIEW);
	GL_Cull(CT_FRONT_SIDED);
}
Beispiel #24
0
/*
====================
BuildOptTriangles

Generate a new list of triangles from the optEdeges
====================
*/
static void BuildOptTriangles( optIsland_t *island ) {
	optVertex_t		*ov, *second, *third, *middle;
	optEdge_t		*e1, *e1Next, *e2, *e2Next, *check, *checkNext;

	// free them
	FreeOptTriangles( island );

	// clear the vertex emitted flags
	for ( ov = island->verts ; ov ; ov = ov->islandLink ) {
		ov->emited = false;
	}

	// clear the edge triangle links
	for ( check = island->edges ; check ; check = check->islandLink ) {
		check->frontTri = check->backTri = NULL;
	}

	// check all possible triangle made up out of the
	// edges coming off the vertex
	for ( ov = island->verts ; ov ; ov = ov->islandLink ) {
		if ( !ov->edges ) {
			continue;
		}

#if 0
if ( dmapGlobals.drawflag && ov == (optVertex_t *)0x1845a60 ) {
for ( e1 = ov->edges ; e1 ; e1 = e1Next ) {
	qglBegin( GL_LINES );
	qglColor3f( 0,1,0 );
	qglVertex3fv( e1->v1->pv.ToFloatPtr() );
	qglVertex3fv( e1->v2->pv.ToFloatPtr() );
	qglEnd();
	qglFlush();
	if ( e1->v1 == ov ) {
		e1Next = e1->v1link;
	} else if ( e1->v2 == ov ) {
		e1Next = e1->v2link;
	}
}
}
#endif
		for ( e1 = ov->edges ; e1 ; e1 = e1Next ) {
			if ( e1->v1 == ov ) {
				second = e1->v2;
				e1Next = e1->v1link;
			} else if ( e1->v2 == ov ) {
				second = e1->v1;
				e1Next = e1->v2link;
			} else {
				common->Error( "BuildOptTriangles: mislinked edge" );
			}

			// if the vertex has already been used, it can't be used again
			if ( second->emited ) {
				continue;
			}

			for ( e2 = ov->edges ; e2 ; e2 = e2Next ) {
				if ( e2->v1 == ov ) {
					third = e2->v2;
					e2Next = e2->v1link;
				} else if ( e2->v2 == ov ) {
					third = e2->v1;
					e2Next = e2->v2link;
				} else {
					common->Error( "BuildOptTriangles: mislinked edge" );
				}
				if ( e2 == e1 ) {
					continue;
				}

				// if the vertex has already been used, it can't be used again
				if ( third->emited ) {
					continue;
				}

				// if the triangle is backwards or degenerate, don't use it
				if ( !IsTriangleValid( ov, second, third ) ) {
					continue;
				}

				// see if any other edge bisects these two, which means
				// this triangle shouldn't be used
				for ( check = ov->edges ; check ; check = checkNext ) {
					if ( check->v1 == ov ) {
						middle = check->v2;
						checkNext = check->v1link;
					} else if ( check->v2 == ov ) {
						middle = check->v1;
						checkNext = check->v2link;
					} else {
						common->Error( "BuildOptTriangles: mislinked edge" );
					}

					if ( check == e1 || check == e2 ) {
						continue;
					}

					if ( IsTriangleValid( ov, second, middle ) 
						&& IsTriangleValid( ov, middle, third ) ) {
						break;	// should use the subdivided ones
					}
				}

				if ( check ) {
					continue;	// don't use it
				}

				// the triangle is valid
				CreateOptTri( ov, e1, e2, island );
			}
		}

		// later vertexes will not emit triangles that use an
		// edge that this vert has already used
		ov->emited = true;
	}
}
Beispiel #25
0
/*
 * Interpolates between two frames and origins
 */
void
R_DrawAliasFrameLerp ( dmdl_t *paliashdr, float backlerp )
{
#if defined(VERTEX_ARRAYS)
    uint16_t total;
    GLenum type;
#endif
	float l;
	daliasframe_t   *frame, *oldframe;
	dtrivertx_t *v, *ov, *verts;
	int     *order;
	int count;
	float frontlerp;
	float alpha;
	vec3_t move, delta, vectors [ 3 ];
	vec3_t frontv, backv;
	int i;
	int index_xyz;
	float   *lerp;

	frame = (daliasframe_t *) ( (byte *) paliashdr + paliashdr->ofs_frames
								+ currententity->frame * paliashdr->framesize );
	verts = v = frame->verts;

	oldframe = (daliasframe_t *) ( (byte *) paliashdr + paliashdr->ofs_frames
								   + currententity->oldframe * paliashdr->framesize );
	ov = oldframe->verts;

	order = (int *) ( (byte *) paliashdr + paliashdr->ofs_glcmds );

	if ( currententity->flags & RF_TRANSLUCENT )
	{
		alpha = currententity->alpha;
	}
	else
	{
		alpha = 1.0;
	}

	if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM ) )
	{
		qglDisable( GL_TEXTURE_2D );
	}

	frontlerp = 1.0 - backlerp;

	/* move should be the delta back to the previous frame * backlerp */
	VectorSubtract( currententity->oldorigin, currententity->origin, delta );
	AngleVectors( currententity->angles, vectors [ 0 ], vectors [ 1 ], vectors [ 2 ] );

	move [ 0 ] = DotProduct( delta, vectors [ 0 ] );   /* forward */
	move [ 1 ] = -DotProduct( delta, vectors [ 1 ] );  /* left */
	move [ 2 ] = DotProduct( delta, vectors [ 2 ] );   /* up */

	VectorAdd( move, oldframe->translate, move );

	for ( i = 0; i < 3; i++ )
	{
		move [ i ] = backlerp * move [ i ] + frontlerp * frame->translate [ i ];
	}

	for ( i = 0; i < 3; i++ )
	{
		frontv [ i ] = frontlerp * frame->scale [ i ];
		backv [ i ] = backlerp * oldframe->scale [ i ];
	}

	lerp = s_lerped [ 0 ];

	R_LerpVerts( paliashdr->num_xyz, v, ov, verts, lerp, move, frontv, backv );

	if ( gl_vertex_arrays->value )
	{
		float colorArray [ MAX_VERTS * 4 ];

		qglEnableClientState( GL_VERTEX_ARRAY );
		qglVertexPointer( 3, GL_FLOAT, 16, s_lerped );

		if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM ) )
		{
			qglColor4f( shadelight [ 0 ], shadelight [ 1 ], shadelight [ 2 ], alpha );
		}
		else
		{
			qglEnableClientState( GL_COLOR_ARRAY );
			qglColorPointer( 3, GL_FLOAT, 0, colorArray );

			/* pre light everything */
			for ( i = 0; i < paliashdr->num_xyz; i++ )
			{
				float l = shadedots [ verts [ i ].lightnormalindex ];

				colorArray [ i * 3 + 0 ] = l * shadelight [ 0 ];
				colorArray [ i * 3 + 1 ] = l * shadelight [ 1 ];
				colorArray [ i * 3 + 2 ] = l * shadelight [ 2 ];
			}
		}

#if !defined(VERTEX_ARRAYS)
		if ( qglLockArraysEXT != 0 )
		{
			qglLockArraysEXT( 0, paliashdr->num_xyz );
		}
#endif

		while ( 1 )
		{
			/* get the vertex count and primitive type */
			count = *order++;

			if ( !count )
			{
				break; /* done */
			}

			if ( count < 0 )
			{
				count = -count;
#if defined(VERTEX_ARRAYS)
                type = GL_TRIANGLE_FAN;
#else
				qglBegin( GL_TRIANGLE_FAN );
#endif
			}
			else
			{
#if defined(VERTEX_ARRAYS)
                type = GL_TRIANGLE_STRIP;
#else
				qglBegin( GL_TRIANGLE_STRIP );
#endif
			}

#if defined(VERTEX_ARRAYS)
            total = count;
            GLfloat vtx[3*total];
            GLfloat tex[2*total];
            uint32_t index_vtx = 0;
            uint32_t index_tex = 0;
#endif

			if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM ) )
			{
				do
				{
					index_xyz = order [ 2 ];
					order += 3;

#if defined(VERTEX_ARRAYS)
                    vtx[index_vtx++] = s_lerped [ index_xyz ][0];
                    vtx[index_vtx++] = s_lerped [ index_xyz ][1];
                    vtx[index_vtx++] = s_lerped [ index_xyz ][2];
#else
					qglVertex3fv( s_lerped [ index_xyz ] );
#endif
				}
				while ( --count );
			}
			else
			{
				do
				{
#if defined(VERTEX_ARRAYS)
                    tex[index_tex++] = ( (float *) order ) [ 0 ];
                    tex[index_tex++] = ( (float *) order ) [ 1 ];
					index_xyz = order [ 2 ];

					order += 3;
#else
					/* texture coordinates come from the draw list */
					qglTexCoord2f( ( (float *) order ) [ 0 ], ( (float *) order ) [ 1 ] );
					index_xyz = order [ 2 ];

					order += 3;

					qglArrayElement( index_xyz );
#endif
				}
				while ( --count );
			}

#if defined(VERTEX_ARRAYS)
            qglEnableClientState( GL_VERTEX_ARRAY );

            qglVertexPointer( 3, GL_FLOAT, 0, vtx );
            qglDrawArrays( type, 0, total );

            qglDisableClientState( GL_VERTEX_ARRAY );
#else
			qglEnd();
#endif
		}
#if !defined(VERTEX_ARRAYS)
		if ( qglUnlockArraysEXT != 0 )
		{
			qglUnlockArraysEXT();
		}
#endif
	}
	else
	{
		while ( 1 )
		{
			/* get the vertex count and primitive type */
			count = *order++;

			if ( !count )
			{
				break; /* done */
			}

			if ( count < 0 )
			{
				count = -count;
#if defined(VERTEX_ARRAYS)
                type = GL_TRIANGLE_FAN;
#else
				qglBegin( GL_TRIANGLE_FAN );
#endif
			}
			else
			{
#if defined(VERTEX_ARRAYS)
                type = GL_TRIANGLE_STRIP;
#else
				qglBegin( GL_TRIANGLE_STRIP );
#endif
			}

#if defined(VERTEX_ARRAYS)
            total = count;
            GLfloat vtx[3*total];
            GLfloat tex[2*total];
            GLfloat clr[4*total];
            uint32_t index_vtx = 0;
            uint32_t index_tex = 0;
            uint32_t index_clr = 0;
#endif

			if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) )
			{
				do
				{
					index_xyz = order [ 2 ];
					order += 3;

#if defined(VERTEX_ARRAYS)
                    clr[index_clr++] = shadelight [ 0 ];
                    clr[index_clr++] = shadelight [ 1 ];
                    clr[index_clr++] = shadelight [ 2 ];
                    clr[index_clr++] = alpha;

                    vtx[index_vtx++] = s_lerped [ index_xyz ][ 0 ];
                    vtx[index_vtx++] = s_lerped [ index_xyz ][ 1 ];
                    vtx[index_vtx++] = s_lerped [ index_xyz ][ 2 ];
#else
					qglColor4f( shadelight [ 0 ], shadelight [ 1 ], shadelight [ 2 ], alpha );
					qglVertex3fv( s_lerped [ index_xyz ] );
#endif
				}
				while ( --count );
			}
			else
			{
				do
				{
					/* texture coordinates come from the draw list */
#if defined(VERTEX_ARRAYS)
                    tex[index_tex++] = ( (float *) order ) [ 0 ];
                    tex[index_tex++] = ( (float *) order ) [ 1 ];
#else
					qglTexCoord2f( ( (float *) order ) [ 0 ], ( (float *) order ) [ 1 ] );
#endif
					index_xyz = order [ 2 ];
					order += 3;

					/* normals and vertexes come from the frame list */
					l = shadedots [ verts [ index_xyz ].lightnormalindex ];

#if defined(VERTEX_ARRAYS)
                    clr[index_clr++] = l * shadelight [ 0 ];
                    clr[index_clr++] = l * shadelight [ 1 ];
                    clr[index_clr++] = l * shadelight [ 2 ];
                    clr[index_clr++] = alpha;

                    vtx[index_vtx++] = s_lerped [ index_xyz ][ 0 ];
                    vtx[index_vtx++] = s_lerped [ index_xyz ][ 1 ];
                    vtx[index_vtx++] = s_lerped [ index_xyz ][ 2 ];
#else
					qglColor4f( l * shadelight [ 0 ], l * shadelight [ 1 ], l * shadelight [ 2 ], alpha );
					qglVertex3fv( s_lerped [ index_xyz ] );
#endif
				}
				while ( --count );
			}

#if defined(VERTEX_ARRAYS)
            qglEnableClientState( GL_VERTEX_ARRAY );
            qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
            qglEnableClientState( GL_COLOR_ARRAY );

            qglVertexPointer( 3, GL_FLOAT, 0, vtx );
            qglTexCoordPointer( 2, GL_FLOAT, 0, tex );
            qglColorPointer( 4, GL_FLOAT, 0, clr );
            qglDrawArrays( type, 0, total );

            qglDisableClientState( GL_VERTEX_ARRAY );
            qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
            qglDisableClientState( GL_COLOR_ARRAY );
#else
			qglEnd();
#endif
		}
	}

	if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM ) )
	{
		qglEnable( GL_TEXTURE_2D );
	}
}
Beispiel #26
0
/*
=====================
SplitOriginalEdgesAtCrossings
=====================
*/
void SplitOriginalEdgesAtCrossings( optimizeGroup_t *opt ) {
	int				i, j, k, l;
	int				numOriginalVerts;
	edgeCrossing_t	**crossings;

	numOriginalVerts = numOptVerts;
	// now split any crossing edges and create optEdges
	// linked to the vertexes

	// debug drawing bounds
	dmapGlobals.drawBounds = optBounds;

	dmapGlobals.drawBounds[0][0] -= 2;
	dmapGlobals.drawBounds[0][1] -= 2;
	dmapGlobals.drawBounds[1][0] += 2;
	dmapGlobals.drawBounds[1][1] += 2;

	// generate crossing points between all the original edges
	crossings = (edgeCrossing_t **)Mem_ClearedAlloc( numOriginalEdges * sizeof( *crossings ), TAG_DMAP );

	for ( i = 0 ; i < numOriginalEdges ; i++ ) {
		if ( dmapGlobals.drawflag ) {
			DrawOriginalEdges( numOriginalEdges, originalEdges );
			qglBegin( GL_LINES );
			qglColor3f( 0, 1, 0 );
			qglVertex3fv( originalEdges[i].v1->pv.ToFloatPtr() );
			qglColor3f( 0, 0, 1 );
			qglVertex3fv( originalEdges[i].v2->pv.ToFloatPtr() );
			qglEnd();
			qglFlush();
		}
		for ( j = i+1 ; j < numOriginalEdges ; j++ ) {
			optVertex_t	*v1, *v2, *v3, *v4;
			optVertex_t	*newVert;
			edgeCrossing_t	*cross;

			v1 = originalEdges[i].v1;
			v2 = originalEdges[i].v2;
			v3 = originalEdges[j].v1;
			v4 = originalEdges[j].v2;

			if ( !EdgesCross( v1, v2, v3, v4 ) ) {
				continue;
			}

			// this is the only point in optimization where
			// completely new points are created, and it only
			// happens if there is overlapping coplanar
			// geometry in the source triangles
			newVert = EdgeIntersection( v1, v2, v3, v4, opt );

			if ( !newVert ) {
//common->Printf( "lines %i (%i to %i) and %i (%i to %i) are colinear\n", i, v1 - optVerts, v2 - optVerts, 
//		   j, v3 - optVerts, v4 - optVerts );	// !@#
				// colinear, so add both verts of each edge to opposite
				if ( VertexBetween( v3, v1, v2 ) ) {
					cross = (edgeCrossing_t *)Mem_ClearedAlloc( sizeof( *cross ), TAG_DMAP );
					cross->ov = v3;
					cross->next = crossings[i];
					crossings[i] = cross;
				}

				if ( VertexBetween( v4, v1, v2 ) ) {
					cross = (edgeCrossing_t *)Mem_ClearedAlloc( sizeof( *cross ), TAG_DMAP );
					cross->ov = v4;
					cross->next = crossings[i];
					crossings[i] = cross;
				}

				if ( VertexBetween( v1, v3, v4 ) ) {
					cross = (edgeCrossing_t *)Mem_ClearedAlloc( sizeof( *cross ), TAG_DMAP );
					cross->ov = v1;
					cross->next = crossings[j];
					crossings[j] = cross;
				}

				if ( VertexBetween( v2, v3, v4 ) ) {
					cross = (edgeCrossing_t *)Mem_ClearedAlloc( sizeof( *cross ), TAG_DMAP );
					cross->ov = v2;
					cross->next = crossings[j];
					crossings[j] = cross;
				}

				continue;
			}
#if 0
if ( newVert && newVert != v1 && newVert != v2 && newVert != v3 && newVert != v4 ) {
common->Printf( "lines %i (%i to %i) and %i (%i to %i) cross at new point %i\n", i, v1 - optVerts, v2 - optVerts, 
		   j, v3 - optVerts, v4 - optVerts, newVert - optVerts );
} else if ( newVert ) {
common->Printf( "lines %i (%i to %i) and %i (%i to %i) intersect at old point %i\n", i, v1 - optVerts, v2 - optVerts, 
		  j, v3 - optVerts, v4 - optVerts, newVert - optVerts );
}
#endif
			if ( newVert != v1 && newVert != v2 ) {
				cross = (edgeCrossing_t *)Mem_ClearedAlloc( sizeof( *cross ), TAG_DMAP );
				cross->ov = newVert;
				cross->next = crossings[i];
				crossings[i] = cross;
			}

			if ( newVert != v3 && newVert != v4 ) {
				cross = (edgeCrossing_t *)Mem_ClearedAlloc( sizeof( *cross ), TAG_DMAP );
				cross->ov = newVert;
				cross->next = crossings[j];
				crossings[j] = cross;
			}

		}
	}


	// now split each edge by its crossing points
	// colinear edges will have duplicated edges added, but it won't hurt anything
	for ( i = 0 ; i < numOriginalEdges ; i++ ) {
		edgeCrossing_t	*cross, *nextCross;
		int				numCross;
		optVertex_t		**sorted;

		numCross = 0;
		for ( cross = crossings[i] ; cross ; cross = cross->next ) {
			numCross++;
		}
		numCross += 2;	// account for originals
		sorted = (optVertex_t **)Mem_Alloc( numCross * sizeof( *sorted ), TAG_DMAP );
		sorted[0] = originalEdges[i].v1;
		sorted[1] = originalEdges[i].v2;
		j = 2;
		for ( cross = crossings[i] ; cross ; cross = nextCross ) {
			nextCross = cross->next;
			sorted[j] = cross->ov;
			Mem_Free( cross );
			j++;
		}

		// add all possible fragment combinations that aren't divided
		// by another point
		for ( j = 0 ; j < numCross ; j++ ) {
			for ( k = j+1 ; k < numCross ; k++ ) {
				for ( l = 0 ; l < numCross ; l++ ) {
					if ( sorted[l] == sorted[j] || sorted[l] == sorted[k] ) {
						continue;
					}
					if ( sorted[j] == sorted[k] ) {
						continue;
					}
					if ( VertexBetween( sorted[l], sorted[j], sorted[k] ) ) {
						break;
					}
				}
				if ( l == numCross ) {
//common->Printf( "line %i fragment from point %i to %i\n", i, sorted[j] - optVerts, sorted[k] - optVerts );
					AddEdgeIfNotAlready( sorted[j], sorted[k] );
				}
			}
		}

		Mem_Free( sorted );
	}


	Mem_Free( crossings );
	Mem_Free( originalEdges );

	// check for duplicated edges
	for ( i = 0 ; i < numOptEdges ; i++ ) {
		for ( j = i+1 ; j < numOptEdges ; j++ ) {
			if ( ( optEdges[i].v1 == optEdges[j].v1 && optEdges[i].v2 == optEdges[j].v2 ) 
				|| ( optEdges[i].v1 == optEdges[j].v2 && optEdges[i].v2 == optEdges[j].v1 ) ) {
				common->Printf( "duplicated optEdge\n" );
			}
		}
	}

	if ( dmapGlobals.verbose ) {
		common->Printf( "%6i original edges\n", numOriginalEdges );
		common->Printf( "%6i edges after splits\n", numOptEdges );
		common->Printf( "%6i original vertexes\n", numOriginalVerts );
		common->Printf( "%6i vertexes after splits\n", numOptVerts );
	}
}
Beispiel #27
0
void R_RenderShadowEdges( void ) {
	int		i;
	int		c;
	int		j;
	int		i2;
#if 0
	int		c_edges, c_rejected;
	int		c2, k;
	int		hit[2];
#endif
#ifdef _STENCIL_REVERSE
	int		numTris;
	int		o1, o2, o3;
#endif

	// an edge is NOT a silhouette edge if its face doesn't face the light,
	// or if it has a reverse paired edge that also faces the light.
	// A well behaved polyhedron would have exactly two faces for each edge,
	// but lots of models have dangling edges or overfanned edges
#if 0
	c_edges = 0;
	c_rejected = 0;
#endif

#ifdef HAVE_GLES
	idx = 0;
#endif

	for ( i = 0 ; i < tess.numVertexes ; i++ ) {
		c = numEdgeDefs[ i ];
		for ( j = 0 ; j < c ; j++ ) {
			if ( !edgeDefs[ i ][ j ].facing ) {
				continue;
			}

			//with this system we can still get edges shared by more than 2 tris which
			//produces artifacts including seeing the shadow through walls. So for now
			//we are going to render all edges even though it is a tiny bit slower. -rww
#if 1
			i2 = edgeDefs[ i ][ j ].i2;
#ifdef HAVE_GLES
			// A single drawing call is better than many. So I prefer a singe TRIANGLES call than many TRIANGLE_STRIP call
			// even if it seems less efficiant, it's faster on the PANDORA
			indexes[idx++] = i;
			indexes[idx++] = i + tess.numVertexes;
			indexes[idx++] = i2;
			indexes[idx++] = i2;
			indexes[idx++] = i + tess.numVertexes;
			indexes[idx++] = i2 + tess.numVertexes;
#else
			qglBegin( GL_TRIANGLE_STRIP );
				qglVertex3fv( tess.xyz[ i ] );
				qglVertex3fv( tess.xyz[ i + tess.numVertexes ] );
				qglVertex3fv( tess.xyz[ i2 ] );
				qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
			qglEnd();
#endif
#else
			hit[0] = 0;
			hit[1] = 0;

			i2 = edgeDefs[ i ][ j ].i2;
			c2 = numEdgeDefs[ i2 ];
			for ( k = 0 ; k < c2 ; k++ ) {
				if ( edgeDefs[ i2 ][ k ].i2 == i ) {
					hit[ edgeDefs[ i2 ][ k ].facing ]++;
				}
			}

			// if it doesn't share the edge with another front facing
			// triangle, it is a sil edge
			if (hit[1] != 1)
			{
				qglBegin( GL_TRIANGLE_STRIP );
				qglVertex3fv( tess.xyz[ i ] );
				qglVertex3fv( tess.xyz[ i + tess.numVertexes ] );
				qglVertex3fv( tess.xyz[ i2 ] );
				qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
				qglEnd();
				c_edges++;
			} else {
				c_rejected++;
			}
#endif
		}
	}

#ifdef _STENCIL_REVERSE
	//Carmack Reverse<tm> method requires that volumes
	//be capped properly -rww
	numTris = tess.numIndexes / 3;

	for ( i = 0 ; i < numTris ; i++ )
	{
		if ( !facing[i] )
		{
			continue;
		}

		o1 = tess.indexes[ i*3 + 0 ];
		o2 = tess.indexes[ i*3 + 1 ];
		o3 = tess.indexes[ i*3 + 2 ];

#ifdef HAVE_GLES
		indexes[idx++] = o1;
		indexes[idx++] = o2;
		indexes[idx++] = o3;
		indexes[idx++] = o3 + tess.numVertexes;
		indexes[idx++] = o2 + tess.numVertexes;
		indexes[idx++] = o1 + tess.numVertexes;
#else
		qglBegin(GL_TRIANGLES);
			qglVertex3fv(tess.xyz[o1]);
			qglVertex3fv(tess.xyz[o2]);
			qglVertex3fv(tess.xyz[o3]);
		qglEnd();
		qglBegin(GL_TRIANGLES);
			qglVertex3fv(tess.xyz[o3 + tess.numVertexes]);
			qglVertex3fv(tess.xyz[o2 + tess.numVertexes]);
			qglVertex3fv(tess.xyz[o1 + tess.numVertexes]);
		qglEnd();
#endif
	}
#ifdef HAVE_GLES
	qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
#endif
#endif
}
Beispiel #28
0
static	void RemoveIfColinear( optVertex_t *ov, optIsland_t *island ) {
	optEdge_t	*e, *e1, *e2;
	optVertex_t *v1, *v2, *v3;
	idVec3		dir1, dir2;
	float		dist;
	idVec3		point;
	idVec3		offset;
	float		off;

	v2 = ov;

	// we must find exactly two edges before testing for colinear
	e1 = NULL;
	e2 = NULL;
	for ( e = ov->edges ; e ; ) {
		if ( !e1 ) {
			e1 = e;
		} else if ( !e2 ) {
			e2 = e;
		} else {
			return;		// can't remove a vertex with three edges
		}
		if ( e->v1 == v2 ) {
			e = e->v1link;
		} else if ( e->v2 == v2 ) {
			e = e->v2link;
		} else {
			common->Error( "RemoveIfColinear: mislinked edge" );
			return;
		}
	}

	// can't remove if no edges
	if ( !e1 ) {
		return;
	}

	if ( !e2 ) {
		// this may still happen legally when a tiny triangle is
		// the only thing in a group
		common->Printf( "WARNING: vertex with only one edge\n" );
		return;
	}

	if ( e1->v1 == v2 ) {
		v1 = e1->v2;
	} else if ( e1->v2 == v2 ) {
		v1 = e1->v1;
	} else {
		common->Error( "RemoveIfColinear: mislinked edge" );
		return;
	}
	if ( e2->v1 == v2 ) {
		v3 = e2->v2;
	} else if ( e2->v2 == v2 ) {
		v3 = e2->v1;
	} else {
		common->Error( "RemoveIfColinear: mislinked edge" );
		return;
	}

	if ( v1 == v3 ) {
		common->Error( "RemoveIfColinear: mislinked edge" );
		return;
	}

	// they must point in opposite directions
	dist = ( v3->pv - v2->pv ) * ( v1->pv - v2->pv );
	if ( dist >= 0 ) {
		return;
	}

	// see if they are colinear
	VectorSubtract( v3->v.xyz, v1->v.xyz, dir1 );
	dir1.Normalize();
	VectorSubtract( v2->v.xyz, v1->v.xyz, dir2 );
	dist = DotProduct( dir2, dir1 );
	VectorMA( v1->v.xyz, dist, dir1, point );
	VectorSubtract( point, v2->v.xyz, offset );
	off = offset.Length();

	if ( off > COLINEAR_EPSILON ) {
		return;
	}

	if ( dmapGlobals.drawflag ) {
		qglBegin( GL_LINES );
		qglColor3f( 1, 1, 0 );
		qglVertex3fv( v1->pv.ToFloatPtr() );
		qglVertex3fv( v2->pv.ToFloatPtr() );
		qglEnd();
		qglFlush();
		qglBegin( GL_LINES );
		qglColor3f( 0, 1, 1 );
		qglVertex3fv( v2->pv.ToFloatPtr() );
		qglVertex3fv( v3->pv.ToFloatPtr() );
		qglEnd();
		qglFlush();
	}

	// replace the two edges with a single edge
	UnlinkEdge( e1, island );
	UnlinkEdge( e2, island );

	// v2 should have no edges now
	if ( v2->edges ) {
		common->Error( "RemoveIfColinear: didn't remove properly" );
		return;
	}


	// if there is an existing edge that already
	// has these exact verts, we have just collapsed a
	// sliver triangle out of existance, and all the edges
	// can be removed
	for ( e = island->edges ; e ; e = e->islandLink ) {
		if ( ( e->v1 == v1 && e->v2 == v3 ) 
		|| ( e->v1 == v3 && e->v2 == v1 ) ) {
			UnlinkEdge( e, island );
			RemoveIfColinear( v1, island );
			RemoveIfColinear( v3, island );
			return;
		}
	}

	// if we can't add the combined edge, link
	// the originals back in
	if ( !TryAddNewEdge( v1, v3, island ) ) {
		e1->islandLink = island->edges;
		island->edges = e1;
		LinkEdge( e1 );

		e2->islandLink = island->edges;
		island->edges = e2;
		LinkEdge( e2 );
		return;
	}

	// recursively try to combine both verts now,
	// because things may have changed since the last combine test
	RemoveIfColinear( v1, island );
	RemoveIfColinear( v3, island );
}
Beispiel #29
0
static void R_DrawStripElements( int numIndexes, const glIndex_t *indexes, void ( APIENTRY *element )(GLint) ) {
	int i;
	int last[3] = { -1, -1, -1 };
	qboolean even;

	c_begins++;

	if ( numIndexes <= 0 ) {
		return;
	}

	qglBegin( GL_TRIANGLE_STRIP );

	// prime the strip
	element( indexes[0] );
	element( indexes[1] );
	element( indexes[2] );
	c_vertexes += 3;

	last[0] = indexes[0];
	last[1] = indexes[1];
	last[2] = indexes[2];

	even = qfalse;

	for ( i = 3; i < numIndexes; i += 3 )
	{
		// odd numbered triangle in potential strip
		if ( !even )
		{
			// check previous triangle to see if we're continuing a strip
			if ( ( indexes[i+0] == last[2] ) && ( indexes[i+1] == last[1] ) )
			{
				element( indexes[i+2] );
				c_vertexes++;
				assert( indexes[i+2] < tess.numVertexes );
				even = qtrue;
			}
			// otherwise we're done with this strip so finish it and start
			// a new one
			else
			{
				qglEnd();

				qglBegin( GL_TRIANGLE_STRIP );
				c_begins++;

				element( indexes[i+0] );
				element( indexes[i+1] );
				element( indexes[i+2] );

				c_vertexes += 3;

				even = qfalse;
			}
		}
		else
		{
			// check previous triangle to see if we're continuing a strip
			if ( ( last[2] == indexes[i+1] ) && ( last[0] == indexes[i+0] ) )
			{
				element( indexes[i+2] );
				c_vertexes++;

				even = qfalse;
			}
			// otherwise we're done with this strip so finish it and start
			// a new one
			else
			{
				qglEnd();

				qglBegin( GL_TRIANGLE_STRIP );
				c_begins++;

				element( indexes[i+0] );
				element( indexes[i+1] );
				element( indexes[i+2] );
				c_vertexes += 3;

				even = qfalse;
			}
		}

		// cache the last three vertices
		last[0] = indexes[i+0];
		last[1] = indexes[i+1];
		last[2] = indexes[i+2];
	}

	qglEnd();
}
Beispiel #30
0
/*
=================
R_DrawAliasModel

=================
*/
void R_DrawAliasModel (entity_t *e)
{
    int			i;
    dmdl_t		*paliashdr;
    float		an;
    vec3_t		bbox[8];
    image_t		*skin;

    if ( !( e->flags & RF_WEAPONMODEL ) )
    {
        if ( R_CullAliasModel( bbox, e ) )
            return;
    }

    if ( e->flags & RF_WEAPONMODEL )
    {
        if ( r_lefthand->value == 2 )
            return;
    }

    paliashdr = (dmdl_t *)currentmodel->extradata;

    //
    // get lighting information
    //
    // PMM - rewrote, reordered to handle new shells & mixing
    // PMM - 3.20 code .. replaced with original way of doing it to keep mod authors happy
    //
    if ( currententity->flags & ( RF_SHELL_HALF_DAM | RF_SHELL_GREEN | RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE ) )
    {
        VectorClear (shadelight);
        if (currententity->flags & RF_SHELL_HALF_DAM)
        {
            shadelight[0] = 0.56;
            shadelight[1] = 0.59;
            shadelight[2] = 0.45;
        }
        if ( currententity->flags & RF_SHELL_DOUBLE )
        {
            shadelight[0] = 0.9;
            shadelight[1] = 0.7;
        }
        if ( currententity->flags & RF_SHELL_RED )
            shadelight[0] = 1.0;
        if ( currententity->flags & RF_SHELL_GREEN )
            shadelight[1] = 1.0;
        if ( currententity->flags & RF_SHELL_BLUE )
            shadelight[2] = 1.0;
    }
    /*
    		// PMM -special case for godmode
    		if ( (currententity->flags & RF_SHELL_RED) &&
    			(currententity->flags & RF_SHELL_BLUE) &&
    			(currententity->flags & RF_SHELL_GREEN) )
    		{
    			for (i=0 ; i<3 ; i++)
    				shadelight[i] = 1.0;
    		}
    		else if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE ) )
    		{
    			VectorClear (shadelight);

    			if ( currententity->flags & RF_SHELL_RED )
    			{
    				shadelight[0] = 1.0;
    				if (currententity->flags & (RF_SHELL_BLUE|RF_SHELL_DOUBLE) )
    					shadelight[2] = 1.0;
    			}
    			else if ( currententity->flags & RF_SHELL_BLUE )
    			{
    				if ( currententity->flags & RF_SHELL_DOUBLE )
    				{
    					shadelight[1] = 1.0;
    					shadelight[2] = 1.0;
    				}
    				else
    				{
    					shadelight[2] = 1.0;
    				}
    			}
    			else if ( currententity->flags & RF_SHELL_DOUBLE )
    			{
    				shadelight[0] = 0.9;
    				shadelight[1] = 0.7;
    			}
    		}
    		else if ( currententity->flags & ( RF_SHELL_HALF_DAM | RF_SHELL_GREEN ) )
    		{
    			VectorClear (shadelight);
    			// PMM - new colors
    			if ( currententity->flags & RF_SHELL_HALF_DAM )
    			{
    				shadelight[0] = 0.56;
    				shadelight[1] = 0.59;
    				shadelight[2] = 0.45;
    			}
    			if ( currententity->flags & RF_SHELL_GREEN )
    			{
    				shadelight[1] = 1.0;
    			}
    		}
    	}
    			//PMM - ok, now flatten these down to range from 0 to 1.0.
    	//		max_shell_val = max(shadelight[0], max(shadelight[1], shadelight[2]));
    	//		if (max_shell_val > 0)
    	//		{
    	//			for (i=0; i<3; i++)
    	//			{
    	//				shadelight[i] = shadelight[i] / max_shell_val;
    	//			}
    	//		}
    	// pmm
    */
    else if ( currententity->flags & RF_FULLBRIGHT )
    {
        for (i=0 ; i<3 ; i++)
            shadelight[i] = 1.0;
    }
    else
    {
        R_LightPoint (currententity->origin, shadelight);

        // player lighting hack for communication back to server
        // big hack!
        if ( currententity->flags & RF_WEAPONMODEL )
        {
            // pick the greatest component, which should be the same
            // as the mono value returned by software
            if (shadelight[0] > shadelight[1])
            {
                if (shadelight[0] > shadelight[2])
                    r_lightlevel->value = 150*shadelight[0];
                else
                    r_lightlevel->value = 150*shadelight[2];
            }
            else
            {
                if (shadelight[1] > shadelight[2])
                    r_lightlevel->value = 150*shadelight[1];
                else
                    r_lightlevel->value = 150*shadelight[2];
            }

        }

        if ( gl_monolightmap->string[0] != '0' )
        {
            float s = shadelight[0];

            if ( s < shadelight[1] )
                s = shadelight[1];
            if ( s < shadelight[2] )
                s = shadelight[2];

            shadelight[0] = s;
            shadelight[1] = s;
            shadelight[2] = s;
        }
    }

    if ( currententity->flags & RF_MINLIGHT )
    {
        for (i=0 ; i<3 ; i++)
            if (shadelight[i] > 0.1)
                break;
        if (i == 3)
        {
            shadelight[0] = 0.1;
            shadelight[1] = 0.1;
            shadelight[2] = 0.1;
        }
    }

    if ( currententity->flags & RF_GLOW )
    {   // bonus items will pulse with time
        float	scale;
        float	min;

        scale = 0.1 * sin(r_newrefdef.time*7);
        for (i=0 ; i<3 ; i++)
        {
            min = shadelight[i] * 0.8;
            shadelight[i] += scale;
            if (shadelight[i] < min)
                shadelight[i] = min;
        }
    }

// =================
// PGM	ir goggles color override
    if ( r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE)
    {
        shadelight[0] = 1.0;
        shadelight[1] = 0.0;
        shadelight[2] = 0.0;
    }
// PGM
// =================

    shadedots = r_avertexnormal_dots[((int)(currententity->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];

    an = currententity->angles[1]/180*M_PI;
    shadevector[0] = cos(-an);
    shadevector[1] = sin(-an);
    shadevector[2] = 1;
    VectorNormalize (shadevector);

    //
    // locate the proper data
    //

    c_alias_polys += paliashdr->num_tris;

    //
    // draw all the triangles
    //
    if (currententity->flags & RF_DEPTHHACK) // hack the depth range to prevent view model from poking into walls
        qglDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));

    if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) )
    {
        extern void MYgluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar );

        qglMatrixMode( GL_PROJECTION );
        qglPushMatrix();
        qglLoadIdentity();
        qglScalef( -1, 1, 1 );
        MYgluPerspective( r_newrefdef.fov_y, ( float ) r_newrefdef.width / r_newrefdef.height,  4,  4096);
        qglMatrixMode( GL_MODELVIEW );

        qglCullFace( GL_BACK );
    }

    qglPushMatrix ();
    e->angles[PITCH] = -e->angles[PITCH];				// sigh.
    e->angles[ROLL] = e->angles[ROLL] * R_RollMult();	// Knightmare- roll is backwards
    R_RotateForEntity (e, true);
    e->angles[PITCH] = -e->angles[PITCH];				// sigh.
    e->angles[ROLL] = e->angles[ROLL] * R_RollMult();	// Knightmare- roll is backwards

    // select skin
    if (currententity->skin)
        skin = currententity->skin;	// custom player skin
    else
    {
        if (currententity->skinnum >= MAX_MD2SKINS)
            skin = currentmodel->skins[0];
        else
        {
            skin = currentmodel->skins[currententity->skinnum];
            if (!skin)
                skin = currentmodel->skins[0];
        }
    }
    if (!skin)
        skin = r_notexture;	// fallback...
    GL_Bind(skin->texnum);

    // draw it

    qglShadeModel (GL_SMOOTH);

    GL_TexEnv( GL_MODULATE );
    if ( currententity->flags & RF_TRANSLUCENT )
    {
        qglEnable (GL_BLEND);
    }


    if ( (currententity->frame >= paliashdr->num_frames)
            || (currententity->frame < 0) )
    {
        ri.Con_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such frame %d\n",
                       currentmodel->name, currententity->frame);
        currententity->frame = 0;
        currententity->oldframe = 0;
    }

    if ( (currententity->oldframe >= paliashdr->num_frames)
            || (currententity->oldframe < 0))
    {
        ri.Con_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such oldframe %d\n",
                       currentmodel->name, currententity->oldframe);
        currententity->frame = 0;
        currententity->oldframe = 0;
    }

    if ( !r_lerpmodels->value )
        currententity->backlerp = 0;
    GL_DrawAliasFrameLerp (paliashdr, currententity->backlerp);

    GL_TexEnv( GL_REPLACE );
    qglShadeModel (GL_FLAT);

    qglPopMatrix ();

//#if 1
    if (gl_showbbox->value)	// Knightmare- show bbox option
    {
        qglColor4f (1.0f, 1.0f, 1.0f, 1.0f);
        qglDisable( GL_CULL_FACE );
        qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
        qglDisable( GL_TEXTURE_2D );
        /*	qglBegin( GL_TRIANGLE_STRIP );
        	for ( i = 0; i < 8; i++ )
        	{
        		qglVertex3fv( bbox[i] );
        	}
        	qglEnd();*/
        qglBegin( GL_QUADS );

        qglVertex3fv( bbox[0] );
        qglVertex3fv( bbox[1] );
        qglVertex3fv( bbox[3] );
        qglVertex3fv( bbox[2] );

        qglVertex3fv( bbox[4] );
        qglVertex3fv( bbox[5] );
        qglVertex3fv( bbox[7] );
        qglVertex3fv( bbox[6] );

        qglVertex3fv( bbox[0] );
        qglVertex3fv( bbox[1] );
        qglVertex3fv( bbox[5] );
        qglVertex3fv( bbox[4] );

        qglVertex3fv( bbox[2] );
        qglVertex3fv( bbox[3] );
        qglVertex3fv( bbox[7] );
        qglVertex3fv( bbox[6] );

        qglEnd();

        qglEnable( GL_TEXTURE_2D );
        qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
        qglEnable( GL_CULL_FACE );
    }
//#endif

    if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) )
    {
        qglMatrixMode( GL_PROJECTION );
        qglPopMatrix();
        qglMatrixMode( GL_MODELVIEW );
        qglCullFace( GL_FRONT );
    }

    if ( currententity->flags & RF_TRANSLUCENT )
    {
        qglDisable (GL_BLEND);
    }

    if (currententity->flags & RF_DEPTHHACK)
        qglDepthRange (gldepthmin, gldepthmax);

    if (gl_shadows->value && !(currententity->flags & (RF_TRANSLUCENT | RF_WEAPONMODEL)))
    {
        //	qglPushMatrix ();
        //	R_RotateForEntity (e, false);
        //	qglDisable (GL_TEXTURE_2D);
        //	qglEnable (GL_BLEND);
        //	qglColor4f (0, 0, 0, gl_shadowalpha->value); // was 0.5

        GL_DrawAliasShadow (e, paliashdr, currententity->frame );

        //	qglEnable (GL_TEXTURE_2D);
        //	qglDisable (GL_BLEND);
        //	qglPopMatrix ();
    }
    qglColor4f (1,1,1,1);
}