Пример #1
0
	SpaceShooter::SpaceShooter()
	{
		Renderer::Get().Initialize();

		// Create the player's view.
		Quaternion viewRotation( Vector3::Right, Pi / 2.f );
		mCamera = ViewPtr( new View( Vector3( 0.f, 60.f, 0.f ), viewRotation, 1.04719755f, 1920.0f / 1080.0f, 0.1f, 100.f, false ) );
		Renderer::Get().SetCamera( mCamera );

		// Create the background.
		MaterialPtr backgroundMaterial = MaterialPtr( new Material( L"Resources\\Shaders\\tangent.hlsl", L"Resources\\Textures\\starfield.dds" ) );
		RawMeshPtr backgroundMesh = RawMeshPtr( new RawMesh() );
		GenerateQuadVerticies( *backgroundMesh.get(), 90.f, 45.f );
		MeshPrimitivePtr background = MeshPrimitivePtr( new MeshPrimitive( backgroundMesh, backgroundMaterial, GetTangentSpaceVertexSource() ) );
		mBackground = GameObjectPtr( new GameObject( background ) );
		Matrix4 backgroundOffset;
		backgroundOffset.CreateFromQuaternion( Quaternion( Vector3::Right, Pi / 2.f ) );
		mBackground->SetOffset( backgroundOffset );
		mBackground->SetTranslation( Vector3( 0.f, -10.f, 0.f ) );
		mBackground->Attach();

		// Load the player's ship.
		MaterialPtr playerShipMaterial = MaterialPtr( new Material( L"Resources\\Shaders\\tangent.hlsl", L"Resources\\Textures\\frigate.dds" ) );
		RawMeshPtr shipMesh = RawMeshPtr( new RawMesh() );
		LoadMeshFromObjFile( "Resources\\Meshes\\frigate_normal.obj", *shipMesh.get() );
		CalculateTangents( *shipMesh.get() );
		MeshPrimitivePtr player = MeshPrimitivePtr( new MeshPrimitive( shipMesh, playerShipMaterial, GetTangentSpaceVertexSource() ) );
		mPlayerObject = PlayerShipPtr( new PlayerShip( player ) );
		mPlayerObject->SetScale( 0.3f );
		mPlayerObject->SetBounds( 6.5f );
		Matrix4 playerOffset;
		playerOffset.CreateFromQuaternion( Quaternion( Vector3::Up, Pi / 2.f ) );
		mPlayerObject->SetOffset( playerOffset );
		mPlayerObject->SetFrictionFactor( 0.5f );
		mPlayerObject->Attach();

		// Load asteroids
		MaterialPtr asteroidMaterial = MaterialPtr( new Material( L"Resources\\Shaders\\tangent.hlsl", L"Resources\\Textures\\asteroid.dds" ) );
		RawMeshPtr asteroidMesh = RawMeshPtr( new RawMesh() );
		LoadMeshFromObjFile( "Resources\\Meshes\\asteroid1.obj", *asteroidMesh.get() );
		CalculateTangents( *asteroidMesh.get() );
		for ( int i = 0; i < 5; i++ )
		{
			MeshPrimitivePtr asteroid = MeshPrimitivePtr( new MeshPrimitive( asteroidMesh, asteroidMaterial, GetTangentSpaceVertexSource() ) );
			GameObjectPtr newAsteroid = GameObjectPtr( new Asteroid( asteroid ) );
			newAsteroid->SetScale( 1.f );
			newAsteroid->SetBounds( 4.f );
			newAsteroid->SetTranslation( Vector3( RandomFloat( -40.f, 40.f ), 0.f, RandomFloat( -40.f, 40.f ) ) );
			mAsteroids.push_back( newAsteroid );
			newAsteroid->Attach();
		}

		// Load the player's jet particles.
		playerJetParticles = ParticleSystemPtr( new ParticleSystem() );
		ParticleSystemLoader loader;
		loader.LoadFromFile( "Resources\\ParticleSystems\\jet_fuel.part", playerJetParticles );
		playerJetParticles->SetEmitterState( false );	// turn the particles off to start with
		Renderer::Get().AddTranslucentPrimitive( playerJetParticles );
	}
