Ignore:
Timestamp:
07/05/13 23:44:24 (12 years ago)
Author:
epyon
Message:
  • obj_loader - support for tangent space calculation
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/formats/obj_loader.cc

    r138 r147  
    119119struct mesh_obj_reader : public obj_reader
    120120{
    121         mesh_obj_reader( mesh* m ) : m_mesh( m ), m_position( nullptr ), m_normal( nullptr ), m_tex_coord( nullptr ) {}
     121        mesh_obj_reader( mesh* m ) : m_mesh( m ), m_position( nullptr ), m_normal( nullptr ), m_tex_coord( nullptr ), m_tangent( nullptr ) {}
    122122        virtual std::size_t add_face( uint32* v, uint32* t, uint32* n, size_t count );
     123        virtual void calculate_tangents();
    123124
    124125        vertex_attribute< vec3 >* m_position;
    125126        vertex_attribute< vec3 >* m_normal;
    126127        vertex_attribute< vec2 >* m_tex_coord;
     128        vertex_attribute< vec4 >* m_tangent;
    127129        mesh* m_mesh;
    128130};
     
    169171}
    170172
    171 nv::obj_loader::obj_loader()
    172         : m_mesh( nullptr )
     173// based on http://www.terathon.com/code/tangent.html
     174void mesh_obj_reader::calculate_tangents()
     175{
     176        m_tangent = m_mesh->add_attribute< vec4 >( "tangent" );
     177
     178        std::vector< vec3 >& vp = m_position->get();
     179        std::vector< vec2 >& vt = m_tex_coord->get();
     180        std::vector< vec3 >& vn = m_normal->get();
     181        std::vector< vec4 >& tg = m_tangent->get();
     182
     183        std::size_t count  = vp.size();
     184        std::size_t tcount = count / 3;
     185
     186        std::vector< vec3 > tan1( count );
     187        std::vector< vec3 > tan2( count );
     188        tg.resize( count );
     189
     190        for (std::size_t a = 0; a < tcount; ++a )
     191        {
     192                uint32 i1 = a * 3;
     193                uint32 i2 = a * 3 + 1;
     194                uint32 i3 = a * 3 + 2;
     195
     196                const vec3& v1 = vp[i1];
     197                const vec3& v2 = vp[i2];
     198                const vec3& v3 = vp[i3];
     199
     200                const vec2& w1 = vt[i1];
     201                const vec2& w2 = vt[i2];
     202                const vec2& w3 = vt[i3];
     203
     204                vec3 xyz1 = v2 - v1;
     205                vec3 xyz2 = v3 - v1;
     206                vec2 st1  = w2 - w1;
     207                vec2 st2  = w3 - w1;
     208
     209                float x1 = v2.x - v1.x;
     210                float y1 = v2.y - v1.y;
     211                float z1 = v2.z - v1.z;
     212
     213                float x2 = v3.x - v1.x;
     214                float y2 = v3.y - v1.y;
     215                float z2 = v3.z - v1.z;
     216
     217                float s1 = w2.x - w1.x;
     218                float t1 = w2.y - w1.y;
     219                float s2 = w3.x - w1.x;
     220                float t2 = w3.y - w1.y;
     221
     222                float r = 1.0f / (s1 * t2 - s2 * t1);
     223
     224                vec3 sdir = ( t2 * xyz1 - t1 * xyz2 ) * r;
     225                vec3 tdir = ( s1 * xyz2 - s2 * xyz1 ) * r;
     226
     227                // the += below obviously doesn't make sense in this case, but I'll
     228                // leave it here for when I move to indices
     229                tan1[i1] += sdir;
     230                tan1[i2] += sdir;
     231                tan1[i3] += sdir;
     232
     233                tan2[i1] += tdir;
     234                tan2[i2] += tdir;
     235                tan2[i3] += tdir;
     236        }
     237
     238        for (std::size_t a = 0; a < count; ++a )
     239        {
     240                const vec3& n = vn[a];
     241                const vec3& t = tan1[a];
     242
     243                tg[a] = vec4( glm::normalize(t - n * glm::dot( n, t )),
     244                    (glm::dot(glm::cross(n, t), tan2[a]) < 0.0f) ? -1.0f : 1.0f );
     245        }
     246
     247}
     248
     249nv::obj_loader::obj_loader( bool tangents )
     250        : m_mesh( nullptr ), m_tangents( tangents )
    173251{
    174252
     
    191269        reader.read_stream( sstream );
    192270        m_size = reader.size;
     271        if ( m_tangents )
     272        {
     273                reader.calculate_tangents();
     274        }
    193275        return true;
    194276}
Note: See TracChangeset for help on using the changeset viewer.