Beispiel #1
3
// not the general case. just the simple case of a square
bool MyPolygon::calcTangents()
{
    const Vec3& v1 = vtx[0]->p;
    const Vec3& v2 = vtx[1]->p;
    const Vec3& v3 = vtx[2]->p;

    const Vec2& w1 = texAncs[0];
    const Vec2& w2 = texAncs[1];
    const Vec2& w3 = texAncs[2];

    float x1 = v2.x - v1.x;
    float x2 = v3.x - v1.x;
    float y1 = v2.y - v1.y;
    float y2 = v3.y - v1.y;
    float z1 = v2.z - v1.z;
    float z2 = v3.z - v1.z;

    float s1 = w2.x - w1.x;
    float s2 = w3.x - w1.x;
    float t1 = w2.y - w1.y;
    float t2 = w3.y - w1.y;

    float r = 1.0F / (s1 * t2 - s2 * t1);
    Vec3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
        (t2 * z1 - t1 * z2) * r);
    Vec3 tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,
        (s1 * z2 - s2 * z1) * r);

    tangent = sdir;

    bitangent = tdir;
    return true;
}
Beispiel #2
0
void Mesh::updateTangents()
{
	glm::vec3 * tan1 = new glm::vec3[verts.size()];// * 2];
	//glm::vec3 * tan2 = tan1 + verts.size();
	//ZeroMemory(tan1, vertexCount * sizeof(Vector3D) * 2);
	for (uint i = 0; i < indices.size()/3; i++)
	{
		long i1 = indices[0 + i*3];
		long i2 = indices[1 + i*3];
		long i3 = indices[2 + i*3];

		Vert& v1 = verts[i1];
		Vert& v2 = verts[i2];
		Vert& v3 = verts[i3];

		float x1 = v2.pos.x - v1.pos.x;
		float x2 = v3.pos.x - v1.pos.x;
		float y1 = v2.pos.y - v1.pos.y;
		float y2 = v3.pos.y - v1.pos.y;
		float z1 = v2.pos.z - v1.pos.z;
		float z2 = v3.pos.z - v1.pos.z;

		float s1 = v2.uv.x - v1.uv.x;
		float s2 = v3.uv.x - v1.uv.x;
		float t1 = v2.uv.y - v1.uv.y;

		float t2 = v3.uv.y - v1.uv.y;

		float r = 1.0f / (s1 * t2 - s2 * t1);
		glm::vec3 sdir( (t2 * x1 - t1 * x2) * r,     (t2 * y1 - t1 * y2) * r,      (t2 * z1 - t1 * z2) * r);
		glm::vec3 tdir( (s1 * x2 - s2 * x1) * r,     (s1 * y2 - s2 * y1) * r,      (s1 * z2 - s2 * z1) * r);

		tan1[i1] += sdir;
		tan1[i2] += sdir;
		tan1[i3] += sdir;

		//tan2[i1] += tdir;
		//tan2[i2] += tdir;
		//tan2[i3] += tdir;

	}
	for (uint i = 0; i < verts.size(); i++)
	{
		glm::vec3& n = verts[i].norm;
		glm::vec3& t = tan1[i];
		// Gram-Schmidt orthogonalized
		verts[i].tan = glm::vec4(glm::normalize((t - n * glm::dot(n, t))),0);

		// Calculate handedness
		//verts[i].tan.w = (glm::dot(glm::cross(n, t), tan2[i]) < 0.0F) ? -1.0F : 1.0F;
	}
	delete[] tan1;
}
Beispiel #3
0
  void calcTangent(Face& face) {
    glm::vec3 v1({face.verts[0].pos[0], face.verts[0].pos[1], face.verts[0].pos[2]});
    glm::vec3 v2({face.verts[1].pos[0], face.verts[1].pos[1], face.verts[1].pos[2]});
    glm::vec3 v3({face.verts[2].pos[0], face.verts[2].pos[1], face.verts[2].pos[2]});

    glm::vec2 w1({face.verts[0].uv[0], face.verts[0].uv[1]});
    glm::vec2 w2({face.verts[1].uv[0], face.verts[1].uv[1]});
    glm::vec2 w3({face.verts[2].uv[0], face.verts[2].uv[1]});

    float x1 = v2.x - v1.x;
    float x2 = v3.x - v1.x;
    float y1 = v2.y - v1.y;
    float y2 = v3.y - v1.y;
    float z1 = v2.z - v1.z;
    float z2 = v3.z - v1.z;
    float s1 = w2.x - w1.x;
    float s2 = w3.x - w1.x;
    float t1 = w2.y - w1.y;
    float t2 = w3.y - w1.y;
    float r = 1.0F / (s1 * t2 - s2 * t1);
    glm::vec3 sdir({
	(t2 * x1 - t1 * x2) * r,
	(t2 * y1 - t1 * y2) * r,
	(t2 * z1 - t1 * z2) * r
	});
    glm::vec3 tdir({
	(s1 * x2 - s2 * x1) * r,
	(s1 * y2 - s2 * y1) * r,
	(s1 * z2 - s2 * z1) * r
	});
    for(Vertex& v: face.verts) {
      // Gram-Schmidt orthogonalize
      glm::vec3 t = sdir;
      glm::vec3 n = glm::vec3{
	v.normal[0],
	v.normal[1],
	v.normal[2]
      };
      const auto& bt = glm::normalize(glm::vec3{(t - n * glm::dot(n, t))});
      v.tangent[0] = bt.x;
      v.tangent[1] = bt.y;
      v.tangent[2] = bt.z;
    }
  }