Пример #2
0
void ModelLoader::AddTri(const vector<vector<int>>& data)
{
    ASSERT (m_pCurrentMesh != 0, "");

    unsigned int index[3];

    for (int i = 0; i < 3; ++i)
    {
        index[i] = m_VPNTTData.size();
		Vector3 tangent = Vector3(0,0,0);
        VertexPosNormTanTex vpntt(
                m_VertexData[data[i][0] - 1],
                m_NormalData[data[i][2] - 1],
				tangent,
                m_TextureData[data[i][1] - 1]);

        stringstream stream;
        stream << data[i][0] << "/" << data[i][1] << "/" << data[i][2];
        if (m_VPNTTMap.count(stream.str()) == 0)
        {
            m_VPNTTData.push_back(vpntt);
            m_VPNTTMap[stream.str()] = index[i];
        }
        else
        {
            index[i] = m_VPNTTMap[stream.str()];
        }   
    }
    
    m_IndexData.push_back(index[2]);
    m_IndexData.push_back(index[1]);
    m_IndexData.push_back(index[0]);

	CalculateTangents(m_VPNTTData[index[2]], m_VPNTTData[index[1]], m_VPNTTData[index[0]]);
}
Пример #3
0
bool Mesh::load(const std::string& filename) {
    std::shared_ptr<ObjMesh> mesh = nullptr;

    if ( !LoadObjMesh(filename, mesh) ) return false;

    if ( mesh->faces.size() > 0 ) {
        if ( mesh->faces[0].type != TRIANGLE ) {
            std::cerr << "[Mesh:load] Error: Only triangle-face Obj files supported." << std::endl;
            return false;
        }
    }

    this->name = mesh->name;
    std::vector<Vector3f> normals;
    std::vector<Vector4f> tangents;
    std::vector<unsigned int> indices;
    std::vector<unsigned int> textureIndices;
    std::vector<unsigned int> normalIndices;

    //--------------------------------------------------------------------------
    // Copy the face indices from the *.obj file to this mesh.
    //--------------------------------------------------------------------------
    indices.resize(mesh->faces.size() * TRIANGLE_EDGE_COUNT);
    normalIndices.resize(mesh->faces.size() * TRIANGLE_EDGE_COUNT);
    textureIndices.resize(mesh->faces.size() * TRIANGLE_EDGE_COUNT);
    unsigned int index = 0;
    for ( unsigned int i = 0; i < mesh->faces.size(); i++ ) {
        indices[index] = static_cast<unsigned int>(mesh->faces[i].vertexIndices[A]);
        indices[index + 1] = static_cast<unsigned int>(mesh->faces[i].vertexIndices[B]);
        indices[index + 2] = static_cast<unsigned int>(mesh->faces[i].vertexIndices[C]);

        normalIndices[index] = static_cast<unsigned int>(mesh->faces[i].normalIndices[A]);
        normalIndices[index + 1] = static_cast<unsigned int>(mesh->faces[i].normalIndices[B]);
        normalIndices[index + 2] = static_cast<unsigned int>(mesh->faces[i].normalIndices[C]);

        textureIndices[index] = static_cast<unsigned int>(mesh->faces[i].textureIndices[A]);
        textureIndices[index + 1] = static_cast<unsigned int>(mesh->faces[i].textureIndices[B]);
        textureIndices[index + 2] = static_cast<unsigned int>(mesh->faces[i].textureIndices[C]);

        index += TRIANGLE_EDGE_COUNT;
    }

    //--------------------------------------------------------------------------
    // Calcualte the vertex normals, tangents, and face normals.
    //--------------------------------------------------------------------------
    //CalculateNormals(indices, mesh->vertices, normals);
    normals.resize(mesh->normals.size());
    for ( unsigned int i = 0; i < mesh->normals.size(); i++ ) {
        normals[i] = mesh->normals[i];
    }
    Decompress(indices, normalIndices, textureIndices, mesh->vertices, normals, mesh->textureCoordinates, tangents, this->vertices, this->faces);
    CalculateTangents(this->vertices, this->faces);
    this->constructOnGPU();
    return true;
}
Пример #4
0
	void RenderDataManager::InitializeNode(TQuad* q)
	{
		assert(!q->renderData);

		QuadRenderData* rd = q->renderData = Allocate();

		// Allocate vertex data space
		const size_t vertexSize = q->GetVertexSize();
		if (static_cast<int>(vertexSize) != rd->vertexSize) {
			const size_t size = NUM_VERTICES * vertexSize;

			if (rd->vertexBuffer.GetSize() != size) {
				rd->vertexBuffer.Init(size);
			}
			rd->vertexSize = vertexSize;
		}

		// build the vertex buffer
		Vector3* v = (Vector3*)rd->vertexBuffer.LockData();

		uint vda = q->textureSetup->vertexDataReq; 		// vertex data requirements
		const Heightmap* hm = roothm->GetLevel(q->depth); // get the right heightmap level

		for (int y = q->hmPos.y; y <= (q->hmPos.y + QUAD_W); y++)
			for (int x = q->hmPos.x; x <= (q->hmPos.x + QUAD_W); x++)
			{
				*(v++) = Vector3(x * hm->squareSize, hm->atSynced(x, y), y * hm->squareSize);

				Vector3 tangent, binormal;
				CalculateTangents(hm, x,y, tangent, binormal);
				Vector3 normal = binormal.cross(tangent);
				normal.ANormalize();

				if (vda & VRT_Normal)
					*(v++) = normal;

				if (vda & VRT_TangentSpaceMatrix)
				{
					tangent.ANormalize();
					binormal.ANormalize();

					// orthonormal matrix, so inverse=transpose
					// Take the inverse of the tangent space -> world space transformation
					Vector3* tgs2ws = v;
					tgs2ws[0] = Vector3(tangent.x, binormal.x, normal.x);
					tgs2ws[1] = Vector3(tangent.y, binormal.y, normal.y);
					tgs2ws[2] = Vector3(tangent.z, binormal.z, normal.z);
					v += 3;
				}
			}
		rd->vertexBuffer.UnlockData();
		rd->SetQuad(q);
	}
