Kaynağa Gözat

Tangent generation and normal map shader support

Ivan Safrin 14 yıl önce
ebeveyn
işleme
04a22925fc

BIN
Assets/Default asset pack/default.pak


+ 150 - 0
Assets/Default asset pack/default/NorColSpec.frag

@@ -0,0 +1,150 @@
+varying vec3 normal;
+varying vec3 tangent;
+varying vec3 binormal;
+varying vec4 pos;
+varying vec4 vertexColor;
+uniform sampler2D diffuse;
+uniform sampler2D normal_map;
+uniform sampler2D specular_map;
+
+float calculateAttenuation(in int i, in float dist)
+{
+    return(1.0 / (gl_LightSource[i].constantAttenuation +
+                  gl_LightSource[i].linearAttenuation * dist +
+                  gl_LightSource[i].quadraticAttenuation * dist * dist));
+}
+
+void pointLight(in int i, in vec3 bump, in vec3 normal, in vec3 tangent, in vec3 binormal, in vec4 pos, inout vec4 diffuse, inout vec4 specular) {
+	vec4 color = gl_FrontMaterial.diffuse;
+	vec4 matspec = gl_FrontMaterial.specular;
+	float shininess = gl_FrontMaterial.shininess;
+	vec4 lightspec = gl_LightSource[i].specular;
+	vec4 lpos = gl_LightSource[i].position;
+	
+	vec3 tmpVec = lpos.xyz - pos.xyz;	
+	lpos.x = dot(tmpVec, tangent);
+	lpos.y = dot(tmpVec, binormal);
+	lpos.z = dot(tmpVec, normal);	
+	
+	float distSqr = dot(lpos.xyz, lpos.xyz);
+	vec3 lVec = lpos.xyz * inversesqrt(distSqr);
+	
+	tmpVec = -pos.xyz;
+	vec3 v;
+	v.x = dot(tmpVec, tangent);
+	v.y = dot(tmpVec, binormal);
+	v.z = dot(tmpVec, normal);	
+	
+	v = normalize(v);
+
+	float nDotL = dot(lVec, bump);
+	if(nDotL > 0.0) {
+		float dist = length(lpos.xyz);    
+		float attenuation = calculateAttenuation(i, dist);
+
+		diffuse  += color * max(0.0, nDotL) * gl_LightSource[i].diffuse * attenuation;
+
+	  if (shininess != 0.0) {
+    	specular += lightspec * matspec * pow(clamp(dot(reflect(-lVec, bump), v),0.0,1.0), shininess) * attenuation;
+	  }
+	}
+}
+
+
+void spotLight(in int i, in vec3 bump, in vec3 normal, in vec3 tangent, in vec3 binormal, in vec4 pos, inout vec4 diffuse, inout vec4 specular) {
+	vec4 color = gl_FrontMaterial.diffuse;
+	vec4 matspec = gl_FrontMaterial.specular;
+	float shininess = gl_FrontMaterial.shininess;
+	vec4 lightspec = gl_LightSource[i].specular;
+	vec4 lpos = gl_LightSource[i].position;
+	
+	vec3 tmpVec = lpos.xyz - pos.xyz;	
+	lpos.x = dot(tmpVec, tangent);
+	lpos.y = dot(tmpVec, binormal);
+	lpos.z = dot(tmpVec, normal);	
+	
+	float distSqr = dot(lpos.xyz, lpos.xyz);
+	vec3 lVec = lpos.xyz * inversesqrt(distSqr);
+	
+	tmpVec = -pos.xyz;
+	vec3 v;
+	v.x = dot(tmpVec, tangent);
+	v.y = dot(tmpVec, binormal);
+	v.z = dot(tmpVec, normal);	
+	
+	v = normalize(v);
+	
+	tmpVec = gl_LightSource[i].spotDirection.xyz;
+	vec3 lDir;
+	lDir.x = dot(tmpVec, tangent);
+	lDir.y = dot(tmpVec, binormal);
+	lDir.z = dot(tmpVec, normal);	
+	
+	lDir = normalize(lDir);
+
+	
+	float cos_outer_cone_angle = gl_LightSource[i].spotExponent;
+	float cos_cur_angle = dot(-lDir, lVec);
+	float cos_inner_cone_angle = gl_LightSource[i].spotCosCutoff;
+
+	float cos_inner_minus_outer_angle = cos_inner_cone_angle - cos_outer_cone_angle;
+	float spot = clamp((cos_cur_angle - cos_outer_cone_angle) / cos_inner_minus_outer_angle, 0.0, 1.0);
+	       	
+
+	float nDotL = dot(lVec, bump);
+	if(nDotL > 0.0) {
+		float dist = length(lpos.xyz);    
+		float attenuation = calculateAttenuation(i, dist);
+
+		diffuse  += color * max(0.0, nDotL) * gl_LightSource[i].diffuse * attenuation * spot;
+
+	  if (shininess != 0.0) {
+    	specular += lightspec * matspec * pow(clamp(dot(reflect(-lVec, bump), v),0.0,1.0), shininess) * attenuation * spot;
+	  }
+	}}
+
+void doLights(in int numLights, in vec3 bump, in vec3 normal, in vec3 tangent, in vec3 binormal, in vec4 pos, inout vec4 diffuse, inout vec4 specular) {
+	for (int i = 0; i < numLights; i++) {
+		if (gl_LightSource[i].spotCutoff == 180.0) {
+			pointLight(i, bump, normal, tangent, binormal, pos, diffuse, specular);
+		} else {
+			spotLight(i, bump, normal, tangent, binormal, pos, diffuse, specular);
+		}
+    }
+}
+
+
+void main()
+{
+	vec4 diffuse_val  = vec4(0.0);
+	vec4 specular_val = vec4(0.0);
+	
+	vec3 bump = normalize( texture2D(normal_map, gl_TexCoord[0].st).xyz * 2.0 - 1.0);
+		
+	doLights(6, bump, normal, tangent, binormal, pos, diffuse_val, specular_val);
+	
+	specular_val.xyz *= texture2D(specular_map, gl_TexCoord[0].st).xyz * gl_FrontMaterial.specular.a;
+	
+	diffuse_val.a = 1.0;
+	specular_val.a = 1.0;
+		
+	vec4 texColor = texture2D(diffuse, gl_TexCoord[0].st);		
+		
+    vec4 color = (diffuse_val  * texColor * vertexColor) +
+                 (specular_val * 1.0)+
+                 (gl_FrontMaterial.ambient * texColor * vertexColor);
+    color = clamp(color, 0.0, 1.0);
+    
+    // fog
+	const float LOG2 = 1.442695;
+	float z = gl_FragCoord.z / gl_FragCoord.w;
+	float fogFactor = exp2( -gl_Fog.density * 
+				   gl_Fog.density * 
+				   z * 
+				   z * 
+				   LOG2 );
+
+	fogFactor = clamp(fogFactor, 0.0, 1.0);
+	gl_FragColor = mix(gl_Fog.color, color, fogFactor );    
+
+}