Beispiel #4
0
status_t
ThemeManager::LoadThemes()
{
	FENTRY;
	int dirwhich;
	BPath path;
	BDirectory dir;
	entry_ref ref;
	status_t err;
	
	for (dirwhich = 0; dirwhich < 2; dirwhich++) {
		if (!dirwhich)	/* find system settings dir */
			err = find_directory(B_BEOS_ETC_DIRECTORY, &path);
		else			/* find user settings dir */
			err = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
		if (err)	return err;
		
		err = dir.SetTo(path.Path());
		if (err)	return err;
		BEntry ent;
		if (dir.FindEntry(Z_THEMES_FOLDER_NAME, &ent) < B_OK) {
			dir.CreateDirectory(Z_THEMES_FOLDER_NAME, NULL);
		}
		
		path.Append(Z_THEMES_FOLDER_NAME);
		
		err = dir.SetTo(path.Path());
		if (err)	return err;
		
		err = dir.Rewind();
		if (err)	return err;
		
		while ((err = dir.GetNextRef(&ref)) == B_OK) {
			BPath themepath(&ref);
			BDirectory tdir(themepath.Path());
			err = tdir.InitCheck();
			if (err) /* not a dir */
				continue;
			err = LoadTheme(themepath.Path());
		}
	}
	return B_OK;
}
Beispiel #5
0
void CalculateTangents(vector<VertexPosNormTanTex>& vecVPNTData, const vector<DWORD>& vecIndexData)
{
    Vector3* tan1 = new Vector3[vecVPNTData.size()];
    Vector3* tan2 = new Vector3[vecVPNTData.size()];
    ZeroMemory(tan1, vecVPNTData.size() * 12);
    ZeroMemory(tan2, vecVPNTData.size() * 12);
    for (DWORD i = 0; i < vecIndexData.size(); i += 3)
    {
        int i1 = vecIndexData[i], 
            i2 = vecIndexData[i+1], 
            i3 = vecIndexData[i+2];

	    const Vector3& v1 = vecVPNTData[i1].position;
	    const Vector3& v2 = vecVPNTData[i2].position;
	    const Vector3& v3 = vecVPNTData[i3].position;

	    const Vector2& tx1 = vecVPNTData[i1].tex;
	    const Vector2& tx2 = vecVPNTData[i2].tex;
	    const Vector2& tx3 = vecVPNTData[i3].tex;

	    float x1 = v2.X - v1.X;
	    float x2 = v3.X - v1.X;
	    float y1 = v2.Y - v1.Y;
	    float y2 = v3.Y - v1.Y;
	    float z1 = v2.Z - v1.Z;
	    float z2 = v3.Z - v1.Z;

	    float s1 = tx2.X - tx1.X;
	    float s2 = tx3.X - tx1.X;
	    float t1 = tx2.Y - tx1.Y;
	    float t2 = tx3.Y - tx1.Y;

	    float r = 1.0f / (s1 * t2 - s2 * t1);

	    Vector3 sdir(
            (t2 * x1 - t1 * x2) * r, 
            (t2 * y1 - t1 * y2) * r, 
            (t2 * z1 - t1 * z2) * r );
	    Vector3 tdir(
            (s1 * x2 - s2 * x1) * r, 
            (s1 * y2 - s2 * y1) * r, 
            (s1 * z2 - s2 * z1) * r );

        tan1[i1] += sdir;
        tan1[i2] += sdir;
        tan1[i3] += sdir;

        tan2[i1] += tdir;
        tan2[i2] += tdir;
        tan2[i3] += tdir;
    }

    for(DWORD i = 0; i < vecVPNTData.size(); ++i)
    {
        const Vector3& n = vecVPNTData[i].normal;
        const Vector3& t = tan1[i];

        vecVPNTData[i].tangent = (t - n * n.Dot(t));
        vecVPNTData[i].tangent.Normalize();

        if (vecVPNTData[i].tangent.Dot(vecVPNTData[i].normal) > 0.0001f)
            PANIC("Tangent not loodrecht op Normal");
    }


    delete[] tan1;
    delete[] tan2;
}
Beispiel #6
0
bool CalculateMeshTangents (LPD3DXBASEMESH pMesh, DWORD dwTextureCoordsIndex)
{
	long vertexCount;
	long triangleCount;

	DWORD dwPosOffset = 0xFFFFFFFF, dwNormalOffset = 0xFFFFFFFF, dwTangentOffset = 0xFFFFFFFF;
	DWORD dwBinormalOffset = 0xFFFFFFFF, dwTexccordOffset = 0xFFFFFFFF;
	DWORD i, dwVertexStride;
	bool b16bitIndices;
	unsigned short	*indicex16bit;
	unsigned long	*indicex32bit;

	if (pMesh == NULL) return false;

	vertexCount = pMesh->GetNumVertices ();
	triangleCount = pMesh->GetNumFaces ();
	dwVertexStride = pMesh->GetNumBytesPerVertex();
	b16bitIndices = !(pMesh->GetOptions() & D3DXMESH_32BIT);

	D3DVERTEXELEMENT9 meshDecl[MAX_FVF_DECL_SIZE] = {0};
	pMesh->GetDeclaration (meshDecl);
	for (i=0; ;i++)
	{
		switch (meshDecl[i].Usage)
		{
		case D3DDECLUSAGE_POSITION: dwPosOffset = meshDecl[i].Offset; break;
		case D3DDECLUSAGE_NORMAL: dwNormalOffset = meshDecl[i].Offset; break;
		case D3DDECLUSAGE_TANGENT: dwTangentOffset = meshDecl[i].Offset; break;
		case D3DDECLUSAGE_BINORMAL: dwBinormalOffset = meshDecl[i].Offset; break;
		case D3DDECLUSAGE_TEXCOORD:
			if (meshDecl[i].UsageIndex == (BYTE)dwTextureCoordsIndex)
				dwTexccordOffset = meshDecl[i].Offset;
		}
		// posledny element
		if ((i == MAX_FVF_DECL_SIZE) || ((meshDecl[i].Stream == 0xFF) && (meshDecl[i].Type == D3DDECLTYPE_UNUSED)))
			break;
	}

	if (	(dwPosOffset==0xFFFFFFFF) || (dwNormalOffset==0xFFFFFFFF) || \
			(dwTangentOffset==0xFFFFFFFF) || (dwBinormalOffset==0xFFFFFFFF) || \
			(dwTexccordOffset==0xFFFFFFFF))
		return false;


	//////////////////////////////////////////////////////////////////////////

	LPVOID pVertexData;
	LPBYTE pVertexDataByte;
	if (FAILED (pMesh->LockVertexBuffer (0, &pVertexData)))
		return false;
	pVertexDataByte = (LPBYTE)pVertexData;

	LPVOID pIndexData;
	if (FAILED (pMesh->LockIndexBuffer (0, &pIndexData)))
	{
		pMesh->UnlockVertexBuffer();
		return false;
	}
	indicex16bit = (unsigned short*)pIndexData;
	indicex32bit = (unsigned long*)pIndexData;

	P3DXVector3D *tan1 = new P3DXVector3D[vertexCount * 2];
	P3DXVector3D *tan2 = tan1 + vertexCount;
	memset (tan1, 0, vertexCount * sizeof(P3DXVector3D) * 2);

	for (long a = 0; a < triangleCount; a++)
	{
		long i1, i2, i3;

		if (b16bitIndices)
		{
			i1 = indicex16bit[a*3];
			i2 = indicex16bit[a*3 + 1];
			i3 = indicex16bit[a*3 + 2];
		}
		else
		{
			i1 = indicex32bit[a*3];
			i2 = indicex32bit[a*3 + 1];
			i3 = indicex32bit[a*3 + 2];
		}

		const P3DXVector3D &v1 = (P3DXVector3D&) pVertexDataByte[i1*dwVertexStride + dwPosOffset];
		const P3DXVector3D &v2 = (P3DXVector3D&) pVertexDataByte[i2*dwVertexStride + dwPosOffset];
		const P3DXVector3D &v3 = (P3DXVector3D&) pVertexDataByte[i3*dwVertexStride + dwPosOffset];

		const P3DPoint2D &w1 = (P3DPoint2D&) pVertexDataByte[i1*dwVertexStride + dwTexccordOffset];
		const P3DPoint2D &w2 = (P3DPoint2D&) pVertexDataByte[i2*dwVertexStride + dwTexccordOffset];
		const P3DPoint2D &w3 = (P3DPoint2D&) pVertexDataByte[i3*dwVertexStride + dwTexccordOffset];

		float x1 = v2.x - v1.x;
		float x2 = v3.x - v1.x;
		float y1 = v2.y - v1.y;
		float y2 = v3.y - v1.y;
		float z1 = v2.z - v1.z;
		float z2 = v3.z - v1.z;

		float s1 = w2.x - w1.x;
		float s2 = w3.x - w1.x;
		float t1 = w2.y - w1.y;
		float t2 = w3.y - w1.y;

		float r = 1.0F / (s1 * t2 - s2 * t1);
		P3DXVector3D sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
			(t2 * z1 - t1 * z2) * r);
		P3DXVector3D tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,
			(s1 * z2 - s2 * z1) * r);

		tan1[i1] += sdir;
		tan1[i2] += sdir;
		tan1[i3] += sdir;

		tan2[i1] += tdir;
		tan2[i2] += tdir;
		tan2[i3] += tdir;
	}

	for (long a = 0; a < vertexCount; a++)
	{
		const P3DXVector3D &n = (P3DXVector3D&) pVertexDataByte[a*dwVertexStride + dwNormalOffset];
		const P3DXVector3D& t = tan1[a];

		// Gram-Schmidt orthogonalize
		P3DXVector3D vecTangent = t - n * (n * t);
		vecTangent.Normalize ();
		// set tangent
		P3DXVector3D &tangent = (P3DXVector3D&) pVertexDataByte[a*dwVertexStride + dwTangentOffset];
		tangent = vecTangent;

		// Calculate handedness
		float handedness = (((n % t) * tan2[a]) < 0.0F) ? -1.0F : 1.0F;
		// binormal = normal x tangent
		P3DXVector3D vecBinormal = (n % vecTangent) * handedness;
		vecBinormal.Normalize();
		// set binormal
		P3DXVector3D &binormal = (P3DXVector3D&) pVertexDataByte[a*dwVertexStride + dwBinormalOffset];
		binormal = vecBinormal;
	}

	delete[] tan1;
	pMesh->UnlockIndexBuffer();
	pMesh->UnlockVertexBuffer();

	return true;
}
Beispiel #7
0
void ObjGPUData::loadObject(const char* fileName)
{
    std::string folderName = fileName;

    for(int i = folderName.size() - 1; i >= 0; i--)
    {
        if(folderName[i] == '/' || folderName[i] == '\\')
        {
            folderName = folderName.substr(0, i+1);
            break;
        }
        if(i == 0)
            folderName = "";
    }

    std::string objFileName = fileName;
    std::string mtlFileName = fileName;
    objFileName += ".obj";
    mtlFileName += ".mtl";

    std::ifstream mtlFile(mtlFileName.c_str(), std::ios::in);

    if(!mtlFile.is_open())
    {
        printf("Failed to open object %s\n", objFileName.c_str());
        exit(1);
    }

    std::string dataTypeString;
    float xVal, yVal, zVal;
    std::string valString;
    std::stringstream valStream;
    int iVal;

    while(mtlFile >> dataTypeString)
    {

        mtlDataType mtlDataTypeVal = getMtlDataType(dataTypeString);

        switch(mtlDataTypeVal)
        {
        case mtlDataType::mtlDataNEWMTL:
            mtlFile >> valString;
            materials.push_back(Material(valString));
            valString.clear();
            break;

        case mtlDataType::mtlDataNS:
            mtlFile >> xVal;
            materials.back().shine = xVal;
            break;

        case mtlDataType::mtlDataKA:
            mtlFile >> xVal;
            mtlFile >> yVal;
            mtlFile >> zVal;

            materials.back().Ka = glm::vec3(xVal, yVal, zVal);

            break;

        case mtlDataType::mtlDataKD:
            mtlFile >> xVal;
            mtlFile >> yVal;
            mtlFile >> zVal;

            materials.back().Kd = glm::vec3(xVal, yVal, zVal);

            break;

        case mtlDataType::mtlDataKS:
            mtlFile >> xVal;
            mtlFile >> yVal;
            mtlFile >> zVal;

            materials.back().Ks = glm::vec3(xVal, yVal, zVal);

            break;

        case mtlDataType::mtlDataMAP:
        {
            if(materials.back().textureSet)
                break;
            getline(mtlFile, valString);
            int fileNameLocation = valString.find_last_of("/\\");
            if(fileNameLocation != -1)
                valString = valString.substr(fileNameLocation + 1);
            while(valString[0] == ' ' || valString[0] == '\t')
                valString = valString.substr(1);
            if(valString.size() < 4 || valString.substr(valString.size() - 4) != ".dds")
            {
                valString = valString.substr(0, valString.find_last_of('.') + 1);
                valString += "dds";
            }
            materials.back().textureName = valString;
            bool textureExists = false;
            for(int i = 0; i < materials.size() - 1; i++)
            {
                if(materials[i].textureName == valString)
                {
                    textureExists = true;
                    materials.back().texture = materials[i].texture;
                    break;
                }
            }
            if(textureExists)
            {
                valString.clear();
                break;
            }
            materials.back().texture = loadImage((folderName + valString).c_str());
            materials.back().textureSet = true;
            valString.clear();
            break;
        }

        case mtlDataType::mtlDataBUMP:
        {
            if(materials.back().bumpSet)
                break;
            getline(mtlFile, valString);
            int fileNameLocation = valString.find_last_of("/\\");
            if(fileNameLocation != -1)
                valString = valString.substr(fileNameLocation + 1);
            while(valString[0] == ' ' || valString[0] == '\t')
                valString = valString.substr(1);
            if(valString.size() < 4 || valString.substr(valString.size() - 4) != ".dds")
            {
                valString = valString.substr(0, valString.find_last_of('.') + 1);
                valString += "dds";
            }
            materials.back().bumpName = valString;
            bool bumpExists = false;
            for(int i = 0; i < materials.size() - 1; i++)
            {
                if(materials[i].bumpName == valString)
                {
                    bumpExists = true;
                    materials.back().bump = materials[i].bump;
                    break;
                }
            }
            if(bumpExists)
            {
                valString.clear();
                break;
            }
            materials.back().bump = loadImage((folderName + valString).c_str());
            materials.back().bumpSet = true;
            valString.clear();
            break;
        }

        default:
            break;
        }
    }

    mtlFile.close();

    printf("Loading object %s... ", objFileName.c_str());

    std::ifstream objFile(objFileName.c_str(), std::ios::in);

    if(!objFile.is_open())
    {
        printf("Failed to open object %s\n", objFileName.c_str());
        exit(1);
    }

    std::vector<glm::vec3> vList_in;
    std::vector<glm::vec2> vTextureList_in;
    std::vector<glm::vec3> vNormalList_in;
    std::vector<GLuint> iVertex;
    std::vector<GLuint> iTexture;
    std::vector<GLuint> iNormal;

    std::vector<unsigned int> materialIndices_in;

    while(objFile >> dataTypeString)
    {

        dataType dataTypeVal = getDataType(dataTypeString);

        switch(dataTypeVal)
        {
        case dataType::dataV:
            objFile >> xVal;
            objFile >> yVal;
            objFile >> zVal;

            vList_in.push_back(glm::vec3(xVal, yVal, zVal));

            break;

        case dataType::dataVT:
            objFile >> xVal;
            objFile >> yVal;

            vTextureList_in.push_back(glm::vec2(xVal, yVal));

            break;

        case dataType::dataVN:
            objFile >> xVal;
            objFile >> yVal;
            objFile >> zVal;

            vNormalList_in.push_back(glm::vec3(xVal, yVal, zVal));

            break;

        case dataType::dataUSEMTL:
        {
            int index = -1;
            objFile >> valString;

            for(int i = 0; i < materials.size(); i++)
            {
                if(materials[i].materialName == valString)
                {
                    index = i;
                    break;
                }
            }

            if(index == -1)
                exit(1);

            valString.clear();

            materialIndices_in.push_back(iVertex.size());
            materialIndices_in.push_back(index);

            break;
        }


        case dataType::dataF:
        {
            char lastChar;

            for(int i = 0; i < 3; i++)
            {
                getline(objFile, valString, '/');
                valStream << valString;
                valString.clear();
                valStream >> iVal;
                valStream.str(std::string());
                valStream.clear();
                iVertex.push_back(iVal);

                getline(objFile, valString, '/');
                valStream << valString;
                valString.clear();
                valStream >> iVal;
                valStream.str(std::string());
                valStream.clear();
                iTexture.push_back(iVal);

                objFile >> iVal;
                iNormal.push_back(iVal);

                lastChar = objFile.get();
            }

            if(lastChar != '\n')
            {
                while(objFile.peek() == ' ' || objFile.peek() == '\t')
                {
                    objFile.get();
                }

                if(objFile.peek() == '\n')
                    break;

                iVertex.push_back(iVertex[iVertex.size() - 3]);
                iTexture.push_back(iTexture[iTexture.size() - 3]);
                iNormal.push_back(iNormal[iNormal.size() - 3]);

                iVertex.push_back(iVertex[iVertex.size() - 2]);
                iTexture.push_back(iTexture[iTexture.size() - 2]);
                iNormal.push_back(iNormal[iNormal.size() - 2]);

                getline(objFile, valString, '/');
                valStream << valString;
                valString.clear();
                valStream >> iVal;
                valStream.str(std::string());
                valStream.clear();
                iVertex.push_back(iVal);

                getline(objFile, valString, '/');
                valStream << valString;
                valString.clear();
                valStream >> iVal;
                valStream.str(std::string());
                valStream.clear();
                iTexture.push_back(iVal);

                objFile >> iVal;
                iNormal.push_back(iVal);
            }

            break;
        }

        default:
            break;
        }
    }

    objFile.close();

    int first, last;

    std::map<FullVertex,unsigned int> vertexToOutIndex;

    for(int k = 0; k < materialIndices_in.size()/2; ++k)
    {

        first = materialIndices_in[2*k];
        if((2*k + 2) > (materialIndices_in.size() - 1))
            last = iVertex.size();
        else
            last = materialIndices_in[2*k + 2];

        materialIndices.push_back(fList.size());
        materialIndices.push_back(materialIndices_in[2*k + 1]);

        for(int i = first; i < last; i++)
        {

            FullVertex nextVertex = {vList_in[iVertex[i] - 1], vTextureList_in[iTexture[i] - 1], vNormalList_in[iNormal[i] - 1]};

            std::map<FullVertex,unsigned int>::iterator vLocation = vertexToOutIndex.find(nextVertex);

            if(vLocation == vertexToOutIndex.end())
            {
                vList.push_back(vList_in[iVertex[i]-1]);
                vTextureList.push_back(vTextureList_in[iTexture[i]-1]);
                vNormalList.push_back(vNormalList_in[iNormal[i]-1]);

                vertexToOutIndex[nextVertex] = vList.size() - 1;
                fList.push_back(vList.size() - 1);
            }
            else
            {
                fList.push_back(vLocation->second);
            }
        }
    }


    //  Invert all texture v-coordinates for use with DXT compression textures

    for(int i = 0; i < vTextureList.size(); i++)
    {
        vTextureList[i][1] = 1 - vTextureList[i][1];
    }


    //  Generate tangent vectors for normals
    //  Sourced from http://www.terathon.com/code/tangent.html

    std::vector<glm::vec3> tan1(vList.size());
    std::vector<glm::vec3> tan2(vList.size());

    for (unsigned int a = 0; a < fList.size(); a+=3)
    {
        GLuint i1 = fList[a + 0];
        GLuint i2 = fList[a + 1];
        GLuint i3 = fList[a + 2];

        glm::vec3 v1 = vList[i1];
        glm::vec3 v2 = vList[i2];
        glm::vec3 v3 = vList[i3];

        glm::vec2 w1 = vTextureList[i1];
        glm::vec2 w2 = vTextureList[i2];
        glm::vec2 w3 = vTextureList[i3];

        float x1 = v2.x - v1.x;
        float x2 = v3.x - v1.x;
        float y1 = v2.y - v1.y;
        float y2 = v3.y - v1.y;
        float z1 = v2.z - v1.z;
        float z2 = v3.z - v1.z;

        float s1 = w2.x - w1.x;
        float s2 = w3.x - w1.x;
        float t1 = w2.y - w1.y;
        float t2 = w3.y - w1.y;

        float r = 1.0f / (s1 * t2 - s2 * t1);

        glm::vec3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
        glm::vec3 tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);

        tan1[i1] += sdir;
        tan1[i2] += sdir;
        tan1[i3] += sdir;

        tan2[i1] += tdir;
        tan2[i2] += tdir;
        tan2[i3] += tdir;
    }

    for (unsigned int a = 0; a < vList.size(); a++)
    {
        glm::vec3 n = vNormalList[a];
        glm::vec3 t = tan1[a];

        // Gram-Schmidt orthogonalize
        glm::vec4 tangent = glm::vec4(glm::normalize(t - n * glm::dot(n, t)), 0.0f);

        // Calculate handedness
        tangent.w = (glm::dot(glm::cross(n, t), tan2[a]) < 0.0f) ? -1.0f : 1.0f;

        vTangentList.push_back(tangent);
    }

    printf("DONE\n");

    return;

}
void Model::computeTangentSpace()
{
	for(int iMesh = 0; iMesh < m_NumMeshes; iMesh++)
	{
		if(m_pMesh.size() <= 0)break;

		Mesh *p_Mesh = &m_pMesh[iMesh];

		t_TangentSpace *p_TmpTangentSpace = new t_TangentSpace[p_Mesh->m_NumFaces];
		memset(p_TmpTangentSpace, 0, sizeof(t_TangentSpace) * p_Mesh->m_NumFaces);

		p_Mesh->m_pTangentSpace = new t_TangentSpace [p_Mesh->m_NumVerts];

		for(int i = 0; i < p_Mesh->m_NumFaces; i++)
		{
			int i1 = p_Mesh->m_pFaces[i].vertIndex[0];
			int i2 = p_Mesh->m_pFaces[i].vertIndex[1];
			int i3 = p_Mesh->m_pFaces[i].vertIndex[2];

			Vec3 p1 = p_Mesh->m_pVerts[i1];
			Vec3 p2 = p_Mesh->m_pVerts[i2];
			Vec3 p3 = p_Mesh->m_pVerts[i3];

			Vec3 v1 = p2 - p1;
			Vec3 v2 = p3 - p1;

			p_TmpTangentSpace[i].normal = Cross(v1, v2);

			Vec2 w1 = p_Mesh->m_pTexVerts[i1];
			Vec2 w2 = p_Mesh->m_pTexVerts[i2];
			Vec2 w3 = p_Mesh->m_pTexVerts[i3];

			float s1 = w2.x - w1.x;
			float s2 = w3.x - w1.x;
			float t1 = w2.y - w1.y;
			float t2 = w3.y - w1.y;

			float r = 1.0f / (s1 * t2 - s2 *t1);
			
			Vec3 sdir((t2 * v1.x - t1 * v2.x) * r, (t2 * v1.y - t1 * v2.y) * r, (t2 * v1.z - t1 * v2.z) * r);
			Vec3 tdir((s1 * v2.x - s2 * v1.x) * r, (s1 * v2.y - s2 * v1.y) * r, (s1 * v2.z - s2 * v1.z) * r);

			p_TmpTangentSpace[i].tangent += sdir;
			p_TmpTangentSpace[i].tangent.Normalize();

			p_TmpTangentSpace[i].binormal += tdir;
			p_TmpTangentSpace[i].binormal = -Normalize(p_TmpTangentSpace[i].binormal);
		}

		Vec3 normalSum = Vec3(0.0, 0.0, 0.0);
		Vec3 binormalSum = Vec3(0.0, 0.0, 0.0);
		Vec3 tangentSum = Vec3(0.0, 0.0, 0.0);
		int shared = 0;
		int sharedn = 0;

		for (int i = 0; i < p_Mesh->m_NumVerts; i++)
		{
			DWORD smoothGroup;
			for (int j = 0; j < p_Mesh->m_NumFaces; j++)
			{
				if (p_Mesh->m_pFaces[j].vertIndex[0] == i || 
					p_Mesh->m_pFaces[j].vertIndex[1] == i || 
					p_Mesh->m_pFaces[j].vertIndex[2] == i)
				{
					smoothGroup  = p_Mesh->m_pFaces[j].smoothGroup;
					normalSum	+= p_TmpTangentSpace[j].normal;
					binormalSum	+= p_TmpTangentSpace[j].binormal;
					tangentSum  += p_TmpTangentSpace[j].tangent;
					shared++;
					sharedn++;

				}
			}

			Vec3 vertPos = p_Mesh->m_pVerts[i];

		for (int j = 0; j < p_Mesh->m_NumFaces; j++)
			{
				t_Face *p_Face = &p_Mesh->m_pFaces[j];

				for(int k = 0; k < 3; k++)
				{
					if (p_Face->vertIndex[k] != i && p_Mesh->m_pVerts[ p_Face->vertIndex[k] ] == vertPos && p_Face->smoothGroup == smoothGroup)
					{
						//smoothGroup  = p_Mesh->m_pFaces[j].smoothGroup;
						normalSum	+= p_TmpTangentSpace[j].normal;
						binormalSum	+= p_TmpTangentSpace[j].binormal;
						tangentSum  += p_TmpTangentSpace[j].tangent;
						sharedn++;
					}
				}

			}

			p_Mesh->m_pTangentSpace[i].normal = normalSum / (float)sharedn;
			p_Mesh->m_pTangentSpace[i].normal.Normalize();
			p_Mesh->m_pTangentSpace[i].binormal = binormalSum / (float)sharedn;
			p_Mesh->m_pTangentSpace[i].binormal.Normalize();
			p_Mesh->m_pTangentSpace[i].tangent = tangentSum / (float)sharedn;
			p_Mesh->m_pTangentSpace[i].tangent.Normalize();

			normalSum	= Vec3(0.0, 0.0, 0.0);
			binormalSum	= Vec3(0.0, 0.0, 0.0);
			tangentSum	= Vec3(0.0, 0.0, 0.0);
			shared = 0;
		}

		delete [] p_TmpTangentSpace;
	}
}
Beispiel #9
0
static
void
generateTangentAndHandednessBuffer( osgCal::MeshData* m,
                                    const CalIndex*   indexBuffer )
{
    if ( !m->texCoordBuffer.valid() )
    {
        return;
    }

    int vertexCount = m->vertexBuffer->size();
    int faceCount   = m->getIndicesCount() / 3;    

    m->tangentAndHandednessBuffer = new TangentAndHandednessBuffer( vertexCount );

    CalVector* tan1 = new CalVector[vertexCount];
    CalVector* tan2 = new CalVector[vertexCount];

    const GLfloat* texCoordBufferData = (GLfloat*) m->texCoordBuffer->getDataPointer();

    const GLfloat* vb = (GLfloat*) m->vertexBuffer->getDataPointer();
#ifdef OSG_CAL_BYTE_BUFFERS
    GLfloat* thb = new GLfloat[ vertexCount*4 ];
    const GLfloat* nb = floatNormalBuffer;
#else
    GLfloat* thb = (GLfloat*) m->tangentAndHandednessBuffer->getDataPointer();
//    GLshort* thb = (GLshort*) m->tangentAndHandednessBuffer->getDataPointer();
    const GLfloat* nb = (GLfloat*) m->normalBuffer->getDataPointer();
#endif

    for ( int face = 0; face < faceCount; face++ )
    {
        for ( int j = 0; j < 3; j++ )
        {
            // there seems to be no visual difference in calculating
            // tangent per vertex (as is tan1[i1] += spos(j=0,1,2))
            // or per face (tan1[i1,i2,i3] += spos)
            CalIndex i1 = indexBuffer[face*3+(j+0)%3];
            CalIndex i2 = indexBuffer[face*3+(j+1)%3];
            CalIndex i3 = indexBuffer[face*3+(j+2)%3];
        
            const float* v1 = &vb[i1*3];
            const float* v2 = &vb[i2*3];
            const float* v3 = &vb[i3*3];

            const float* w1 = &texCoordBufferData[i1*2];
            const float* w2 = &texCoordBufferData[i2*2];
            const float* w3 = &texCoordBufferData[i3*2];

#define x(_a) (_a[0])
#define y(_a) (_a[1])
#define z(_a) (_a[2])
        
            float x1 = x(v2) - x(v1);
            float x2 = x(v3) - x(v1);
            float y1 = y(v2) - y(v1);
            float y2 = y(v3) - y(v1);
            float z1 = z(v2) - z(v1);
            float z2 = z(v3) - z(v1);
        
            float s1 = x(w2) - x(w1);
            float s2 = x(w3) - x(w1);
            float t1 = y(w2) - y(w1);
            float t2 = y(w3) - y(w1);

#undef x
#undef y
#undef z
        
            //float r = 1.0F / (s1 * t2 - s2 * t1);
            float r = (s1 * t2 - s2 * t1) < 0 ? -1.0 : 1.0;
            CalVector sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
                           (t2 * z1 - t1 * z2) * r);
            CalVector tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,
                           (s1 * z2 - s2 * z1) * r);

            // sdir & tdir can be 0 (when UV unwrap doesn't exists
            // or has errors like coincide points)
            // we ignore them
            if ( sdir.length() > 0 )
            {
                sdir.normalize(); 

                tan1[i1] += sdir;
                //tan1[i2] += sdir;
                //tan1[i3] += sdir;
            }

            if ( tdir.length() > 0 )
            {
                tdir.normalize();

                tan2[i1] += tdir;
                //tan2[i2] += tdir;
                //tan2[i3] += tdir;
            }
        }
    }
    
    for (long a = 0; a < vertexCount; a++)
    {
        CalVector tangent;
        CalVector binormal;
        CalVector t = tan1[a];
        CalVector b = tan2[a];
        CalVector n = CalVector( nb[a*3+0],
                                 nb[a*3+1],
                                 nb[a*3+2] );

        // tangent & bitangent can be zero when UV unwrap doesn't exists
        // or has errors like coincide points
        if ( t.length() > 0 )
        {
            t.normalize();
        
            // Gram-Schmidt orthogonalize
            tangent = t - n * (n*t);
            tangent.normalize();

            // Calculate handedness
            binormal = CalVector(n % tangent) *
                ((((n % t) * b) < 0.0F) ? -1.0f : 1.0f);
            binormal.normalize();
        }
        else if ( b.length() > 0 )
        {
            b.normalize();
        
            // Gram-Schmidt orthogonalize
            binormal = b - n * (n*b);
            binormal.normalize();

            // Calculate handedness
            tangent = CalVector(n % binormal) *
                ((((n % b) * t) < 0.0F) ? -1.0f : 1.0f);
            tangent.normalize();
        }

//         std::cout << "t = " << tangent.x  << '\t' << tangent.y  << '\t' << tangent.z  << '\n';
//         std::cout << "b = " << binormal.x << '\t' << binormal.y << '\t' << binormal.z << '\n';
//            std::cout << "n = " << n.x        << '\t' << n.y        << '\t' << n.z        << '\n';

//         thb[a*4+0] = floatToHalf( tangent.x ); //tangent.x * 0x7FFF;
//         thb[a*4+1] = floatToHalf( tangent.y ); //tangent.y * 0x7FFF;
//         thb[a*4+2] = floatToHalf( tangent.z ); //tangent.z * 0x7FFF;
//         thb[a*4+3] = floatToHalf((((n % tangent) * binormal) > 0.0F) ? -1.0f : 1.0f); // handedness
        thb[a*4+0] = tangent.x; 
        thb[a*4+1] = tangent.y;
        thb[a*4+2] = tangent.z;
        thb[a*4+3] = ((((n % tangent) * binormal) > 0.0F) ? -1.0f : 1.0f); // handedness
    }
    
    delete[] tan1;
    delete[] tan2;

