Improve tangent export

This commit is contained in:
Lubos Lenco 2016-03-09 13:08:46 +01:00
parent 8098ae931d
commit 886725f42a
5 changed files with 110 additions and 49 deletions

View file

@ -59,12 +59,13 @@ deltaSubscaleName = ["dxscl", "dyscl", "dzscl"]
axisName = ["x", "y", "z"]
class ExportVertex:
__slots__ = ("hash", "vertexIndex", "faceIndex", "position", "normal", "color", "texcoord0", "texcoord1")
__slots__ = ("hash", "vertexIndex", "faceIndex", "position", "normal", "color", "texcoord0", "texcoord1", "tangent")
def __init__(self):
self.color = [1.0, 1.0, 1.0]
self.texcoord0 = [0.0, 0.0]
self.texcoord1 = [0.0, 0.0]
self.tangent = [0.0, 0.0, 0.0]
def __eq__(self, v):
if (self.hash != v.hash):
@ -79,6 +80,8 @@ class ExportVertex:
return (False)
if (self.texcoord1 != v.texcoord1):
return (False)
if (self.tangent != v.tangent):
return (False)
return (True)
def Hash(self):
@ -95,6 +98,9 @@ class ExportVertex:
h = h * 21737 + hash(self.texcoord0[1])
h = h * 21737 + hash(self.texcoord1[0])
h = h * 21737 + hash(self.texcoord1[1])
h = h * 21737 + hash(self.tangent[0]) # Appended
h = h * 21737 + hash(self.tangent[1])
h = h * 21737 + hash(self.tangent[2])
self.hash = h
class Object:
@ -329,7 +335,22 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
return ((ArmoryExporter.AnimationKeysDifferent(fcurve)) or (ArmoryExporter.AnimationTangentsNonzero(fcurve)))
@staticmethod
def DeindexMesh(mesh, materialTable):
def calc_tangent(v0, v1, v2, uv0, uv1, uv2):
deltaPos1 = v1 - v0
deltaPos2 = v2 - v0
deltaUV1 = uv1 - uv0
deltaUV2 = uv2 - uv0
d = (deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x)
if d != 0:
r = 1.0 / d
else:
r = 1.0
tangent = (deltaPos1 * deltaUV2.y - deltaPos2 * deltaUV1.y) * r
return tangent
@staticmethod
def DeindexMesh(mesh, materialTable, export_tangents):
# This function deindexes all vertex positions, colors, and texcoords.
# Three separate ExportVertex structures are created for each triangle.
vertexArray = mesh.vertices
@ -475,6 +496,63 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
vertexIndex += 1
faceIndex += 1
if (export_tangents):
vertexIndex = 0
faceIndex = 0
for face in mesh.tessfaces:
# TODO: Speed up
pos = exportVertexArray[vertexIndex].position
tc = exportVertexArray[vertexIndex].texcoord0
v0 = Vector((pos[0], pos[1], pos[2]))
uv0 = Vector((tc[0], tc[1]))
pos = exportVertexArray[vertexIndex + 1].position
tc = exportVertexArray[vertexIndex + 1].texcoord0
v1 = Vector((pos[0], pos[1], pos[2]))
uv1 = Vector((tc[0], tc[1]))
pos = exportVertexArray[vertexIndex + 2].position
tc = exportVertexArray[vertexIndex + 2].texcoord0
v2 = Vector((pos[0], pos[1], pos[2]))
uv2 = Vector((tc[0], tc[1]))
tangent = ArmoryExporter.calc_tangent(v0, v1, v2, uv0, uv1, uv2)
exportVertexArray[vertexIndex].tangent = tangent
vertexIndex += 1
exportVertexArray[vertexIndex].tangent = tangent
vertexIndex += 1
exportVertexArray[vertexIndex].tangent = tangent
vertexIndex += 1
if (len(face.vertices) == 4):
pos = exportVertexArray[vertexIndex].position
tc = exportVertexArray[vertexIndex].texcoord0
v0 = Vector((pos[0], pos[1], pos[2]))
uv0 = Vector((tc[0], tc[1]))
pos = exportVertexArray[vertexIndex + 1].position
tc = exportVertexArray[vertexIndex + 1].texcoord0
v1 = Vector((pos[0], pos[1], pos[2]))
uv1 = Vector((tc[0], tc[1]))
pos = exportVertexArray[vertexIndex + 2].position
tc = exportVertexArray[vertexIndex + 2].texcoord0
v2 = Vector((pos[0], pos[1], pos[2]))
uv2 = Vector((tc[0], tc[1]))
tangent = ArmoryExporter.calc_tangent(v0, v1, v2, uv0, uv1, uv2)
exportVertexArray[vertexIndex].tangent = tangent
vertexIndex += 1
exportVertexArray[vertexIndex].tangent = tangent
vertexIndex += 1
exportVertexArray[vertexIndex].tangent = tangent
vertexIndex += 1
faceIndex += 1
for ev in exportVertexArray:
ev.Hash()
@ -1391,7 +1469,8 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
# Triangulate mesh and remap vertices to eliminate duplicates.
materialTable = []
exportVertexArray = ArmoryExporter.DeindexMesh(exportMesh, materialTable)
export_tangents = self.get_export_tangents(exportMesh)
exportVertexArray = ArmoryExporter.DeindexMesh(exportMesh, materialTable, export_tangents)
triangleCount = len(materialTable)
indexTable = []
@ -1439,6 +1518,14 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
ta2.size = 2
ta2.values = self.WriteVertexArray2D(unifiedVertexArray, "texcoord1")
om.vertex_arrays.append(ta2)
# Tangents
if (export_tangents):
tana = Object()
tana.attrib = "tangent"
tana.size = 3
tana.values = self.WriteVertexArray3D(unifiedVertexArray, "tangent")
om.vertex_arrays.append(tana)
# If there are multiple morph targets, export them here.
# if (shapeKeys):
@ -1523,47 +1610,7 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
ia.size = 3
ia.values = self.WriteTriangleArray(materialTriangleCount[m], materialIndexTable)
ia.material = self.WriteInt(m)
om.index_arrays.append(ia)
# Export tangents
# TODO: check for texture coords
if (self.get_export_tangents(exportMesh) == True and len(exportMesh.uv_textures) > 0):
ia = om.index_arrays[0].values
posa = pa.values
uva = ta.values
tangents = []
for i in range(0, int(len(ia) / 3)):
i0 = ia[i * 3 + 0]
i1 = ia[i * 3 + 1]
i2 = ia[i * 3 + 2]
# TODO: Speed up
v0 = Vector((posa[i0 * 3 + 0], posa[i0 * 3 + 1], posa[i0 * 3 + 2]))
v1 = Vector((posa[i1 * 3 + 0], posa[i1 * 3 + 1], posa[i1 * 3 + 2]))
v2 = Vector((posa[i2 * 3 + 0], posa[i2 * 3 + 1], posa[i2 * 3 + 2]))
uv0 = Vector((uva[i0 * 2 + 0], uva[i0 * 2 + 1]))
uv1 = Vector((uva[i1 * 2 + 0], uva[i1 * 2 + 1]))
uv2 = Vector((uva[i2 * 2 + 0], uva[i2 * 2 + 1]))
deltaPos1 = v1 - v0
deltaPos2 = v2 - v0
deltaUV1 = uv1 - uv0
deltaUV2 = uv2 - uv0
d = (deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x)
if d != 0:
r = 1.0 / d
else:
r = 1.0
tangent = (deltaPos1 * deltaUV2.y - deltaPos2 * deltaUV1.y) * r
tangents.append(tangent.x)
tangents.append(tangent.y)
tangents.append(tangent.z)
tana = Object()
tana.attrib = "tangent"
tana.size = 3
tana.values = tangents
om.vertex_arrays.append(tana)
om.index_arrays.append(ia)
# If the mesh is skinned, export the skinning data here.
if (armature):

