Exemplo n.º 1
0
void Style::addData(TileData& _data, MapTile& _tile, const MapProjection& _mapProjection) {
    onBeginBuildTile(_tile);

    std::shared_ptr<VboMesh> mesh(newMesh());

    for (auto& layer : _data.layers) {

        // Skip any layers that this style doesn't have a rule for
        auto it = m_layers.begin();
        while (it != m_layers.end() && it->first != layer.name) { ++it; }
        if (it == m_layers.end()) { continue; }

        // Loop over all features
        for (auto& feature : layer.features) {

            /*
             * TODO: do filter evaluation for each feature for sublayer!
             *     construct a unique ID for a the set of filters matched
             *     use this ID pass to the style's parseStyleParams method to construct styleParam cache
             *     NOTE: for the time being use layerName as ID for cache
             */

            feature.props.numericProps["zoom"] = _tile.getID().z;

            switch (feature.geometryType) {
                case GeometryType::POINTS:
                    // Build points
                    for (auto& point : feature.points) {
                        buildPoint(point, parseStyleParams(it->first, it->second), feature.props, *mesh);
                    }
                    break;
                case GeometryType::LINES:
                    // Build lines
                    for (auto& line : feature.lines) {
                        buildLine(line, parseStyleParams(it->first, it->second), feature.props, *mesh);
                    }
                    break;
                case GeometryType::POLYGONS:
                    // Build polygons
                    for (auto& polygon : feature.polygons) {
                        buildPolygon(polygon, parseStyleParams(it->first, it->second), feature.props, *mesh);
                    }
                    break;
                default:
                    break;
            }
        }
    }

    onEndBuildTile(_tile, mesh);

    if (mesh->numVertices() == 0) {
        mesh.reset();
    } else {
        mesh->compileVertexBuffer();

        _tile.addGeometry(*this, mesh);
    }
}
Exemplo n.º 2
0
int init( void )
{
    // general settings
    srand( time( NULL ) );
    glClearColor( skyColor.x, skyColor.y, skyColor.z, 1.0 );
    glEnable( GL_DEPTH_TEST );
    glEnable( GL_TEXTURE_3D );
    glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
    glPixelStorei( GL_PACK_ALIGNMENT, 1 );
    glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
    
    // set up data and shaders
    for( int y = 0; y < 3; ++y )
    {
        for( int x = 0; x < 3; ++x )
        {
            newMesh( x, y, LEFT | DOWN );
        }
    }
    for( int y = 0; y < 3; ++y )  // normals must be calculated AFTER all vertices are set
    {
        for( int x = 0; x < 3; ++x )
        {
            createMeshNormals( x, y );
        }
    }
    resetView();
    shaderProgram = InitShader( "vert.glsl", "frag.glsl" );
    
    // buffer vertex and index data
    glGenBuffers( 9, (GLuint*)pointBuffer );
    glGenBuffers( 9, (GLuint*)indexBuffer );
    for( int x = 0; x < 3; ++x )
    {
        for( int y = 0; y < 3; ++y )
        {
            bufferData( x, y );
        }
    }
    
    // create ground texture
    createAndBufferTexture();
    
    // connect vertex attributes
    vPositionLoc = glGetAttribLocation( shaderProgram, "a_vPosition" );
    glEnableVertexAttribArray( vPositionLoc );
    vNormalLoc = glGetAttribLocation( shaderProgram, "a_vNormal" );
    glEnableVertexAttribArray( vNormalLoc );
    
    // get location of uniforms
    maxHeightLoc = glGetUniformLocation( shaderProgram, "u_fMaxHeight" );
    mvMatrixLoc = glGetUniformLocation( shaderProgram, "u_mv_Matrix" );
    
    glUniform1f( maxHeightLoc, maxHeight );
    
    return 1;
}
Exemplo n.º 3
0
MeshLib::NodePartitionedMesh* NodePartitionedMeshReader::readBinary(
    const std::string &file_name_base)
{
    //----------------------------------------------------------------------------------
    // Read headers
    const std::string fname_header = file_name_base +  "_partitioned_msh_";
    const std::string fname_num_p_ext = std::to_string(_mpi_comm_size) + ".bin";

    if (!readBinaryDataFromFile(fname_header + "cfg" + fname_num_p_ext,
        static_cast<MPI_Offset>(
            static_cast<unsigned>(_mpi_rank) * sizeof(_mesh_info)),
        MPI_LONG, _mesh_info))
        return nullptr;

    //----------------------------------------------------------------------------------
    // Read Nodes
    std::vector<NodeData> nodes(_mesh_info.nodes);

    if (!readBinaryDataFromFile(fname_header + "nod" + fname_num_p_ext,
        static_cast<MPI_Offset>(_mesh_info.offset[2]), _mpi_node_type, nodes))
        return nullptr;

    std::vector<MeshLib::Node*> mesh_nodes;
    std::vector<unsigned long> glb_node_ids;
    setNodes(nodes, mesh_nodes, glb_node_ids);

    //----------------------------------------------------------------------------------
    // Read non-ghost elements
    std::vector<unsigned long> elem_data(
        _mesh_info.regular_elements + _mesh_info.offset[0]);
    if (!readBinaryDataFromFile(fname_header + "ele" + fname_num_p_ext,
        static_cast<MPI_Offset>(_mesh_info.offset[3]), MPI_LONG, elem_data))
        return nullptr;

    std::vector<MeshLib::Element*> mesh_elems(
        _mesh_info.regular_elements + _mesh_info.ghost_elements);
    setElements(mesh_nodes, elem_data, mesh_elems);

    //----------------------------------------------------------------------------------
    //Read ghost element
    std::vector<unsigned long> ghost_elem_data(
        _mesh_info.ghost_elements + _mesh_info.offset[1]);

    if (!readBinaryDataFromFile(fname_header + "ele_g" + fname_num_p_ext,
        static_cast<MPI_Offset>(_mesh_info.offset[4]), MPI_LONG, ghost_elem_data))
        return nullptr;

    const bool process_ghost = true;
    setElements(mesh_nodes, ghost_elem_data, mesh_elems, process_ghost);

    //----------------------------------------------------------------------------------
    return newMesh(BaseLib::extractBaseName(file_name_base),
               mesh_nodes, glb_node_ids, mesh_elems);
}
Exemplo n.º 4
0
void SpeckleyElements::buildMeshes()
{
    // build a new mesh containing only the required nodes
    if (numElements > 0) {
        if (nodeMesh && nodeMesh->getNumNodes() > 0) {
            SpeckleyNodes_ptr newMesh(new SpeckleyNodes(nodeMesh, nodes, name));
            nodeMesh.swap(newMesh);
        } else {
            nodeMesh.reset(new SpeckleyNodes(originalMesh, nodes, name));
        }
#ifdef _DEBUG
        cout << nodeMesh->getName() << " has " << nodeMesh->getNumNodes()
            << " nodes and " << numElements << " elements" << endl;
#endif
    }
}
Exemplo n.º 5
0
triMeshT* a3dsCreateMesh(const a3dsDataT* a3ds, const string* object_name) {
    const a3dsObjectDataT* o = a3dsGetObjectData(a3ds, object_name);

    if (!o || !o->mesh)
        return (NULL);

    triMeshT* mesh  = newMesh(o->mesh->num_tris*3, o->mesh->num_tris);
    triT*     tris  = meshTrisPtr (mesh);
    vertexT*  verts = meshVertsPtr(mesh);

    // We separate the triangles so that none of them share the same vertices.
    for (int i = 0; i < o->mesh->num_tris; i++) {
        tris[i] = (triT) { i*3, i*3+1, i*3+2 };
        
        int v0 = o->mesh->tris[i].v0,
            v1 = o->mesh->tris[i].v1,
            v2 = o->mesh->tris[i].v2;

        if (o->mesh->smoothing_groups) verts->k = o->mesh->smoothing_groups[i];
        if (o->mesh->vert_uv) verts->uv = *(vec2*)&o->mesh->vert_uv[v0];
        (verts++)->p = *(vec3*)&o->mesh->vert_pos[v0];

        if (o->mesh->smoothing_groups) verts->k = o->mesh->smoothing_groups[i];
        if (o->mesh->vert_uv) verts->uv = *(vec2*)&o->mesh->vert_uv[v1];
        (verts++)->p = *(vec3*)&o->mesh->vert_pos[v1];

        if (o->mesh->smoothing_groups) verts->k = o->mesh->smoothing_groups[i];
        if (o->mesh->vert_uv) verts->uv = *(vec2*)&o->mesh->vert_uv[v2];
        (verts++)->p = *(vec3*)&o->mesh->vert_pos[v2];
    }

    calcSmoothNormals(mesh);
    updateMesh(mesh);

    return (mesh);
}
Exemplo n.º 6
0
void Style::buildFeature(Tile& _tile, const Feature& _feat, const DrawRule& _rule) const {

    if (!checkRule(_rule)) { return; }

    bool visible;
    if (_rule.get(StyleParamKey::visible, visible) && !visible) {
        return;
    }

    auto& mesh = _tile.getMesh(*this);

    if (!mesh) {
        mesh.reset(newMesh());
    }

    switch (_feat.geometryType) {
        case GeometryType::points:
            for (auto& point : _feat.points) {
                buildPoint(point, _rule, _feat.props, *mesh, _tile);
            }
            break;
        case GeometryType::lines:
            for (auto& line : _feat.lines) {
                buildLine(line, _rule, _feat.props, *mesh, _tile);
            }
            break;
        case GeometryType::polygons:
            for (auto& polygon : _feat.polygons) {
                buildPolygon(polygon, _rule, _feat.props, *mesh, _tile);
            }
            break;
        default:
            break;
    }

}
Exemplo n.º 7
0
AS3_Val initializeMesh( void * self, AS3_Val args )
{
	Mesh         * mesh;

	Texture      * * tp;
	Material     * * mp;

	unsigned int   vl, fl, i, * fs;

	int          * rmp;

	float        * vs;

	Vector3D     * * vp;

	Vector       * uvp;

	AS3_ArrayValue( args, "PtrType, PtrType, PtrType, PtrType, PtrType, PtrType, IntType, IntType",& vs, & fs, & uvp, & mp, & tp, & rmp, & vl, & fl );

	mesh = newMesh( vl, fl );

	for( i = 0; i < vl; i ++ )
	{
		mesh_push_vertex( mesh, vs[i * 3], vs[i * 3 + 1], vs[i * 3 + 2] );
	}

	//free( vs );

	for( i = 0; i < fl; i ++ )
	{
		mesh_push_triangle( 
			mesh,
			(* mesh -> vertices) + fs[i * 3], 
			(* mesh -> vertices) + fs[i * 3 + 1], 
			(* mesh -> vertices) + fs[i * 3 + 2],
			uvp + i * 3    ,
			uvp + i * 3 + 1,
			uvp + i * 3 + 2,
			mp[i],
			tp[i],
			rmp[i] );
	}

	mesh_updateFaces(mesh);
	mesh_updateVertices(mesh);
	//free( fs );

	//free( rmp );

	if( ( vp = ( Vector3D * *   )malloc( sizeof( Vector3D * ) * mesh -> nVertices ) ) == NULL )
	{
		return AS3_Array( "PtrType, PtrType, PtrType, PtrType, PtrType, PtrType, PtrType, PtrType, PtrType, PtrType, PtrType, PtrType, PtrType",
							mesh,
							& mesh->lightEnable,
							& mesh->fogEnable,
							& mesh->useMipmap,
							//& mesh->terrainTrace,
							& mesh->mip_dist,
							& mesh->v_dirty, 
							& mesh->octree_depth,
							& mesh->addressMode,
							& mesh->texTransform->rotation,
							mesh->texTransform->offset,
							mesh->texTransform->scale,
							& mesh->texTransformDirty,
							& mesh->hit,
							& mesh->skinMeshController,
							mesh->octree->data->aabb);
	}

	for( i = 0; i < mesh -> nVertices; i ++ )
	{
		vp[i] = mesh -> vertices[i]->position;
	}

	return AS3_Array( "PtrType, PtrType, PtrType, PtrType, PtrType, PtrType, PtrType, PtrType, PtrType, PtrType, PtrType, PtrType, PtrType, PtrType, PtrType",
						mesh,
						& mesh->lightEnable,
						& mesh->fogEnable,
						& mesh->useMipmap,
						//& mesh->terrainTrace,
						& mesh->mip_dist,
						& mesh->v_dirty,
						& mesh->octree_depth,
						& mesh->addressMode,
						& mesh->texTransform->rotation, 
						mesh->texTransform->offset,
						mesh->texTransform->scale,
						& mesh->texTransformDirty,
						& mesh->hit,
						& mesh->skinMeshController,
						mesh->octree->data->aabb,
						& vp);
}
Exemplo n.º 8
0
    bool ModelDefinition::Deserialize(Deserializer &deserializer)
    {
        // Clear everything.
        this->ClearMeshes();
        this->ClearBones();
        this->ClearAnimations(true);        // <-- 'true' = clear animation segments, too.
        this->ClearConvexHulls();


        // We keep looping until we hit the null or unknown chunk.
        Serialization::ChunkHeader header;
        while (deserializer.Peek(&header, sizeof(header)) == sizeof(header))
        {
            bool finished = false;

            switch (header.id)
            {
            case Serialization::ChunkID_Model_Bones:
                {
                    deserializer.Seek(sizeof(header));

                    if (header.version == 1)
                    {
                        uint32_t boneCount;
                        deserializer.Read(boneCount);

                        for (uint32_t iBone = 0; iBone < boneCount; ++iBone)
                        {
                            // Name.
                            String name;
                            deserializer.ReadString(name);

                            // Local transform.
                            glm::vec3 position;
                            glm::quat rotation;
                            glm::vec3 scale;

                            deserializer.Read(position);
                            deserializer.Read(rotation);
                            deserializer.Read(scale);

                            // 4x4 offset matrix.
                            glm::mat4 offsetMatrix;
                            deserializer.Read(offsetMatrix);


                            auto bone = new Bone;
                            bone->SetName(name.c_str());
                            bone->SetPosition(position);
                            bone->SetRotation(rotation);
                            bone->SetScale(scale);
                            bone->SetOffsetMatrix(offsetMatrix);
                            this->AddBone(bone);


                            // We need to create a channel for this bone. We then need to map that channel to a bone.
                            auto &channel = m_animation.CreateChannel();
                            this->animationChannelBones.Add(bone, &channel);
                        }


                        // Parents.
                        auto boneParentIndices = static_cast<uint32_t*>(malloc(boneCount * sizeof(uint32_t)));
                        deserializer.Read(boneParentIndices, boneCount * sizeof(uint32_t));

                        for (uint32_t iBone = 0; iBone < boneCount; ++iBone)
                        {
                            uint32_t parentIndex = boneParentIndices[iBone];

                            if (parentIndex != static_cast<uint32_t>(-1))
                            {
                                m_bones[parentIndex]->AttachChild(*m_bones[iBone]);
                            }
                        }

                        free(boneParentIndices);
                    }
                    else
                    {
                        // Unsupported Version.
                        deserializer.Seek(header.sizeInBytes);
                    }

                    break;
                }

            case Serialization::ChunkID_Model_Meshes:
                {
                    deserializer.Seek(sizeof(header));

                    if (header.version == 1)
                    {
                        uint32_t meshCount;
                        deserializer.Read(meshCount);

                        for (uint32_t iMesh = 0; iMesh < meshCount; ++iMesh)
                        {
                            ModelDefinition::Mesh newMesh(m_context);

                            // Name.
                            deserializer.ReadString(newMesh.name);


                            // Material
                            String materialName;
                            deserializer.ReadString(materialName);

                            newMesh.material = m_context.GetMaterialLibrary().Create(materialName.c_str());



                            // Geometry
                            VertexFormat vertexFormat;
                            vertexFormat.Deserialize(deserializer);
                            newMesh.geometry = Renderer::CreateVertexArray(VertexArrayUsage_Static, vertexFormat);
                            
                            // Vertices.
                            uint32_t vertexCount;
                            deserializer.Read(vertexCount);

                            if (vertexCount > 0)
                            {
                                newMesh.geometry->SetVertexData(nullptr, static_cast<size_t>(vertexCount));
                                auto vertexData = newMesh.geometry->MapVertexData();
                                {
                                    deserializer.Read(vertexData, vertexCount * vertexFormat.GetSizeInBytes());
                                }
                                newMesh.geometry->UnmapVertexData();
                            }

                            // Indices.
                            uint32_t indexCount;
                            deserializer.Read(indexCount);

                            if (indexCount > 0)
                            {
                                newMesh.geometry->SetIndexData(nullptr, static_cast<size_t>(indexCount));
                                auto indexData = newMesh.geometry->MapIndexData();
                                {
                                    deserializer.Read(indexData, indexCount * sizeof(uint32_t));
                                }
                                newMesh.geometry->UnmapIndexData();
                            }



                            // Skinning Vertex Attributes
                            uint32_t skinningVertexAttributeCount;
                            deserializer.Read(skinningVertexAttributeCount);

                            if (skinningVertexAttributeCount > 0)
                            {
                                newMesh.skinningVertexAttributes = new SkinningVertexAttribute[skinningVertexAttributeCount];

                                auto counts = static_cast<uint16_t*>(malloc(skinningVertexAttributeCount * sizeof(uint16_t)));
                                deserializer.Read(counts, skinningVertexAttributeCount * sizeof(uint16_t));

                                uint32_t totalBoneWeights;
                                deserializer.Read(totalBoneWeights);

                                auto boneWeights = static_cast<BoneWeightPair*>(malloc(totalBoneWeights * sizeof(BoneWeightPair)));
                                deserializer.Read(boneWeights, totalBoneWeights * sizeof(BoneWeightPair));


                                auto currentBoneWeight = boneWeights;
                                for (uint32_t iVertex = 0; iVertex < skinningVertexAttributeCount; ++iVertex)
                                {
                                    auto count = counts[iVertex];

                                    // Here we allocate the buffer for the bones. We trick the vector here by modifying attributes directly.
                                    newMesh.skinningVertexAttributes[iVertex].bones.Reserve(count);
                                    newMesh.skinningVertexAttributes[iVertex].bones.count = count;

                                    for (uint16_t iBone = 0; iBone < count; ++iBone)
                                    {
                                        newMesh.skinningVertexAttributes[iVertex].bones[iBone] = *currentBoneWeight++;
                                    }
                                }

                                free(counts);
                                free(boneWeights);
                            }


                            // Uniforms.
                            newMesh.defaultUniforms.Deserialize(deserializer);


                            // Finally, add the mesh.
                            this->AddMesh(newMesh);
                        }
                    }
                    else
                    {
                        // Unsupported Version.
                        deserializer.Seek(header.sizeInBytes);
                    }

                    break;
                }

            case Serialization::ChunkID_Model_Animation:
                {
                    deserializer.Seek(sizeof(header));

                    if (header.version == 1)
                    {
                        uint32_t keyFrameCount;
                        deserializer.Read(keyFrameCount);

                        for (size_t iKeyFrame = 0; iKeyFrame < keyFrameCount; ++iKeyFrame)
                        {
                            float time;
                            deserializer.Read(time);

                            size_t keyFrameIndex = m_animation.AppendKeyFrame(static_cast<double>(time));


                            // With the key frame added, we now need to iterate over each channel in the key frame.
                            uint32_t channelCount;
                            deserializer.Read(channelCount);

                            for (uint32_t iChannel = 0; iChannel < channelCount; ++iChannel)
                            {
                                uint32_t boneIndex;
                                deserializer.Read(boneIndex);

                                auto bone = m_bones[boneIndex];
                                assert(bone != nullptr);
                                {
                                    auto iChannelBone = this->animationChannelBones.Find(bone);
                                    assert(iChannelBone != nullptr);
                                    {
                                        auto channel = iChannelBone->value;

                                        glm::vec3 position;
                                        glm::quat rotation;
                                        glm::vec3 scale;
                                        
                                        deserializer.Read(position);
                                        deserializer.Read(rotation);
                                        deserializer.Read(scale);

                                        auto key = new TransformAnimationKey(position, rotation, scale);
                                        channel->SetKey(keyFrameIndex, key);


                                        // We need to cache the key.
                                        this->animationKeyCache.PushBack(key);
                                    }
                                }
                            }
                        }

                        deserializer.Read(this->animationAABBPadding);
                    }
                    else
                    {
                        // Unsupported Version.
                        deserializer.Seek(header.sizeInBytes);
                    }

                    break;
                }

            case Serialization::ChunkID_Model_AnimationSegments:
                {
                    deserializer.Seek(sizeof(header));

                    if (header.version == 1)
                    {
                        uint32_t animationSegmentCount;
                        deserializer.Read(animationSegmentCount);
                        
                        for (uint32_t iSegment = 0; iSegment < animationSegmentCount; ++iSegment)
                        {
                            String name;
                            uint32_t startKeyFrame;
                            uint32_t endKeyFrame;

                            deserializer.ReadString(name);
                            deserializer.Read(startKeyFrame);
                            deserializer.Read(endKeyFrame);

                            m_animation.AddNamedSegment(name.c_str(), static_cast<size_t>(startKeyFrame), static_cast<size_t>(endKeyFrame));
                        }
                    }
                    else
                    {
                        // Unsupported Version.
                        deserializer.Seek(header.sizeInBytes);
                    }

                    break;
                }

            case Serialization::ChunkID_Model_AnimationSequences:
                {
                    deserializer.Seek(sizeof(header));

                    if (header.version == 1)
                    {
                    }
                    else
                    {
                        // Unsupported Version.
                        deserializer.Seek(header.sizeInBytes);
                    }

                    break;
                }

            case Serialization::ChunkID_Model_ConvexHulls:
                {
                    deserializer.Seek(sizeof(header));

                    if (header.version == 1)
                    {
                        uint32_t convexHullCount;
                        deserializer.Read(convexHullCount);

                        uint32_t* vertexCounts = static_cast<uint32_t*>(malloc(convexHullCount * sizeof(uint32_t)));
                        uint32_t* indexCounts  = static_cast<uint32_t*>(malloc(convexHullCount * sizeof(uint32_t)));

                        deserializer.Read(vertexCounts, convexHullCount * sizeof(uint32_t));
                        deserializer.Read(indexCounts,  convexHullCount * sizeof(uint32_t));


                        uint32_t totalVertexCount;
                        deserializer.Read(totalVertexCount);

                        uint32_t totalIndexCount;
                        deserializer.Read(totalIndexCount);


                        auto vertices = static_cast<float*   >(malloc(totalVertexCount * sizeof(float)));
                        auto indices  = static_cast<uint32_t*>(malloc(totalIndexCount  * sizeof(uint32_t)));

                        deserializer.Read(vertices, totalVertexCount * sizeof(float));
                        deserializer.Read(indices,  totalIndexCount  * sizeof(uint32_t));


                        auto currentVertices = vertices;
                        auto currentIndices  = indices;

                        for (uint32_t iConvexHull = 0; iConvexHull < convexHullCount; ++iConvexHull)
                        {
                            size_t vertexCount = static_cast<size_t>(vertexCounts[iConvexHull]);
                            size_t indexCount  = static_cast<size_t>(indexCounts[iConvexHull]);

                            m_convexHulls.PushBack(new ConvexHull(currentVertices, vertexCount, currentIndices, indexCount));

                            // Now we need to move our pointers forward.
                            currentVertices += vertexCount * 3;
                            currentIndices  += indexCount;
                        }


                        // Build Settings.
                        deserializer.Read(this->convexHullBuildSettings);


                        free(vertexCounts);
                        free(indexCounts);
                        free(vertices);
                        free(indices);
                    }
                    else
                    {
                        // Unsupported Version.
                        deserializer.Seek(header.sizeInBytes);
                    }

                    break;
                }

            case Serialization::ChunkID_Null:
                {
                    deserializer.Seek(sizeof(header));

                    finished = true;
                    break;
                }

            default:
                {
                    // Unknown chunk = Error.
                    finished = true;
                    return false;
                }
            }


            if (finished)
            {
                break;
            }
        }


        // If we get here, we were successful.
        return true;
    }