+ 18 - 0
Assets/Default asset pack/default/NormalShader.vert

@@ -0,0 +1,18 @@
+varying vec3 normal;
+varying vec3 tangent;
+varying vec3 binormal;
+varying vec4 pos;
+varying vec4 rawpos;
+varying vec4 vertexColor;
+attribute vec3 vTangent;
+
+void main() {
+	normal = gl_NormalMatrix * gl_Normal;
+	tangent = gl_NormalMatrix * vTangent; 
+	binormal = cross(normal, tangent);
+	gl_Position = ftransform();
+	pos = gl_ModelViewMatrix * gl_Vertex;
+	rawpos = gl_Vertex;
+    vertexColor = gl_Color;
+	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+}

+ 11 - 1
Assets/Default asset pack/default/default.mat

@@ -72,7 +72,17 @@
 				<params>			
 				<params>			
 				</params>				
 				</params>				
 			</fp>
 			</fp>
-		</shader>										
+		</shader>
+		<shader type="glsl" name="NorColSpec" numAreaLights="4" numSpotLights="2">		
+			<vp source="NormalShader.vert">
+				<params>			
+				</params>				
+			</vp>
+			<fp source="NorColSpec.frag">
+				<params>			
+				</params>				
+			</fp>
+		</shader>											
 	</shaders>	
 	</shaders>	
 	<materials>
 	<materials>
 		<material name="Default">
 		<material name="Default">

+ 5 - 0
Bindings/Contents/LUA/API/Polycode/Material.lua

@@ -7,6 +7,8 @@ class "Material" (Resource)
 function Material:__index__(name)
 function Material:__index__(name)
 	if name == "specularValue" then
 	if name == "specularValue" then
 		return Polycore.Material_get_specularValue(self.__ptr)
 		return Polycore.Material_get_specularValue(self.__ptr)
+	elseif name == "specularStrength" then
+		return Polycore.Material_get_specularStrength(self.__ptr)
 	elseif name == "specularColor" then
 	elseif name == "specularColor" then
 		retVal = Polycore.Material_get_specularColor(self.__ptr)
 		retVal = Polycore.Material_get_specularColor(self.__ptr)
 		if Polycore.__ptr_lookup[retVal] ~= nil then
 		if Polycore.__ptr_lookup[retVal] ~= nil then
@@ -33,6 +35,9 @@ function Material:__set_callback(name,value)
 	if name == "specularValue" then
 	if name == "specularValue" then
 		Polycore.Material_set_specularValue(self.__ptr, value)
 		Polycore.Material_set_specularValue(self.__ptr, value)
 		return true
 		return true
+	elseif name == "specularStrength" then
+		Polycore.Material_set_specularStrength(self.__ptr, value)
+		return true
 	end
 	end
 	return false
 	return false
 end
 end

+ 4 - 0
Bindings/Contents/LUA/API/Polycode/Mesh.lua

@@ -149,6 +149,10 @@ function Mesh:calculateNormals(smooth, smoothAngle)
 	local retVal = Polycore.Mesh_calculateNormals(self.__ptr, smooth, smoothAngle)
 	local retVal = Polycore.Mesh_calculateNormals(self.__ptr, smooth, smoothAngle)
 end
 end
 
 
+function Mesh:calculateTangents()
+	local retVal =  Polycore.Mesh_calculateTangents(self.__ptr)
+end
+
 function Mesh:getMeshType()
 function Mesh:getMeshType()
 	local retVal =  Polycore.Mesh_getMeshType(self.__ptr)
 	local retVal =  Polycore.Mesh_getMeshType(self.__ptr)
 	return retVal
 	return retVal

+ 16 - 0
Bindings/Contents/LUA/API/Polycode/Polygon.lua

@@ -69,6 +69,10 @@ function Polygon:calculateNormal()
 	local retVal =  Polycore.Polygon_calculateNormal(self.__ptr)
 	local retVal =  Polycore.Polygon_calculateNormal(self.__ptr)
 end
 end
 
 
+function Polygon:calculateTangent()
+	local retVal =  Polycore.Polygon_calculateTangent(self.__ptr)
+end
+
 function Polygon:getFaceNormal()
 function Polygon:getFaceNormal()
 	local retVal =  Polycore.Polygon_getFaceNormal(self.__ptr)
 	local retVal =  Polycore.Polygon_getFaceNormal(self.__ptr)
 	if retVal == nil then return nil end
 	if retVal == nil then return nil end
@@ -81,6 +85,18 @@ function Polygon:getFaceNormal()
 	end
 	end
 end
 end
 
 
+function Polygon:getFaceTangent()
+	local retVal =  Polycore.Polygon_getFaceTangent(self.__ptr)
+	if retVal == nil then return nil end
+	if Polycore.__ptr_lookup[retVal] ~= nil then
+		return Polycore.__ptr_lookup[retVal]
+	else
+		Polycore.__ptr_lookup[retVal] = Vector3("__skip_ptr__")
+		Polycore.__ptr_lookup[retVal].__ptr = retVal
+		return Polycore.__ptr_lookup[retVal]
+	end
+end
+
 function Polygon:getBounds2D()
 function Polygon:getBounds2D()
 	local retVal =  Polycore.Polygon_getBounds2D(self.__ptr)
 	local retVal =  Polycore.Polygon_getBounds2D(self.__ptr)
 	if retVal == nil then return nil end
 	if retVal == nil then return nil end

