Exemple #1
0
/*
==================
CM_ValidateFacet

If the facet isn't bounded by its borders, we screwed up.
==================
*/
static qboolean CM_ValidateFacet(cFacet_t * facet)
{
	float           plane[4];
	int             j;
	winding_t      *w;
	vec3_t          bounds[2];

	if(facet->surfacePlane == -1)
	{
		return qfalse;
	}

	VectorCopy4(planes[facet->surfacePlane].plane, plane);
	w = BaseWindingForPlane(plane, plane[3]);
	for(j = 0; j < facet->numBorders && w; j++)
	{
		if(facet->borderPlanes[j] == -1)
		{
			FreeWinding(w);
			return qfalse;
		}
		VectorCopy4(planes[facet->borderPlanes[j]].plane, plane);
		if(!facet->borderInward[j])
		{
			VectorSubtract(vec3_origin, plane, plane);
			plane[3] = -plane[3];
		}
		ChopWindingInPlace(&w, plane, plane[3], 0.1f);
	}

	if(!w)
	{
		return qfalse;			// winding was completely chopped away
	}

	// see if the facet is unreasonably large
	WindingBounds(w, bounds[0], bounds[1]);
	FreeWinding(w);

	for(j = 0; j < 3; j++)
	{
		if(bounds[1][j] - bounds[0][j] > MAX_WORLD_COORD)
		{
			return qfalse;		// we must be missing a plane
		}
		if(bounds[0][j] >= MAX_WORLD_COORD)
		{
			return qfalse;
		}
		if(bounds[1][j] <= MIN_WORLD_COORD)
		{
			return qfalse;
		}
	}
	return qtrue;				// winding is fine
}
Exemple #2
0
/*
==================
CM_FindPlane2
==================
*/
static int CM_FindPlane2(float plane[4], int *flipped)
{
	int             i;

	// see if the points are close enough to an existing plane
	for(i = 0; i < numPlanes; i++)
	{
		if(CM_PlaneEqual(&planes[i], plane, flipped))
			return i;
	}

	// add a new plane
	if(numPlanes == MAX_PATCH_PLANES)
	{
		Com_Error(ERR_DROP, "CM_FindPlane2: MAX_PATCH_PLANES");
	}

	VectorCopy4(plane, planes[numPlanes].plane);
	planes[numPlanes].signbits = CM_SignbitsForNormal(plane);

	numPlanes++;

	*flipped = qfalse;

	return numPlanes - 1;
}
Exemple #3
0
// shows current date and JA++ version
static void DrawClientInfo( float fade ) {
	struct tm *timeinfo;
	time_t tm;
	char buf[256];
	const qhandle_t fontHandle = MenuFontToHandle( FONT_JAPPMONO );
	const float fontScale = 0.5f;
	const float lineHeight = trap->R_Font_HeightPixels( fontHandle, fontScale );
	float y = SCREEN_HEIGHT - lineHeight - 4.0f;
	vector4 colour;

	VectorCopy4( &g_color_table[ColorIndex( COLOR_ORANGE )], &colour );
	colour.a = fade;

#ifdef REVISION
	// JA++ version
	trap->R_Font_DrawString( SCREEN_WIDTH - trap->R_Font_StrLenPixels( REVISION, fontHandle, fontScale ) - 21.0f, y,
		REVISION, &colour, fontHandle | STYLE_DROPSHADOW, -1, fontScale );
	y -= lineHeight;
#endif

	// date
	time( &tm );
	timeinfo = localtime( &tm );

	Com_sprintf( buf, sizeof(buf), "%s %i%s %04i, %02i:%02i:%02i", months[timeinfo->tm_mon], timeinfo->tm_mday,
		GetDateSuffix( timeinfo->tm_mday ), 1900 + timeinfo->tm_year, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec );

	trap->R_Font_DrawString( SCREEN_WIDTH - trap->R_Font_StrLenPixels( buf, fontHandle, fontScale ) - 12.0f, y, buf,
		&colour, fontHandle | STYLE_DROPSHADOW, -1, fontScale );
}
/*
==============
RB_InstantQuad

based on Tess_InstantQuad from xreal
==============
*/
void RB_InstantQuad2(vec4_t quadVerts[4], vec2_t texCoords[4])
{
	GLimp_LogComment("--- RB_InstantQuad2 ---\n");

	tess.numVertexes = 0;
	tess.numIndexes = 0;
	tess.firstIndex = 0;

	VectorCopy4(quadVerts[0], tess.xyz[tess.numVertexes]);
	VectorCopy2(texCoords[0], tess.texCoords[tess.numVertexes]);
	tess.numVertexes++;

	VectorCopy4(quadVerts[1], tess.xyz[tess.numVertexes]);
	VectorCopy2(texCoords[1], tess.texCoords[tess.numVertexes]);
	tess.numVertexes++;

	VectorCopy4(quadVerts[2], tess.xyz[tess.numVertexes]);
	VectorCopy2(texCoords[2], tess.texCoords[tess.numVertexes]);
	tess.numVertexes++;

	VectorCopy4(quadVerts[3], tess.xyz[tess.numVertexes]);
	VectorCopy2(texCoords[3], tess.texCoords[tess.numVertexes]);
	tess.numVertexes++;

	tess.indexes[tess.numIndexes++] = 0;
	tess.indexes[tess.numIndexes++] = 1;
	tess.indexes[tess.numIndexes++] = 2;
	tess.indexes[tess.numIndexes++] = 0;
	tess.indexes[tess.numIndexes++] = 2;
	tess.indexes[tess.numIndexes++] = 3;
	tess.minIndex = 0;
	tess.maxIndex = 3;

	RB_UpdateTessVao(ATTR_POSITION | ATTR_TEXCOORD);

	R_DrawElementsVao(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex);

	tess.numIndexes = 0;
	tess.numVertexes = 0;
	tess.firstIndex = 0;
	tess.minIndex = 0;
	tess.maxIndex = 0;
}
Exemple #5
0
/*
==================
CM_FindPlane
==================
*/
static int CM_FindPlane(float *p1, float *p2, float *p3)
{
	float           plane[4];
	int             i;
	float           d;

	if(!CM_PlaneFromPoints(plane, p1, p2, p3))
	{
		return -1;
	}

	// see if the points are close enough to an existing plane
	for(i = 0; i < numPlanes; i++)
	{
		if(DotProduct(plane, planes[i].plane) < 0)
		{
			continue;			// allow backwards planes?
		}

		d = DotProduct(p1, planes[i].plane) - planes[i].plane[3];
		if(d < -PLANE_TRI_EPSILON || d > PLANE_TRI_EPSILON)
		{
			continue;
		}

		d = DotProduct(p2, planes[i].plane) - planes[i].plane[3];
		if(d < -PLANE_TRI_EPSILON || d > PLANE_TRI_EPSILON)
		{
			continue;
		}

		d = DotProduct(p3, planes[i].plane) - planes[i].plane[3];
		if(d < -PLANE_TRI_EPSILON || d > PLANE_TRI_EPSILON)
		{
			continue;
		}

		// found it
		return i;
	}

	// add a new plane
	if(numPlanes == MAX_PATCH_PLANES)
	{
		Com_Error(ERR_DROP, "MAX_PATCH_PLANES");
	}

	VectorCopy4(plane, planes[numPlanes].plane);
	planes[numPlanes].signbits = CM_SignbitsForNormal(plane);

	numPlanes++;

	return numPlanes - 1;
}
Exemple #6
0
void GLSL_SetUniformVec4(shaderProgram_t *program, int uniformNum, const vec4_t v)
{
	GLint *uniforms = program->uniforms;
	vec_t *compare = (float *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]);

	if (uniforms[uniformNum] == -1)
		return;

	if (uniformsInfo[uniformNum].type != GLSL_VEC4)
	{
		ri.Printf( PRINT_WARNING, "GLSL_SetUniformVec4: wrong type for uniform %i in program %s\n", uniformNum, program->name);
		return;
	}

	if (VectorCompare4(v, compare))
	{
		return;
	}

	VectorCopy4(v, compare);

	qglUniform4fARB(uniforms[uniformNum], v[0], v[1], v[2], v[3]);
}
/*
================
CG_DrawHealth
================
*/
static void CG_DrawHealth( menuDef_t *menuHUD )
{
	vec4_t			glowColor;
	playerState_t	*ps;
	int				healthAmt, maxAmt;
	//int				i,currValue,inc;
	double			percentage, factor;
	itemDef_t		*focusItem;

	const char *text;
	int x;

	static double	fcurrent = 0;
	vec4_t	fadecolor = {1, 1, 1, 0.5f};
	static vec4_t	draincolor = {1, 0.4f, 0.4f, 1};
	static vec4_t	fillcolor = {0.4f, 1, 0.4f, 1};
	vec4_t	opacity;

	int state = 0;

	MAKERGBA(opacity, 1, 1, 1, cg.jkg_HUDOpacity);

	// Can we find the menu?
	if (!menuHUD)
	{
		return;
	}

	ps = &cg.snap->ps;

	// What's the health?
	healthAmt = ps->stats[STAT_HEALTH];
	maxAmt = ps->stats[STAT_MAX_HEALTH];
	//if (healthAmt > ps->stats[STAT_MAX_HEALTH])
	//{
	//	healthAmt = ps->stats[STAT_MAX_HEALTH];
	//}

	focusItem = Menu_FindItemByName(menuHUD, "healthbar");

	if (focusItem)
	{
		percentage = (double)healthAmt / (double)maxAmt;
		if (percentage > 1) {
			percentage = 1;
		} else if (percentage < 0) {
			percentage = 0;
		}
		factor = /*0.62109375f **/ percentage /*+ 0.330078125f*/;
		/*if(factor > 0.95f)
		{
			factor = 1.0f; //eezstreet - mega hack
		}*/

		if (fcurrent < factor) {
			// Raise it
			fcurrent += (cg.frameDelta * .0003); // Go up 30% per second
			if (fcurrent > factor) {
				// We passed it
				fcurrent = factor;
			}
		} else if (fcurrent > factor) {
			// Lower it
			fcurrent -= (cg.frameDelta * .0003); // Go up 30% per second
			if (fcurrent < factor) {
				fcurrent = factor;
			}
		} else
		{
			//Stay the same
		}

		if (fcurrent != 0) {
			if (fcurrent < factor) {
				state = 1;
				// We're filling up, draw up to fcurrent solid, and up to factor translucent
				trap_R_SetColor(opacity);
				trap_R_DrawStretchPic(focusItem->window.rect.x, focusItem->window.rect.y, focusItem->window.rect.w * fcurrent, focusItem->window.rect.h, 0, 0, fcurrent, 1, focusItem->window.background);
				fadecolor[3] *= cg.jkg_HUDOpacity;
				trap_R_SetColor(fadecolor);
				trap_R_DrawStretchPic(focusItem->window.rect.x + focusItem->window.rect.w * fcurrent, focusItem->window.rect.y, focusItem->window.rect.w * (factor - fcurrent), focusItem->window.rect.h, fcurrent, 0, factor, 1, focusItem->window.background);
				trap_R_SetColor(NULL);
			} else if (fcurrent > factor) {
				state = 2;
				// We're draining, draw up to factor solid, and up to fcurrent translucent
				trap_R_SetColor(opacity);
				trap_R_DrawStretchPic(focusItem->window.rect.x, focusItem->window.rect.y, focusItem->window.rect.w * factor, focusItem->window.rect.h, 0, 0, factor, 1, focusItem->window.background);
				fadecolor[3] *= cg.jkg_HUDOpacity;
				trap_R_SetColor(fadecolor);
				trap_R_DrawStretchPic(focusItem->window.rect.x + focusItem->window.rect.w * factor, focusItem->window.rect.y, focusItem->window.rect.w * (fcurrent - factor), focusItem->window.rect.h, factor, 0, fcurrent, 1, focusItem->window.background);
				trap_R_SetColor(NULL);
			} else {
				state = 0;
				// Just solid
				trap_R_SetColor(opacity);
				trap_R_DrawStretchPic(focusItem->window.rect.x, focusItem->window.rect.y, focusItem->window.rect.w * factor, focusItem->window.rect.h, 0, 0, factor, 1, focusItem->window.background);
			}
		}
	}

	focusItem = Menu_FindItemByName(menuHUD, "healthtext");

	if (focusItem)
	{
		// Center and draw the text, apply glow if needed
		if (state == 1) {
			VectorCopy4(fillcolor, glowColor);
		} else if (state == 2) {
			VectorCopy4(draincolor, glowColor);
		} else {
			VectorCopy4(colorWhite, glowColor);
			if (healthAmt < 25) {
				// Glow the text from red to white
				float fade = 0.5f + cos((float)cg.time/250) *.5;
				glowColor[1] = glowColor[2] = fade;
			}
		}
		glowColor[3] *= cg.jkg_HUDOpacity;
		text = va("%i / %i", healthAmt, maxAmt);
		x = ((focusItem->window.rect.w/2) - (trap_R_Font_StrLenPixels(text, cgs.media.hudfont1, 0.6f) / 2)) + focusItem->window.rect.x;
		trap_R_Font_DrawString(
			x,
			focusItem->window.rect.y,
			text,
			glowColor,
			cgs.media.hudfont1,
			-1,
			0.6f);
		trap_R_SetColor(NULL);
	}
}
Exemple #8
0
/*
=============
RB_StretchPic
=============
*/
const void *RB_StretchPic ( const void *data ) {
	const stretchPicCommand_t	*cmd;
	shader_t *shader;
	int		numVerts, numIndexes;

	cmd = (const stretchPicCommand_t *)data;

	// FIXME: HUGE hack
	if (glRefConfig.framebufferObject)
	{
		if (!tr.renderFbo || backEnd.framePostProcessed)
		{
			FBO_Bind(NULL);
		}
		else
		{
			FBO_Bind(tr.renderFbo);
		}
	}

	RB_SetGL2D();

	shader = cmd->shader;
	if ( shader != tess.shader ) {
		if ( tess.numIndexes ) {
			RB_EndSurface();
		}
		backEnd.currentEntity = &backEnd.entity2D;
		RB_BeginSurface( shader, 0, 0 );
	}

	RB_CHECKOVERFLOW( 4, 6 );
	numVerts = tess.numVertexes;
	numIndexes = tess.numIndexes;

	tess.numVertexes += 4;
	tess.numIndexes += 6;

	tess.indexes[ numIndexes ] = numVerts + 3;
	tess.indexes[ numIndexes + 1 ] = numVerts + 0;
	tess.indexes[ numIndexes + 2 ] = numVerts + 2;
	tess.indexes[ numIndexes + 3 ] = numVerts + 2;
	tess.indexes[ numIndexes + 4 ] = numVerts + 0;
	tess.indexes[ numIndexes + 5 ] = numVerts + 1;

	{
		vec4_t color;

		VectorScale4(backEnd.color2D, 1.0f / 255.0f, color);

		VectorCopy4(color, tess.vertexColors[ numVerts ]);
		VectorCopy4(color, tess.vertexColors[ numVerts + 1]);
		VectorCopy4(color, tess.vertexColors[ numVerts + 2]);
		VectorCopy4(color, tess.vertexColors[ numVerts + 3 ]);
	}

	tess.xyz[ numVerts ][0] = cmd->x;
	tess.xyz[ numVerts ][1] = cmd->y;
	tess.xyz[ numVerts ][2] = 0;

	tess.texCoords[ numVerts ][0][0] = cmd->s1;
	tess.texCoords[ numVerts ][0][1] = cmd->t1;

	tess.xyz[ numVerts + 1 ][0] = cmd->x + cmd->w;
	tess.xyz[ numVerts + 1 ][1] = cmd->y;
	tess.xyz[ numVerts + 1 ][2] = 0;

	tess.texCoords[ numVerts + 1 ][0][0] = cmd->s2;
	tess.texCoords[ numVerts + 1 ][0][1] = cmd->t1;

	tess.xyz[ numVerts + 2 ][0] = cmd->x + cmd->w;
	tess.xyz[ numVerts + 2 ][1] = cmd->y + cmd->h;
	tess.xyz[ numVerts + 2 ][2] = 0;

	tess.texCoords[ numVerts + 2 ][0][0] = cmd->s2;
	tess.texCoords[ numVerts + 2 ][0][1] = cmd->t2;

	tess.xyz[ numVerts + 3 ][0] = cmd->x;
	tess.xyz[ numVerts + 3 ][1] = cmd->y + cmd->h;
	tess.xyz[ numVerts + 3 ][2] = 0;

	tess.texCoords[ numVerts + 3 ][0][0] = cmd->s1;
	tess.texCoords[ numVerts + 3 ][0][1] = cmd->t2;

	return (const void *)(cmd + 1);
}
Exemple #9
0
void FBO_BlitFromTexture(struct image_s *src, ivec4_t inSrcBox, vec2_t inSrcTexScale, FBO_t *dst, ivec4_t inDstBox, struct shaderProgram_s *shaderProgram, vec4_t inColor, int blend)
{
	ivec4_t dstBox, srcBox;
	vec2_t srcTexScale;
	vec4_t color;
	vec4_t quadVerts[4];
	vec2_t texCoords[4];
	vec2_t invTexRes;
	FBO_t *oldFbo = glState.currentFBO;
	mat4_t projection;
	int width, height;

	if (!src)
		return;

	if (inSrcBox)
	{
		VectorSet4(srcBox, inSrcBox[0], inSrcBox[1], inSrcBox[0] + inSrcBox[2],  inSrcBox[1] + inSrcBox[3]);
	}
	else
	{
		VectorSet4(srcBox, 0, 0, src->width, src->height);
	}

	// framebuffers are 0 bottom, Y up.
	if (inDstBox)
	{
		if (dst)
		{
			dstBox[0] = inDstBox[0];
			dstBox[1] = dst->height - inDstBox[1] - inDstBox[3];
			dstBox[2] = inDstBox[0] + inDstBox[2];
			dstBox[3] = dst->height - inDstBox[1];
		}
		else
		{
			dstBox[0] = inDstBox[0];
			dstBox[1] = glConfig.vidHeight - inDstBox[1] - inDstBox[3];
			dstBox[2] = inDstBox[0] + inDstBox[2];
			dstBox[3] = glConfig.vidHeight - inDstBox[1];
		}
	}
	else if (dst)
	{
		VectorSet4(dstBox, 0, dst->height, dst->width, 0);
	}
	else
	{
		VectorSet4(dstBox, 0, glConfig.vidHeight, glConfig.vidWidth, 0);
	}

	if (inSrcTexScale)
	{
		VectorCopy2(inSrcTexScale, srcTexScale);
	}
	else
	{
		srcTexScale[0] = srcTexScale[1] = 1.0f;
	}

	if (inColor)
	{
		VectorCopy4(inColor, color);
	}
	else
	{
		VectorCopy4(colorWhite, color);
	}

	if (!shaderProgram)
	{
		shaderProgram = &tr.textureColorShader;
	}

	FBO_Bind(dst);

	if (glState.currentFBO)
	{
		width = glState.currentFBO->width;
		height = glState.currentFBO->height;
	}
	else
	{
		width = glConfig.vidWidth;
		height = glConfig.vidHeight;
	}

	qglViewport( 0, 0, width, height );
	qglScissor( 0, 0, width, height );

	Mat4Ortho(0, width, height, 0, 0, 1, projection);

	qglDisable( GL_CULL_FACE );

	GL_BindToTMU(src, TB_COLORMAP);

	VectorSet4(quadVerts[0], dstBox[0], dstBox[1], 0, 1);
	VectorSet4(quadVerts[1], dstBox[2], dstBox[1], 0, 1);
	VectorSet4(quadVerts[2], dstBox[2], dstBox[3], 0, 1);
	VectorSet4(quadVerts[3], dstBox[0], dstBox[3], 0, 1);

	texCoords[0][0] = srcBox[0] / (float)src->width; texCoords[0][1] = 1.0f - srcBox[1] / (float)src->height;
	texCoords[1][0] = srcBox[2] / (float)src->width; texCoords[1][1] = 1.0f - srcBox[1] / (float)src->height;
	texCoords[2][0] = srcBox[2] / (float)src->width; texCoords[2][1] = 1.0f - srcBox[3] / (float)src->height;
	texCoords[3][0] = srcBox[0] / (float)src->width; texCoords[3][1] = 1.0f - srcBox[3] / (float)src->height;

	invTexRes[0] = 1.0f / src->width  * srcTexScale[0];
	invTexRes[1] = 1.0f / src->height * srcTexScale[1];

	GL_State( blend );

	GLSL_BindProgram(shaderProgram);
	
	GLSL_SetUniformMat4(shaderProgram, UNIFORM_MODELVIEWPROJECTIONMATRIX, projection);
	GLSL_SetUniformVec4(shaderProgram, UNIFORM_COLOR, color);
	GLSL_SetUniformVec2(shaderProgram, UNIFORM_INVTEXRES, invTexRes);
	GLSL_SetUniformVec2(shaderProgram, UNIFORM_AUTOEXPOSUREMINMAX, tr.refdef.autoExposureMinMax);
	GLSL_SetUniformVec3(shaderProgram, UNIFORM_TONEMINAVGMAXLINEAR, tr.refdef.toneMinAvgMaxLinear);

	RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes);

	FBO_Bind(oldFbo);
}
Exemple #10
0
void CG_FilledBar( float x, float y, float w, float h, const float *startColorIn, float *endColor, const float *bgColor, float frac, int flags ) {
	vec4_t backgroundcolor = {1, 1, 1, 0.25f}, colorAtPos;  // colorAtPos is the lerped color if necessary
	vec4_t startColor;

	int indent = BAR_BORDERSIZE;

	VectorCopy4( startColorIn, startColor );

	if ( ( flags & BAR_BG ) && bgColor ) { // BAR_BG set, and color specified, use specified bg color
		Vector4Copy( bgColor, backgroundcolor );
	}

	// hud alpha
	if ( !( flags & BAR_NOHUDALPHA ) ) {
		startColor[3] *= cg_hudAlpha.value;
		if ( endColor ) {
			endColor[3] *= cg_hudAlpha.value;
		}
		if ( backgroundcolor ) {
			backgroundcolor[3] *= cg_hudAlpha.value;
		}
	}

	if ( flags & BAR_LERP_COLOR ) {
		Vector4Average( startColor, endColor, frac, colorAtPos );
	}

	// background
	if ( ( flags & BAR_BG ) ) {
		// draw background at full size and shrink the remaining box to fit inside with a border.  (alternate border may be specified by a BAR_BGSPACING_xx)
		CG_FillRect(   x,
					   y,
					   w,
					   h,
					   backgroundcolor );

		if ( flags & BAR_BGSPACING_X0Y0 ) {          // fill the whole box (no border)

		} else if ( flags & BAR_BGSPACING_X0Y5 ) {   // spacing created for weapon heat
			indent *= 3;
			y += indent;
			h -= ( 2 * indent );

		} else {                                // default spacing of 2 units on each side
			x += indent;
			y += indent;
			w -= ( 2 * indent );
			h -= ( 2 * indent );
		}
	}


	// adjust for horiz/vertical and draw the fractional box
	if ( flags & BAR_VERT ) {
		if ( flags & BAR_LEFT ) {    // TODO: remember to swap colors on the ends here
			y += ( h * ( 1 - frac ) );
		} else if ( flags & BAR_CENTER ) {
			y += ( h * ( 1 - frac ) / 2 );
		}

		if ( flags & BAR_LERP_COLOR ) {
			CG_FillRect( x, y, w, h * frac, colorAtPos );
		} else {
//			CG_FillRectGradient ( x, y, w, h * frac, startColor, endColor, 0 );
			CG_FillRect( x, y, w, h * frac, startColor );
		}

	} else {

		if ( flags & BAR_LEFT ) {    // TODO: remember to swap colors on the ends here
			x += ( w * ( 1 - frac ) );
		} else if ( flags & BAR_CENTER ) {
			x += ( w * ( 1 - frac ) / 2 );
		}

		if ( flags & BAR_LERP_COLOR ) {
			CG_FillRect( x, y, w * frac, h, colorAtPos );
		} else {
//			CG_FillRectGradient ( x, y, w * frac, h, startColor, endColor, 0 );
			CG_FillRect( x, y, w * frac, h, startColor );
		}
	}

}
Exemple #11
0
void FBO_BlitFromTexture(struct image_s *src, vec4_t inSrcTexCorners, vec2_t inSrcTexScale, FBO_t *dst, ivec4_t inDstBox, struct shaderProgram_s *shaderProgram, vec4_t inColor, int blend)
{
	ivec4_t dstBox;
	vec4_t color;
	vec4_t quadVerts[4];
	vec2_t texCoords[4];
	vec2_t invTexRes;
	FBO_t *oldFbo = glState.currentFBO;
	mat4_t projection;
	int width, height;

	if (!src)
	{
		ri.Printf(PRINT_WARNING, "Tried to blit from a NULL texture!\n");
		return;
	}

	width  = dst ? dst->width  : glConfig.vidWidth;
	height = dst ? dst->height : glConfig.vidHeight;

	if (inSrcTexCorners)
	{
		VectorSet2(texCoords[0], inSrcTexCorners[0], inSrcTexCorners[1]);
		VectorSet2(texCoords[1], inSrcTexCorners[2], inSrcTexCorners[1]);
		VectorSet2(texCoords[2], inSrcTexCorners[2], inSrcTexCorners[3]);
		VectorSet2(texCoords[3], inSrcTexCorners[0], inSrcTexCorners[3]);
	}
	else
	{
		VectorSet2(texCoords[0], 0.0f, 1.0f);
		VectorSet2(texCoords[1], 1.0f, 1.0f);
		VectorSet2(texCoords[2], 1.0f, 0.0f);
		VectorSet2(texCoords[3], 0.0f, 0.0f);
	}

	// framebuffers are 0 bottom, Y up.
	if (inDstBox)
	{
		dstBox[0] = inDstBox[0];
		dstBox[1] = height - inDstBox[1] - inDstBox[3];
		dstBox[2] = inDstBox[0] + inDstBox[2];
		dstBox[3] = height - inDstBox[1];
	}
	else
	{
		VectorSet4(dstBox, 0, height, width, 0);
	}

	if (inSrcTexScale)
	{
		VectorCopy2(inSrcTexScale, invTexRes);
	}
	else
	{
		VectorSet2(invTexRes, 1.0f, 1.0f);
	}

	if (inColor)
	{
		VectorCopy4(inColor, color);
	}
	else
	{
		VectorCopy4(colorWhite, color);
	}

	if (!shaderProgram)
	{
		shaderProgram = &tr.textureColorShader;
	}

	FBO_Bind(dst);

	qglViewport( 0, 0, width, height );
	qglScissor( 0, 0, width, height );

	Mat4Ortho(0, width, height, 0, 0, 1, projection);

	GL_Cull( CT_TWO_SIDED );

	GL_BindToTMU(src, TB_COLORMAP);

	VectorSet4(quadVerts[0], dstBox[0], dstBox[1], 0.0f, 1.0f);
	VectorSet4(quadVerts[1], dstBox[2], dstBox[1], 0.0f, 1.0f);
	VectorSet4(quadVerts[2], dstBox[2], dstBox[3], 0.0f, 1.0f);
	VectorSet4(quadVerts[3], dstBox[0], dstBox[3], 0.0f, 1.0f);

	invTexRes[0] /= src->width;
	invTexRes[1] /= src->height;

	GL_State( blend );

	GLSL_BindProgram(shaderProgram);
	
	GLSL_SetUniformMat4(shaderProgram, UNIFORM_MODELVIEWPROJECTIONMATRIX, projection);
	GLSL_SetUniformVec4(shaderProgram, UNIFORM_COLOR, color);
	GLSL_SetUniformVec2(shaderProgram, UNIFORM_INVTEXRES, invTexRes);
	GLSL_SetUniformVec2(shaderProgram, UNIFORM_AUTOEXPOSUREMINMAX, tr.refdef.autoExposureMinMax);
	GLSL_SetUniformVec3(shaderProgram, UNIFORM_TONEMINAVGMAXLINEAR, tr.refdef.toneMinAvgMaxLinear);

	RB_InstantQuad2(quadVerts, texCoords);

	FBO_Bind(oldFbo);
}
Exemple #12
0
/*
==================
CM_AddFacetBevels
==================
*/
static inline void CM_AddFacetBevels( facet_t *facet ) {

	int i, j, k, l;
	int axis, dir, order, flipped;
	float plane[4], d, newplane[4];
	winding_t *w, *w2;
	vec3_t mins, maxs, vec, vec2;

	VectorCopy4( planes[ facet->surfacePlane ].plane, plane );

	w = BaseWindingForPlane( plane,  plane[3] );
	for ( j = 0 ; j < facet->numBorders && w ; j++ ) {
		if (facet->borderPlanes[j] == facet->surfacePlane) continue;
		VectorCopy4( planes[ facet->borderPlanes[j] ].plane, plane );

		if ( !facet->borderInward[j] ) {
			VectorSubtract( vec3_origin, plane, plane );
			plane[3] = -plane[3];
		}

		ChopWindingInPlace( &w, plane, plane[3], 0.1f );
	}
	if ( !w ) {
		return;
	}

	WindingBounds(w, mins, maxs);

	// add the axial planes
	order = 0;
	for ( axis = 0 ; axis < 3 ; axis++ )
	{
		for ( dir = -1 ; dir <= 1 ; dir += 2, order++ )
		{
			VectorClear(plane);
			plane[axis] = dir;
			if (dir == 1) {
				plane[3] = maxs[axis];
			}
			else {
				plane[3] = -mins[axis];
			}
			//if it's the surface plane
			if (CM_PlaneEqual(&planes[facet->surfacePlane], plane, &flipped)) {
				continue;
			}
			// see if the plane is allready present
			for ( i = 0 ; i < facet->numBorders ; i++ ) {
				if (CM_PlaneEqual(&planes[facet->borderPlanes[i]], plane, &flipped))
					break;
			}

			if ( i == facet->numBorders ) {
				if (facet->numBorders > 4 + 6 + 16) Com_Printf("ERROR: too many bevels\n");
				facet->borderPlanes[facet->numBorders] = CM_FindPlane2(plane, &flipped);
				facet->borderNoAdjust[facet->numBorders] = (qboolean)0;
				facet->borderInward[facet->numBorders] = flipped;
				facet->numBorders++;
			}
		}
	}
	//
	// add the edge bevels
	//
	// test the non-axial plane edges
	for ( j = 0 ; j < w->numpoints ; j++ )
	{
		k = (j+1)%w->numpoints;
		VectorSubtract (w->p[j], w->p[k], vec);
		//if it's a degenerate edge
		if (VectorNormalize (vec) < 0.5)
			continue;
		CM_SnapVector(vec);
		for ( k = 0; k < 3 ; k++ )
			if ( vec[k] == -1 || vec[k] == 1 )
				break;	// axial
		if ( k < 3 )
			continue;	// only test non-axial edges

		// try the six possible slanted axials from this edge
		for ( axis = 0 ; axis < 3 ; axis++ )
		{
			for ( dir = -1 ; dir <= 1 ; dir += 2 )
			{
				// construct a plane
				VectorClear (vec2);
				vec2[axis] = dir;
				CrossProduct (vec, vec2, plane);
				if (VectorNormalize (plane) < 0.5)
					continue;
				plane[3] = DotProduct (w->p[j], plane);

				// if all the points of the facet winding are
				// behind this plane, it is a proper edge bevel
				for ( l = 0 ; l < w->numpoints ; l++ )
				{
					d = DotProduct (w->p[l], plane) - plane[3];
					if (d > 0.1)
						break;	// point in front
				}
				if ( l < w->numpoints )
					continue;

				//if it's the surface plane
				if (CM_PlaneEqual(&planes[facet->surfacePlane], plane, &flipped)) {
					continue;
				}
				// see if the plane is allready present
				for ( i = 0 ; i < facet->numBorders ; i++ ) {
					if (CM_PlaneEqual(&planes[facet->borderPlanes[i]], plane, &flipped)) {
							break;
					}
				}

				if ( i == facet->numBorders ) {
					if (facet->numBorders > 4 + 6 + 16) Com_Printf("ERROR: too many bevels\n");
					facet->borderPlanes[facet->numBorders] = CM_FindPlane2(plane, &flipped);

					for ( k = 0 ; k < facet->numBorders ; k++ ) {
						if (facet->borderPlanes[facet->numBorders] ==
							facet->borderPlanes[k]) Com_Printf("WARNING: bevel plane already used\n");
					}

					facet->borderNoAdjust[facet->numBorders] = (qboolean)0;
					facet->borderInward[facet->numBorders] = flipped;
					//
					w2 = CopyWinding(w);
					VectorCopy4(planes[facet->borderPlanes[facet->numBorders]].plane, newplane);
					if (!facet->borderInward[facet->numBorders])
					{
						VectorNegate(newplane, newplane);
						newplane[3] = -newplane[3];
					} //end if
					ChopWindingInPlace( &w2, newplane, newplane[3], 0.1f );
					if (!w2) {
#ifndef BSPC
						Com_DPrintf("WARNING: CM_AddFacetBevels... invalid bevel\n");
#endif
						continue;
					}
					else {
						FreeWinding(w2);
					}
					//
					facet->numBorders++;
					//already got a bevel
//					break;
				}
			}
		}
	}
	FreeWinding( w );

#ifndef BSPC
	//add opposite plane
	facet->borderPlanes[facet->numBorders] = facet->surfacePlane;
	facet->borderNoAdjust[facet->numBorders] = (qboolean)0;
	facet->borderInward[facet->numBorders] = qtrue;
	facet->numBorders++;
#endif //BSPC

}
Exemple #13
0
/*
==============
RB_AddQuadStampExt
==============
*/
void RB_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, float color[4], float s1, float t1, float s2, float t2 ) {
	vec3_t		normal;
	int16_t     iNormal[4];
	uint16_t    iColor[4];
	int			ndx;

	RB_CheckVao(tess.vao);

	RB_CHECKOVERFLOW( 4, 6 );

	ndx = tess.numVertexes;

	// triangle indexes for a simple quad
	tess.indexes[ tess.numIndexes ] = ndx;
	tess.indexes[ tess.numIndexes + 1 ] = ndx + 1;
	tess.indexes[ tess.numIndexes + 2 ] = ndx + 3;

	tess.indexes[ tess.numIndexes + 3 ] = ndx + 3;
	tess.indexes[ tess.numIndexes + 4 ] = ndx + 1;
	tess.indexes[ tess.numIndexes + 5 ] = ndx + 2;

	tess.xyz[ndx][0] = origin[0] + left[0] + up[0];
	tess.xyz[ndx][1] = origin[1] + left[1] + up[1];
	tess.xyz[ndx][2] = origin[2] + left[2] + up[2];

	tess.xyz[ndx+1][0] = origin[0] - left[0] + up[0];
	tess.xyz[ndx+1][1] = origin[1] - left[1] + up[1];
	tess.xyz[ndx+1][2] = origin[2] - left[2] + up[2];

	tess.xyz[ndx+2][0] = origin[0] - left[0] - up[0];
	tess.xyz[ndx+2][1] = origin[1] - left[1] - up[1];
	tess.xyz[ndx+2][2] = origin[2] - left[2] - up[2];

	tess.xyz[ndx+3][0] = origin[0] + left[0] - up[0];
	tess.xyz[ndx+3][1] = origin[1] + left[1] - up[1];
	tess.xyz[ndx+3][2] = origin[2] + left[2] - up[2];


	// constant normal all the way around
	VectorSubtract( vec3_origin, backEnd.viewParms.or.axis[0], normal );

	R_VaoPackNormal(iNormal, normal);

	VectorCopy4(iNormal, tess.normal[ndx]);
	VectorCopy4(iNormal, tess.normal[ndx + 1]);
	VectorCopy4(iNormal, tess.normal[ndx + 2]);
	VectorCopy4(iNormal, tess.normal[ndx + 3]);

	// standard square texture coordinates
	VectorSet2(tess.texCoords[ndx], s1, t1);
	VectorSet2(tess.lightCoords[ndx], s1, t1);

	VectorSet2(tess.texCoords[ndx+1], s2, t1);
	VectorSet2(tess.lightCoords[ndx+1], s2, t1);

	VectorSet2(tess.texCoords[ndx+2], s2, t2);
	VectorSet2(tess.lightCoords[ndx+2], s2, t2);

	VectorSet2(tess.texCoords[ndx+3], s1, t2);
	VectorSet2(tess.lightCoords[ndx+3], s1, t2);

	// constant color all the way around
	// should this be identity and let the shader specify from entity?

	R_VaoPackColor(iColor, color);

	VectorCopy4(iColor, tess.color[ndx]);
	VectorCopy4(iColor, tess.color[ndx + 1]);
	VectorCopy4(iColor, tess.color[ndx + 2]);
	VectorCopy4(iColor, tess.color[ndx + 3]);

	tess.numVertexes += 4;
	tess.numIndexes += 6;
}
Exemple #14
0
/*
====================
CM_TraceThroughPatchCollide
====================
*/
void CM_TraceThroughPatchCollide( traceWork_t *tw, trace_t &trace, const struct patchCollide_s *pc )
{
	int i, j, hit, hitnum;
	float offset, enterFrac, leaveFrac, t;
	patchPlane_t *planes;
	facet_t	*facet;
	float plane[4], bestplane[4];
	vec3_t startp, endp;
#ifndef BSPC
	static cvar_t *cv;
#endif //BSPC

#ifndef CULL_BBOX
	// I'm not sure if test is strictly correct.  Are all
	// bboxes axis aligned?  Do I care?  It seems to work
	// good enough...
	for ( i = 0 ; i < 3 ; i++ ) {
		if ( tw->bounds[0][i] > pc->bounds[1][i]
			|| tw->bounds[1][i] < pc->bounds[0][i] ) {
			return;
		}
	}
#endif

	if (tw->isPoint) {
		CM_TracePointThroughPatchCollide( tw, trace, pc );
		return;
	}
	//
	facet = pc->facets;
	for ( i = 0 ; i < pc->numFacets ; i++, facet++ ) {
		enterFrac = -1.0;
		leaveFrac = 1.0;
		hitnum = -1;
		//
		planes = &pc->planes[ facet->surfacePlane ];
		VectorCopy(planes->plane, plane);
		plane[3] = planes->plane[3];
		if ( tw->sphere.use ) {
			// adjust the plane distance appropriately for radius
			plane[3] += tw->sphere.radius;

			// find the closest point on the capsule to the plane
			t = DotProduct( plane, tw->sphere.offset );
			if ( t > 0.0f )
			{
				VectorSubtract( tw->start, tw->sphere.offset, startp );
				VectorSubtract( tw->end, tw->sphere.offset, endp );
			}
			else
			{
				VectorAdd( tw->start, tw->sphere.offset, startp );
				VectorAdd( tw->end, tw->sphere.offset, endp );
			}
		}
		else {
			offset = DotProduct( tw->offsets[ planes->signbits ], plane);
			plane[3] -= offset;
			VectorCopy( tw->start, startp );
			VectorCopy( tw->end, endp );
		}
		//
		if (!CM_CheckFacetPlane(plane, startp, endp, &enterFrac, &leaveFrac, &hit))
			continue;
		if (hit) {
			VectorCopy4(plane, bestplane);
		}
		//
		for ( j = 0 ; j < facet->numBorders ; j++ ) {
			planes = &pc->planes[ facet->borderPlanes[j] ];
			if (facet->borderInward[j]) {
				VectorNegate(planes->plane, plane);
				plane[3] = -planes->plane[3];
			}
			else {
				VectorCopy(planes->plane, plane);
				plane[3] = planes->plane[3];
			}
			if ( tw->sphere.use ) {
				// adjust the plane distance appropriately for radius
				plane[3] += tw->sphere.radius;

				// find the closest point on the capsule to the plane
				t = DotProduct( plane, tw->sphere.offset );
				if ( t > 0.0f )
				{
					VectorSubtract( tw->start, tw->sphere.offset, startp );
					VectorSubtract( tw->end, tw->sphere.offset, endp );
				}
				else
				{
					VectorAdd( tw->start, tw->sphere.offset, startp );
					VectorAdd( tw->end, tw->sphere.offset, endp );
				}
			}
			else {
				// NOTE: this works even though the plane might be flipped because the bbox is centered
				offset = DotProduct( tw->offsets[ planes->signbits ], plane);
				plane[3] += fabs(offset);
				VectorCopy( tw->start, startp );
				VectorCopy( tw->end, endp );
			}
			//
			if (!CM_CheckFacetPlane(plane, startp, endp, &enterFrac, &leaveFrac, &hit))
				break;
			if (hit) {
				hitnum = j;
				VectorCopy4(plane, bestplane);
			}
		}
		if (j < facet->numBorders) continue;
		//never clip against the back side
		if (hitnum == facet->numBorders - 1) continue;
		//
		if (enterFrac < leaveFrac && enterFrac >= 0) {
			if (enterFrac < trace.fraction) {
				if (enterFrac < 0) {
					enterFrac = 0;
				}
#ifndef BSPC
				if (!cv) {
					cv = Cvar_Get( "r_debugSurfaceUpdate", "1", 0 );
				}
				if (cv && cv->integer) {
					debugPatchCollide = pc;
					debugFacet = facet;
				}
#endif // BSPC

				trace.fraction = enterFrac;
				VectorCopy( bestplane, trace.plane.normal );
				trace.plane.dist = bestplane[3];
			}
		}
	}
}
void JKG_BG_ParseGangWarsTeam(const char *filename)
{
	fileHandle_t f;
	int len;
	char buffer[8192];
	char parseBuf[4096];

	len = trap->FS_Open(filename, &f, FS_READ);

	if(!f)
	{
		Com_Printf("^1Error loading Gang wars file (%s): NULL handle\n", filename);
		return;
	}
	if(!len || len >= 8192)
	{
		Com_Printf("^1Error loading Gang wars file (%s): Invalid file size range\n", filename);
		trap->FS_Close(f);
		return;
	}

	trap->FS_Read(buffer, len, f);

	trap->FS_Close(f);

	buffer[len] = '\0';

	if (BG_GetPairedValue(buffer, "name", parseBuf))
	{
		strcpy(bgGangWarsTeams[bgnumGangWarTeams].name, parseBuf);
	}
	else
	{
		Com_Error(ERR_DROP, "Gang wars team (%s) with no name!\n", filename);
		return;
	}

	if (BG_GetPairedValue(buffer, "reference", parseBuf))
	{
		strcpy(bgGangWarsTeams[bgnumGangWarTeams].refPtr, parseBuf);
	}
	else
	{
		Com_Error(ERR_DROP, "Gang wars team (%s) with no reference name!\n", filename);
		return;
	}

	memset(bgGangWarsTeams[bgnumGangWarTeams].modelStore, 0, sizeof(bgGangWarsTeams[bgnumGangWarTeams].modelStore));
	
#if defined(_GAME) || defined(_UI)
	bgGangWarsTeams[bgnumGangWarTeams].teamIcon = 0;
#elif defined(_CGAME)
	if (BG_GetPairedValue(buffer, "icon", parseBuf))
	{
		bgGangWarsTeams[bgnumGangWarTeams].teamIcon = trap->R_RegisterShader(parseBuf);
	}
	else
	{
		bgGangWarsTeams[bgnumGangWarTeams].teamIcon = trap->R_RegisterShader("sprites/team_red");
	}
#endif

	if ( BG_GetPairedValue( buffer, "useTeamColors", parseBuf ) )
	{
		bgGangWarsTeams[bgnumGangWarTeams].useTeamColors = (qboolean)atoi(parseBuf);
	}
	else
	{
		bgGangWarsTeams[bgnumGangWarTeams].useTeamColors = qfalse;
	}

	if (BG_GetPairedValue(buffer, "joinstring", parseBuf))
	{
		strcpy(bgGangWarsTeams[bgnumGangWarTeams].joinstring, parseBuf);
	}
	else
	{
		bgGangWarsTeams[bgnumGangWarTeams].joinstring[0] = 0;
	}
	if (BG_GetPairedValue(buffer, "leadstring", parseBuf))
	{
		strcpy(bgGangWarsTeams[bgnumGangWarTeams].leadstring, parseBuf);
	}
	else
	{
		bgGangWarsTeams[bgnumGangWarTeams].leadstring[0] = 0;
	}
	if (BG_GetPairedValue(buffer, "longname", parseBuf))
	{
		strcpy(bgGangWarsTeams[bgnumGangWarTeams].longname, parseBuf);
	}
	else
	{
		bgGangWarsTeams[bgnumGangWarTeams].longname[0] = 0;
	}
	if (BG_GetPairedValue(buffer, "menujoinstring", parseBuf))
	{
		strcpy(bgGangWarsTeams[bgnumGangWarTeams].menujoinstring, parseBuf);
	}
	else
	{
		bgGangWarsTeams[bgnumGangWarTeams].menujoinstring[0] = 0;
	}
	if (BG_GetPairedValue(buffer, "menustring", parseBuf))
	{
		strcpy(bgGangWarsTeams[bgnumGangWarTeams].menustring, parseBuf);
	}
	else
	{
		bgGangWarsTeams[bgnumGangWarTeams].menustring[0] = 0;
	}
	if (BG_GetPairedValue(buffer, "toomanystring", parseBuf))
	{
		strcpy(bgGangWarsTeams[bgnumGangWarTeams].toomanystring, parseBuf);
	}
	else
	{
		bgGangWarsTeams[bgnumGangWarTeams].toomanystring[0] = 0;
	}

	// Team colors! :3
	if (BG_GetPairedValue(buffer, "teamColor", parseBuf))
	{
		// Parse this good
		char *buffer = parseBuf+1;
		char tempBuffer[8];
		vec4_t tempColor;
		int i = 0;
		int j;
		for(j = 0; j < 4; j++)
		{
			while(buffer[i] != ',' && buffer[i] != '\0' && buffer[i] != '\r' && buffer[i] != '\n' && buffer[i] != '}')
			{
				tempBuffer[i] = buffer[i];
				i++;
			}
			tempBuffer[i] = '\0';
			// Grab the value
			tempColor[j] = atof(tempBuffer);
			tempColor[j] /= 255.0f;
			tempBuffer[0] = '\0';
			buffer += i;
			i = 0;
			buffer++;
		}
		VectorCopy4(tempColor, bgGangWarsTeams[bgnumGangWarTeams].teamColor);
	}
	else
	{
		vec4_t tempColor;
		tempColor[0] = tempColor[1] = tempColor[2] = tempColor[3] = 1.0f;
		VectorCopy4(tempColor, bgGangWarsTeams[bgnumGangWarTeams].teamColor);
	}

	// Now we do a mega hack
	if (BG_GetPairedValue(buffer, "modelstore", parseBuf))
	{
		// These are comma-delimited fields which specify each model
		// E.G.: "kyle/default,jan/default" would be the default
		int l = strlen(parseBuf);
		int i, j;
		j = 0;
		for(i = 0; i < l; i++)
		{
			if(parseBuf[i] == ',')
			{
				strncpy(bgGangWarsTeams[bgnumGangWarTeams].modelStore[bgGangWarsTeams[bgnumGangWarTeams].numModelsInStore], parseBuf+j, i-j);
				bgGangWarsTeams[bgnumGangWarTeams].modelStore[bgGangWarsTeams[bgnumGangWarTeams].numModelsInStore][i-j+1] = '\0';
				bgGangWarsTeams[bgnumGangWarTeams].numModelsInStore++;
				j = i + 1;
			}
			if(parseBuf[i] == '\n')
			{
				break;
			}
			if(parseBuf[i] == '\0')
			{
				break;
			}
		}
	}
	else
	{
		//Just use Kyle for default I guess..
		char defaultModel[MAX_QPATH];
		strcpy(defaultModel, "kyle/default");
		strcpy(bgGangWarsTeams[bgnumGangWarTeams].modelStore[0], defaultModel);
		strcpy(defaultModel, "jan/default");
		strcpy(bgGangWarsTeams[bgnumGangWarTeams].modelStore[1], defaultModel);
	}

	if ( BG_GetPairedValue( buffer, "defaultModel", parseBuf ) )
	{
		strcpy(bgGangWarsTeams[bgnumGangWarTeams].defaultModel, parseBuf);
		size_t lastChar = strlen(bgGangWarsTeams[bgnumGangWarTeams].defaultModel)-1;
		if(bgGangWarsTeams[bgnumGangWarTeams].defaultModel[lastChar] == ',') {
			// This isn't a list. Commas don't belong in this field.
			bgGangWarsTeams[bgnumGangWarTeams].defaultModel[lastChar] = '\0';
		}
	}
	else
	{
		if(!Q_stricmp(bgGangWarsTeams[bgnumGangWarTeams].modelStore[0], "NULL"))
		{
			strcpy(bgGangWarsTeams[bgnumGangWarTeams].defaultModel, "kyle");
		}
		else
		{
			strcpy(bgGangWarsTeams[bgnumGangWarTeams].defaultModel, bgGangWarsTeams[bgnumGangWarTeams].modelStore[0]);	// Use the first model as the default if none specified
		}
	}

	bgnumGangWarTeams++;
}
Exemple #16
0
int main(int argc, char** argv)
{
    FileSystem::getExePath();

    Renderer = new API_OpenGL(SCREEN_X, SCREEN_Y);

#if defined(USE_GLUT)
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(SCREEN_X, SCREEN_Y);
    glutCreateWindow("jade3D Viewer");
#endif

    // RENDERER
    Renderer->InitGL();
    Renderer->clearColor(0.45f,0.45f,0.45f,1);
    Renderer->setRendererState(RENDER_TEXTURE, true);
    Renderer->setRendererState(RENDER_GRID, true);
    Renderer->setRendererState(RENDER_NORMAL, !true);
    Renderer->setRendererState(RENDER_LIGHTNING, true);
    Renderer->setRendererState(RENDER_MATERIAL, true);
    Renderer->ReSizeGLScene(SCREEN_X, SCREEN_Y);

    // SCENE
    scene = new Scene(Renderer);

#if 1
    scene->importScene("scene01.jscene");
#else

    // CAMERA
    Camera * camera = new Camera();
    camera->setCameraPos(1.0f, 4.0f, 10.0f);
    //camera->setCameraPos(1.0f, 4.0f, 80.0f);
    camera->setCameraRot(-20, 10, 0);

    // LIGHT
    Light_t	light1;
    vec4_t la = { 0.0f, 0.0f, 0.0f, 1.0f };
    vec4_t ld = { 1.0f, 1.0f, 1.0f, 1.0f };
    vec4_t ls = {0.0f, 0.0f, 0.0f, 0};
    vec4_t lp = {-3.0f, 4.0f, 2.0f, 0};
    VectorCopy4(la, light1.ambient);
    VectorCopy4(ld, light1.diffuse);
    VectorCopy4(ls, light1.specular);
    VectorCopy4(lp, light1.position);

    // BRUSH
    MeshManager * cube = new MeshManager(Renderer);
    bool res = cube->loadMeshFromFile("gun1.ase", true); // Cube.obj // boule.obj // gun1.ase
    vec3_t p = {0, -3, 0};
    vec3_t s = {0.2f, 0.2f, 0.2f};
    cube->SetPos(p);
    cube->SetSize(s);

    MeshManager * cube2 = new MeshManager(Renderer);
    cube2->loadMeshFromFile("gun2.ase", true);
    vec3_t p2 = {0, -8, 25};
    vec3_t s2 = {0.4f, 0.4f, 0.4f};
    cube2->SetPos(p2);
    cube2->SetSize(s2);

    MeshManager * cube3 = new MeshManager(Renderer);
    cube3->loadMeshFromFile("Cube.obj", true);
    vec3_t p3 = {-3, 1, 0};
    //vec3_t s2 = {0.2f, 0.2f, 0.2f};
    cube3->SetPos(p3);
    //cube3->SetSize(s);

    MeshManager * cube4 = new MeshManager(Renderer);
    cube4->loadMeshFromFile("boule.obj", true);
    vec3_t p4 = {-3, 2, 5};
    cube4->SetPos(p4);

    MeshManager * cube5 = new MeshManager(Renderer);
    cube5->loadMeshFromFile("boule2.obj", true);
    vec3_t p5 = {2, 2, 7};
    vec3_t s5 = {3.0f, 3.0f, 3.0f};
    cube5->SetPos(p5);
    cube5->SetSize(s5);

    MeshManager * cube6 = new MeshManager(Renderer);
    cube6->loadMeshFromFile("Cube.obj", true);
    vec3_t p6 = {3, -2, 3};
    vec3_t s6 = {0.3f, 0.3f, 0.3f};
    cube6->SetPos(p6);
    cube6->SetSize(s6);

    scene->addCamera(camera);
    scene->addLight(light1);
    scene->addBrush(cube);
    scene->addBrush(cube2);
    scene->addBrush(cube3);
    scene->addBrush(cube4);
    scene->addBrush(cube5);
    scene->addBrush(cube6);
    scene->exportScene("scene01.jscene");
#endif

#if defined(USE_GLUT)
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutIdleFunc(idle);
    glutKeyboardFunc(processNormalKeys);
    glutSpecialFunc(processSpecialKeys);
    glutMainLoop();
#endif

    return EXIT_SUCCESS;
}
Exemple #17
0
static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIndexes, glIndex_t *indexes, int dlightBits, int pshadowBits)
{
	int             i;
	glIndex_t      *inIndex;
	srfVert_t      *dv;
	float          *xyz, *texCoords, *lightCoords;
	int16_t        *lightdir;
	int16_t        *normal;
	int16_t        *tangent;
	glIndex_t      *outIndex;
	uint16_t       *color;

	RB_CheckVao(tess.vao);

	RB_CHECKOVERFLOW( numVerts, numIndexes );

	inIndex = indexes;
	outIndex = &tess.indexes[ tess.numIndexes ];
	for ( i = 0 ; i < numIndexes ; i++ ) {
		*outIndex++ = tess.numVertexes + *inIndex++;
	}
	tess.numIndexes += numIndexes;

	if ( tess.shader->vertexAttribs & ATTR_POSITION )
	{
		dv = verts;
		xyz = tess.xyz[ tess.numVertexes ];
		for ( i = 0 ; i < numVerts ; i++, dv++, xyz+=4 )
			VectorCopy(dv->xyz, xyz);
	}

	if ( tess.shader->vertexAttribs & ATTR_NORMAL )
	{
		dv = verts;
		normal = tess.normal[ tess.numVertexes ];
		for ( i = 0 ; i < numVerts ; i++, dv++, normal+=4 )
			VectorCopy4(dv->normal, normal);
	}

	if ( tess.shader->vertexAttribs & ATTR_TANGENT )
	{
		dv = verts;
		tangent = tess.tangent[ tess.numVertexes ];
		for ( i = 0 ; i < numVerts ; i++, dv++, tangent+=4 )
			VectorCopy4(dv->tangent, tangent);
	}

	if ( tess.shader->vertexAttribs & ATTR_TEXCOORD )
	{
		dv = verts;
		texCoords = tess.texCoords[tess.numVertexes];
		for ( i = 0 ; i < numVerts ; i++, dv++, texCoords+=2 )
			VectorCopy2(dv->st, texCoords);
	}

	if ( tess.shader->vertexAttribs & ATTR_LIGHTCOORD )
	{
		dv = verts;
		lightCoords = tess.lightCoords[ tess.numVertexes ];
		for ( i = 0 ; i < numVerts ; i++, dv++, lightCoords+=2 )
			VectorCopy2(dv->lightmap, lightCoords);
	}

	if ( tess.shader->vertexAttribs & ATTR_COLOR )
	{
		dv = verts;
		color = tess.color[ tess.numVertexes ];
		for ( i = 0 ; i < numVerts ; i++, dv++, color+=4 )
			VectorCopy4(dv->color, color);
	}

	if ( tess.shader->vertexAttribs & ATTR_LIGHTDIRECTION )
	{
		dv = verts;
		lightdir = tess.lightdir[ tess.numVertexes ];
		for ( i = 0 ; i < numVerts ; i++, dv++, lightdir+=4 )
			VectorCopy4(dv->lightdir, lightdir);
	}

#if 0  // nothing even uses vertex dlightbits
	for ( i = 0 ; i < numVerts ; i++ ) {
		tess.vertexDlightBits[ tess.numVertexes + i ] = dlightBits;
	}
#endif

	tess.dlightBits |= dlightBits;
	tess.pshadowBits |= pshadowBits;

	tess.numVertexes += numVerts;
}
Exemple #18
0
/*
=============
RB_SurfaceGrid

Just copy the grid of points and triangulate
=============
*/
static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
	int		i, j;
	float	*xyz;
	float	*texCoords, *lightCoords;
	int16_t *normal;
	int16_t *tangent;
	uint16_t *color;
	int16_t *lightdir;
	srfVert_t	*dv;
	int		rows, irows, vrows;
	int		used;
	int		widthTable[MAX_GRID_SIZE];
	int		heightTable[MAX_GRID_SIZE];
	float	lodError;
	int		lodWidth, lodHeight;
	int		numVertexes;
	int		dlightBits;
	int     pshadowBits;
	//int		*vDlightBits;

	if (RB_SurfaceVaoCached(srf->numVerts, srf->verts, srf->numIndexes,
		srf->indexes, srf->dlightBits, srf->pshadowBits))
	{
		return;
	}

	RB_CheckVao(tess.vao);

	dlightBits = srf->dlightBits;
	tess.dlightBits |= dlightBits;

	pshadowBits = srf->pshadowBits;
	tess.pshadowBits |= pshadowBits;

	// determine the allowable discrepance
	lodError = LodErrorForVolume( srf->lodOrigin, srf->lodRadius );

	// determine which rows and columns of the subdivision
	// we are actually going to use
	widthTable[0] = 0;
	lodWidth = 1;
	for ( i = 1 ; i < srf->width-1 ; i++ ) {
		if ( srf->widthLodError[i] <= lodError ) {
			widthTable[lodWidth] = i;
			lodWidth++;
		}
	}
	widthTable[lodWidth] = srf->width-1;
	lodWidth++;

	heightTable[0] = 0;
	lodHeight = 1;
	for ( i = 1 ; i < srf->height-1 ; i++ ) {
		if ( srf->heightLodError[i] <= lodError ) {
			heightTable[lodHeight] = i;
			lodHeight++;
		}
	}
	heightTable[lodHeight] = srf->height-1;
	lodHeight++;


	// very large grids may have more points or indexes than can be fit
	// in the tess structure, so we may have to issue it in multiple passes

	used = 0;
	while ( used < lodHeight - 1 ) {
		// see how many rows of both verts and indexes we can add without overflowing
		do {
			vrows = ( SHADER_MAX_VERTEXES - tess.numVertexes ) / lodWidth;
			irows = ( SHADER_MAX_INDEXES - tess.numIndexes ) / ( lodWidth * 6 );

			// if we don't have enough space for at least one strip, flush the buffer
			if ( vrows < 2 || irows < 1 ) {
				RB_EndSurface();
				RB_BeginSurface(tess.shader, tess.fogNum, tess.cubemapIndex );
			} else {
				break;
			}
		} while ( 1 );
		
		rows = irows;
		if ( vrows < irows + 1 ) {
			rows = vrows - 1;
		}
		if ( used + rows > lodHeight ) {
			rows = lodHeight - used;
		}

		numVertexes = tess.numVertexes;

		xyz = tess.xyz[numVertexes];
		normal = tess.normal[numVertexes];
		tangent = tess.tangent[numVertexes];
		texCoords = tess.texCoords[numVertexes];
		lightCoords = tess.lightCoords[numVertexes];
		color = tess.color[numVertexes];
		lightdir = tess.lightdir[numVertexes];
		//vDlightBits = &tess.vertexDlightBits[numVertexes];

		for ( i = 0 ; i < rows ; i++ ) {
			for ( j = 0 ; j < lodWidth ; j++ ) {
				dv = srf->verts + heightTable[ used + i ] * srf->width
					+ widthTable[ j ];

				if ( tess.shader->vertexAttribs & ATTR_POSITION )
				{
					VectorCopy(dv->xyz, xyz);
					xyz += 4;
				}

				if ( tess.shader->vertexAttribs & ATTR_NORMAL )
				{
					VectorCopy4(dv->normal, normal);
					normal += 4;
				}

				if ( tess.shader->vertexAttribs & ATTR_TANGENT )
				{
					VectorCopy4(dv->tangent, tangent);
					tangent += 4;
				}

				if ( tess.shader->vertexAttribs & ATTR_TEXCOORD )
				{
					VectorCopy2(dv->st, texCoords);
					texCoords += 2;
				}

				if ( tess.shader->vertexAttribs & ATTR_LIGHTCOORD )
				{
					VectorCopy2(dv->lightmap, lightCoords);
					lightCoords += 2;
				}

				if ( tess.shader->vertexAttribs & ATTR_COLOR )
				{
					VectorCopy4(dv->color, color);
					color += 4;
				}

				if ( tess.shader->vertexAttribs & ATTR_LIGHTDIRECTION )
				{
					VectorCopy4(dv->lightdir, lightdir);
					lightdir += 4;
				}

				//*vDlightBits++ = dlightBits;
			}
		}


		// add the indexes
		{
			int		numIndexes;
			int		w, h;

			h = rows - 1;
			w = lodWidth - 1;
			numIndexes = tess.numIndexes;
			for (i = 0 ; i < h ; i++) {
				for (j = 0 ; j < w ; j++) {
					int		v1, v2, v3, v4;
			
					// vertex order to be reckognized as tristrips
					v1 = numVertexes + i*lodWidth + j + 1;
					v2 = v1 - 1;
					v3 = v2 + lodWidth;
					v4 = v3 + 1;

					tess.indexes[numIndexes] = v2;
					tess.indexes[numIndexes+1] = v3;
					tess.indexes[numIndexes+2] = v1;
					
					tess.indexes[numIndexes+3] = v1;
					tess.indexes[numIndexes+4] = v3;
					tess.indexes[numIndexes+5] = v4;
					numIndexes += 6;
				}
			}

			tess.numIndexes = numIndexes;
		}

		tess.numVertexes += rows * lodWidth;

		used += rows - 1;
	}
}
/*
================
CG_DrawArmor
================
*/
static void CG_DrawArmor( menuDef_t *menuHUD )
{
	//vec4_t			calcColor;
	vec4_t			glowColor;
	playerState_t	*ps;
	int				armor, maxArmor;
	itemDef_t		*focusItem;
	double			percentage, factor ; //quarterArmor;
	//int				i,currValue,inc;

	const char *text;
	int x;

	static double	fcurrent = 0;
	vec4_t	fadecolor = {1, 1, 1, 0.5f};
	static vec4_t	draincolor = {1, 0.4f, 0.4f, 1};
	static vec4_t	fillcolor = {0.4f, 1, 0.4f, 1};
	vec4_t	opacity;

	int state = 0;

	MAKERGBA(opacity, 1, 1, 1, cg.jkg_HUDOpacity);

	//ps = &cg.snap->ps;
	ps = &cg.predictedPlayerState;

	// Can we find the menu?
	if (!menuHUD)
	{
		return;
	}

	armor = ps->stats[STAT_ARMOR];
	maxArmor = ps->stats[STAT_MAX_ARMOR];


	// TEST: just render the whole thing for now, we'll fix it later
	focusItem = Menu_FindItemByName(menuHUD, "shieldbar");

	if (focusItem)
	{
		percentage = (double)armor / (double)maxArmor;
		if (percentage > 1) {
			percentage = 1;
		} else if (percentage < 0) {
			percentage = 0;
		}
		factor = /*0.6171875f **/ percentage /*+ 0.34375f*/;
		/*if(factor > 0.95f)
		{
			factor = 1.0f; //eezstreet - mega hack
		}*/
		// Fade our fcurrent to this factor
		if (fcurrent < factor) {
			// Raise it
			fcurrent += (cg.frameDelta * .0003); // Go up 30% per second
			if (fcurrent > factor) {
				// We passed it
				fcurrent = factor;
			}
		} else if (fcurrent > factor) {
			// Lower it
			fcurrent -= (cg.frameDelta * .0003); // Go up 30% per second
			if (fcurrent < factor) {
				fcurrent = factor;
			}
		}

		if (fcurrent != 0) {
			if (fcurrent < factor) {
				state = 1;
				// We're filling up, draw up to fcurrent solid, and up to factor translucent
				trap_R_SetColor(opacity);
				trap_R_DrawStretchPic(focusItem->window.rect.x, focusItem->window.rect.y, focusItem->window.rect.w * fcurrent, focusItem->window.rect.h, 0, 0, fcurrent, 1, focusItem->window.background);
				fadecolor[3] *= cg.jkg_HUDOpacity;
				trap_R_SetColor(fadecolor);
				trap_R_DrawStretchPic(focusItem->window.rect.x + focusItem->window.rect.w * fcurrent, focusItem->window.rect.y, focusItem->window.rect.w * (factor - fcurrent), focusItem->window.rect.h, fcurrent, 0, factor, 1, focusItem->window.background);
				trap_R_SetColor(opacity);
			} else if (fcurrent > factor) {
				state = 2;
				// We're draining, draw up to factor solid, and up to fcurrent translucent
				trap_R_DrawStretchPic(focusItem->window.rect.x, focusItem->window.rect.y, focusItem->window.rect.w * factor, focusItem->window.rect.h, 0, 0, factor, 1, focusItem->window.background);
				fadecolor[3] *= cg.jkg_HUDOpacity;
				trap_R_SetColor(fadecolor);
				trap_R_DrawStretchPic(focusItem->window.rect.x + focusItem->window.rect.w * factor, focusItem->window.rect.y, focusItem->window.rect.w * (fcurrent - factor), focusItem->window.rect.h, factor, 0, fcurrent, 1, focusItem->window.background);
				trap_R_SetColor(opacity);
			} else {
				state = 0;
				// Just solid
				trap_R_SetColor(opacity);
				trap_R_DrawStretchPic(focusItem->window.rect.x, focusItem->window.rect.y, focusItem->window.rect.w * factor, focusItem->window.rect.h, 0, 0, factor, 1, focusItem->window.background);
			}
		}
	}


	if (!armor) {
		return;
	}

	focusItem = Menu_FindItemByName(menuHUD, "shieldtext");

	if (focusItem)
	{
		if (state == 1) {
			VectorCopy4(fillcolor, glowColor);
		} else if (state == 2) {
			VectorCopy4(draincolor, glowColor);
		} else {
			VectorCopy4(colorWhite, glowColor);
		}
		glowColor[3] *= cg.jkg_HUDOpacity;
		// Center and draw the text, positioning will be finetuned later on :P
		text = va("%i / %i", armor, maxArmor);
		x = ((focusItem->window.rect.w/2) - (trap_R_Font_StrLenPixels(text, cgs.media.hudfont1, 0.6f) / 2)) + focusItem->window.rect.x;
		trap_R_Font_DrawString(
			x,
			focusItem->window.rect.y,
			text,
			glowColor,
			cgs.media.hudfont1,
			-1,
			0.6f);
		trap_R_SetColor(NULL);
	}
}
Exemple #20
0
void CM_DrawDebugSurface( void (*drawPoly)(int color, int numPoints, float *points) ) {
	static cvar_t	*cv;
#ifndef BSPC
	static cvar_t	*cv2;
#endif
	const patchCollide_t	*pc;
	facet_t			*facet;
	winding_t		*w;
	int				i, j, k, n;
	int				curplanenum, planenum, curinward, inward;
	float			plane[4];
	vec3_t mins = {-15, -15, -28}, maxs = {15, 15, 28};
	//vec3_t mins = {0, 0, 0}, maxs = {0, 0, 0};
	vec3_t v1, v2;

#ifndef BSPC
	if ( !cv2 )
	{
		cv2 = Cvar_Get( "r_debugSurface", "0", 0 );
	}

	if (cv2->integer != 1)
	{
		BotDrawDebugPolygons(drawPoly, cv2->integer);
		return;
	}
#endif

	if ( !debugPatchCollide ) {
		return;
	}

#ifndef BSPC
	if ( !cv ) {
		cv = Cvar_Get( "cm_debugSize", "2", 0 );
	}
#endif
	pc = debugPatchCollide;

	for ( i = 0, facet = pc->facets ; i < pc->numFacets ; i++, facet++ ) {

		for ( k = 0 ; k < facet->numBorders + 1; k++ ) {
			//
			if (k < facet->numBorders) {
				planenum = facet->borderPlanes[k];
				inward = facet->borderInward[k];
			}
			else {
				planenum = facet->surfacePlane;
				inward = qfalse;
				//continue;
			}

			VectorCopy4( pc->planes[ planenum ].plane, plane );

			//planenum = facet->surfacePlane;
			if ( inward ) {
				VectorSubtract( vec3_origin, plane, plane );
				plane[3] = -plane[3];
			}

			plane[3] += cv->value;
			//*
			for (n = 0; n < 3; n++)
			{
				if (plane[n] > 0) v1[n] = maxs[n];
				else v1[n] = mins[n];
			} //end for
			VectorNegate(plane, v2);
			plane[3] += fabs(DotProduct(v1, v2));
			//*/

			w = BaseWindingForPlane( plane,  plane[3] );
			for ( j = 0 ; j < facet->numBorders + 1 && w; j++ ) {
				//
				if (j < facet->numBorders) {
					curplanenum = facet->borderPlanes[j];
					curinward = facet->borderInward[j];
				}
				else {
					curplanenum = facet->surfacePlane;
					curinward = qfalse;
					//continue;
				}
				//
				if (curplanenum == planenum) continue;

				VectorCopy4( pc->planes[ curplanenum ].plane, plane );
				if ( !curinward ) {
					VectorSubtract( vec3_origin, plane, plane );
					plane[3] = -plane[3];
				}
		//			if ( !facet->borderNoAdjust[j] ) {
					plane[3] -= cv->value;
		//			}
				for (n = 0; n < 3; n++)
				{
					if (plane[n] > 0) v1[n] = maxs[n];
					else v1[n] = mins[n];
				} //end for
				VectorNegate(plane, v2);
				plane[3] -= fabs(DotProduct(v1, v2));

				ChopWindingInPlace( &w, plane, plane[3], 0.1f );
			}
			if ( w ) {
				if ( facet == debugFacet ) {
					drawPoly( 4, w->numpoints, w->p[0] );
					//Com_Printf("blue facet has %d border planes\n", facet->numBorders);
				} else {
					drawPoly( 1, w->numpoints, w->p[0] );
				}
				FreeWinding( w );
			}
			else
				Com_Printf("winding chopped away by border planes\n");
		}
	}

	// draw the debug block
	{
		matrix3_t v;

		VectorCopy( debugBlockPoints[0], v[0] );
		VectorCopy( debugBlockPoints[1], v[1] );
		VectorCopy( debugBlockPoints[2], v[2] );
		drawPoly( 2, 3, v[0] );

		VectorCopy( debugBlockPoints[2], v[0] );
		VectorCopy( debugBlockPoints[3], v[1] );
		VectorCopy( debugBlockPoints[0], v[2] );
		drawPoly( 2, 3, v[0] );
	}

#if 0
	vec3_t			v[4];

	v[0][0] = pc->bounds[1][0];
	v[0][1] = pc->bounds[1][1];
	v[0][2] = pc->bounds[1][2];

	v[1][0] = pc->bounds[1][0];
	v[1][1] = pc->bounds[0][1];
	v[1][2] = pc->bounds[1][2];

	v[2][0] = pc->bounds[0][0];
	v[2][1] = pc->bounds[0][1];
	v[2][2] = pc->bounds[1][2];

	v[3][0] = pc->bounds[0][0];
	v[3][1] = pc->bounds[1][1];
	v[3][2] = pc->bounds[1][2];

	drawPoly( 4, v[0] );
#endif
}
Exemple #21
0
static void LerpMeshVertexes(mdvSurface_t *surf, float backlerp)
{
	float *outXyz;
	int16_t *outNormal, *outTangent;
	mdvVertex_t *newVerts;
	int		vertNum;

	newVerts = surf->verts + backEnd.currentEntity->e.frame * surf->numVerts;

	outXyz =     tess.xyz[tess.numVertexes];
	outNormal =  tess.normal[tess.numVertexes];
	outTangent = tess.tangent[tess.numVertexes];

	if (backlerp == 0)
	{
		//
		// just copy the vertexes
		//

		for (vertNum=0 ; vertNum < surf->numVerts ; vertNum++)
		{
			VectorCopy(newVerts->xyz,    outXyz);
			VectorCopy4(newVerts->normal, outNormal);
			VectorCopy4(newVerts->tangent, outTangent);

			newVerts++;
			outXyz += 4;
			outNormal += 4;
			outTangent += 4;
		}
	}
	else
	{
		//
		// interpolate and copy the vertex and normal
		//

		mdvVertex_t *oldVerts;

		oldVerts = surf->verts + backEnd.currentEntity->e.oldframe * surf->numVerts;

		for (vertNum=0 ; vertNum < surf->numVerts ; vertNum++)
		{
			VectorLerp(newVerts->xyz,    oldVerts->xyz,    backlerp, outXyz);

			outNormal[0] = (int16_t)(newVerts->normal[0] * (1.0f - backlerp) + oldVerts->normal[0] * backlerp);
			outNormal[1] = (int16_t)(newVerts->normal[1] * (1.0f - backlerp) + oldVerts->normal[1] * backlerp);
			outNormal[2] = (int16_t)(newVerts->normal[2] * (1.0f - backlerp) + oldVerts->normal[2] * backlerp);
			outNormal[3] = 0;

			outTangent[0] = (int16_t)(newVerts->tangent[0] * (1.0f - backlerp) + oldVerts->tangent[0] * backlerp);
			outTangent[1] = (int16_t)(newVerts->tangent[1] * (1.0f - backlerp) + oldVerts->tangent[1] * backlerp);
			outTangent[2] = (int16_t)(newVerts->tangent[2] * (1.0f - backlerp) + oldVerts->tangent[2] * backlerp);
			outTangent[3] = newVerts->tangent[3];

			newVerts++;
			oldVerts++;
			outXyz += 4;
			outNormal += 4;
			outTangent += 4;
		}
	}

}