/*	TODO:
		- Firstly save each iteration of our water, so we can keep track of colour etc.
		- Recalc colour for different dynamic moving lights.
*/
void Warp_DrawWaterPoly(glpoly_t *p)
{
	VideoObject_t	*voWaterPoly;
	vec3_t			vWave,vLightColour;
	float			*v;
	int				i;

	voWaterPoly = malloc(p->numverts*sizeof(VideoObject_t));
	if(!voWaterPoly)
	{
		Sys_Error("Failed to allocate water poly!\n");
		return;
	}

	v = p->verts[0];

	for(i = 0; i < p->numverts; i++,v += VERTEXSIZE)
	{
		voWaterPoly[i].vTextureCoord[0][0]	= WARPCALC(v[3],v[4]);
		voWaterPoly[i].vTextureCoord[0][1]	= WARPCALC(v[4],v[3]);
		voWaterPoly[i].vColour[3] = Math_Clamp(0, r_wateralpha.value, 1.0f);

		Math_VectorCopy(v,vWave);

		// Shitty lit water, use dynamic light points in the future...
		{
			MathVector_t	mvLightColour;

			// Use vWave position BEFORE we move it, otherwise the water will flicker.
			mvLightColour = Light_GetSample(vWave);

			Math_MVToVector(mvLightColour,vLightColour);
			Math_VectorScale(vLightColour,1.0f/200.0f,vLightColour);
			Math_VectorDivide(vLightColour,0.2f,vLightColour);
		}

		Math_VectorCopy(vLightColour,voWaterPoly[i].vColour);

		// [20/1/2013] Added in subtle water bobbing, based on this code http://www.quake-1.com/docs/quakesrc.org/26.html ~hogsy
		vWave[2] =	v[2]+
					2.0f*(float)sin(v[0]*0.025f+cl.time)*(float)sin(v[2]*0.05f+cl.time)+
					2.0f*(float)sin(v[1]*0.025f+cl.time*2.0f)*(float)sin(v[2]*0.05f+cl.time);

		Math_VectorCopy(vWave,voWaterPoly[i].vVertex);
	}

	Video_DrawObject(voWaterPoly,VIDEO_PRIMITIVE_TRIANGLE_FAN,p->numverts);

	free(voWaterPoly);
}
Example #2
0
/*	Typically called before an object is drawn.
*/
void Material_Draw(Material_t *Material, int Skin, 
	VideoVertex_t *ObjectVertex, VideoPrimitive_t ObjectPrimitive, unsigned int ObjectSize,
	bool ispost)
{
	if (r_drawflat_cheatsafe || !Material)
		return;

	if ((Material->override_wireframe && (r_showtris.iValue != 1) || !Material->override_wireframe) && (r_lightmap_cheatsafe || r_showtris.bValue))
	{
		if (!ispost)
		{
			// Select the first TMU.
			Video_SelectTexture(0);

			// Set it as white.
			Video_SetTexture(g_mGlobalColour->msSkin[MATERIAL_COLOUR_WHITE].mtTexture->gMap);
		}
		return;
	}

	MaterialSkin_t *msCurrentSkin;
	if (Material->iFlags & MATERIAL_FLAG_ANIMATED)
		msCurrentSkin = Material_GetAnimatedSkin(Material);
	else
		msCurrentSkin = Material_GetSkin(Material, Skin);
	if (!msCurrentSkin)
		Sys_Error("Failed to get valid skin! (%s)\n", Material->cName);

	// Handle any generic blending.
	if ((msCurrentSkin->uiFlags & MATERIAL_FLAG_BLEND) || (Material->fAlpha < 1))
	{
		if (!ispost)
		{
			vlDepthMask(false);

			VideoLayer_Enable(VIDEO_BLEND);

			if (msCurrentSkin->uiFlags & MATERIAL_FLAG_ADDITIVE)
				// Additive blending isn't done by default.
				VideoLayer_BlendFunc(VIDEO_BLEND_ADDITIVE);
		}
		else
		{
			vlDepthMask(true);

			VideoLayer_Disable(VIDEO_BLEND);

			if (msCurrentSkin->uiFlags & MATERIAL_FLAG_ADDITIVE)
				// Return blend mode to its default.
				VideoLayer_BlendFunc(VIDEO_BLEND_DEFAULT);
		}
	}

	unsigned int i, uiCurrentUnit;
	for (i = 0, uiCurrentUnit = 0; i < msCurrentSkin->uiTextures; i++, uiCurrentUnit++)
	{
#ifdef VIDEO_LIGHTMAP_HACKS
		// Skip the lightmap, since it's manually handled.
		if (uiCurrentUnit == VIDEO_TEXTURE_LIGHT)
			uiCurrentUnit++;
#endif

		// Attempt to select the unit (if it's already selected, then it'll just return).
		Video_SelectTexture(uiCurrentUnit);

		if (!ispost)
		{
			// Enable it.
			VideoLayer_Enable(VIDEO_TEXTURE_2D);

			// Bind it.
			Video_SetTexture(msCurrentSkin->mtTexture[i].gMap);

			// Allow us to manipulate the texture.
			if (msCurrentSkin->mtTexture[i].matrixmod)
			{
				glMatrixMode(GL_TEXTURE);
				glLoadIdentity();
				if ((msCurrentSkin->mtTexture[i].vScroll[0] > 0) || (msCurrentSkin->mtTexture[i].vScroll[0] < 0) ||
					(msCurrentSkin->mtTexture[i].vScroll[1] > 0) || (msCurrentSkin->mtTexture[i].vScroll[1] < 0))
					glTranslatef(
						msCurrentSkin->mtTexture[i].vScroll[0] * cl.time,
						msCurrentSkin->mtTexture[i].vScroll[1] * cl.time,
						0);
				if ((msCurrentSkin->mtTexture[i].fRotate > 0) || (msCurrentSkin->mtTexture[i].fRotate < 0))
					glRotatef(msCurrentSkin->mtTexture[i].fRotate*cl.time, 0, 0, 1.0f);
				glMatrixMode(GL_MODELVIEW);
			}
		}

		switch (msCurrentSkin->mtTexture[i].mttType)
		{
		case MATERIAL_TEXTURE_LIGHTMAP:
		case MATERIAL_TEXTURE_DIFFUSE:
			if (!ispost)
			{
#if 0 // TODO: Material shader assignments!!!!
				VideoShader_SetVariablei(iDiffuseUniform, Video.current_textureunit);
#endif

				if (uiCurrentUnit > 0)
				{
					VideoLayer_SetTextureEnvironmentMode(VIDEO_TEXTURE_MODE_DECAL);

					// Check if we've been given a video object to use...
					if (ObjectVertex)
					{
						unsigned int j;

						// Go through the whole object.
						for (j = 0; j < ObjectSize; j++)
						{
							// Copy over original texture coords.
							Video_ObjectTexture(&ObjectVertex[j], uiCurrentUnit,
								// Use base texture coordinates as a reference.
								ObjectVertex[j].mvST[0][0],
								ObjectVertex[j].mvST[0][1]);
						}
					}
				}
				else
					VideoLayer_SetTextureEnvironmentMode(msCurrentSkin->mtTexture[i].EnvironmentMode);

				if ((msCurrentSkin->mtTexture[i].uiFlags & MATERIAL_FLAG_ALPHA) || (msCurrentSkin->uiFlags & MATERIAL_FLAG_ALPHA))
					VideoLayer_Enable(VIDEO_ALPHA_TEST);
			}
			else
			{
				if ((msCurrentSkin->mtTexture[i].uiFlags & MATERIAL_FLAG_ALPHA) || (msCurrentSkin->uiFlags & MATERIAL_FLAG_ALPHA))
				{
					VideoLayer_Disable(VIDEO_ALPHA_TEST);

					if ((msCurrentSkin->uiFlags & MATERIAL_FLAG_ALPHATRICK) && (cv_video_alphatrick.bValue && (ObjectSize > 0)))
					{
						vlDepthMask(false);
						VideoLayer_Enable(VIDEO_BLEND);

						// Draw the object again (don't bother passing material).
						Video_DrawObject(ObjectVertex, ObjectPrimitive, ObjectSize, NULL, 0);

						VideoLayer_Disable(VIDEO_BLEND);
						vlDepthMask(true);
					}
				}

				VideoLayer_SetTextureEnvironmentMode(VIDEO_TEXTURE_MODE_MODULATE);
			}
			break;
		case MATERIAL_TEXTURE_DETAIL:
			if (!ispost)
			{
				if (!cv_video_drawdetail.bValue)
				{
					Video_DisableCapabilities(VIDEO_TEXTURE_2D);
					break;
				}

				VideoLayer_SetTextureEnvironmentMode(VIDEO_TEXTURE_MODE_COMBINE);
				glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
				glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 2);

				// Check if we've been given a video object to use...
				if (ObjectVertex)
				{
					unsigned int j;

					// Go through the whole object.
					for (j = 0; j < ObjectSize; j++)
					{
						// Copy over original texture coords.
						Video_ObjectTexture(&ObjectVertex[j], uiCurrentUnit,
							// Use base texture coordinates as a reference.
							ObjectVertex[j].mvST[0][0] * cv_video_detailscale.value,
							ObjectVertex[j].mvST[0][1] * cv_video_detailscale.value);

						// TODO: Modify them to the appropriate scale.

					}
				}
			}
			else
			{
				VideoLayer_SetTextureEnvironmentMode(VIDEO_TEXTURE_MODE_MODULATE);
				glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 1);
			}
			break;
		case MATERIAL_TEXTURE_FULLBRIGHT:
			if (!ispost)
			{
				if (!gl_fullbrights.bValue)
				{
					Video_DisableCapabilities(VIDEO_TEXTURE_2D);
					break;
				}

				VideoLayer_SetTextureEnvironmentMode(VIDEO_TEXTURE_MODE_ADD);

				if (uiCurrentUnit > 0)
				{
					// Check if we've been given a video object to use...
					if (ObjectVertex)
					{
						unsigned int j;

						// Go through the whole object.
						for (j = 0; j < ObjectSize; j++)
						{
							// Copy over original texture coords.
							Video_ObjectTexture(&ObjectVertex[j], uiCurrentUnit,
								// Use base texture coordinates as a reference.
								ObjectVertex[j].mvST[0][0],
								ObjectVertex[j].mvST[0][1]);
						}
					}
				}
			}
			else
				VideoLayer_SetTextureEnvironmentMode(VIDEO_TEXTURE_MODE_MODULATE);
			break;
		case MATERIAL_TEXTURE_SPHERE:
			if (!ispost)
			{
				VideoLayer_SetTextureEnvironmentMode(VIDEO_TEXTURE_MODE_COMBINE);

				Video_GenerateSphereCoordinates();

				VideoLayer_Enable(VIDEO_TEXTURE_GEN_S | VIDEO_TEXTURE_GEN_T);
			}
			else
			{
				VideoLayer_SetTextureEnvironmentMode(VIDEO_TEXTURE_MODE_MODULATE);
				VideoLayer_Disable(VIDEO_TEXTURE_GEN_S | VIDEO_TEXTURE_GEN_T);
			}
			break;
		default:
			Sys_Error("Invalid texture type for material! (%s) (%i)\n", Material->cPath, msCurrentSkin->mtTexture[i].mttType);
		}

		if (ispost)
		{
			// Reset any manipulation within the matrix.
			if (msCurrentSkin->mtTexture[i].matrixmod)
			{
				glMatrixMode(GL_TEXTURE);
				glLoadIdentity();
				glTranslatef(0, 0, 0);
				glRotatef(0, 0, 0, 0);
				glMatrixMode(GL_MODELVIEW);
			}

			// Disable the texture.
			VideoLayer_Disable(VIDEO_TEXTURE_2D);
		}
	}
}