+ 18 - 0
Bindings/Contents/LUA/API/Polycode/Vertex.lua

@@ -32,6 +32,15 @@ function Vertex:__index__(name)
 			Polycore.__ptr_lookup[retVal].__ptr = retVal
 			Polycore.__ptr_lookup[retVal].__ptr = retVal
 			return Polycore.__ptr_lookup[retVal]
 			return Polycore.__ptr_lookup[retVal]
 		end
 		end
+	elseif name == "tangent" then
+		retVal = Polycore.Vertex_get_tangent(self.__ptr)
+		if Polycore.__ptr_lookup[retVal] ~= nil then
+			return Polycore.__ptr_lookup[retVal]
+		else
+			Polycore.__ptr_lookup[retVal] = Vector3("__skip_ptr__")
+			Polycore.__ptr_lookup[retVal].__ptr = retVal
+			return Polycore.__ptr_lookup[retVal]
+		end
 	elseif name == "vertexColor" then
 	elseif name == "vertexColor" then
 		retVal = Polycore.Vertex_get_vertexColor(self.__ptr)
 		retVal = Polycore.Vertex_get_vertexColor(self.__ptr)
 		if Polycore.__ptr_lookup[retVal] ~= nil then
 		if Polycore.__ptr_lookup[retVal] ~= nil then
@@ -41,6 +50,15 @@ function Vertex:__index__(name)
 			Polycore.__ptr_lookup[retVal].__ptr = retVal
 			Polycore.__ptr_lookup[retVal].__ptr = retVal
 			return Polycore.__ptr_lookup[retVal]
 			return Polycore.__ptr_lookup[retVal]
 		end
 		end
+	elseif name == "texCoord" then
+		retVal = Polycore.Vertex_get_texCoord(self.__ptr)
+		if Polycore.__ptr_lookup[retVal] ~= nil then
+			return Polycore.__ptr_lookup[retVal]
+		else
+			Polycore.__ptr_lookup[retVal] = Vector2("__skip_ptr__")
+			Polycore.__ptr_lookup[retVal].__ptr = retVal
+			return Polycore.__ptr_lookup[retVal]
+		end
 	elseif name == "useVertexColor" then
 	elseif name == "useVertexColor" then
 		return Polycore.Vertex_get_useVertexColor(self.__ptr)
 		return Polycore.Vertex_get_useVertexColor(self.__ptr)
 	end
 	end

+ 52 - 0
Bindings/Contents/LUA/Include/PolycodeLUAWrappers.h

@@ -3615,6 +3615,13 @@ static int Polycore_Material_get_specularValue(lua_State *L) {
 	return 1;
 	return 1;
 }
 }
 
 