#ifdef OSG_CAL_BYTE_BUFFERS
    GLbyte* tangents = (GLbyte*) tangentBuffer->getDataPointer();
    GLbyte* binormals = (GLbyte*) binormalBuffer->getDataPointer();

    for ( int i = 0; i < vertexCount*3; i++ )
    {
        tangents[i]  = static_cast< GLbyte >( tangentBuffer[i]*127.0 );
        binormals[i] = static_cast< GLbyte >( binormalBuffer[i]*127.0 );
        //std::cout << (int)tangents[i] << '\n';
    }

    delete[] tangentBuffer;
    delete[] binormalBuffer;
#endif
}
void calculateTangents( const void* pVertices, size_t numVertices,
                        uint32 posOff, uint32 texOff, uint32 normOff, uint32 vertStride,
                        const void* pIndices, size_t numIndices, gfx::IndexStride indexStride,
                        he::PrimitiveList<vec3>& outTangents)
{
    he::PrimitiveList<vec3> tan1(numVertices);
    tan1.resize(numVertices);

    const char* pCharVertices(static_cast<const char*>(pVertices));

    const uint16* indicesUShort(nullptr); 
    const uint32* indicesUInt(nullptr); 
    
    if (indexStride == gfx::IndexStride_UShort)
        indicesUShort = static_cast<const uint16*>(pIndices);
    else if (indexStride == gfx::IndexStride_UInt)
        indicesUInt = static_cast<const uint32*>(pIndices);
    else
        LOG(LogType_ProgrammerAssert, "unkown index stride: %d", indexStride);
    
    for (uint32 i = 0; i < numIndices; i += 3) //per triangle
    {
        uint32 i1(0), i2(0), i3(0);
        if (indexStride == gfx::IndexStride_UShort)
        {
            i1 = indicesUShort[i];
            i2 = indicesUShort[i + 1];
            i3 = indicesUShort[i + 2];
        }
        else if (indexStride == gfx::IndexStride_UInt)
        {
            i1 = indicesUInt[i];
            i2 = indicesUInt[i + 1];
            i3 = indicesUInt[i + 2];
        }

        const vec3& v1 = *reinterpret_cast<const vec3*>(pCharVertices + (i1 * vertStride + posOff));
        const vec3& v2 = *reinterpret_cast<const vec3*>(pCharVertices + (i2 * vertStride + posOff));
        const vec3& v3 = *reinterpret_cast<const vec3*>(pCharVertices + (i3 * vertStride + posOff));

        const vec2& tx1 = *reinterpret_cast<const vec2*>(pCharVertices + (i1 * vertStride + texOff));
        const vec2& tx2 = *reinterpret_cast<const vec2*>(pCharVertices + (i2 * vertStride + texOff));
        const vec2& tx3 = *reinterpret_cast<const vec2*>(pCharVertices + (i3 * vertStride + texOff));

        float x1 = v2.x - v1.x;
        float x2 = v3.x - v1.x;
        float y1 = v2.y - v1.y;
        float y2 = v3.y - v1.y;
        float z1 = v2.z - v1.z;
        float z2 = v3.z - v1.z;

        float s1 = tx2.x - tx1.x;
        float s2 = tx3.x - tx1.x;
        float t1 = tx2.y - tx1.y;
        float t2 = tx3.y - tx1.y;

        float r = 1.0f / (s1 * t2 - s2 * t1);

        vec3 sdir(
            (t2 * x1 - t1 * x2) * r, 
            (t2 * y1 - t1 * y2) * r, 
            (t2 * z1 - t1 * z2) * r );
        vec3 tdir(
            (s1 * x2 - s2 * x1) * r, 
            (s1 * y2 - s2 * y1) * r, 
            (s1 * z2 - s2 * z1) * r );

        tan1[i1] += sdir;
        tan1[i2] += sdir;
        tan1[i3] += sdir;
    }

    for (uint32 i = 0; i < numVertices; ++i)
    {
        const vec3& n = *reinterpret_cast<const vec3*>(pCharVertices + (i * vertStride + normOff));
        const vec3& t = tan1[i];

        outTangents.add(normalize(t - n * dot(n, t)));
    }
}
void CHLSL_Mesh::GenerateTangentSpace()
{
	//for ( int t = 0; t < m_iNumTriangles; t++ )
	//{
	//	CHLSL_Triangle &tri = m_Triangles[ t ];
	//	for ( int v = 0; v < 3; v++ )
	//	{
	//		CHLSL_Vertex &vert = tri.vertices[ v ];
	//	}
	//}

	for (int a = 0; a < m_iNumVertices; a++)
	{
		CHLSL_Vertex &vert = m_Vertices[a];
		Q_memset( vert.tangent_s, 0, sizeof( float ) * 4 );
		Q_memset( vert.tangent_t, 0, sizeof( float ) * 3 );
	}

	CHLSL_Triangle *tri = m_Triangles;
    for (int a = 0; a < m_iNumTriangles; a++)
    {
		CHLSL_Vertex &vert_1 = *tri->vertices[0];
		CHLSL_Vertex &vert_2 = *tri->vertices[1];
		CHLSL_Vertex &vert_3 = *tri->vertices[2];

		Vector v1;
		Vector v2;
		Vector v3;
		VectorCopy( vert_1.pos, v1.Base() );
		VectorCopy( vert_2.pos, v2.Base() );
		VectorCopy( vert_3.pos, v3.Base() );
#if 0
		Vector w1( vert_1.uv[0][0], vert_1.uv[0][1], 0 );
		Vector w2( vert_2.uv[0][0], vert_2.uv[0][1], 0 );
		Vector w3( vert_3.uv[0][0], vert_3.uv[0][1], 0 );

		Vector tan_s_2d( 1, 0, 0 );
		Vector tan_t_2d( 0, 1, 0 );
		Vector delta_vert2 = v2 - v1;
		Vector delta_vert3 = v3 - v1;
		Vector delta_uv2 = w2 - w1;
		Vector delta_uv3 = w3 - w1;

		Vector n;
		VectorCopy( vert_1.normal, n.Base() );
		delta_vert2 -= DotProduct( delta_vert2, n ) * n;
		delta_vert3 -= DotProduct( delta_vert3, n ) * n;

		//delta_vert2.NormalizeInPlace();
		//delta_vert3.NormalizeInPlace();
		delta_uv2.NormalizeInPlace();
		delta_uv3.NormalizeInPlace();

		Vector sdir( vec3_origin );
		Vector tdir( vec3_origin );

		sdir += DotProduct( tan_s_2d, delta_uv2 ) * delta_vert2;
		sdir += DotProduct( tan_s_2d, delta_uv3 ) * delta_vert3;

		tdir += DotProduct( tan_t_2d, delta_uv2 ) * delta_vert2;
		tdir += DotProduct( tan_t_2d, delta_uv3 ) * delta_vert3;
#else
		
		Vector2D w1( vert_1.uv[0][0], vert_1.uv[0][1] );
		Vector2D w2( vert_2.uv[0][0], vert_2.uv[0][1] );
		Vector2D w3( vert_3.uv[0][0], vert_3.uv[0][1] );

		float x1 = v2.x - v1.x;
		float x2 = v3.x - v1.x;
		float y1 = v2.y - v1.y;
		float y2 = v3.y - v1.y;
		float z1 = v2.z - v1.z;
		float z2 = v3.z - v1.z;

		float s1 = w2.x - w1.x;
		float s2 = w3.x - w1.x;
		float t1 = w2.y - w1.y;
		float t2 = w3.y - w1.y;

		float r = (s1 * t2 - s2 * t1);
		if ( r != 0 )
			r = 1.0f / r;

		Vector sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
				(t2 * z1 - t1 * z2) * r);
		Vector tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,
				(s1 * z2 - s2 * z1) * r);
	