Exemplo n.º 9
0
	vector<ObjIndex> *ObjLoader::currentList()
	{
		if (objIndices.size() == 0)
			newMesh("child");
		return objIndices[objIndices.size() - 1];
	}
Exemplo n.º 10
0
	std::shared_ptr<ILoadableObject> ObjLoader::load(AssetManager *assetMgr, AssetInfo &asset)
	{
		shared_ptr<Node> node(new Node());

		std::string currentDir = std::string(asset.getFilePath());
		std::string nodeFileName = currentDir.substr(currentDir.find_last_of("\\/")+1);
		nodeFileName = nodeFileName.substr(0, nodeFileName.find_first_of(".")); // trim extension

		node->setName(nodeFileName);

		std::string line;
		while (std::getline(*asset.getStream(), line))
		{
			vector<string> tokens = split(line, ' ');
			tokens = removeEmptyStrings(tokens);

			if (tokens.size() == 0 || strcmp(tokens[0].c_str(), "#") == 0)
			{
			}
			else if (strcmp(tokens[0].c_str(), "v") == 0)
			{
				float x = parse<float>(tokens[1]);
				float y = parse<float>(tokens[2]);
				float z = parse<float>(tokens[3]);
				Vector3f vec(x, y, z);
				positions.push_back(vec);
			}
			else if (strcmp(tokens[0].c_str(), "vn") == 0)
			{
				float x = parse<float>(tokens[1]);
				float y = parse<float>(tokens[2]);
				float z = parse<float>(tokens[3]);
				Vector3f vec(x, y, z);
				normals.push_back(vec);
			}
			else if (strcmp(tokens[0].c_str(), "vt") == 0)
			{
				float x = parse<float>(tokens[1]);
				float y = parse<float>(tokens[2]);
				Vector2f vec(x, y);
				texCoords.push_back(vec);
			}
			else if (strcmp(tokens[0].c_str(), "f") == 0)
			{
				vector<ObjIndex> *c_idx = currentList();
				for (int i = 0; i < tokens.size() - 3; i++)
				{
					c_idx->push_back(parseObjIndex(tokens[1]));
					c_idx->push_back(parseObjIndex(tokens[2 + i]));
					c_idx->push_back(parseObjIndex(tokens[3 + i]));
				}
			}
			else if (strcmp(tokens[0].c_str(), "mtllib") == 0)
			{
				string libLoc = tokens[1];

				std::string currentDir = std::string(asset.getFilePath());
				currentDir = currentDir.substr(0, currentDir.find_last_of("\\/"));

				if (!contains(currentDir, "/") && !contains(currentDir, "\\"))	// the file path is just current file name,															   
				{																// so just make the string empty
					currentDir = "";
				}

				currentDir += "/" + libLoc;

				std::shared_ptr<MaterialList> mtlList = assetMgr->loadAs<MaterialList>(currentDir.c_str());
				this->mtlList = *mtlList.get();
			}
			else if (strcmp(tokens[0].c_str(), "usemtl") == 0)
			{
				string matname = tokens[1];
				newMesh(matname);
			}
		}

		for (int i = 0; i < objIndices.size(); i++)
		{
			vector<ObjIndex> *c_idx = objIndices[i];
			vector<Vertex> vertices;

			for (int j = 0; j < c_idx->size(); j++)
			{
				Vertex vert(positions[(*c_idx)[j].vertex_idx],
						   (hasTexCoords ? texCoords[(*c_idx)[j].texcoord_idx] : Vector2f()),
						   (hasNormals ? normals[(*c_idx)[j].normal_idx] : Vector3f()));

				vertices.push_back(vert);
			}

			shared_ptr<Mesh> mesh(new Mesh());
			mesh->setVertices(vertices);

			if (hasNormals)
				mesh->getAttributes().setAttribute(VertexAttributes::NORMALS);
			if (hasTexCoords)
				mesh->getAttributes().setAttribute(VertexAttributes::TEXCOORDS0);

			shared_ptr<Geometry> geom(new Geometry());
			geom->setName(names[i]);
			geom->setMesh(mesh);
			geom->setMaterial(materialWithName(namesMtl[i]));
			node->add(geom);

			delete c_idx;
		}

		return std::static_pointer_cast<ILoadableObject>(node);
	}