+static int Polycore_Material_get_specularStrength(lua_State *L) {
+	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
+	Material *inst = (Material*)lua_topointer(L, 1);
+	lua_pushnumber(L, inst->specularStrength);
+	return 1;
+}
+
 static int Polycore_Material_get_specularColor(lua_State *L) {
 static int Polycore_Material_get_specularColor(lua_State *L) {
 	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
 	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
 	Material *inst = (Material*)lua_topointer(L, 1);
 	Material *inst = (Material*)lua_topointer(L, 1);
@@ -3637,6 +3644,14 @@ static int Polycore_Material_set_specularValue(lua_State *L) {
 	return 0;
 	return 0;
 }
 }
 
 
+static int Polycore_Material_set_specularStrength(lua_State *L) {
+	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
+	Material *inst = (Material*)lua_topointer(L, 1);
+	Number param = lua_tonumber(L, 2);
+	inst->specularStrength = param;
+	return 0;
+}
+
 static int Polycore_Material(lua_State *L) {
 static int Polycore_Material(lua_State *L) {
 	luaL_checktype(L, 1, LUA_TSTRING);
 	luaL_checktype(L, 1, LUA_TSTRING);
 	String name = String(lua_tostring(L, 1));
 	String name = String(lua_tostring(L, 1));
@@ -4393,6 +4408,13 @@ static int Polycore_Mesh_calculateNormals(lua_State *L) {
 	return 0;
 	return 0;
 }
 }
 
 
+static int Polycore_Mesh_calculateTangents(lua_State *L) {
+	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
+	Mesh *inst = (Mesh*)lua_topointer(L, 1);
+	inst->calculateTangents();
+	return 0;
+}
+
 static int Polycore_Mesh_getMeshType(lua_State *L) {
 static int Polycore_Mesh_getMeshType(lua_State *L) {
 	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
 	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
 	Mesh *inst = (Mesh*)lua_topointer(L, 1);
 	Mesh *inst = (Mesh*)lua_topointer(L, 1);
@@ -5377,6 +5399,13 @@ static int Polycore_Polygon_calculateNormal(lua_State *L) {
 	return 0;
 	return 0;
 }
 }
 
 
+static int Polycore_Polygon_calculateTangent(lua_State *L) {
+	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
+	Polygon *inst = (Polygon*)lua_topointer(L, 1);
+	inst->calculateTangent();
+	return 0;
+}
+
 static int Polycore_Polygon_getFaceNormal(lua_State *L) {
 static int Polycore_Polygon_getFaceNormal(lua_State *L) {
 	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
 	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
 	Polygon *inst = (Polygon*)lua_topointer(L, 1);
 	Polygon *inst = (Polygon*)lua_topointer(L, 1);
@@ -5386,6 +5415,15 @@ static int Polycore_Polygon_getFaceNormal(lua_State *L) {
 	return 1;
 	return 1;
 }
 }
 
 
+static int Polycore_Polygon_getFaceTangent(lua_State *L) {
+	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
+	Polygon *inst = (Polygon*)lua_topointer(L, 1);
+	Vector3 *retInst = new Vector3();
+	*retInst = inst->getFaceTangent();
+	lua_pushlightuserdata(L, retInst);
+	return 1;
+}
+
 static int Polycore_Polygon_getBounds2D(lua_State *L) {
 static int Polycore_Polygon_getBounds2D(lua_State *L) {
 	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
 	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
 	Polygon *inst = (Polygon*)lua_topointer(L, 1);
 	Polygon *inst = (Polygon*)lua_topointer(L, 1);
@@ -11106,6 +11144,13 @@ static int Polycore_Vertex_get_normal(lua_State *L) {
 	return 1;
 	return 1;
 }
 }
 
 
+static int Polycore_Vertex_get_tangent(lua_State *L) {
+	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
+	Vertex *inst = (Vertex*)lua_topointer(L, 1);
+	lua_pushlightuserdata(L, &inst->tangent);
+	return 1;
+}
+
 static int Polycore_Vertex_get_vertexColor(lua_State *L) {
 static int Polycore_Vertex_get_vertexColor(lua_State *L) {
 	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
 	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
 	Vertex *inst = (Vertex*)lua_topointer(L, 1);
 	Vertex *inst = (Vertex*)lua_topointer(L, 1);
@@ -11113,6 +11158,13 @@ static int Polycore_Vertex_get_vertexColor(lua_State *L) {
 	return 1;
 	return 1;
 }
 }
 
 
+static int Polycore_Vertex_get_texCoord(lua_State *L) {
+	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
+	Vertex *inst = (Vertex*)lua_topointer(L, 1);
+	lua_pushlightuserdata(L, &inst->texCoord);
+	return 1;
+}
+
 static int Polycore_Vertex_get_useVertexColor(lua_State *L) {
 static int Polycore_Vertex_get_useVertexColor(lua_State *L) {
 	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
 	luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
 	Vertex *inst = (Vertex*)lua_topointer(L, 1);
 	Vertex *inst = (Vertex*)lua_topointer(L, 1);

+ 7 - 0
Bindings/Contents/LUA/Source/PolycodeLUA.cpp

@@ -388,9 +388,11 @@ int luaopen_Polycode(lua_State *L) {
 		{"Logger_logw", Polycore_Logger_logw},
 		{"Logger_logw", Polycore_Logger_logw},
 		{"delete_Logger", Polycore_delete_Logger},
 		{"delete_Logger", Polycore_delete_Logger},
 		{"Material_get_specularValue", Polycore_Material_get_specularValue},
 		{"Material_get_specularValue", Polycore_Material_get_specularValue},
+		{"Material_get_specularStrength", Polycore_Material_get_specularStrength},
 		{"Material_get_specularColor", Polycore_Material_get_specularColor},
 		{"Material_get_specularColor", Polycore_Material_get_specularColor},
 		{"Material_get_diffuseColor", Polycore_Material_get_diffuseColor},
 		{"Material_get_diffuseColor", Polycore_Material_get_diffuseColor},
 		{"Material_set_specularValue", Polycore_Material_set_specularValue},
 		{"Material_set_specularValue", Polycore_Material_set_specularValue},
+		{"Material_set_specularStrength", Polycore_Material_set_specularStrength},
 		{"Material", Polycore_Material},
 		{"Material", Polycore_Material},
 		{"Material_addShader", Polycore_Material_addShader},
 		{"Material_addShader", Polycore_Material_addShader},
 		{"Material_getNumShaders", Polycore_Material_getNumShaders},
 		{"Material_getNumShaders", Polycore_Material_getNumShaders},
@@ -462,6 +464,7 @@ int luaopen_Polycode(lua_State *L) {
 		{"Mesh_getVertexBuffer", Polycore_Mesh_getVertexBuffer},
 		{"Mesh_getVertexBuffer", Polycore_Mesh_getVertexBuffer},
 		{"Mesh_getRadius", Polycore_Mesh_getRadius},
 		{"Mesh_getRadius", Polycore_Mesh_getRadius},
 		{"Mesh_calculateNormals", Polycore_Mesh_calculateNormals},
 		{"Mesh_calculateNormals", Polycore_Mesh_calculateNormals},
+		{"Mesh_calculateTangents", Polycore_Mesh_calculateTangents},
 		{"Mesh_getMeshType", Polycore_Mesh_getMeshType},
 		{"Mesh_getMeshType", Polycore_Mesh_getMeshType},
 		{"Mesh_setMeshType", Polycore_Mesh_setMeshType},
 		{"Mesh_setMeshType", Polycore_Mesh_setMeshType},
 		{"Mesh_calculateBBox", Polycore_Mesh_calculateBBox},
 		{"Mesh_calculateBBox", Polycore_Mesh_calculateBBox},
@@ -573,7 +576,9 @@ int luaopen_Polycode(lua_State *L) {
 		{"Polygon_addVertex", Polycore_Polygon_addVertex},
 		{"Polygon_addVertex", Polycore_Polygon_addVertex},
 		{"Polygon_removeVertex", Polycore_Polygon_removeVertex},
 		{"Polygon_removeVertex", Polycore_Polygon_removeVertex},
 		{"Polygon_calculateNormal", Polycore_Polygon_calculateNormal},
 		{"Polygon_calculateNormal", Polycore_Polygon_calculateNormal},
+		{"Polygon_calculateTangent", Polycore_Polygon_calculateTangent},
 		{"Polygon_getFaceNormal", Polycore_Polygon_getFaceNormal},
 		{"Polygon_getFaceNormal", Polycore_Polygon_getFaceNormal},
+		{"Polygon_getFaceTangent", Polycore_Polygon_getFaceTangent},
 		{"Polygon_getBounds2D", Polycore_Polygon_getBounds2D},
 		{"Polygon_getBounds2D", Polycore_Polygon_getBounds2D},
 		{"Polygon_setNormal", Polycore_Polygon_setNormal},
 		{"Polygon_setNormal", Polycore_Polygon_setNormal},
 		{"Polygon_flipUVY", Polycore_Polygon_flipUVY},
 		{"Polygon_flipUVY", Polycore_Polygon_flipUVY},
@@ -1178,7 +1183,9 @@ int luaopen_Polycode(lua_State *L) {
 		{"Vertex_get_restNormal", Polycore_Vertex_get_restNormal},
 		{"Vertex_get_restNormal", Polycore_Vertex_get_restNormal},
 		{"Vertex_get_restPosition", Polycore_Vertex_get_restPosition},
 		{"Vertex_get_restPosition", Polycore_Vertex_get_restPosition},
 		{"Vertex_get_normal", Polycore_Vertex_get_normal},
 		{"Vertex_get_normal", Polycore_Vertex_get_normal},
+		{"Vertex_get_tangent", Polycore_Vertex_get_tangent},
 		{"Vertex_get_vertexColor", Polycore_Vertex_get_vertexColor},
 		{"Vertex_get_vertexColor", Polycore_Vertex_get_vertexColor},
+		{"Vertex_get_texCoord", Polycore_Vertex_get_texCoord},
 		{"Vertex_get_useVertexColor", Polycore_Vertex_get_useVertexColor},
 		{"Vertex_get_useVertexColor", Polycore_Vertex_get_useVertexColor},
 		{"Vertex_set_useVertexColor", Polycore_Vertex_set_useVertexColor},
 		{"Vertex_set_useVertexColor", Polycore_Vertex_set_useVertexColor},
 		{"Vertex", Polycore_Vertex},
 		{"Vertex", Polycore_Vertex},

+ 1 - 0
Core/Contents/Include/PolyMaterial.h

@@ -51,6 +51,7 @@ namespace Polycode {
 			void loadMaterial(const String& fileName);
 			void loadMaterial(const String& fileName);
 			
 			
 			Number specularValue;
 			Number specularValue;
+			Number specularStrength;
 			Color specularColor;
 			Color specularColor;
 			Color diffuseColor;
 			Color diffuseColor;
 						
 						

+ 14 - 2
Core/Contents/Include/PolyMesh.h

@@ -77,11 +77,18 @@ namespace Polycode {
 		* Vertex normal array.
 		* Vertex normal array.
 		*/				
 		*/				
 		static const int NORMAL_DATA_ARRAY = 2;				
 		static const int NORMAL_DATA_ARRAY = 2;				
-		
+
 		/**
 		/**
 		* Vertex texture coordinate array.
 		* Vertex texture coordinate array.
 		*/						
 		*/						
 		static const int TEXCOORD_DATA_ARRAY = 3;
 		static const int TEXCOORD_DATA_ARRAY = 3;
+		
+		/**
+		* Tangent vector array.
+		*/				
+		static const int TANGENT_DATA_ARRAY = 4;				
+		
+		
 	};
 	};
 		
 		
 
 
@@ -256,11 +263,16 @@ namespace Polycode {
 			Number getRadius();
 			Number getRadius();
 			
 			
 			/**
 			/**
-			* Recalculates the mesh normals (flat normals only).
+			* Recalculates the mesh normals
 			* @param smooth If true, will use smooth normals.
 			* @param smooth If true, will use smooth normals.
 			* @param smoothAngle If smooth, this parameter sets the angle tolerance for the approximation function.
 			* @param smoothAngle If smooth, this parameter sets the angle tolerance for the approximation function.
 			*/
 			*/
 			void calculateNormals(bool smooth=true, Number smoothAngle=90.0);	
 			void calculateNormals(bool smooth=true, Number smoothAngle=90.0);	
+
+			/**
+			* Recalculates the tangent space vector for all vertices.
+			*/ 
+			void calculateTangents();
 			
 			
 			std::vector<Polygon*> getConnectedFaces(Vertex *v);
 			std::vector<Polygon*> getConnectedFaces(Vertex *v);
 			
 			

+ 13 - 0
Core/Contents/Include/PolyPolygon.h

@@ -91,12 +91,24 @@ namespace Polycode {
 			* Calculates the average normal for the vertices.
 			* Calculates the average normal for the vertices.
 			*/
 			*/
 			void calculateNormal();
 			void calculateNormal();
+
+			/**
+			* Calculates the tangent space vector for the vertices.
+			*/
+			void calculateTangent();
 			
 			
 			/**
 			/**
 			* Returns the face normal.
 			* Returns the face normal.
 			* @return Face normal.
 			* @return Face normal.
 			*/ 
 			*/ 
 			Vector3 getFaceNormal();
 			Vector3 getFaceNormal();
+
+			/**
+			* Returns the face tangent vector.
+			* @return Face tangent vector.
+			*/ 
+			Vector3 getFaceTangent();
+
 			
 			
 			Rectangle getBounds2D();
 			Rectangle getBounds2D();
 			
 			
@@ -121,6 +133,7 @@ namespace Polycode {
 			unsigned int vertexCount;
 			unsigned int vertexCount;
 			std::vector<Vertex*> vertices;
 			std::vector<Vertex*> vertices;
 			Vector3			normal;
 			Vector3			normal;
+			Vector3			tangent;			
 	};
 	};
 
 
 }
 }

+ 10 - 1
Core/Contents/Include/PolyVertex.h

@@ -170,18 +170,27 @@ namespace Polycode {
 			* Vertex normal.
 			* Vertex normal.
 			*/
 			*/
 			Vector3 normal;
 			Vector3 normal;
+
+			/**
+			* Vertex tangent.
+			*/
+			Vector3 tangent;
 			
 			
 			/**
 			/**
 			* Vertex color.
 			* Vertex color.
 			*/
 			*/
 			Color vertexColor;		
 			Color vertexColor;		
 			
 			
+			/**
+			* Texture coordinates
+			*/
+			Vector2 texCoord;
+			
 			bool useVertexColor;
 			bool useVertexColor;
 				
 				
 		protected:
 		protected:
 		
 		
 			std::vector <BoneAssignment*> boneAssignments;
 			std::vector <BoneAssignment*> boneAssignments;
-			Vector2 texCoord;
 		
 		
 	};
 	};
 }
 }

+ 26 - 2
Core/Contents/Source/PolyGLRenderer.cpp

@@ -714,7 +714,7 @@ void OpenGLRenderer::applyMaterial(Material *material,  ShaderBinding *localOpti
 	data4[0] = material->specularColor.r;
 	data4[0] = material->specularColor.r;
 	data4[1] = material->specularColor.g;
 	data4[1] = material->specularColor.g;
 	data4[2] = material->specularColor.b;
 	data4[2] = material->specularColor.b;
-	data4[3] = material->specularColor.a;
+	data4[3] = material->specularStrength;
 				
 				
 	glMaterialfv(GL_FRONT, GL_SPECULAR, data4);
 	glMaterialfv(GL_FRONT, GL_SPECULAR, data4);
 
 
@@ -823,6 +823,11 @@ void OpenGLRenderer::pushRenderDataArray(RenderDataArray *array) {
 			glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0);			
 			glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0);			
 			glNormalPointer(GL_FLOAT, 0, array->arrayPtr);	
 			glNormalPointer(GL_FLOAT, 0, array->arrayPtr);	
 		break;
 		break;
+		case RenderDataArray::TANGENT_DATA_ARRAY:
+			glEnableVertexAttribArrayARB(6);		
+			glVertexAttribPointer(6, array->size, GL_FLOAT, 0, 0, array->arrayPtr);
+		break;
+		
 	}
 	}
 }
 }
 
 
@@ -889,6 +894,22 @@ RenderDataArray *OpenGLRenderer::createRenderDataArrayForMesh(Mesh *mesh, int ar
 			}			
 			}			
 		}
 		}
 		break;
 		break;
+		case RenderDataArray::TANGENT_DATA_ARRAY:
+		{
+			buffer = (GLfloat*)malloc(1);	
+			
+			for(int i=0; i < mesh->getPolygonCount(); i++) {
+				for(int j=0; j < mesh->getPolygon(i)->getVertexCount(); j++) {
+					newBufferSize = bufferSize + 3;			
+					buffer = (GLfloat*)realloc(buffer, newBufferSize * sizeof(GLfloat));		
+					buffer[bufferSize+0] = mesh->getPolygon(i)->getVertex(j)->tangent.x;
+					buffer[bufferSize+1] = mesh->getPolygon(i)->getVertex(j)->tangent.y;
+					buffer[bufferSize+2] = mesh->getPolygon(i)->getVertex(j)->tangent.z;				
+					bufferSize = newBufferSize;					
+				}		   
+			}			
+		}
+		break;		
 		case RenderDataArray::TEXCOORD_DATA_ARRAY:
 		case RenderDataArray::TEXCOORD_DATA_ARRAY:
 		{
 		{
 			buffer = (GLfloat*)malloc(1);				
 			buffer = (GLfloat*)malloc(1);				
@@ -931,7 +952,10 @@ RenderDataArray *OpenGLRenderer::createRenderDataArray(int arrayType) {
 			break;			
 			break;			
 		case RenderDataArray::NORMAL_DATA_ARRAY:
 		case RenderDataArray::NORMAL_DATA_ARRAY:
 			newArray->size = 3;
 			newArray->size = 3;
-			break;						
+			break;	
+		case RenderDataArray::TANGENT_DATA_ARRAY:
+			newArray->size = 3;
+			break;														
 		case RenderDataArray::TEXCOORD_DATA_ARRAY:
 		case RenderDataArray::TEXCOORD_DATA_ARRAY:
 			newArray->size = 2;
 			newArray->size = 2;
 			break;									
 			break;									

+ 4 - 1
Core/Contents/Source/PolyGLSLShader.cpp

@@ -113,10 +113,13 @@ void GLSLShaderBinding::addParam(const String& type, const String& name, const S
 GLSLShader::GLSLShader(GLSLProgram *vp, GLSLProgram *fp) : Shader(Shader::MODULE_SHADER) {
 GLSLShader::GLSLShader(GLSLProgram *vp, GLSLProgram *fp) : Shader(Shader::MODULE_SHADER) {
 	this->vp = vp;
 	this->vp = vp;
 	this->fp = fp;
 	this->fp = fp;
-	
+		
 	shader_id = glCreateProgram();
 	shader_id = glCreateProgram();
     glAttachShader(shader_id, fp->program);
     glAttachShader(shader_id, fp->program);
     glAttachShader(shader_id, vp->program);
     glAttachShader(shader_id, vp->program);
+	
+	glBindAttribLocation(shader_id, 6, "vTangent");
+		
     glLinkProgram(shader_id);	
     glLinkProgram(shader_id);	
 }
 }
 
 

+ 3 - 3
Core/Contents/Source/PolyGLSLShaderModule.cpp

@@ -33,8 +33,8 @@ THE SOFTWARE.
 
 
 #include "tinyxml.h"
 #include "tinyxml.h"
 
 
-#ifdef _WINDOWS
-#include <windows.h>
+#ifdef _WINDOWS
+#include <windows.h>
 #endif
 #endif
 
 
 #if defined(__APPLE__) && defined(__MACH__)
 #if defined(__APPLE__) && defined(__MACH__)
@@ -628,7 +628,7 @@ bool GLSLShaderModule::applyShaderMaterial(Renderer *renderer, Material *materia
 		glActiveTexture(GL_TEXTURE0 + textureIndex);		
 		glActiveTexture(GL_TEXTURE0 + textureIndex);		
 		glBindTexture(GL_TEXTURE_2D, ((OpenGLTexture*)cgBinding->textures[i].texture)->getTextureID());	
 		glBindTexture(GL_TEXTURE_2D, ((OpenGLTexture*)cgBinding->textures[i].texture)->getTextureID());	
 		textureIndex++;
 		textureIndex++;
-	}	
+	}		
 
 
 	//			Logger::log("applying %s (%s %s)\n", material->getShader()->getName().c_str(), cgShader->vp->getResourceName().c_str(), cgShader->fp->getResourceName().c_str());
 	//			Logger::log("applying %s (%s %s)\n", material->getShader()->getName().c_str(), cgShader->vp->getResourceName().c_str(), cgShader->fp->getResourceName().c_str());
 
 

+ 1 - 0
Core/Contents/Source/PolyMaterial.cpp

@@ -29,6 +29,7 @@ using namespace Polycode;
 Material::Material(const String& name) : Resource(Resource::RESOURCE_MATERIAL) {
 Material::Material(const String& name) : Resource(Resource::RESOURCE_MATERIAL) {
 	this->name = name;
 	this->name = name;
 	specularValue = 75.0;
 	specularValue = 75.0;
+	specularStrength = 1.0;
 }
 }
 
 
 Material::~Material() {
 Material::~Material() {

+ 5 - 0
Core/Contents/Source/PolyMaterialManager.cpp

@@ -288,6 +288,11 @@ Material *MaterialManager::materialFromXMLNode(TiXmlNode *node) {
 			newMaterial->specularValue = atof(pChild3->ToElement()->GetText());
 			newMaterial->specularValue = atof(pChild3->ToElement()->GetText());
 		}
 		}
 
 
+		if(strcmp(pChild3->Value(), "specularStrength") == 0) {
+			newMaterial->specularStrength = atof(pChild3->ToElement()->GetText());
+		}
+
+
 		if(strcmp(pChild3->Value(), "specularColor") == 0) {		
 		if(strcmp(pChild3->Value(), "specularColor") == 0) {		
 			String value = pChild3->ToElement()->GetText();
 			String value = pChild3->ToElement()->GetText();
 			vector<String> values = value.split(" ");
 			vector<String> values = value.split(" ");

+ 50 - 12
Core/Contents/Source/PolyMesh.cpp

@@ -221,10 +221,13 @@ namespace Polycode {
 			addPolygon(poly);
 			addPolygon(poly);
 		}
 		}
 		
 		
+		calculateTangents();
+		
 		arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
 		arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
 		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
 		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
 		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;
 		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;
-		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;							
+		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;	
+		arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true;								
 	}
 	}
 	
 	
 	void Mesh::saveToFile(const String& fileName) {
 	void Mesh::saveToFile(const String& fileName) {
@@ -248,7 +251,7 @@ namespace Polycode {
 		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
 		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
 		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;						
 		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;						
 		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;										
 		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;										
-		
+		arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true;		
 	}
 	}
 	
 	
 	void Mesh::createVPlane(Number w, Number h) { 
 	void Mesh::createVPlane(Number w, Number h) { 
@@ -268,11 +271,12 @@ namespace Polycode {
 		}
 		}
 
 
 		calculateNormals();
 		calculateNormals();
+		calculateTangents();
 		arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
 		arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
 		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
 		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
 		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;						
 		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;						
 		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;										
 		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;										
-		
+		arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true;		
 	}	
 	}	
 	
 	
 	void Mesh::createPlane(Number w, Number h) { 
 	void Mesh::createPlane(Number w, Number h) { 
@@ -292,11 +296,12 @@ namespace Polycode {
 		}
 		}
 
 
 		calculateNormals();
 		calculateNormals();
+		calculateTangents();
 		arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
 		arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
 		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
 		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
 		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;						
 		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;						
 		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;										
 		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;										
-		
+		arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true;		
 	}
 	}
 
 
 	Vector3 Mesh::recenterMesh() {
 	Vector3 Mesh::recenterMesh() {
@@ -436,11 +441,12 @@ namespace Polycode {
 		}
 		}
 
 
 		calculateNormals();
 		calculateNormals();
+		calculateTangents();
 		arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
 		arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
 		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
 		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
 		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;						
 		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;						
 		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;										
 		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;										
-		
+		arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true;		
 	}
 	}
 	
 	
 	unsigned int Mesh::getVertexCount() {
 	unsigned int Mesh::getVertexCount() {
@@ -508,11 +514,12 @@ namespace Polycode {
 		
 		
 	
 	
 		calculateNormals();
 		calculateNormals();
+		calculateTangents();
 		arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
 		arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
 		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
 		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
 		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;						
 		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;						
 		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;										
 		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;										
-				
+		arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true;				
 	}
 	}
 
 
 	void Mesh::createCylinder(Number height, Number radius, int numSegments) {
 	void Mesh::createCylinder(Number height, Number radius, int numSegments) {
@@ -577,11 +584,12 @@ namespace Polycode {
 		
 		
 		
 		
 		calculateNormals();
 		calculateNormals();
+		calculateTangents();
 		arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
 		arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
 		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
 		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
 		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;						
 		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;						
 		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;										
 		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;										
-		
+		arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true;		
 	}
 	}
 	
 	
 	void Mesh::createCone(Number height, Number radius, int numSegments) {
 	void Mesh::createCone(Number height, Number radius, int numSegments) {
@@ -633,11 +641,12 @@ namespace Polycode {
 		
 		
 		
 		
 		calculateNormals();
 		calculateNormals();
+		calculateTangents();
 		arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
 		arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
 		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
 		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
 		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;						
 		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;						
 		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;										
 		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;										
-			
+		arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true;			
 	
 	
 	}
 	}
 
 
@@ -693,10 +702,12 @@ namespace Polycode {
 		}
 		}
 
 
 		calculateNormals();
 		calculateNormals();
+		calculateTangents();
 		arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
 		arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
 		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
 		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
 		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;						
 		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;						
-		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;										
+		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;		
+		arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true;									
 	}
 	}
 	
 	
 	void Mesh::useVertexNormals(bool val) {
 	void Mesh::useVertexNormals(bool val) {
@@ -723,6 +734,32 @@ namespace Polycode {
 		return retVec;
 		return retVec;
 	}
 	}
 	
 	
+	void Mesh::calculateTangents() {
+		for(int i =0; i < polygons.size(); i++) {
+			polygons[i]->calculateTangent();
+		}		
+		/*
+		for(int i=0; i < polygons.size(); i++) {
+			for(int j=0; j < polygons[i]->getVertexCount(); j++) {		
+				Vertex *v =  polygons[i]->getVertex(j);
+
+				Vector3 tangent;		
+				vector<Polygon*> connectedFaces = getConnectedFaces(v);
+				int numConnected = connectedFaces.size();
+				if(numConnected > 2)
+					numConnected = 2;
+				for(int k=0; k < numConnected; k++) {					
+					tangent += connectedFaces[k]->getFaceTangent();
+				}						
+				tangent = tangent / numConnected;
+				tangent.Normalize();
+				v->tangent = tangent;
+			}
+		}		
+		*/
+		arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true;		
+	}
+	
 	void Mesh::calculateNormals(bool smooth, Number smoothAngle) {
 	void Mesh::calculateNormals(bool smooth, Number smoothAngle) {
 		for(int i =0; i < polygons.size(); i++) {
 		for(int i =0; i < polygons.size(); i++) {
 			polygons[i]->calculateNormal();
 			polygons[i]->calculateNormal();
@@ -744,9 +781,9 @@ namespace Polycode {
 				}
 				}
 			}
 			}
 		
 		
-		} 
+		}
 		
 		
-		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;										
+		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;		
 	}
 	}
 	
 	
 	int Mesh::getMeshType() {
 	int Mesh::getMeshType() {
@@ -762,7 +799,8 @@ namespace Polycode {
 		arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
 		arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
 		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
 		arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true;				
 		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;		
 		arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true;		
-		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;								
+		arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;		
+		arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true;								
 	}
 	}
 	
 	
 	
 	

+ 37 - 0
Core/Contents/Source/PolyPolygon.cpp

@@ -56,6 +56,10 @@ Vertex *Polygon::getVertex(unsigned int index) {
 	return vertices[index];
 	return vertices[index];
 }
 }
 
 
