void JsonSerializer::deserialize(float& value, float default_value) { if (!m_is_string_token) { value = tokenToFloat(); } else { value = default_value; } deserializeToken(); }
void JsonSerializer::deserializeArrayItem(float& value, float default_value) { deserializeArrayComma(); if (m_is_string_token) { value = default_value; } else { value = tokenToFloat(); } deserializeToken(); }
void JsonSerializer::deserialize(const char* label, float& value, float default_value) { deserializeLabel(label); if (!m_is_string_token) { value = tokenToFloat(); deserializeToken(); } else { value = default_value; } }
// ============================================== // // Load a mesh material from a file t_error ResourceManager::LoadMeshMaterial (const char* filename, Mesh* mesh) { // load the mesh material file ifstream fileHandle( filename ); if ( !fileHandle.is_open() ) { Log( str( format( "Error opening material file (%1%)" ) % filename ), LOG_ERROR ); throw BadFileException(filename); } // parse mtl file string buffer; while ( fileHandle.good() ) { getline( fileHandle, buffer ); if ( buffer.empty() ) continue; // setup tokenizer CharSeparator tokenSeparator( " \t" ); CharTokenizer tokens( buffer, tokenSeparator ); CharTokenizer::iterator token = tokens.begin(); CharTokenizer::iterator lastToken = tokens.end(); // Log ( str( format( "buffer: %1%" ) % (buffer) ) ); // Log ( str( format( "token: %1%" ) % (*token) ) ); if ( (*token)[0] == '#' ) { continue; } // comment else if ( (*token) == "Ka" ) { // ambient colour float r = tokenToFloat(++token); float g = tokenToFloat(++token); float b = tokenToFloat(++token); Log( str( format( "Ka: %1%,%2%,%3%" ) % r % g % b ), LOG_DEBUG ); mesh->color_ambient = fTriple( r, g, b ); } else if ( (*token) == "Kd" ) { // diffuse colour float r = tokenToFloat(++token); float g = tokenToFloat(++token); float b = tokenToFloat(++token); Log( str( format( "Kd: %1%,%2%,%3%" ) % r % g % b ), LOG_DEBUG ); mesh->color_diffuse = fTriple( r, g, b ); } else if ( (*token) == "Ks" ) { // specular colour float r = tokenToFloat(++token); float g = tokenToFloat(++token); float b = tokenToFloat(++token); Log( str( format( "Ks: %1%,%2%,%3%" ) % r % g % b ), LOG_DEBUG ); mesh->color_specular = fTriple( r, g, b ); } else if ( (*token) == "map_Kd" ) { // texture // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // TODO: load texture in resource mgr; use a lookup table to find the gl id and point to that string texFilename = *(++token); mesh->loadTexture( texFilename.c_str(), MeshRenderData::MESH_RENDER_TEXTURE ); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! } else if ( (*token) == "bump" ) { // bumpmap string texFilename = *(++token); mesh->loadTexture( texFilename.c_str(), MeshRenderData::MESH_RENDER_TEXBUMP ); } else { Log ( str( format( "Unknown line: %1%" ) % buffer ) ); } } fileHandle.close(); return NO_ERROR; }
// ============================================== // // Load a mesh from a file Entity* ResourceManager::LoadMesh (RenderGroup* renderer, const char* filename) { // load the mesh file ifstream fileHandle( filename ); if ( !fileHandle.is_open() ) { Log( str( format( "Error opening mesh file (%1%)" ) % filename ), LOG_ERROR ); throw BadFileException(filename); } // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // TODO: store mesh elsewhere Mesh* mesh; if (renderer) { mesh = new Mesh(true); mesh->renderData->gl = renderer->program->programid; glGenTextures(2, mesh->renderData->textures); } else { mesh = new Mesh(false); } // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // parse obj file string buffer; while ( fileHandle.good() ) { getline( fileHandle, buffer ); if ( buffer.empty() ) continue; // setup tokenizer CharSeparator tokenSeparator( " \t" ); CharTokenizer tokens( buffer, tokenSeparator ); CharTokenizer::iterator token = tokens.begin(); CharTokenizer::iterator lastToken = tokens.end(); // Log ( str( format( "buffer: %1%" ) % (buffer) ) ); // Log ( str( format( "token: %1%" ) % (*token) ) ); if ( (*token)[0] == '#' ) { continue; } // comment else if ( (*token) == "v" ) { // vertex float x = tokenToFloat(++token); float y = tokenToFloat(++token); float z = tokenToFloat(++token); mesh->addVertex( x, y, z ); } else if ( (*token) == "vn" ) { // vertex normal float x = tokenToFloat(++token); float y = tokenToFloat(++token); float z = tokenToFloat(++token); mesh->addVertexNormal( x, y, z ); } else if ( *token == "vt" ) { // vertex texcoord float s = tokenToFloat(++token); float t = tokenToFloat(++token); mesh->addVertexTex( s, t ); } else if ( *token == "f" ) { // face /* each face contains 3 or more vertices * * Vertex only format is: v1 v2 v3 ... * Vertex/Texture format: v1/vt1 v2/vt2 v3/vt3 ... * Vertex/Tex/Norm format: v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3 ... * Vertex/Normal format: v1//vn1 v2//vn2 v3//vn3 ... * **/ (++token); ushort point_index = 0; // this helps with auto-face texcoord deciding (in case no UV mapping is specified) short v_index, n_index, t_index; do { // setup sub-tokenizer (vert, norm, texcoord) v_index = -1, n_index = -1, t_index = -1; // NOTE: -1 means nonexistent; do NOT use ushort since 0 is a legal index CharTokenizer v_indices( (*token), CharSeparator("/ ","",boost::keep_empty_tokens) ); CharTokenizer::iterator index = v_indices.begin(); for (uchar tokenIndex=0; (index) != v_indices.end() && tokenIndex <= 2 ; ++tokenIndex, ++index ) { if ( (*index).empty() ) continue; switch (tokenIndex) { case 0: // Vertex Index // Log( str( format( "Face Index: %1%" ) % tokenToUShort( index ) ) ); v_index = tokenToUShort( index ) - 1; break; case 1: // Texcoord Index // Log( str( format( "Tex Index: %1%" ) % tokenToUShort( index ) ) ); t_index = tokenToUShort( index ) -1; break; case 2: // Norm Index // Log( str( format( "Norm Index: %1%" ) % tokenToUShort( index ) ) ); n_index = tokenToUShort( index ) -1; break; } } // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // if no texcoord specified then create one // TODO: this assumes we're running quads, provide a NON-HARDCODED solution if ( t_index == -1 ) { if ( mesh->texcoords.empty() ) { float top = 0.0f, bottom = 1.0f; // TODO: test st coords for correct top/bottom mesh->texcoords.push_back( 1.0f ); // bottom right mesh->texcoords.push_back( bottom ); mesh->texcoords.push_back( 1.0f ); // top right mesh->texcoords.push_back( top ); mesh->texcoords.push_back( 0.0f ); // top left mesh->texcoords.push_back( top ); mesh->texcoords.push_back( 0.0f ); // bottom left mesh->texcoords.push_back( bottom ); } t_index = point_index % 4; } // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! mesh->pushVertex( v_index, t_index, n_index ); point_index++; } while( (++token) != tokens.end() ); if ( point_index == 3 ) { // tri-face; since we're expecting quads just overlap the 2 end points mesh->pushVertex( v_index, t_index, n_index ); } } else if ( *token == "mtllib" ) { // material file // TODO: test that this will work on Windows (\\ path end could return only \ which may break the mtl filename) ushort path_ending = string( filename ).find_last_of( "/\\" ) + 1; // works for /home/user/.. or c:\\programfiles\\.. string mtlFilename = string( filename ).substr( 0, path_ending ).append( *(++token) ); // load material file if ( LoadMeshMaterial( mtlFilename.c_str(), mesh ) & ERROR ) { Log( str( format( "Error opening material file (%1%)" ) % mtlFilename ), LOG_ERROR ); throw BadFileException(mtlFilename); } Log( str( format( "Loaded material file (%1%)" ) % mtlFilename ), LOG_INFO ); } else { Log ( str( format( "Unknown line: %1%" ) % buffer ) ); } } fileHandle.close(); // finish the entity construction mesh->setupRenderData(); Entity* entity = new Entity(); entity->mesh = mesh; entity->updateAABB(); world->entities.push_back(entity); if (renderer) renderer->entities.push_back(entity); return entity; }