/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #include "core/geometry.h" #include "log/log.h" using namespace GS::Core; //------------------------------------------------------------------------------ bool Geometry::ComputePolygonTangent(uint uv_index, bool force) { if (!pol.GetCount() || !vtx.GetCount()) return false; if (!force && (pol_tangent.GetCount() == pol.GetCount())) return true; if (!ComputePolygonNormal()) return false; if ((uv_index >= __UV_PER_GEOMETRY__) || !uv[uv_index]) return false; // Allocate polygon tangents. if (!pol_tangent.Allocate(pol.GetCount())) __ERR__(__LOG_W__ << "Geometry::ComputePolygonTangent() failed to allocate buffer!\n", false) Array pol_index; ComputePolygonIndex(pol_index); for (uint c = 0; c < pol.GetCount(); c++) if (pol[c].vtx_count > 2) { // Compute tangent frame for this polygon. Vector4 side_0 = vtx[pol[c].binding[0]] - vtx[pol[c].binding[1]], side_1 = vtx[pol[c].binding[2]] - vtx[pol[c].binding[1]]; float delta_U_0 = uv[uv_index][pol_index[c] + 0].x - uv[uv_index][pol_index[c] + 1].x, delta_U_1 = uv[uv_index][pol_index[c] + 2].x - uv[uv_index][pol_index[c] + 1].x, delta_V_0 = uv[uv_index][pol_index[c] + 0].y - uv[uv_index][pol_index[c] + 1].y, delta_V_1 = uv[uv_index][pol_index[c] + 2].y - uv[uv_index][pol_index[c] + 1].y; Vector4 T = (side_0 * delta_V_1 - side_1 * delta_V_0).Normalized().Reversed(), B = (side_0 * delta_U_1 - side_1 * delta_U_0).Normalized(); if (T.Cross(B).Dot(pol_normal[c]) < 0) { T.Reverse(); B.Reverse(); } pol_tangent[c].B = B; pol_tangent[c].T = T; } return true; } bool Geometry::ComputeVertexTangent(bool rev_t, bool rev_b, bool force) { if (!pol.GetCount() || !vtx.GetCount()) return false; if (!force && (vtx_tangent.GetCount() == binding.GetCount())) return true; if (!ComputeVertexNormal() || !ComputePolygonTangent()) return false; Array vtx_to_pol; ComputeVertexToPolygon(vtx_to_pol); // Allocate full blown edge normal array. if (vtx_tangent.Allocate(binding.GetCount())) for (uint cp = 0, ttp = 0; cp < pol.GetCount(); ++cp) for (uint cv = 0; cv < pol[cp].vtx_count; ++cv) { uint gv = pol[cp].binding[cv]; Vector4 T(0, 0, 0), B(0, 0, 0); for (uint cg = 0; cg < vtx_to_pol[gv].pol_count; cg++) { Vector4 _T = pol_tangent[vtx_to_pol[gv].pol_index[cg]].T, _B = pol_tangent[vtx_to_pol[gv].pol_index[cg]].B; if (pol_tangent[cp].T.Dot(_T) < 0.f) _T = _T.Reversed(); if (pol_tangent[cp].B.Dot(_B) < 0.f) _B = _B.Reversed(); T += _T; B += _B; } T -= vtx_normal[ttp] * vtx_normal[ttp].Dot(T); T = T.Normalized(); B = vtx_normal[ttp].Cross(T); vtx_tangent[ttp].T = rev_t ? T.Reversed() : T; vtx_tangent[ttp].B = rev_b ? B.Reversed() : B; ++ttp; } return true; } //------------------------------------------------------------------------------