Ignore:
Timestamp:
05/16/14 05:48:01 (11 years ago)
Author:
epyon
Message:
  • mesh data interface and usage
  • new wavefront importer (old pending removal)
  • updates to test projects
File:
1 edited

Legend:

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

    r225 r238  
    1111using namespace nv;
    1212
     13struct obj_vertex_vt
     14{
     15        vec3 position;
     16        vec2 texcoord;
     17
     18        obj_vertex_vt( vec3 a_position, vec2 a_texcoord )
     19                : position( a_position ), texcoord( a_texcoord ) {}
     20};
     21
     22struct obj_vertex_vtn
     23{
     24        vec3 position;
     25        vec2 texcoord;
     26        vec3 normal;
     27
     28        obj_vertex_vtn( vec3 a_position, vec2 a_texcoord, vec3 a_normal )
     29                : position( a_position ), texcoord( a_texcoord ), normal( a_normal ) {}
     30};
     31
     32
     33struct obj_vertex_vtnt
     34{
     35        vec3 position;
     36        vec2 texcoord;
     37        vec3 normal;
     38        vec4 tangent;
     39
     40        obj_vertex_vtnt( vec3 a_position, vec2 a_texcoord, vec3 a_normal )
     41                : position( a_position ), texcoord( a_texcoord ), normal( a_normal ) {}
     42};
     43
    1344struct obj_reader
    1445{
     
    2455        obj_reader();
    2556        bool read_stream( std::istream& stream );
    26 
    27         virtual std::size_t add_face( uint32* vi, uint32* ti, uint32* ni, size_t count ) = 0;
     57        virtual size_t add_face( uint32* vi, uint32* ti, uint32* ni, size_t count ) = 0;
     58        virtual size_t raw_size() { return 0; }
     59        virtual const uint8* raw_pointer() { return nullptr; }
     60        virtual void calculate_tangents() {}
     61
    2862        virtual ~obj_reader(){}
    2963};
     
    120154{
    121155        mesh_obj_reader( mesh_data_creator* m ) : m_mesh( m ) {}
    122         virtual std::size_t add_face( uint32* v, uint32* t, uint32* n, size_t count );
     156        virtual std::size_t add_face( uint32* vi, uint32* ti, uint32* ni, size_t count );
    123157        virtual void calculate_tangents();
    124158
     
    238272bool nv::obj_loader::load( stream& source )
    239273{
    240         if ( m_mesh != nullptr )
    241         {
    242                 delete m_mesh;
    243         }
     274        if ( m_mesh != nullptr ) delete m_mesh;
    244275        mesh_data_creator creator;
    245276        mesh_obj_reader reader( &creator );
     
    254285        return true;
    255286}
     287
     288struct mesh_data_reader_vt : public obj_reader
     289{
     290        mesh_data_reader_vt()  {}
     291        virtual std::size_t add_face( uint32* vi, uint32* ti, uint32*, size_t count )
     292        {
     293                if ( count < 3 ) return 0; // TODO : report error?
     294                // TODO : support if normals not present;
     295                std::size_t result = 0;
     296                // Simple triangulation - obj's shouldn't have more than quads anyway
     297                for ( size_t i = 2; i < count; ++i )
     298                {
     299                        result++;
     300                        m_data.emplace_back( v[ vi[ 0 ]   ], t[ ti[ 0   ] ] );
     301                        m_data.emplace_back( v[ vi[ i-1 ] ], t[ ti[ i-1 ] ] );
     302                        m_data.emplace_back( v[ vi[ i ]   ], t[ ti[ i   ] ] );
     303                }
     304                return result;
     305        }
     306        std::vector< obj_vertex_vt > m_data;
     307        virtual size_t raw_size() { return m_data.size() * sizeof( obj_vertex_vt ); }
     308        virtual const uint8* raw_pointer() { return (const uint8*)m_data.data(); }
     309};
     310
     311struct mesh_data_reader_vtn : public obj_reader
     312{
     313        mesh_data_reader_vtn()  {}
     314        virtual std::size_t add_face( uint32* vi, uint32* ti, uint32* ni, size_t count )
     315        {
     316                if ( count < 3 ) return 0; // TODO : report error?
     317                // TODO : support if normals not present;
     318                std::size_t result = 0;
     319                // Simple triangulation - obj's shouldn't have more than quads anyway
     320                for ( size_t i = 2; i < count; ++i )
     321                {
     322                        result++;
     323                        m_data.emplace_back( v[ vi[ 0 ]   ], t[ ti[ 0   ] ], n[ ni[ 0   ] ] );
     324                        m_data.emplace_back( v[ vi[ i-1 ] ], t[ ti[ i-1 ] ], n[ ni[ i-1 ] ] );
     325                        m_data.emplace_back( v[ vi[ i ]   ], t[ ti[ i   ] ], n[ ni[ i   ] ] );
     326                }
     327                return result;
     328        }
     329        std::vector< obj_vertex_vtn > m_data;
     330        virtual size_t raw_size() { return m_data.size() * sizeof( obj_vertex_vtn ); }
     331        virtual const uint8* raw_pointer() { return (const uint8*)m_data.data(); }
     332};
     333
     334struct mesh_data_reader_vtnt : public obj_reader
     335{
     336        mesh_data_reader_vtnt()  {}
     337        virtual std::size_t add_face( uint32* vi, uint32* ti, uint32* ni, size_t count )
     338        {
     339                if ( count < 3 ) return 0; // TODO : report error?
     340                // TODO : support if normals not present;
     341                std::size_t result = 0;
     342                // Simple triangulation - obj's shouldn't have more than quads anyway
     343                for ( size_t i = 2; i < count; ++i )
     344                {
     345                        result++;
     346                        m_data.emplace_back( v[ vi[ 0 ]   ], t[ ti[ 0   ] ], n[ ni[ 0   ] ] );
     347                        m_data.emplace_back( v[ vi[ i-1 ] ], t[ ti[ i-1 ] ], n[ ni[ i-1 ] ] );
     348                        m_data.emplace_back( v[ vi[ i ]   ], t[ ti[ i   ] ], n[ ni[ i   ] ] );
     349                }
     350                return result;
     351        }
     352        std::vector< obj_vertex_vtnt > m_data;
     353        virtual size_t raw_size() { return m_data.size() * sizeof( obj_vertex_vtnt ); }
     354        virtual const uint8* raw_pointer() { return (const uint8*)m_data.data(); }
     355
     356        // based on http://www.terathon.com/code/tangent.html
     357        void calculate_tangents()
     358        {
     359                //              const std::vector< vec3 >& vp = m_mesh->get_positions();
     360                //              const std::vector< vec2 >& vt = m_mesh->get_texcoords();
     361                //              const std::vector< vec3 >& vn = m_mesh->get_normals();
     362                //              std::vector< vec3 >& tg = m_mesh->get_tangents();
     363
     364                size_t count  = m_data.size();
     365                size_t tcount = count / 3;
     366
     367                std::vector< vec3 > tan1( count );
     368                std::vector< vec3 > tan2( count );
     369
     370                for (size_t a = 0; a < tcount; ++a )
     371                {
     372                        size_t i1 = a * 3;
     373                        size_t i2 = a * 3 + 1;
     374                        size_t i3 = a * 3 + 2;
     375                        obj_vertex_vtnt& vtx1 = m_data[ i1 ];
     376                        obj_vertex_vtnt& vtx2 = m_data[ i2 ];
     377                        obj_vertex_vtnt& vtx3 = m_data[ i3 ];
     378
     379                        // TODO: simplify
     380                        vec3 xyz1 = vtx2.position - vtx1.position;
     381                        vec3 xyz2 = vtx3.position - vtx1.position;
     382                        //vec2 st1  = w2 - w1;
     383                        //vec2 st2  = w3 - w1;
     384
     385                        float s1 = vtx2.texcoord.x - vtx1.texcoord.x;
     386                        float t1 = vtx2.texcoord.y - vtx1.texcoord.y;
     387                        float s2 = vtx3.texcoord.x - vtx1.texcoord.x;
     388                        float t2 = vtx3.texcoord.y - vtx1.texcoord.y;
     389
     390                        float stst = s1 * t2 - s2 * t1;
     391                        float r = 0.0f;
     392                        if (stst > 0.0f || stst < 0.0f) r = 1.0f / stst;
     393
     394                        vec3 sdir = ( t2 * xyz1 - t1 * xyz2 ) * r;
     395                        vec3 tdir = ( s1 * xyz2 - s2 * xyz1 ) * r;
     396
     397                        // the += below obviously doesn't make sense in this case, but I'll
     398                        // leave it here for when I move to indices
     399                        tan1[i1] += sdir;
     400                        tan1[i2] += sdir;
     401                        tan1[i3] += sdir;
     402
     403                        // tan2 not needed anymore??
     404                        tan2[i1] += tdir;
     405                        tan2[i2] += tdir;
     406                        tan2[i3] += tdir;
     407                }
     408
     409                for (std::size_t a = 0; a < count; ++a )
     410                {
     411                        const vec3& n = m_data[a].normal;
     412                        const vec3& t = tan1[a];
     413                        if ( ! (t.x == 0.0f && t.y == 0.0f && t.z == 0.0f) )
     414                        {
     415                                m_data[a].tangent    = vec4( glm::normalize(t - n * glm::dot( n, t )), 0.0f );
     416                                m_data[a].tangent[3] = (glm::dot(glm::cross(n, t), tan2[a]) < 0.0f) ? -1.0f : 1.0f;
     417                        }
     418                }
     419
     420        }
     421
     422
     423};
     424
     425nv::wavefront_loader::wavefront_loader( bool normals /*= true*/, bool tangents /*= false */ )
     426        : m_normals( normals ), m_tangents( tangents ), m_mesh( nullptr )
     427{
     428        if ( normals )
     429        {
     430                if ( tangents )
     431                        m_descriptor.initialize<obj_vertex_vtnt>();
     432                else
     433                        m_descriptor.initialize<obj_vertex_vtn>();
     434        }
     435        else
     436                m_descriptor.initialize<obj_vertex_vt>();
     437}
     438
     439bool nv::wavefront_loader::load( stream& source )
     440{
     441        if ( m_mesh ) delete m_mesh;
     442       
     443        obj_reader* reader = nullptr;
     444        if ( m_normals )
     445        {
     446                if ( m_tangents )
     447                        reader = new mesh_data_reader_vtnt();
     448                else
     449                        reader = new mesh_data_reader_vtn();
     450        }
     451        else
     452                reader = new mesh_data_reader_vt();
     453        std_stream sstream( &source );
     454        reader->read_stream( sstream );
     455
     456        if ( m_tangents )
     457        {
     458                reader->calculate_tangents();
     459        }
     460       
     461
     462        mesh_raw_channel* channel = new mesh_raw_channel();
     463        nv::uint8* data = nullptr;
     464        if ( reader->raw_size() > 0 )
     465        {
     466                data = new uint8[ reader->raw_size() ];
     467                std::copy_n( reader->raw_pointer(), reader->raw_size(), data );
     468        }
     469        channel->data  = data;
     470        channel->desc  = m_descriptor;
     471        channel->count = reader->size * 3;
     472        channel->size  = reader->raw_size();
     473        delete reader;
     474
     475        m_mesh = new mesh_data();
     476        m_mesh->add_channel( channel );
     477        return true;
     478
     479}
     480
     481mesh_data* nv::wavefront_loader::release_mesh_data()
     482{
     483        mesh_data* result = m_mesh;
     484        m_mesh = nullptr;
     485        return result;
     486}
     487
     488nv::wavefront_loader::~wavefront_loader()
     489{
     490        if ( m_mesh ) delete m_mesh;
     491}
Note: See TracChangeset for help on using the changeset viewer.