Ejemplo n.º 1
0
void CPatchRData::BuildIndices()
{
	PROFILE3("build indices");

	CTerrain* terrain = m_Patch->m_Parent;

	ssize_t px = m_Patch->m_X * PATCH_SIZE;
	ssize_t pz = m_Patch->m_Z * PATCH_SIZE;

	// must have allocated some vertices before trying to build corresponding indices
	ENSURE(m_VBBase);

	// number of vertices in each direction in each patch
	ssize_t vsize=PATCH_SIZE+1;

	std::vector<unsigned short> indices;
	indices.reserve(PATCH_SIZE * PATCH_SIZE * 4);

	// release existing splats
	m_Splats.clear();

	// build grid of textures on this patch
	std::vector<CTerrainTextureEntry*> textures;
	CTerrainTextureEntry* texgrid[PATCH_SIZE][PATCH_SIZE];
	for (ssize_t j=0;j<PATCH_SIZE;j++) {
		for (ssize_t i=0;i<PATCH_SIZE;i++) {
			CTerrainTextureEntry* tex=m_Patch->m_MiniPatches[j][i].GetTextureEntry();
			texgrid[j][i]=tex;
			if (std::find(textures.begin(),textures.end(),tex)==textures.end()) {
				textures.push_back(tex);
			}
		}
	}

	// now build base splats from interior textures
	m_Splats.resize(textures.size());
	// build indices for base splats
	size_t base=m_VBBase->m_Index;
	ENSURE(base + vsize*vsize < 65536); // mustn't overflow u16 indexes
	for (size_t i=0;i<m_Splats.size();i++) {
		CTerrainTextureEntry* tex=textures[i];

		SSplat& splat=m_Splats[i];
		splat.m_Texture=tex;
		splat.m_IndexStart=indices.size();

		for (ssize_t j = 0; j < PATCH_SIZE; j++)
		{
			for (ssize_t i = 0; i < PATCH_SIZE; i++)
			{
				if (texgrid[j][i] == tex)
				{
					bool dir = terrain->GetTriangulationDir(px+i, pz+j);
					if (dir)
					{
						indices.push_back(u16(((j+0)*vsize+(i+0))+base));
						indices.push_back(u16(((j+0)*vsize+(i+1))+base));
						indices.push_back(u16(((j+1)*vsize+(i+0))+base));

						indices.push_back(u16(((j+0)*vsize+(i+1))+base));
						indices.push_back(u16(((j+1)*vsize+(i+1))+base));
						indices.push_back(u16(((j+1)*vsize+(i+0))+base));
					}
					else
					{
						indices.push_back(u16(((j+0)*vsize+(i+0))+base));
						indices.push_back(u16(((j+0)*vsize+(i+1))+base));
						indices.push_back(u16(((j+1)*vsize+(i+1))+base));

						indices.push_back(u16(((j+1)*vsize+(i+1))+base));
						indices.push_back(u16(((j+1)*vsize+(i+0))+base));
						indices.push_back(u16(((j+0)*vsize+(i+0))+base));
					}
				}
			}
		}
		splat.m_IndexCount=indices.size()-splat.m_IndexStart;
	}

	// Release existing vertex buffer chunk
	if (m_VBBaseIndices)
	{
		g_VBMan.Release(m_VBBaseIndices);
		m_VBBaseIndices = 0;
	}

	ENSURE(indices.size());

	// Construct vertex buffer
	m_VBBaseIndices = g_VBMan.Allocate(sizeof(u16), indices.size(), GL_STATIC_DRAW, GL_ELEMENT_ARRAY_BUFFER);
	m_VBBaseIndices->m_Owner->UpdateChunkVertices(m_VBBaseIndices, &indices[0]);
}
Ejemplo n.º 2
0
void CPatchRData::AddBlend(std::vector<SBlendVertex>& blendVertices, std::vector<u16>& blendIndices, 
			   u16 i, u16 j, u8 shape, CTerrainTextureEntry* texture)
{
	CTerrain* terrain = m_Patch->m_Parent;

	ssize_t gx = m_Patch->m_X * PATCH_SIZE + i;
	ssize_t gz = m_Patch->m_Z * PATCH_SIZE + j;

	// uses the current neighbour texture
	BlendShape8 shape8;
	for (size_t m = 0; m < 8; ++m)
		shape8[m] = (shape & (1 << m)) ? 0 : 1;

	// calculate the required alphamap and the required rotation of the alphamap from blendshape
	unsigned int alphamapflags;
	int alphamap = CAlphaMapCalculator::Calculate(shape8, alphamapflags);

	// now actually render the blend tile (if we need one)
	if (alphamap == -1)
		return;
	
	float u0 = texture->m_TerrainAlpha->second.m_AlphaMapCoords[alphamap].u0;
	float u1 = texture->m_TerrainAlpha->second.m_AlphaMapCoords[alphamap].u1;
	float v0 = texture->m_TerrainAlpha->second.m_AlphaMapCoords[alphamap].v0;
	float v1 = texture->m_TerrainAlpha->second.m_AlphaMapCoords[alphamap].v1;

	if (alphamapflags & BLENDMAP_FLIPU)
		std::swap(u0, u1);

	if (alphamapflags & BLENDMAP_FLIPV)
		std::swap(v0, v1);

	int base = 0;
	if (alphamapflags & BLENDMAP_ROTATE90)
		base = 1;
	else if (alphamapflags & BLENDMAP_ROTATE180)
		base = 2;
	else if (alphamapflags & BLENDMAP_ROTATE270)
		base = 3;

	SBlendVertex vtx[4];
	vtx[(base + 0) % 4].m_AlphaUVs[0] = u0;
	vtx[(base + 0) % 4].m_AlphaUVs[1] = v0;
	vtx[(base + 1) % 4].m_AlphaUVs[0] = u1;
	vtx[(base + 1) % 4].m_AlphaUVs[1] = v0;
	vtx[(base + 2) % 4].m_AlphaUVs[0] = u1;
	vtx[(base + 2) % 4].m_AlphaUVs[1] = v1;
	vtx[(base + 3) % 4].m_AlphaUVs[0] = u0;
	vtx[(base + 3) % 4].m_AlphaUVs[1] = v1;

	SBlendVertex dst;

	const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
	CVector3D normal;

	bool cpuLighting = (g_Renderer.GetRenderPath() == CRenderer::RP_FIXED);

	size_t index = blendVertices.size();

	terrain->CalcPosition(gx, gz, dst.m_Position);
	terrain->CalcNormal(gx, gz, normal);
	dst.m_Normal = normal;
	dst.m_DiffuseColor = cpuLighting ? lightEnv.EvaluateTerrainDiffuseScaled(normal) : lightEnv.EvaluateTerrainDiffuseFactor(normal);
	dst.m_AlphaUVs[0] = vtx[0].m_AlphaUVs[0];
	dst.m_AlphaUVs[1] = vtx[0].m_AlphaUVs[1];
	blendVertices.push_back(dst);

	terrain->CalcPosition(gx + 1, gz, dst.m_Position);
	terrain->CalcNormal(gx + 1, gz, normal);
	dst.m_Normal = normal;
	dst.m_DiffuseColor = cpuLighting ? lightEnv.EvaluateTerrainDiffuseScaled(normal) : lightEnv.EvaluateTerrainDiffuseFactor(normal);
	dst.m_AlphaUVs[0] = vtx[1].m_AlphaUVs[0];
	dst.m_AlphaUVs[1] = vtx[1].m_AlphaUVs[1];
	blendVertices.push_back(dst);

	terrain->CalcPosition(gx + 1, gz + 1, dst.m_Position);
	terrain->CalcNormal(gx + 1, gz + 1, normal);
	dst.m_Normal = normal;
	dst.m_DiffuseColor = cpuLighting ? lightEnv.EvaluateTerrainDiffuseScaled(normal) : lightEnv.EvaluateTerrainDiffuseFactor(normal);
	dst.m_AlphaUVs[0] = vtx[2].m_AlphaUVs[0];
	dst.m_AlphaUVs[1] = vtx[2].m_AlphaUVs[1];
	blendVertices.push_back(dst);

	terrain->CalcPosition(gx, gz + 1, dst.m_Position);
	terrain->CalcNormal(gx, gz + 1, normal);
	dst.m_Normal = normal;
	dst.m_DiffuseColor = cpuLighting ? lightEnv.EvaluateTerrainDiffuseScaled(normal) : lightEnv.EvaluateTerrainDiffuseFactor(normal);
	dst.m_AlphaUVs[0] = vtx[3].m_AlphaUVs[0];
	dst.m_AlphaUVs[1] = vtx[3].m_AlphaUVs[1];
	blendVertices.push_back(dst);

	bool dir = terrain->GetTriangulationDir(gx, gz);
	if (dir)
	{
		blendIndices.push_back(index+0);
		blendIndices.push_back(index+1);
		blendIndices.push_back(index+3);

		blendIndices.push_back(index+1);
		blendIndices.push_back(index+2);
		blendIndices.push_back(index+3);
	}
	else
	{
		blendIndices.push_back(index+0);
		blendIndices.push_back(index+1);
		blendIndices.push_back(index+2);

		blendIndices.push_back(index+2);
		blendIndices.push_back(index+3);
		blendIndices.push_back(index+0);
	}
}