- Home /
simply assign tangents to single quad
How can I simply state the tangents for the 4 verts in a quad?
I am having trouble with tangents (not understanding them or shaders) , you can see this by the pointlight in the scene having no effect on the mesh material, with either a diffuse shader or a specular shader.
I have little experience with images (none with creating normal/bump/spec/alpha maps) and no understanding of shaders, but I figured I had to calculate tangents as a vector that goes from previous vertex to next along X direction. Got lost on this, so tried passing my mesh to Eric's TangentSolver script (http://answers.unity3d.com/questions/7789/calculating-tangents-vector4.html, alt link in the script). This also didn't work, so I am lost as to understand how to build my meshes to be light-responsive. Any help or information as always is greatly appreciated in advance =]
Mesh Script
#pragma strict
public var myMaterial : Material;
public var meshSize : Vector2 = Vector2( 8, 6 );
private var myMeshObj : GameObject;
private var myMeshFilter : Mesh;
private var uv : Vector2[];
private var verts : Vector3[];
private var tris : int[];
private var normals : Vector3[];
function Start()
{
BuildMesh();
}
function BuildMesh()
{
myMeshObj = this.gameObject;
myMeshObj.AddComponent(MeshFilter);
myMeshObj.AddComponent("MeshRenderer");
myMeshObj.name = "Mesh_Obj";
myMeshObj.transform.position = new Vector3( 0, 0, 0 );
verts = new Vector3[4];
uv = new Vector2[4];
tris = new int[6];
normals = new Vector3[4];
myMeshFilter = myMeshObj.transform.GetComponent(MeshFilter).mesh as Mesh;
myMeshFilter.name = "Menu_Mesh";
// -- Build Mesh --
verts[0] = new Vector3( 0 - (meshSize.x * 0.5), 0 + (meshSize.y * 0.5), 0);
verts[1] = new Vector3( 0 + (meshSize.x * 0.5), 0 + (meshSize.y * 0.5), 0);
verts[2] = new Vector3( 0 - (meshSize.x * 0.5), 0 - (meshSize.y * 0.5), 0);
verts[3] = new Vector3( 0 + (meshSize.x * 0.5), 0 - (meshSize.y * 0.5), 0);
uv[0] = new Vector2( 0.0, 1.0 );
uv[1] = new Vector2( 1.0, 1.0 );
uv[2] = new Vector2( 0.0, 0.0 );
uv[3] = new Vector2( 1.0, 0.0 );
tris[0] = 0;
tris[1] = 1;
tris[2] = 2;
tris[3] = 2;
tris[4] = 1;
tris[5] = 3;
myMeshFilter.vertices = verts;
myMeshFilter.uv = uv;
myMeshFilter.triangles = tris;
myMeshFilter.normals = normals;
myMeshFilter.RecalculateBounds();
// -- Calculate Tangents --
TangentSolver(myMeshFilter);
// -- Add Material --
myMeshObj.renderer.material = myMaterial;
}
TangentSolver.js
#pragma strict
/*
Derived from
Lengyel, Eric. “Computing Tangent Space Basis Vectors for an Arbitrary Mesh”. Terathon Software 3D Graphics Library, 2001.
[url]http://www.terathon.com/code/tangent.html[/url]
*/
class TangentSolver
{
function TangentSolver(theMesh : Mesh)
{
var vertexCount = theMesh.vertexCount;
var vertices = theMesh.vertices;
var normals = theMesh.normals;
var texcoords = theMesh.uv;
var triangles = theMesh.triangles;
var triangleCount = triangles.length/3;
var tangents = new Vector4[vertexCount];
var tan1 = new Vector3[vertexCount];
var tan2 = new Vector3[vertexCount];
var tri = 0;
for (var i:int = 0; i < (triangleCount); i++)
{
var i1 = triangles[tri];
var i2 = triangles[tri+1];
var i3 = triangles[tri+2];
var v1 = vertices[i1];
var v2 = vertices[i2];
var v3 = vertices[i3];
var w1 = texcoords[i1];
var w2 = texcoords[i2];
var w3 = texcoords[i3];
var x1 = v2.x - v1.x;
var x2 = v3.x - v1.x;
var y1 = v2.y - v1.y;
var y2 = v3.y - v1.y;
var z1 = v2.z - v1.z;
var z2 = v3.z - v1.z;
var s1 = w2.x - w1.x;
var s2 = w3.x - w1.x;
var t1 = w2.y - w1.y;
var t2 = w3.y - w1.y;
var r = 1.0 / (s1 * t2 - s2 * t1);
var sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
var tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
tan1[i1] += sdir;
tan1[i2] += sdir;
tan1[i3] += sdir;
tan2[i1] += tdir;
tan2[i2] += tdir;
tan2[i3] += tdir;
tri += 3;
}
for (i = 0; i < (vertexCount); i++)
{
var n = normals[i];
var t = tan1[i];
// Gram-Schmidt orthogonalize
Vector3.OrthoNormalize( n, t );
tangents[i].x = t.x;
tangents[i].y = t.y;
tangents[i].z = t.z;
// Calculate handedness
tangents[i].w = ( Vector3.Dot(Vector3.Cross(n, t), tan2[i]) < 0.0 ) ? -1.0 : 1.0;
}
theMesh.tangents = tangents;
}
}
// ----
$$anonymous$$Y GOD! Are you really generating your own meshes I didn't even know that was possible!
Sure =] this is just a quad to keep the question simple, but have done more funky stuff. Here's the reference : http://docs.unity3d.com/Documentation/ScriptReference/$$anonymous$$esh.html
There is also alot to gain from animating vertices and changing mesh uv's rather than using renderer.material.SetTextureOffset ("_$$anonymous$$ainTex", Vector2(offset,0)); mainly reducing drawcalls was the reason I started =]
Of course it's possible, none of the many extensions to Unity such as GUI, 2D, sprite, Vectrosity, $$anonymous$$egafiers, etc. would work otherwise.
Anyway, tangents have nothing to do with using lights, they are for things like normal maps. $$anonymous$$esh normals are used for lighting.
I think RecalculateNormals is sufficient most of the time, unless you have something specific in $$anonymous$$d for lighting that would require manual calculations. Thanks for the plug. ;)
Answer by AlucardJay · Jun 30, 2012 at 07:41 PM
Like too many times before; even reading the API I have missed the answer staring at me. Thanks to @Eric5h5 guiding my focus, I have found a solution that works. Simply assigning myMeshFilter.RecalculateNormals();
after RecalculateBounds has my mesh lighting up. Just like the smile on my face =]
Now I know what the normals are for, researching became easier. Some good info here : http://answers.unity3d.com/questions/32100/how-do-i-manually-calculate-normals-for-my-meshes.html