Пример #5
0
void ModelLoader::FlushMesh()
{
    ASSERT(m_pCurrentMesh != 0, "");
	
	// TANGENTS
	for (unsigned int i = 0; i < m_VPNTTData.size() / 3; ++i)
	{
		CalculateTangents(m_VPNTTData[i*3],m_VPNTTData[(i*3)+1],m_VPNTTData[(i*3)+2]);
	}

    m_pCurrentMesh->SetVertices(m_VPNTTData);
    m_pCurrentMesh->SetIndices(m_IndexData);
    m_VPNTTData.clear();
    m_VPNTTMap.clear();
    m_pCurrentMesh = 0;
    m_IndexData.clear();
}
Пример #6
0
	void Heightmap::GenerateNormals ()
	{
		normalData = SAFE_NEW uchar [3 * w * h];

		uchar *cnorm = normalData;
		for (int y=0;y<h;y++)
			for (int x=0;x<w;x++) {
				Vector3 tangent, binormal;
				CalculateTangents(this, x,y,tangent,binormal);

				Vector3 normal = binormal.cross(tangent);
				normal.Normalize ();

				*(cnorm++) = (uchar)((normal.x * 0.5f + 0.5f) * 255);
				*(cnorm++) = (uchar)((normal.y * 0.5f + 0.5f) * 255);
				*(cnorm++) = (uchar)((normal.z * 0.5f + 0.5f) * 255);
			}
	}
