Ejemplo n.º 1
0
void CMeshViewer::Draw3D(float TimeDelta)
{
	guard(CMeshViewer::Draw3D);
	assert(Inst);

	if (GShowDebugInfo)
	{
		// draw axis
		BindDefaultMaterial(true);
		glBegin(GL_LINES);
		for (int i = 0; i < 3; i++)
		{
			CVec3 tmp = nullVec3;
			tmp[i] = 1;
			glColor3fv(tmp.v);
			tmp[i] = 70;
			glVertex3fv(tmp.v);
			glVertex3fv(nullVec3.v);
		}
		glEnd();
		glColor3f(1, 1, 1);
	}

	// draw mesh
	glPolygonMode(GL_FRONT_AND_BACK, Wireframe ? GL_LINE : GL_FILL);	//?? bWireframe is inside Inst, but used here only ?
	DrawMesh(Inst);

	unguard;
}
Ejemplo n.º 2
0
void CMeshViewer::DisplayUV(const CMeshVertex* Verts, int VertexSize, const CBaseMeshLod* Mesh, int UVIndex)
{
	guard(CMeshViewer::DisplayUV);

	int width, height;
	Window->GetWindowSize(width, height);
	int w = min(width, height);

	// add some border
	int x0 = width - w;
	int y0 = 10;
	w -= 20;

	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	for (int MaterialIndex = 0; MaterialIndex < Mesh->Sections.Num(); MaterialIndex++)
	{
		const CMeshSection &Sec = Mesh->Sections[MaterialIndex];
		if (!Sec.NumFaces) continue;

		BindDefaultMaterial(true);
		glDisable(GL_CULL_FACE);
		unsigned color = CMeshInstance::GetMaterialDebugColor(MaterialIndex);
		glColor4ubv((GLubyte*)&color);

		CIndexBuffer::IndexAccessor_t Index = Mesh->Indices.GetAccessor();

		glBegin(GL_TRIANGLES);
		for (int i = Sec.FirstIndex; i < Sec.FirstIndex + Sec.NumFaces * 3; i++)
		{
			int VertIndex = Index(i);
			const CMeshVertex* V = OffsetPointer(Verts, VertIndex * VertexSize);
			const CMeshUVFloat& UV = (UVIndex == 0) ? V->UV : Mesh->ExtraUV[UVIndex-1][VertIndex];
			glVertex2f(UV.U * w + x0, UV.V * w + y0);
		}
		glEnd();
	}

	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	unguard;
}
Ejemplo n.º 3
0
void CStatMeshInstance::Draw(unsigned flags)
{
	guard(CStatMeshInstance::Draw);
	int i;

	if (!pMesh->Lods.Num()) return;

	/*const*/ CStaticMeshLod& Mesh = pMesh->Lods[LodNum];	//?? not 'const' because of BuildTangents(); change this?
	int NumSections = Mesh.Sections.Num();
	if (!NumSections || !Mesh.NumVerts) return;

//	if (!Mesh.HasNormals)  Mesh.BuildNormals();
	if (!Mesh.HasTangents) Mesh.BuildTangents();

	// copy of CSkelMeshInstance::Draw sorting code
#if SORT_BY_OPACITY
	// sort sections by material opacity
	int SectionMap[MAX_MESHMATERIALS];
	int secPlace = 0;
	for (int opacity = 0; opacity < 2; opacity++)
	{
		for (i = 0; i < NumSections; i++)
		{
			UUnrealMaterial *Mat = Mesh.Sections[i].Material;
			int op = 0;			// sort value
			if (Mat && Mat->IsTranslucent()) op = 1;
			if (op == opacity) SectionMap[secPlace++] = i;
		}
	}
	assert(secPlace == NumSections);
#endif // SORT_BY_OPACITY

	// draw mesh
	glEnable(GL_LIGHTING);

	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnableClientState(GL_NORMAL_ARRAY);

	glVertexPointer(3, GL_FLOAT, sizeof(CStaticMeshVertex), &Mesh.Verts[0].Position);
	glNormalPointer(GL_FLOAT, sizeof(CStaticMeshVertex), &Mesh.Verts[0].Normal);
	glTexCoordPointer(2, GL_FLOAT, sizeof(CStaticMeshVertex), &Mesh.Verts[0].UV[UVIndex].U);

	/*??
		Can move tangent/binormal setup here too, but this will require to force shader to use fixed attribute locations
		(use glBindAttribLocation before glLinkProgram instead of querying atttribute via glGetAtribLocation).
		In this case:
		- can remove GCurrentShader
		- can eliminate hasTangent checks below and always bind attributes (when supports GL2.0)
		- can share code between SkeletalMesh and StaticMesh:
		  - sort sections
		  - setup arrays; differences:
		    - position and normals are taken from different arrays in static and skeletal meshes
		    - ShowInfluences in SkeletalMeshInstance should disable material binding
		  - draw sections using glDrawElements()
		  - un-setup arrays
		  - use VAO+VBO for rendering
	*/

	for (i = 0; i < NumSections; i++)
	{
#if SORT_BY_OPACITY
		int MaterialIndex = SectionMap[i];
#else
		int MaterialIndex = i;
#endif
		const CMeshSection &Sec = Mesh.Sections[MaterialIndex];
		if (!Sec.NumFaces) continue;

		SetMaterial(Sec.Material, MaterialIndex);

		// check tangent space
		GLint aTangent = -1, aBinormal = -1;
		bool hasTangent = false;
		const CShader *Sh = GCurrentShader;
		if (Sh)
		{
			aTangent   = Sh->GetAttrib("tangent");
			aBinormal  = Sh->GetAttrib("binormal");
			hasTangent = (aTangent >= 0 && aBinormal >= 0);
		}
		if (hasTangent)
		{
			glEnableVertexAttribArray(aTangent);
			glEnableVertexAttribArray(aBinormal);
			glVertexAttribPointer(aTangent,  3, GL_FLOAT, GL_FALSE, sizeof(CStaticMeshVertex), &Mesh.Verts[0].Tangent);
			glVertexAttribPointer(aBinormal, 3, GL_FLOAT, GL_FALSE, sizeof(CStaticMeshVertex), &Mesh.Verts[0].Binormal);
		}
		// draw
		//?? place this code into CIndexBuffer?
		if (Mesh.Indices.Is32Bit())
			glDrawElements(GL_TRIANGLES, Sec.NumFaces * 3, GL_UNSIGNED_INT, &Mesh.Indices.Indices32[Sec.FirstIndex]);
		else
			glDrawElements(GL_TRIANGLES, Sec.NumFaces * 3, GL_UNSIGNED_SHORT, &Mesh.Indices.Indices16[Sec.FirstIndex]);

		// disable tangents
		if (hasTangent)
		{
			glDisableVertexAttribArray(aTangent);
			glDisableVertexAttribArray(aBinormal);
		}
	}

	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState(GL_NORMAL_ARRAY);

	glDisable(GL_LIGHTING);
	BindDefaultMaterial(true);

	// draw mesh normals
	if (flags & DF_SHOW_NORMALS)
	{
		int NumVerts = Mesh.NumVerts;
		glBegin(GL_LINES);
		glColor3f(0.5, 1, 0);
		for (i = 0; i < NumVerts; i++)
		{
			glVertex3fv(Mesh.Verts[i].Position.v);
			CVec3 tmp;
			VectorMA(Mesh.Verts[i].Position, 2, Mesh.Verts[i].Normal, tmp);
			glVertex3fv(tmp.v);
		}
#if SHOW_TANGENTS
		glColor3f(0, 0.5f, 1);
		for (i = 0; i < NumVerts; i++)
		{
			const CVec3 &v = Mesh.Verts[i].Position;
			glVertex3fv(v.v);
			CVec3 tmp;
			VectorMA(v, 2, Mesh.Verts[i].Tangent, tmp);
			glVertex3fv(tmp.v);
		}
		glColor3f(1, 0, 0.5f);
		for (i = 0; i < NumVerts; i++)
		{
			const CVec3 &v = Mesh.Verts[i].Position;
			glVertex3fv(v.v);
			CVec3 tmp;
			VectorMA(v, 2, Mesh.Verts[i].Binormal, tmp);
			glVertex3fv(tmp.v);
		}
#endif // SHOW_TANGENTS
		glEnd();
	}

	unguard;
}
Ejemplo n.º 4
0
void CSkelMeshViewer::Draw3D(float TimeDelta)
{
	guard(CSkelMeshViewer::Draw3D);
	assert(Inst);

	CSkelMeshInstance *MeshInst = static_cast<CSkelMeshInstance*>(Inst);

	// tick animations
	MeshInst->UpdateAnimation(TimeDelta);

#if HIGHLIGHT_CURRENT
	if (TimeSinceCreate < 0)
		TimeSinceCreate += 1.0f;			// ignore this frame for highlighting
	else
		TimeSinceCreate += TimeDelta;

	float lightAmbient[4];
	float boost = 0;
	float highlightTime = max(TimeSinceCreate, 0);

	if (TaggedMeshes.Num() && highlightTime < HIGHLIGHT_DURATION)
	{
		if (highlightTime > HIGHLIGHT_DURATION / 2)
			highlightTime = HIGHLIGHT_DURATION - highlightTime;	// fade
		boost = HIGHLIGHT_STRENGTH * highlightTime / (HIGHLIGHT_DURATION / 2);

		glGetMaterialfv(GL_FRONT, GL_AMBIENT, lightAmbient);
		lightAmbient[0] += boost;
		lightAmbient[1] += boost;
		lightAmbient[2] += boost;
		glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
		glMaterialfv(GL_FRONT, GL_AMBIENT, lightAmbient);
	}
#endif // HIGHLIGHT_CURRENT

	// draw main mesh
	CMeshViewer::Draw3D(TimeDelta);

#if HIGHLIGHT_CURRENT
	if (boost > 0)
	{
		lightAmbient[0] -= boost;
		lightAmbient[1] -= boost;
		lightAmbient[2] -= boost;
		glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
		glMaterialfv(GL_FRONT, GL_AMBIENT, lightAmbient);
	}
#endif // HIGHLIGHT_CURRENT

	int i;

#if SHOW_BOUNDS
	//?? separate function for drawing wireframe Box (pass CCoords, Mins and Maxs to function)
	BindDefaultMaterial(true);
	glBegin(GL_LINES);
	CVec3 verts[8];
	static const int inds[] =
	{
		0,1, 2,3, 0,2, 1,3,
		4,5, 6,7, 4,6, 5,7,
		0,4, 1,5, 2,6, 3,7
	};
	const FBox &B = MeshInst->pMesh->BoundingBox;
	for (i = 0; i < 8; i++)
	{
		CVec3 &v = verts[i];
		v[0] = (i & 1) ? B.Min.X : B.Max.X;
		v[1] = (i & 2) ? B.Min.Y : B.Max.Y;
		v[2] = (i & 4) ? B.Min.Z : B.Max.Z;
		MeshInst->BaseTransformScaled.TransformPointSlow(v, v);
	}
	// can use glDrawElements(), but this will require more GL setup
	glColor3f(0.5,0.5,1);
	for (i = 0; i < ARRAY_COUNT(inds) / 2; i++)
	{
		glVertex3fv(verts[inds[i*2  ]].v);
		glVertex3fv(verts[inds[i*2+1]].v);
	}
	glEnd();
	glColor3f(1, 1, 1);
#endif // SHOW_BOUNDS

	for (i = 0; i < TaggedMeshes.Num(); i++)
	{
		CSkelMeshInstance *mesh = TaggedMeshes[i];
		if (mesh->pMesh == MeshInst->pMesh) continue;	// avoid duplicates
		mesh->UpdateAnimation(TimeDelta);
		DrawMesh(mesh);
	}

	//?? make this common - place into DrawMesh() ?
	//?? problem: overdraw of skeleton when displaying multiple meshes
	//?? (especially when ShowInfluences is on, and meshes has different bone counts - the same bone
	//?? will be painted multiple times with different colors)
	if (ShowSkel)
		MeshInst->DrawSkeleton(ShowLabels, (DrawFlags & DF_SHOW_INFLUENCES) != 0);
	if (ShowAttach)
		MeshInst->DrawAttachments();

	if (IsFollowingMesh)
		FocusCameraOnPoint(MeshInst->GetMeshOrigin());

	unguard;
}
Ejemplo n.º 5
0
void CMaterialViewer::Draw3D(float TimeDelta)
{
	if (IsTexture && ShowChannels) return;

	static const CVec3 origin = { -150, 100, 100 };
//	static const CVec3 origin = { -150, 50, 50 };
	CVec3 lightPosV;
	viewAxis.UnTransformVector(origin, lightPosV);

#if 0
	// show light source
	glDisable(GL_LIGHTING);
	BindDefaultMaterial(true);
	glBegin(GL_LINES);
	glColor3f(1, 0, 0);
	CVec3 tmp;
	tmp = lightPosV;
	tmp[0] -= 20; glVertex3fv(tmp.v); tmp[0] += 40; glVertex3fv(tmp.v);
	tmp = lightPosV;
	tmp[1] -= 20; glVertex3fv(tmp.v); tmp[1] += 40; glVertex3fv(tmp.v);
	tmp = lightPosV;
	tmp[2] -= 20; glVertex3fv(tmp.v); tmp[2] += 40; glVertex3fv(tmp.v);
	glEnd();
#endif

	glColor3f(1, 1, 1);

	if (!IsTexture)
	{
		glEnable(GL_LIGHTING);	// no lighting for textures
		float lightPos[4];
		lightPos[0] = lightPosV[0];
		lightPos[1] = lightPosV[1];
		lightPos[2] = lightPosV[2];
		lightPos[3] = 0;
		glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
//		glMaterialf(GL_FRONT, GL_SHININESS, 20);
	}

	// bind material
	UUnrealMaterial *Mat = static_cast<UUnrealMaterial*>(Object);
	Mat->SetMaterial();

	// check tangent space
	GLint aNormal = -1;
	GLint aTangent = -1;
//	GLint aBinormal = -1;
	const CShader *Sh = GCurrentShader;
	if (Sh)
	{
		aNormal    = Sh->GetAttrib("normal");
		aTangent   = Sh->GetAttrib("tangent");
//		aBinormal  = Sh->GetAttrib("binormal");
	}

	// and draw box ...
#define A 100
// vertex
#define V000 {-A, -A, -A}
#define V001 {-A, -A,  A}
#define V010 {-A,  A, -A}
#define V011 {-A,  A,  A}
#define V100 { A, -A, -A}
#define V101 { A, -A,  A}
#define V110 { A,  A, -A}
#define V111 { A,  A,  A}
	static const CVec3 box[] =
	{
		V001, V000, V010, V011,		// near   (x=-A)
		V111, V110,	V100, V101,		// far    (x=+A)
		V101, V100, V000, V001,		// left   (y=-A)
		V011, V010, V110, V111,		// right  (y=+A)
		V010, V000, V100, V110,		// bottom (z=-A)
		V001, V011, V111, V101,		// top    (z=+A)
#undef A
	};
#define REP4(...)	{__VA_ARGS__},{__VA_ARGS__},{__VA_ARGS__},{__VA_ARGS__}
	static const CVec4 normal[] =
	{
		REP4(-1, 0, 0, 1 ),
		REP4( 1, 0, 0, 1 ),
		REP4( 0,-1, 0, 1 ),
		REP4( 0, 1, 0, 1 ),
		REP4( 0, 0,-1, 1 ),
		REP4( 0, 0, 1, 1 )
	};
	static const CVec3 tangent[] =
	{
		REP4( 0,-1, 0 ),
		REP4( 0, 1, 0 ),
		REP4( 1, 0, 0 ),
		REP4(-1, 0, 0 ),
		REP4( 1, 0, 0 ),
		REP4(-1, 0, 0 )
	};
//	static const CVec3 binormal[] =
//	{
//		REP4( 0, 0, 1 ),
//		REP4( 0, 0, 1 ),
//		REP4( 0, 0, 1 ),
//		REP4( 0, 0, 1 ),
//		REP4( 0,-1, 0 ),
//		REP4( 0,-1, 0 )
//	};
#undef REP4
	static const float tex[][2] =
	{
		{0, 0}, {0, 1}, {1, 1}, {1, 0},
		{0, 0}, {0, 1}, {1, 1}, {1, 0},
		{0, 0}, {0, 1}, {1, 1}, {1, 0},
		{0, 0}, {0, 1}, {1, 1}, {1, 0},
		{0, 0}, {0, 1}, {1, 1}, {1, 0},
		{0, 0}, {0, 1}, {1, 1}, {1, 0}
	};
	static const int inds[] =
	{
		 0, 1, 2, 3,
		 4, 5, 6, 7,
		 8, 9,10,11,
		12,13,14,15,
		16,17,18,19,
		20,21,22,23
	};

#if 0
	// verify tangents, should be suitable for binormal computation in shaders
	// (note: we're not verifying correspondence with UV coordinates)
	for (int i = 0; i < 24; i++)
	{
		CVec4 n4 = normal[i];
		CVec3 n = n4.ToVec3();
		CVec3 t = tangent[i];
		CVec3 b = binormal[i];
		CVec3 b2;
		cross(n, t, b2);
		VectorScale(b2, n4[3], b2);
		float dd = VectorDistance(b2, b);
		if (dd > 0.001f) appPrintf("dist[%d] = %g\n", i, dd);
	}
#endif

	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnableClientState(GL_NORMAL_ARRAY);

	glVertexPointer(3, GL_FLOAT, sizeof(CVec3), box);
	glNormalPointer(GL_FLOAT, sizeof(CVec4), normal);
	glTexCoordPointer(2, GL_FLOAT, 0, tex);

	if (aNormal >= 0)
	{
		glEnableVertexAttribArray(aNormal);
		// send 4 components to decode binormal in shader
		glVertexAttribPointer(aNormal, 4, GL_FLOAT, GL_FALSE, sizeof(CVec4), normal);
	}
	if (aTangent >= 0)
	{
		glEnableVertexAttribArray(aTangent);
		glVertexAttribPointer(aTangent,  3, GL_FLOAT, GL_FALSE, sizeof(CVec3), tangent);
	}
//	if (aBinormal >= 0)
//	{
//		glEnableVertexAttribArray(aBinormal);
//		glVertexAttribPointer(aBinormal, 3, GL_FLOAT, GL_FALSE, sizeof(CVec3), binormal);
//	}

	glDrawElements(GL_QUADS, ARRAY_COUNT(inds), GL_UNSIGNED_INT, inds);

	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState(GL_NORMAL_ARRAY);
	// disable tangents
	if (aNormal >= 0)
		glDisableVertexAttribArray(aNormal);
	if (aTangent >= 0)
		glDisableVertexAttribArray(aTangent);
//	if (aBinormal >= 0)
//		glDisableVertexAttribArray(aBinormal);

	BindDefaultMaterial(true);

#if 0
	glBegin(GL_LINES);
	glColor3f(0.2, 0.2, 1);
	for (int i = 0; i < ARRAY_COUNT(box); i++)
	{
		glVertex3fv(box[i].v);
		CVec3 tmp;
		VectorMA(box[i], 20, normal[i], tmp);
		glVertex3fv(tmp.v);
	}
	glEnd();
	glColor3f(1, 1, 1);
#endif
}
Ejemplo n.º 6
0
void CVertMeshInstance::Draw(unsigned flags)
{
	guard(CVertMeshInstance::Draw);

	if (!Sections.Num()) return;		// empty mesh

	int i;

	// get 2 frames for interpolation
	int FrameNum1, FrameNum2;
	float frac;
	if (AnimIndex != INDEX_NONE)
	{
		const FMeshAnimSeq &A = pMesh->AnimSeqs[AnimIndex];
		FrameNum1 = appFloor(AnimTime);
		FrameNum2 = FrameNum1 + 1;
		if (FrameNum2 >= A.NumFrames)
			FrameNum2 = 0;
		frac      = AnimTime - FrameNum1;
		FrameNum1 += A.StartFrame;
		FrameNum2 += A.StartFrame;
		// clamp frame numbers (has mesh with wrong frame count in last animation:
		// UT1/BotPack/cdgunmainM; this animation is shown in UnrealEd as lerping to null size)
		if (FrameNum1 >= pMesh->FrameCount)
			FrameNum1 = pMesh->FrameCount-1;
		if (FrameNum2 >= pMesh->FrameCount)
			FrameNum2 = pMesh->FrameCount-1;
	}
	else
	{
		FrameNum1 = 0;
		FrameNum2 = 0;
		frac      = 0;
	}

	int base1 = pMesh->VertexCount * FrameNum1;
	int base2 = pMesh->VertexCount * FrameNum2;

	float backLerp = 1 - frac;
	CVec3 Scale1, Scale2;
	Scale1 = Scale2 = CVT(pMesh->MeshScale);
	Scale1.Scale(backLerp);
	Scale2.Scale(frac);

	// compute deformed mesh
	const FMeshWedge *W = &pMesh->Wedges[0];
	CVec3 *pVec    = Verts;
	CVec3 *pNormal = Normals;
	for (i = 0; i < pMesh->Wedges.Num(); i++, pVec++, pNormal++, W++)
	{
		CVec3 tmp;
#if 0
		// path with no frame lerp
		// vertex
		const FMeshVert &V = pMesh->Verts[base1 + W->iVertex];
		tmp[0] = V.X * pMesh->MeshScale.X;
		tmp[1] = V.Y * pMesh->MeshScale.Y;
		tmp[2] = V.Z * pMesh->MeshScale.Z;
		BaseTransform.TransformPoint(tmp, *pVec);
		// normal
		const FMeshNorm &N = pMesh->Normals[base1 + W->iVertex];
		tmp[0] = (N.X - 512.0f) / 512;
		tmp[1] = (N.Y - 512.0f) / 512;
		tmp[2] = (N.Z - 512.0f) / 512;
		BaseTransform.axis.TransformVector(tmp, *pNormal);
#else
		// vertex
		const FMeshVert &V1 = pMesh->Verts[base1 + W->iVertex];
		const FMeshVert &V2 = pMesh->Verts[base2 + W->iVertex];
		tmp[0] = V1.X * Scale1[0] + V2.X * Scale2[0];
		tmp[1] = V1.Y * Scale1[1] + V2.Y * Scale2[1];
		tmp[2] = V1.Z * Scale1[2] + V2.Z * Scale2[2];
		BaseTransform.TransformPoint(tmp, *pVec);
		// normal
		const FMeshNorm &N1 = pMesh->Normals[base1 + W->iVertex];
		const FMeshNorm &N2 = pMesh->Normals[base2 + W->iVertex];
		tmp[0] = (N1.X * backLerp + N2.X * frac - 512.0f) / 512;
		tmp[1] = (N1.Y * backLerp + N2.Y * frac - 512.0f) / 512;
		tmp[2] = (N1.Z * backLerp + N2.Z * frac - 512.0f) / 512;
		BaseTransform.axis.TransformVector(tmp, *pNormal);
#endif
	}

#if 0
	glBegin(GL_POINTS);
	for (i = 0; i < pMesh->Wedges.Num(); i++)
	{
		glVertex3fv(Verts[i].v);
	}
	glEnd();
	return;
#endif

	// draw mesh
	glEnable(GL_LIGHTING);

	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnableClientState(GL_NORMAL_ARRAY);

	glVertexPointer(3, GL_FLOAT, sizeof(CVec3), Verts);
	glNormalPointer(GL_FLOAT, sizeof(CVec3), Normals);
	glTexCoordPointer(2, GL_FLOAT, sizeof(FMeshWedge), &pMesh->Wedges[0].TexUV.U);

	for (i = 0; i < Sections.Num(); i++)
	{
		const CMeshSection &Sec = Sections[i];
		if (!Sec.NumFaces) continue;
		SetMaterial(Sec.Material, i);
		glDrawElements(GL_TRIANGLES, Sec.NumFaces * 3, GL_UNSIGNED_SHORT, &Indices[Sec.FirstIndex]);
	}

	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState(GL_NORMAL_ARRAY);

	glDisable(GL_LIGHTING);
	BindDefaultMaterial(true);

	// draw mesh normals
	if (flags & DF_SHOW_NORMALS)
	{
		glBegin(GL_LINES);
		glColor3f(0.5, 1, 0);
		for (i = 0; i < pMesh->Wedges.Num(); i++)
		{
			glVertex3fv(Verts[i].v);
			CVec3 tmp;
			VectorMA(Verts[i], 2, Normals[i], tmp);
			glVertex3fv(tmp.v);
		}
		glEnd();
	}

	unguard;
}
Ejemplo n.º 7
0
void CStatMeshInstance::Draw(unsigned flags)
{
	guard(CStatMeshInstance::Draw);
	int i;

	if (!pMesh->Lods.Num()) return;

	/*const*/ CStaticMeshLod& Mesh = pMesh->Lods[LodNum];	//?? not 'const' because of BuildTangents(); change this?
	int NumSections = Mesh.Sections.Num();
	if (!NumSections || !Mesh.NumVerts) return;

//	if (!Mesh.HasNormals)  Mesh.BuildNormals();
	if (!Mesh.HasTangents) Mesh.BuildTangents();

	// copy of CSkelMeshInstance::Draw sorting code
#if SORT_BY_OPACITY
	// sort sections by material opacity
	int SectionMap[MAX_MESHMATERIALS];
	int secPlace = 0;
	for (int opacity = 0; opacity < 2; opacity++)
	{
		for (i = 0; i < NumSections; i++)
		{
			UUnrealMaterial *Mat = Mesh.Sections[i].Material;
			int op = 0;			// sort value
			if (Mat && Mat->IsTranslucent()) op = 1;
			if (op == opacity) SectionMap[secPlace++] = i;
		}
	}
	assert(secPlace == NumSections);
#endif // SORT_BY_OPACITY

	// draw mesh
	glEnable(GL_LIGHTING);

	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnableClientState(GL_NORMAL_ARRAY);

	glVertexPointer(3, GL_FLOAT, sizeof(CStaticMeshVertex), &Mesh.Verts[0].Position);
	glNormalPointer(GL_BYTE, sizeof(CStaticMeshVertex), &Mesh.Verts[0].Normal);
	if (UVIndex == 0)
	{
		glTexCoordPointer(2, GL_FLOAT, sizeof(CStaticMeshVertex), &Mesh.Verts[0].UV.U);
	}
	else
	{
		glTexCoordPointer(2, GL_FLOAT, sizeof(CMeshUVFloat), &Mesh.ExtraUV[UVIndex-1][0].U);
	}

	/*??
		Can move tangent/binormal setup here too, but this will require to force shader to use fixed attribute locations
		(use glBindAttribLocation before glLinkProgram instead of querying atttribute via glGetAtribLocation).
		In this case:
		- can remove GCurrentShader
		- can eliminate hasTangent checks below and always bind attributes (when supports GL2.0)
		- can share code between SkeletalMesh and StaticMesh:
		  - sort sections
		  - setup arrays; differences:
		    - position and normals are taken from different arrays in static and skeletal meshes
		    - ShowInfluences in SkeletalMeshInstance should disable material binding
		  - draw sections using glDrawElements()
		  - un-setup arrays
		  - use VAO+VBO for rendering
	*/

	for (i = 0; i < NumSections; i++)
	{
#if SORT_BY_OPACITY
		int MaterialIndex = SectionMap[i];
#else
		int MaterialIndex = i;
#endif
		const CMeshSection &Sec = Mesh.Sections[MaterialIndex];
		if (!Sec.NumFaces) continue;

		SetMaterial(Sec.Material, MaterialIndex);

		// check tangent space
		GLint aNormal = -1;
		GLint aTangent = -1;
//		GLint aBinormal = -1;
		const CShader *Sh = GCurrentShader;
		if (Sh)
		{
			aNormal    = Sh->GetAttrib("normal");
			aTangent   = Sh->GetAttrib("tangent");
//			aBinormal  = Sh->GetAttrib("binormal");
		}
		if (aNormal >= 0)
		{
			glEnableVertexAttribArray(aNormal);
			// send 4 components to decode binormal in shader
			glVertexAttribPointer(aNormal, 4, GL_BYTE, GL_FALSE, sizeof(CStaticMeshVertex), &Mesh.Verts[0].Normal);
		}
		if (aTangent >= 0)
		{
			glEnableVertexAttribArray(aTangent);
			glVertexAttribPointer(aTangent, 3, GL_BYTE, GL_FALSE, sizeof(CStaticMeshVertex), &Mesh.Verts[0].Tangent);
		}
/*		if (aBinormal >= 0)
		{
			glEnableVertexAttribArray(aBinormal);
			glVertexAttribPointer(aBinormal, 3, GL_BYTE, GL_FALSE, sizeof(CStaticMeshVertex), &Mesh.Verts[0].Binormal);
		} */
		// draw
		//?? place this code into CIndexBuffer?
		if (Mesh.Indices.Is32Bit())
			glDrawElements(GL_TRIANGLES, Sec.NumFaces * 3, GL_UNSIGNED_INT, &Mesh.Indices.Indices32[Sec.FirstIndex]);
		else
			glDrawElements(GL_TRIANGLES, Sec.NumFaces * 3, GL_UNSIGNED_SHORT, &Mesh.Indices.Indices16[Sec.FirstIndex]);

		// disable tangents
		if (aNormal >= 0)
			glDisableVertexAttribArray(aNormal);
		if (aTangent >= 0)
			glDisableVertexAttribArray(aTangent);
//		if (aBinormal >= 0)
//			glDisableVertexAttribArray(aBinormal);
	}

	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState(GL_NORMAL_ARRAY);

	glDisable(GL_LIGHTING);
	BindDefaultMaterial(true);

	// draw mesh normals
	if (flags & DF_SHOW_NORMALS)
	{
		//!! TODO: performance issues when displaying a large mesh (1M+ triangles) with normals/tangents.
		//!! Possible solution:
		//!! 1. use vertex buffer for normals, use single draw call
		//!! 2. cache normal data between render frames
		//!! 3. DecodeTangents() will do Unpack() for normal and tangent too, so this work is duplicated here
		int NumVerts = Mesh.NumVerts;
		glBegin(GL_LINES);
		glColor3f(0.5, 1, 0);
		CVecT tmp, unpacked;
		const float VisualLength = 2.0f;
		for (i = 0; i < NumVerts; i++)
		{
			glVertex3fv(Mesh.Verts[i].Position.v);
			Unpack(unpacked, Mesh.Verts[i].Normal);
			VectorMA(Mesh.Verts[i].Position, VisualLength, unpacked, tmp);
			glVertex3fv(tmp.v);
		}
#if SHOW_TANGENTS
		glColor3f(0, 0.5f, 1);
		for (i = 0; i < NumVerts; i++)
		{
			const CVec3 &v = Mesh.Verts[i].Position;
			glVertex3fv(v.v);
			Unpack(unpacked, Mesh.Verts[i].Tangent);
			VectorMA(v, VisualLength, unpacked, tmp);
			glVertex3fv(tmp.v);
		}
		glColor3f(1, 0, 0.5f);
		for (i = 0; i < NumVerts; i++)
		{
			const CMeshVertex& vert = Mesh.Verts[i];
			// decode binormal
			CVecT normal, tangent, binormal;
			vert.DecodeTangents(normal, tangent, binormal);
			// render
			const CVecT &v = vert.Position;
			glVertex3fv(v.v);
			VectorMA(v, VisualLength, binormal, tmp);
			glVertex3fv(tmp.v);
		}
#endif // SHOW_TANGENTS
		glEnd();
	}

	unguard;
}