+Vector3 Polygon::getFaceTangent() {
+	return tangent;
+}
+
 Vector3 Polygon::getFaceNormal() {
 Vector3 Polygon::getFaceNormal() {
 /*
 /*
 	Vector3 fNormal;
 	Vector3 fNormal;
@@ -113,6 +117,39 @@ void Polygon::calculateNormal() {
 	}
 	}
 }
 }
 
 
+void Polygon::calculateTangent() {
+	if(vertices.size() < 3)
+		return;
+		
+	
+	Vector3 side0 = *vertices[0] - *vertices[1];
+	Vector3 side1 = *vertices[2] - *vertices[0];
+	Vector3 normal = side1.crossProduct(side0);
+	normal.Normalize();
+	Number deltaV0 = vertices[0]->texCoord.y - vertices[1]->texCoord.y;
+	Number deltaV1 = vertices[2]->texCoord.y - vertices[0]->texCoord.y;
+	tangent = side0 * deltaV1 - side1 * deltaV0;	
+	tangent.Normalize();
+	
+	Number deltaU0 = vertices[0]->texCoord.x - vertices[1]->texCoord.x;
+	Number deltaU1 = vertices[2]->texCoord.x - vertices[0]->texCoord.x;
+	Vector3 binormal = side0 * deltaU1 - side1 * deltaU0;
+	binormal.Normalize();
+	Vector3 tangentCross = tangent.crossProduct(binormal);
+
+	if (tangentCross.dot(normal) < 0.0f) {
+		tangent = tangent * -1;
+	}
+
+	for(int i=0; i < vertices.size(); i++) {		
+		vertices[i]->tangent.x = tangent.x;
+		vertices[i]->tangent.y = tangent.y;
+		vertices[i]->tangent.z = tangent.z;		
+	}
+	
+	
+}
+
 Vertex *Polygon::addVertex(Number x, Number y, Number z) {
 Vertex *Polygon::addVertex(Number x, Number y, Number z) {
 	Vertex *vertex = new Vertex(x,y,z);
 	Vertex *vertex = new Vertex(x,y,z);
 	vertices.push_back(vertex);
 	vertices.push_back(vertex);

+ 3 - 0
Core/Contents/Source/PolyResourceManager.cpp

@@ -244,6 +244,9 @@ Resource *ResourceManager::getResource(int resourceType, const String& resourceN
 			return resources[i];
 			return resources[i];
 		}
 		}
 	}
 	}
+	if(resourceType == Resource::RESOURCE_TEXTURE && resourceName != "default.png")
+		return getResource(Resource::RESOURCE_TEXTURE, "default.png");
+		
 	Logger::log("return NULL\n");
 	Logger::log("return NULL\n");
 	// need to add some sort of default resource for each type
 	// need to add some sort of default resource for each type
 	return NULL;
 	return NULL;

+ 3 - 1
Core/Contents/Source/PolySceneMesh.cpp

@@ -193,7 +193,8 @@ void SceneMesh::renderMeshLocally() {
 			}
 			}
 		}
 		}
 		mesh->arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
 		mesh->arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true;		
-		mesh->arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;		
+		mesh->arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true;	
+		mesh->arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true;				
 	}
 	}
 
 
 	if(mesh->useVertexColors) {
 	if(mesh->useVertexColors) {
@@ -202,6 +203,7 @@ void SceneMesh::renderMeshLocally() {
 	 
 	 
 	renderer->pushDataArrayForMesh(mesh, RenderDataArray::VERTEX_DATA_ARRAY);
 	renderer->pushDataArrayForMesh(mesh, RenderDataArray::VERTEX_DATA_ARRAY);
 	renderer->pushDataArrayForMesh(mesh, RenderDataArray::NORMAL_DATA_ARRAY);		
 	renderer->pushDataArrayForMesh(mesh, RenderDataArray::NORMAL_DATA_ARRAY);		
+	renderer->pushDataArrayForMesh(mesh, RenderDataArray::TANGENT_DATA_ARRAY);			
 	renderer->pushDataArrayForMesh(mesh, RenderDataArray::TEXCOORD_DATA_ARRAY);	
 	renderer->pushDataArrayForMesh(mesh, RenderDataArray::TEXCOORD_DATA_ARRAY);	
 	
 	
 	renderer->drawArrays(mesh->getMeshType());
 	renderer->drawArrays(mesh->getMeshType());