#endif
		for ( int i = 0; i < 3; i++ )
		{
			Assert( IsFinite( vert_1.tangent_s[i] ) );
			Assert( IsFinite( vert_2.tangent_s[i] ) );
			Assert( IsFinite( vert_3.tangent_s[i] ) );
			Assert( IsFinite( vert_1.tangent_t[i] ) );
			Assert( IsFinite( vert_2.tangent_t[i] ) );
			Assert( IsFinite( vert_3.tangent_t[i] ) );

			vert_1.tangent_s[i] += sdir[i];
			vert_2.tangent_s[i] += sdir[i];
			vert_3.tangent_s[i] += sdir[i];

			vert_1.tangent_t[i] += tdir[i];
			vert_2.tangent_t[i] += tdir[i];
			vert_3.tangent_t[i] += tdir[i];
		}
        //tan1[i1] += sdir;
        //tan1[i2] += sdir;
        //tan1[i3] += sdir;
        //
        //tan2[i1] += tdir;
        //tan2[i2] += tdir;
        //tan2[i3] += tdir;
        
        tri++;
    }
    for (int a = 0; a < m_iNumVertices; a++)
	{
		CHLSL_Vertex &vert = m_Vertices[a];

		Vector n;
		Vector s;
		Vector t;
		VectorCopy( vert.normal, n.Base() );
		VectorCopy( vert.tangent_s, s.Base() );
		VectorCopy( vert.tangent_t, t.Base() );

		n.NormalizeInPlace();
		s.NormalizeInPlace();
		t.NormalizeInPlace();

#if 0
		Vector delta = s + ( t - s ) * 0.5f;
		Vector bidelta;
		CrossProduct( delta, n, bidelta );
		t = bidelta + ( delta - bidelta ) * 0.5f;
		t -= n * DotProduct( t, n );
		t.NormalizeInPlace();
		CrossProduct( n, t, s );
		s.NormalizeInPlace();
#endif
#if 1
		//if ( !IsFinite(t.x) || !IsFinite(t.y) || !IsFinite(t.z) )
		//	t.Init(0,0,1);
		//if ( !IsFinite(s.x) || !IsFinite(s.y) || !IsFinite(s.z) )
		//	s.Init(0,0,1);
		s = (s - n * DotProduct(n, s));
		t = (t - n * DotProduct(n, t)) * -1.0f;
		s.NormalizeInPlace();
		t.NormalizeInPlace();
		float w = (DotProduct(CrossProduct(n, s), t) < 0.0F) ? 1.0F : -1.0F;

#endif

		//t *= -1.0f;
		VectorCopy( s.Base(), vert.tangent_s );
		VectorCopy( t.Base(), vert.tangent_t );

		vert.tangent_s[3] = w;

	}
    
  //  for (long a = 0; a < m_iNumVertices; a++)
  //  {
		//CHLSL_Vertex &vert = *m_Vertices[a];
  //     // const Vector& n = 
		//Vector normal( vert.pos[0], vert.pos[1], vert.pos[2] );
  //      const Vector& t = tan1[a];
  //      
  //      // Gram-Schmidt orthogonalize
  //      tangent[a] = VectorNormalize( (t - n * DotProduct(n, t)) );
  //      
  //      // Calculate handedness
  //      tangent[a].w = (Dot(Cross(n, t), tan2[a]) < 0.0F) ? -1.0F : 1.0F;
  //  }
}
bool BatchGeom::add_tangent_space(){
	if (m_indices == NULL) return false;
	if (!find_attribute(ATT_TEXCOORD) ) return false;    
	if (m_primitive_type != PRIM_TRIANGLES) return false;    
	if (!find_attribute(ATT_TANGENT_S) && !insert_attribute(ATT_TANGENT_S, 3) ) return false;
	if (!find_attribute(ATT_TANGENT_T) && !insert_attribute(ATT_TANGENT_T, 3) ) return false;

	for(unsigned int i=0; i<m_num_indices; ++i) {
		get_tangent_s_by_index( i ) = noVec3( 0.0f, 0.0f, 0.0f );
		get_tangent_t_by_index( i ) = noVec3( 0.0f, 0.0f, 0.0f );		
	}

	for(unsigned int i=0; i<m_num_indices; i+=3) {
		const noVec3 v1 = get_vertex_by_index( i+0 );
		const noVec3 v2 = get_vertex_by_index( i+1 );
		const noVec3 v3 = get_vertex_by_index( i+2 );
		const noVec2 w1 = get_texcoord_by_index( i+0 );
		const noVec2 w2 = get_texcoord_by_index( i+1 );
		const noVec2 w3 = get_texcoord_by_index( i+2 );

		float x1 = v2.x - v1.x;
		float x2 = v3.x - v1.x;
		float y1 = v2.y - v1.y;
		float y2 = v3.y - v1.y;
		float z1 = v2.z - v1.z;
		float z2 = v3.z - v1.z;

		float s1 = w2.x - w1.x;
		float s2 = w3.x - w1.x;
		float t1 = w2.y - w1.y;
		float t2 = w3.y - w1.y;

		float r;

		if(fabs(s1*t2 - s2*t1) <= 0.0001f) {
			r = 1.0f;
		} else {
			r = 1.0f / (s1*t2 - s2*t1);
		}
		noVec3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
		noVec3 tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);

		get_tangent_s_by_index( i+0 ) += sdir;
		get_tangent_s_by_index( i+1 ) += sdir;
		get_tangent_s_by_index( i+2 ) += sdir;

		get_tangent_t_by_index( i+0 ) += tdir;
		get_tangent_t_by_index( i+1 ) += tdir;
		get_tangent_t_by_index( i+2 ) += tdir;		
	}

	for(unsigned int i=0; i<m_num_vertices; ++i) {
		const noVec3 n = get_normal(i);

		// Gram-Schmidt orthogonalize
		get_tangent_t(i) = (get_tangent_t(i) - n * n * get_tangent_t(i)).NormalizeCopy();
		get_tangent_s(i) = (get_tangent_s(i) - n * n * get_tangent_s(i) - n * (n * get_tangent_t(i))).NormalizeCopy();
	}

	return true;   
}
Beispiel #13
0
/*! 
SLMesh::calcTangents computes the tangent and bi-tangent per vertex used for 
GLSL normal map bumb mapping. The code and mathematical derivation is in detail 
explained in: http://www.terathon.com/code/tangent.html
*/
void SLMesh::calcTangents()
{
   if (P && N && Tc)
   {
      // allocat tangents
      delete[] T;
      T = new SLVec4f[numV];
      
      // allocate temp arrays for tangents
      SLVec3f* T1 = new SLVec3f[numV * 2];
      SLVec3f* T2 = T1 + numV;
      memset(T1, 0, numV * sizeof(SLVec3f) * 2);

      for (SLuint m = 0; m < numM; ++m)
      {  for (SLuint f = 0; f < M[m].numF; ++f)
         {
            // Get the 3 vertex indexes
            SLushort iVA = F[M[m].startF + f].iA;
            SLushort iVB = F[M[m].startF + f].iB;
            SLushort iVC = F[M[m].startF + f].iC;

            float x1 = P[iVB].x - P[iVA].x;
            float x2 = P[iVC].x - P[iVA].x;
            float y1 = P[iVB].y - P[iVA].y;
            float y2 = P[iVC].y - P[iVA].y;
            float z1 = P[iVB].z - P[iVA].z;
            float z2 = P[iVC].z - P[iVA].z;

            float s1 = Tc[iVB].x - Tc[iVA].x;
            float s2 = Tc[iVC].x - Tc[iVA].x;
            float t1 = Tc[iVB].y - Tc[iVA].y;
            float t2 = Tc[iVC].y - Tc[iVA].y;

            float r = 1.0F / (s1*t2 - s2*t1);
            SLVec3f sdir((t2*x1 - t1*x2) * r, (t2*y1 - t1*y2) * r, (t2*z1 - t1*z2) * r);
            SLVec3f tdir((s1*x2 - s2*x1) * r, (s1*y2 - s2*y1) * r, (s1*z2 - s2*z1) * r);

            T1[iVA] += sdir;
            T1[iVB] += sdir;
            T1[iVC] += sdir;

            T2[iVA] += tdir;
            T2[iVB] += tdir;
            T2[iVC] += tdir;
         }
      }
       
       for (SLuint i=0; i < numV; ++i)
       {
           // Gram-Schmidt orthogonalize
           T[i] = T1[i] - N[i] * N[i].dot(T1[i]);
           T[i].normalize();
           
           // Calculate temp. bitangent and store its handedness in T.w
           SLVec3f bitangent;
           bitangent.cross(N[i], T1[i]);
           T[i].w = (bitangent.dot(T2[i]) < 0.0f) ? -1.0f : 1.0f;
       }
       
       delete[] T1;
    }
}
Beispiel #14
0
/* http://www.terathon.com/code/tangent.html */
bool CalculateTangents(std::vector<Vertex>& vertices, std::vector<TriangleFace>& faces) {
    if ( vertices.size() == 0 ) {
		std::cerr << "[Mesh:calculateTangents] Error: Vertex array of length 0." << std::endl;
		return false;
	}

    if ( faces.size() == 0 ) {
		std::cerr << "[Mesh:calculateNormals] Error: Face count = 0." << std::endl;
		return false;
	}

    std::size_t triangleCount = faces.size();
    std::vector<Vector3f> tan1 = std::vector<Vector3f>(vertices.size());
    std::vector<Vector3f> tan2 = std::vector<Vector3f>(vertices.size());

    std::size_t i0 = 0, i1 = 0, i2 = 0;
    Vector3f p1, p2, p3;
    Vector3f w1, w2, w3;
    for ( std::size_t i = 0; i < triangleCount; i++ ) {
        i0 = faces[i].indices[A];
        i1 = faces[i].indices[B];
        i2 = faces[i].indices[C];

        p1 = vertices[i0].position;
		p2 = vertices[i1].position;
		p3 = vertices[i2].position;

        w1 = vertices[i0].textureCoord;
        w2 = vertices[i1].textureCoord;
        w3 = vertices[i2].textureCoord;

        float x1 = p2.x() - p1.x();
        float x2 = p3.x() - p1.x();
        float y1 = p2.y() - p1.y();
        float y2 = p3.y() - p1.y();
        float z1 = p2.z() - p1.z();
        float z2 = p3.z() - p1.z();

        float s1 = w2.x() - w1.x();
        float s2 = w3.x() - w1.x();
        float t1 = w2.y() - w1.y();
        float t2 = w3.y() - w1.y();

        float r = 1.0f / (s1 * t2 - s2 * t1);
        Vector3f sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
        Vector3f tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);

        tan1[i0] += sdir;
        tan1[i1] += sdir;
        tan1[i2] += sdir;
        
        tan2[i0] += tdir;
        tan2[i1] += tdir;
        tan2[i2] += tdir;
    }

    for ( std::size_t i = 0; i < vertices.size(); i++ ) {
        const Vector3f& n = vertices[i].normal;
        const Vector3f& t = tan1[i];

        vertices[i].tangent = Vector4f((t - n * (float)Vector3f::Dot(n, t)).normalized());
        if ( vertices[i].tangent.isEquivalent(Vector3f::Zero(), 0.01f) ) {
            if ( n.isEquivalent(Vector3f::UnitY(), 1.0e-4f) )
                vertices[i].tangent = Vector3f::UnitX();
            if ( n.isEquivalent(Vector3f::UnitNY(), 1.0e-4f) )
                vertices[i].tangent = Vector3f::UnitX();
        }

        if ( Vector3f::Dot(Vector3f::Cross(n, t), tan2[i]) < 0.0f ) vertices[i].tangent.w() = -1.0f;
        else vertices[i].tangent.w() = 1.0f;
    }

    return false;
}
Beispiel #15
0
BOOL JsonPlugin::SetDirectory(PCTSTR dir, int iOpMode)
{
    tstring path;
    if(!_tcscmp(dir, _T(".."))) // go to updir (..)
    {
        path = CurrentDir;
        TCHAR* pSlash = _tcsrchr(CurrentDir, '/');
        if(pSlash)
        {
            path = path.substr(0, pSlash - CurrentDir);
        }
        return GoToPath(path.c_str());
    }

    // First, try the name immediately
    if(curObject->IsObject())
    {
        auto mem = curObject->FindMember((PWSTR)WideFromOem(dir));
        if(mem != curObject->MemberEnd())
        {
            if(!mem->value.IsObject() && !mem->value.IsArray())
                return FALSE;
            curObject = &mem->value;
            _tcsncat(CurrentDir, _T("/"), _countof(CurrentDir));
            size_t l = _tcslen(CurrentDir);
            EncodeToBuf(CurrentDir + l, dir, _countof(CurrentDir) - l);
            CurrentDir[_countof(CurrentDir) - 1] = 0;
            return TRUE;
        }
    }
    else if(curObject->IsArray()) //try the value immediately
    {
        PTSTR end;
        long index = _tcstol(dir, &end, 10);
        if(*end == 0)
        {
            auto val = &(*curObject)[index];
            if(!val->IsObject() && !val->IsArray())
                return FALSE;
            curObject = val;
            _tcsncat(CurrentDir, _T("/"), _countof(CurrentDir));
            _tcsncat(CurrentDir, dir, _countof(CurrentDir));
            CurrentDir[_countof(CurrentDir) - 1] = 0;
            return TRUE;
        }
    }

    // Then, try without converting backslashes to slashes (there may be a name with backslashes)
    if(dir[0] != '/') //relative path, add CurrentDir first
    {
        path = CurrentDir;
        path += _T("/");
    }

    if(_tcscmp(dir, _T("/")))
        path += dir;

    if(GoToPath(path.c_str()))
        return TRUE;

    // Convert \ to / and retry
    path.clear();
    tstring tdir(dir);

    for(size_t i = 0; i < tdir.size(); i++)
        if(tdir[i] == '\\')
            tdir[i] = '/';

    if(tdir[0] != '/') //relative path, add CurrentDir first
    {
        path = CurrentDir;
        path += _T("/");
    }
    if(_tcscmp(tdir.c_str(), _T("/")))
        path += tdir;

    return GoToPath(path.c_str());
} //SetDirectory
Beispiel #16
0
void calculate_tangents(V* vertices, size_t vertices_number, I* indices, size_t indices_number)
{
	vec3* tan1 = new vec3[vertices_number * 2];
	vec3* tan2 = tan1 + vertices_number;

	::memset((void*)tan1, 0, vertices_number * 2 * sizeof(vec3));

	for (size_t a = 0; a < indices_number; a += 3)
	{
		I i1 = indices[a];
		I i2 = indices[a + 1];
		I i3 = indices[a + 2];

		const vec3& v1 = vertices[i1].pos;
		const vec3& v2 = vertices[i2].pos;
		const vec3& v3 = vertices[i3].pos;

		const vec2& w1 = vertices[i1].tex;
		const vec2& w2 = vertices[i2].tex;
		const vec2& w3 = vertices[i3].tex;

		float x1 = v2.x() - v1.x();
		float x2 = v3.x() - v1.x();
		float y1 = v2.y() - v1.y();
		float y2 = v3.y() - v1.y();
		float z1 = v2.z() - v1.z();
		float z2 = v3.z() - v1.z();

		float s1 = w2.x() - w1.x();
		float s2 = w3.x() - w1.x();
		float t1 = w2.y() - w1.y();
		float t2 = w3.y() - w1.y();

		float d = (s1 * t2 - s2 * t1);
		float r = d != 0.0f ? 1.0f / d : 0.0f;
		vec3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
			(t2 * z1 - t1 * z2) * r);
		vec3 tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,
			(s1 * z2 - s2 * z1) * r);

		tan1[i1] += sdir;
		tan1[i2] += sdir;
		tan1[i3] += sdir;

		tan2[i1] += tdir;
		tan2[i2] += tdir;
		tan2[i3] += tdir;
	}

	for (size_t a = 0; a < vertices_number; ++a)
	{
		const vec3& n = vertices[a].nrm;
		const vec3& t = tan1[a];

		vec3 tng;
		// Gram-Schmidt orthogonalize
		tng = (t - n * dot(n, t)).normalized();

		// Calculate handedness
		float w = (dot(cross(n, t), tan2[a]) < 0.0f) ? -1.0f : 1.0f;
		vertices[a].tng = vec4(tng, w);
	}

	delete [] tan1;
}
Beispiel #17
0
// Based on the example at http://www.terathon.com/code/tangent.php
void MeshCompiler::CalculateTangents()
{
	// Notes:
	// Bitangent = (Normal x Tangent) * Bitangent orientation
	// Tangent is the tangent-space vector along the +U axis (right)
	// Bitangent is the tangent-space vector along the +V axis (up)

	// Use Gram-Schmidt to orthonormalize the vector

	// Write the handedness (direction of bitangent) in w

	Vector* tan1 = new Vector[ m_Header.m_NumVertices * 2];
	Vector* tan2 = tan1 + m_Header.m_NumVertices;
	memset( tan1, 0, m_Header.m_NumVertices * 2 * sizeof( Vector ) );

	for( uint32 i = 0; i < m_Header.m_NumIndices; i += 3 )
	{
		uint i1 = m_Indices[ i ];
		uint i2 = m_Indices[ i + 1 ];
		uint i3 = m_Indices[ i + 2 ];

		const Vector& v1 = m_Positions[ i1 ];
		const Vector& v2 = m_Positions[ i2 ];
		const Vector& v3 = m_Positions[ i3 ];

		const Vector2& w1 = m_UVs[ i1 ];
		const Vector2& w2 = m_UVs[ i2 ];
		const Vector2& w3 = m_UVs[ i3 ];

		float x1 = v2.x - v1.x;
		float x2 = v3.x - v1.x;
		float y1 = v2.y - v1.y;
		float y2 = v3.y - v1.y;
		float z1 = v2.z - v1.z;
		float z2 = v3.z - v1.z;

		float s1 = w2.x - w1.x;
		float s2 = w3.x - w1.x;
		float t1 = w2.y - w1.y;
		float t2 = w3.y - w1.y;

		float r = 1.f / ( s1 * t2 - s2 * t1 );
		Vector sdir( ( t2 * x1 - t1 * x2 ) * r, ( t2 * y1 - t1 * y2 ) * r, ( t2 * z1 - t1 * z2 ) * r );
		Vector tdir( ( s1 * x2 - s2 * x1 ) * r, ( s1 * y2 - s2 * y1 ) * r, ( s1 * z2 - s2 * z1 ) * r );

		tan1[ i1 ] += sdir;
		tan1[ i2 ] += sdir;
		tan1[ i3 ] += sdir;

		tan2[ i1 ] += tdir;
		tan2[ i2 ] += tdir;
		tan2[ i3 ] += tdir;
	}

	for( uint32 i = 0; i < m_Header.m_NumVertices; ++i )
	{
		const Vector& n = m_Normals[i];
		const Vector& t = tan1[i];

		// Gram-Schmidt orthogonalize
		m_Tangents[i] = ( t - n * n.Dot(t) ).GetNormalized();

		// Calculate handedness
		m_Tangents[i].w = ( n.Cross(t).Dot( tan2[i] ) < 0.f ) ? -1.f : 1.f;
	}

	SafeDeleteArray( tan1 );
}
Beispiel #18
0
void GenerateTangents(void* vertexData, unsigned vertexSize, const void* indexData, unsigned indexSize, unsigned indexStart,
    unsigned indexCount, unsigned normalOffset, unsigned texCoordOffset, unsigned tangentOffset)
{
    // Tangent generation from
    // http://www.terathon.com/code/tangent.html
    unsigned minVertex = M_MAX_UNSIGNED;
    unsigned maxVertex = 0;
    auto* vertices = (unsigned char*)vertexData;

    auto* indexPointer = const_cast<void*>(indexData);
    for (unsigned i = indexStart; i < indexStart + indexCount; ++i)
    {
        unsigned v = GetIndex(indexPointer, indexSize);
        if (v < minVertex)
            minVertex = v;
        if (v > maxVertex)
            maxVertex = v;
    }

    unsigned vertexCount = maxVertex + 1;
    auto* tan1 = new Vector3[vertexCount * 2];
    Vector3* tan2 = tan1 + vertexCount;
    memset(tan1, 0, sizeof(Vector3) * vertexCount * 2);

    indexPointer = const_cast<void*>(indexData);
    for (unsigned i = indexStart; i < indexStart + indexCount; i += 3)
    {
        unsigned i1 = GetIndex(indexPointer, indexSize);
        unsigned i2 = GetIndex(indexPointer, indexSize);
        unsigned i3 = GetIndex(indexPointer, indexSize);

        const Vector3& v1 = *((Vector3*)(vertices + i1 * vertexSize));
        const Vector3& v2 = *((Vector3*)(vertices + i2 * vertexSize));
        const Vector3& v3 = *((Vector3*)(vertices + i3 * vertexSize));

        const Vector2& w1 = *((Vector2*)(vertices + i1 * vertexSize + texCoordOffset));
        const Vector2& w2 = *((Vector2*)(vertices + i2 * vertexSize + texCoordOffset));
        const Vector2& w3 = *((Vector2*)(vertices + i3 * vertexSize + texCoordOffset));

        float x1 = v2.x_ - v1.x_;
        float x2 = v3.x_ - v1.x_;
        float y1 = v2.y_ - v1.y_;
        float y2 = v3.y_ - v1.y_;
        float z1 = v2.z_ - v1.z_;
        float z2 = v3.z_ - v1.z_;

        float s1 = w2.x_ - w1.x_;
        float s2 = w3.x_ - w1.x_;
        float t1 = w2.y_ - w1.y_;
        float t2 = w3.y_ - w1.y_;

        float r = 1.0f / (s1 * t2 - s2 * t1);
        Vector3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
        Vector3 tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);

        tan1[i1] += sdir;
        tan1[i2] += sdir;
        tan1[i3] += sdir;

        tan2[i1] += tdir;
        tan2[i2] += tdir;
        tan2[i3] += tdir;
    }

    for (unsigned i = minVertex; i <= maxVertex; i++)
    {
        const Vector3& n = *((Vector3*)(vertices + i * vertexSize + normalOffset));
        const Vector3& t = tan1[i];
        Vector3 xyz;
        float w;

        // Gram-Schmidt orthogonalize
        xyz = (t - n * n.DotProduct(t)).Normalized();

        // Calculate handedness
        w = n.CrossProduct(t).DotProduct(tan2[i]) < 0.0f ? -1.0f : 1.0f;

        Vector4& tangent = *((Vector4*)(vertices + i * vertexSize + tangentOffset));
        tangent = Vector4(xyz, w);
    }

    delete[] tan1;
}