Пример #7
0
Mesh::Mesh(int vertNum, Vertex* vert, int indNum, unsigned int* indices, ID3D11Device* deviceObj)
{
	numOfIndices = indNum;
	CalculateTangents(&verts[0], verts.size(), &indices[0], numOfIndices);
	// Create vertexBuffers
	D3D11_BUFFER_DESC vbd;
	vbd.Usage = D3D11_USAGE_IMMUTABLE;
	vbd.ByteWidth = sizeof(Vertex) * vertNum;
	vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	vbd.CPUAccessFlags = 0;
	vbd.MiscFlags = 0;
	vbd.StructureByteStride = 0;
	

	// Load Data to Vertex Buffer
	D3D11_SUBRESOURCE_DATA vertData;
	vertData.pSysMem = vert;

	// Create the buffer with the data
	HR(deviceObj->CreateBuffer(&vbd, &vertData, &vBuffer));

	//Create Index Buffer
	D3D11_BUFFER_DESC ibd;
	ibd.Usage = D3D11_USAGE_IMMUTABLE;
	ibd.ByteWidth = sizeof(int) * indNum;
	ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
	ibd.CPUAccessFlags = 0;
	ibd.MiscFlags = 0;
	ibd.StructureByteStride = 0;

	//Load Data to IndexBuffer
	D3D11_SUBRESOURCE_DATA indData;
	indData.pSysMem = indices;


	// Create Index Buffer with the data.
	HR(deviceObj->CreateBuffer(&ibd, &indData, &iBuffer));
}
Пример #8
0
Model<VertexPosNormTanTex>* TerrainLoader::Load(ID3D10Device* pDXDevice, const tstring& key)
{
    Model<VertexPosNormTanTex>* ret = 0;
	if ( m_pAssets->IsAssetPresent(key))
	{
        ret = m_pAssets->GetAsset(key);
	}
	else
	{
        vector<VertexPosNormTanTex> vertices;
        vector<DWORD> indices;

        Texture2D* heightMap = Content->LoadTexture2D(key, true);
        ID3D10Texture2D* pTex2D = heightMap->GetTextureResource();
        
        vertices.reserve(heightMap->GetWidth() * heightMap->GetHeight());
        indices.reserve((heightMap->GetWidth()-1) * (heightMap->GetHeight()-1) * 6);

        D3D10_MAPPED_TEXTURE2D pMappedTex2D;
        pTex2D->Map(0, D3D10_MAP_READ, 0, &pMappedTex2D);

        float heightMult = 1.0f;
        float planarMult = 1.0f / max(heightMap->GetWidth(), heightMap->GetHeight());
        BYTE* pData = static_cast<BYTE*>(pMappedTex2D.pData);
        for (UINT x = 0; x < heightMap->GetHeight(); ++x)
        {
            for (UINT z = 0; z < heightMap->GetWidth(); ++z)
            {
                float height = pData[z * 4 + x * pMappedTex2D.RowPitch + 0] / 255.0f; //get red

                vertices.push_back(VertexPosNormTanTex(
                    static_cast<float>(x) * planarMult, height * heightMult, static_cast<float>(z) * planarMult,
                    0, 0, 0, 
                    0, 0, 0, 
                    static_cast<float>(z) / heightMap->GetWidth(), static_cast<float>(x) / heightMap->GetHeight()));

                if (z != heightMap->GetWidth() - 1 && x != heightMap->GetHeight() - 1)
                {
                    indices.push_back(z + x * heightMap->GetWidth());
                    indices.push_back(z + x * heightMap->GetWidth() + 1);
                    indices.push_back(z + (x + 1) * heightMap->GetWidth());

                    indices.push_back(z + x * heightMap->GetWidth() + 1);
                    indices.push_back(z + (x + 1) * heightMap->GetWidth() + 1);
                    indices.push_back(z + (x + 1) * heightMap->GetWidth());
                }
            }
        }

        pTex2D->Unmap(0);

        CalculateNormals(vertices, indices);
        CalculateTangents(vertices, indices);

        Model<VertexPosNormTanTex>* pModel = new Model<VertexPosNormTanTex>(pDXDevice);
        ModelMesh<VertexPosNormTanTex>* pMesh = pModel->AddMesh(_T(""));

        pMesh->SetVertices(vertices);
        pMesh->SetIndices(indices);

        m_pAssets->AddAsset(key, pModel);
        ret = pModel;
    }

    return ret;
}
Пример #9
0
	void Blendmap::Generate(Heightmap* rootHm, int lodLevel, float hmScale, float hmOffset)
	{
		const Heightmap* heightmap = rootHm->GetLevel(-lodLevel);

		// Allocate the blendmap image
		AlphaImage* bm = new AlphaImage;
		bm->Alloc(heightmap->w-1, heightmap->h-1); // texture dimensions have to be power-of-two

		Blendmap::GeneratorInfo* gi = generatorInfo;

		// Calculate blend factors using the function parameters and heightmap input:
		for (int y=0;y<bm->h;y++)
		{
			for (int x=0;x<bm->w;x++)
			{
				const float h = (heightmap->atSynced(x, y) - hmOffset) / hmScale;
				float factor=1.0f;

				if(h < gi->minHeight - gi->minHeightFuzzy) {
					bm->at(x,y) = 0.0f;
					continue;
				} else if (gi->minHeightFuzzy > 0.0f && h < gi->minHeight + gi->minHeightFuzzy)
					factor = (h - (gi->minHeight - gi->minHeightFuzzy)) / (2.0f * gi->minHeightFuzzy);

				if(h > gi->maxHeight + gi->maxHeightFuzzy) {
					bm->at (x,y) = 0.0f;
					continue;
				} else if (gi->maxHeightFuzzy > 0.0f && h > gi->maxHeight - gi->maxHeightFuzzy)
					factor *= ((gi->maxHeight + gi->maxHeightFuzzy) - h) / (2.0f * gi->maxHeightFuzzy);

                float norm_y = 0.0f;
				if (heightmap->normalData) {
					const uchar* cnorm = heightmap->GetNormal(x, y);
					norm_y = cnorm[1] / 255.0f * 2.0f - 1.0f;
					if (norm_y > 1.0f) norm_y = 1.0f;
				} else {
					Vector3 tangent, binormal;
					CalculateTangents(heightmap, x,y,tangent,binormal);
					Vector3 normal = tangent.cross(binormal);
					normal.ANormalize();
					norm_y = normal.y;
				}

				// flatness=dotproduct of surface normal with up vector
				float slope = 1.0f - fabs(norm_y);

				if (slope < gi->minSlope - gi->minSlopeFuzzy) {
					bm->at(x,y) = 0.0f;
					continue;
				} else if (gi->minSlopeFuzzy > 0.0f && slope < gi->minSlope + gi->minSlopeFuzzy)
					factor *= (h - (gi->minSlope - gi->minSlopeFuzzy)) / ( 2.0f * gi->minSlopeFuzzy);

				if (slope > gi->maxSlope + gi->maxSlopeFuzzy) {
					bm->at(x,y) = 0.0f;
					continue;
				} else if (gi->maxSlopeFuzzy > 0.0f && slope > gi->maxSlope - gi->maxSlopeFuzzy)
					factor *= ((gi->maxSlope + gi->maxSlopeFuzzy) - h) / (2.0f * gi->maxSlopeFuzzy);

				factor *= gi->coverage;
				factor *= (rand() < gi->noise * RAND_MAX) ? 0.0f : 1.0f;

				bm->at(x,y) = factor;
			}
		}

		BlendmapFilter(bm);
		image = bm;
	}