View file

@ -61,7 +61,7 @@ float shadowTest(vec4 lPos, float dotNL) {
vec4 packedZValue = texture(shadowMap, lPosH.st);
float distanceFromLight = packedZValue.z;
float bias = clamp(0.005 * tan(acos(dotNL)), 0.0, 0.01);
float bias = 0.028;//clamp(0.005 * tan(acos(dotNL)), 0.0, 0.01);
// 1.0 = not in shadow, 0.0 = in shadow
return float(distanceFromLight > lPosH.z - bias);
@ -193,6 +193,19 @@ void main() {
#ifdef _NMTex
vec3 n = (texture(snormal, texCoord).rgb * 2.0 - 1.0);
n = normalize(TBN * normalize(n));
// vec3 nn = normalize(normal);
// vec3 dp1 = dFdx( position );
// vec3 dp2 = dFdy( position );
// vec2 duv1 = dFdx( texCoord );
// vec2 duv2 = dFdy( texCoord );
// vec3 dp2perp = cross( dp2, nn );
// vec3 dp1perp = cross( nn, dp1 );
// vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;
// vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;
// float invmax = inversesqrt( max( dot(T,T), dot(B,B) ) );
// mat3 TBN = mat3(T * invmax, B * invmax, nn);
// vec3 n = normalize(TBN * nn);
#else
vec3 n = normalize(normal);
#endif
@ -204,7 +217,7 @@ void main() {
if (receiveShadow) {
if (lPos.w > 0.0) {
visibility = shadowTest(lPos, dotNL);
visibility = 1.0;
// visibility = 1.0;
}
}
@ -259,7 +272,7 @@ void main() {
vec3 indirect = indirectDiffuse + indirectSpecular;
outColor = vec4(vec3((direct + indirect) * visibility), 1.0);
outColor = vec4(vec3(direct * visibility + indirect), 1.0);
#ifdef _OMTex
vec3 occlusion = texture(som, texCoord).rgb;

View file

@ -75,7 +75,7 @@
},
{
"id": "cull_mode",
"value": "clockwise"
"value": "counter_clockwise"
},
{
"id": "blend_source",

View file

@ -130,6 +130,7 @@ void main() {
#endif
vec3 mPos = vec4(M * sPos).xyz;
position = mPos;
lightDir = light - mPos;
eyeDir = eye - mPos;

View file

@ -9,10 +9,10 @@ precision highp float;
#endif
in vec3 pos;
in vec3 nor;
#ifdef _AMTex
in vec2 tex;
#endif
in vec3 nor;
#ifdef _VCols
in vec4 col;
#endif