Пример #10
0
int MeshCompiler::Compile( const char* InFilename, const char* OutFilename, bool LongIndices )
{
	m_StrippedFilename = FileUtil::StripExtensions( FileUtil::StripLeadingFolders( InFilename ) );

	TiXmlDocument XMLDoc;
	XMLDoc.LoadFile( InFilename );
	TiXmlElement* RootElement = XMLDoc.FirstChildElement();	// "mesh"

	// Sanity check
	if( _stricmp( RootElement->Value(), "mesh" ) )
	{
		PRINTF( "Input file is not a valid XML mesh file.\n" );
		return -1;
	}

	STATICHASH( BakeAOForDynamicMeshes );
	STATICHASH( BakeAOForAnimatedMeshes );
	STATICHASH( TraceTriangleBacks );
	STATICHASH( DynamicAORadius );
	STATICHASH( DynamicAOPushOut );
	MAKEHASH( m_StrippedFilename );

	ConfigManager::Load( FileStream( "tools.cfg", FileStream::EFM_Read ) );
	m_BakeAOForDynamicMeshes = ConfigManager::GetArchetypeBool( sBakeAOForDynamicMeshes, ConfigManager::EmptyContext, false, sm_StrippedFilename );
	m_BakeAOForAnimatedMeshes = ConfigManager::GetArchetypeBool( sBakeAOForAnimatedMeshes, ConfigManager::EmptyContext, false, sm_StrippedFilename );
	m_TraceTriangleBacks = ConfigManager::GetArchetypeBool( sTraceTriangleBacks, ConfigManager::EmptyContext, false, sm_StrippedFilename );
	m_AORadius = ConfigManager::GetArchetypeFloat( sDynamicAORadius, ConfigManager::EmptyContext, 0.1f, sm_StrippedFilename );
	m_AOPushOut = ConfigManager::GetArchetypeFloat( sDynamicAOPushOut, ConfigManager::EmptyContext, 0.01f, sm_StrippedFilename );

	m_Header.m_LongIndices = LongIndices;

	// Get armature first, which will make it easier to handle bone references in verts
	TiXmlElement* Arm = RootElement->FirstChildElement( "armature" );
	CompileArmature( Arm );

	int NumFaces = 0;
	for( TiXmlElement* Face = RootElement->FirstChildElement( "face" ); Face; Face = Face->NextSiblingElement( "face" ) )
	{
		CompileFace( Face );
		NumFaces++;
	}

	for( TiXmlElement* Mat = RootElement->FirstChildElement( "material" ); Mat; Mat = Mat->NextSiblingElement( "material" ) )
	{
		CompileMaterial( Mat );
	}

	m_Header.m_NumVertices = m_Positions.Size();
	m_Header.m_NumIndices = m_Indices.Size();

	NormalizeWeights();

	CalculateAABB();

	if( m_Header.m_HasUVs && m_Header.m_HasNormals )
	{
		m_Header.m_HasTangents = true;
	}
	PRINTF( "Calculating tangents...\n" );
	CalculateTangents();

	CalculateAmbientOcclusion();

	PRINTF( "Compile successful!\n" );
	PRINTF( "Imported %d faces.\n", NumFaces );

	Write( FileStream( OutFilename, FileStream::EFM_Write ) );

	PRINTF( "Exported %d vertices.\n", m_Header.m_NumVertices );
	PRINTF( "Exported %d indices (%d triangles).\n", m_Header.m_NumIndices, m_Header.m_NumIndices / 3 );
	if( m_Header.m_HasSkeleton )
	{
		PRINTF( "Exported %d bones.\n", m_Header.m_NumBones );
		PRINTF( "Exported %d frames.\n", m_Header.m_NumFrames );
		PRINTF( "Exported %d animations.\n", m_Header.m_NumAnims );
	}

	return 0;
}
Пример #11
0
Mesh::Mesh(ID3D11Device* deviceObj, char* filename) {
	// File input object
	std::ifstream obj(filename); // <-- Replace filename with your parameter

						
	 // Check for successful open
	if (!obj.is_open())
		return;

	
										 // Still good?
	while (obj.good())
	{
		// Get the line (100 characters should be more than enough)
		obj.getline(chars, 100);

		// Check the type of line
		if (chars[0] == 'v' && chars[1] == 'n')
		{
			// Read the 3 numbers directly into an XMFLOAT3
			XMFLOAT3 norm;
			sscanf_s(
				chars,
				"vn %f %f %f",
				&norm.x, &norm.y, &norm.z);

			// Add to the list of normals
			normals.push_back(norm);
		}
		else if (chars[0] == 'v' && chars[1] == 't')
		{
			// Read the 2 numbers directly into an XMFLOAT2
			XMFLOAT2 uv;
			sscanf_s(
				chars,
				"vt %f %f",
				&uv.x, &uv.y);

			// Add to the list of uv's
			uvs.push_back(uv);
		}
		else if (chars[0] == 'v')
		{
			// Read the 3 numbers directly into an XMFLOAT3
			XMFLOAT3 pos;
			sscanf_s(
				chars,
				"v %f %f %f",
				&pos.x, &pos.y, &pos.z);

			// Add to the positions
			positions.push_back(pos);
		}
		else if (chars[0] == 'f')
		{
			// Read the 9 face indices into an array
			unsigned int i[9];
			sscanf_s(
				chars,
				"f %d/%d/%d %d/%d/%d %d/%d/%d",
				&i[0], &i[1], &i[2],
				&i[3], &i[4], &i[5],
				&i[6], &i[7], &i[8]);

			// - Create the verts by looking up
			//    corresponding data from vectors
			// - OBJ File indices are 1-based, so
			//    they need to be adusted
			Vertex v1;
			v1.Position = positions[i[0] - 1];
			v1.UV = uvs[i[1] - 1];
			v1.Normal = normals[i[2] - 1];

			Vertex v2;
			v2.Position = positions[i[3] - 1];
			v2.UV = uvs[i[4] - 1];
			v2.Normal = normals[i[5] - 1];

			Vertex v3;
			v3.Position = positions[i[6] - 1];
			v3.UV = uvs[i[7] - 1];
			v3.Normal = normals[i[8] - 1];

			// Flip the UV's since they're probably "upside down"
			v1.UV.y = 1.0f - v1.UV.y;
			v2.UV.y = 1.0f - v2.UV.y;
			v3.UV.y = 1.0f - v3.UV.y;

			// Add the verts to the vector
			verts.push_back(v1);
			verts.push_back(v2);
			verts.push_back(v3);

			// Add three more indices
			indices.push_back(vertCounter++);
			indices.push_back(vertCounter++);
			indices.push_back(vertCounter++);
		}
	}

	// Close
	obj.close();

	numOfIndices = indices.size();
	CalculateTangents(&verts[0], verts.size(), &indices[0], numOfIndices);
	// Create vertexBuffers
	D3D11_BUFFER_DESC vbd;
	vbd.Usage = D3D11_USAGE_IMMUTABLE;
	vbd.ByteWidth = sizeof(Vertex) * verts.size();
	vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	vbd.CPUAccessFlags = 0;
	vbd.MiscFlags = 0;
	vbd.StructureByteStride = 0;
	// Load Data to Vertex Buffer
	D3D11_SUBRESOURCE_DATA vertData;
	vertData.pSysMem = &verts[0];
	// Create the buffer with the data
	HR(deviceObj->CreateBuffer(&vbd, &vertData, &vBuffer));

	//Create Index Buffer
	D3D11_BUFFER_DESC ibd;
	ibd.Usage = D3D11_USAGE_IMMUTABLE;
	ibd.ByteWidth = sizeof(int) * indices.size();
	ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
	ibd.CPUAccessFlags = 0;
	ibd.MiscFlags = 0;
	ibd.StructureByteStride = 0;
	//Load Data to IndexBuffer
	D3D11_SUBRESOURCE_DATA indData;
	indData.pSysMem = &indices[0];
	// Create Index Buffer with the data.
	HR(deviceObj->CreateBuffer(&ibd, &indData, &iBuffer));


}