Пример #1
3
TEST(OptimizationBfgsUpdate, bfgs_update_secant) {
  typedef stan::optimization::BFGSUpdate_HInv<> QNUpdateT;
  typedef QNUpdateT::VectorT VectorT;

  const unsigned int nDim = 10;
  QNUpdateT bfgsUp;
  VectorT yk(nDim), sk(nDim), sdir(nDim);

  // Construct a set of BFGS update vectors and check that
  // the secant equation H*yk = sk is always satisfied.
  for (unsigned int i = 0; i < nDim; i++) {
    sk.setZero(nDim);
    yk.setZero(nDim);
    sk[i] = 1;
    yk[i] = 1;

    bfgsUp.update(yk,sk,i==0);

    // Because the constructed update vectors are all orthogonal the secant
    // equation should be exactlty satisfied for all nDim updates.
    for (unsigned int j = 0; j <= i; j++) {
      sk.setZero(nDim);
      yk.setZero(nDim);
      sk[i - j] = 1;
      yk[i - j] = 1;

      bfgsUp.search_direction(sdir,yk);
      
      EXPECT_NEAR((sdir + sk).norm(),0.0,1e-10);
    }
  }
}
Пример #2
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;
}
Tonic::Generator CloudsVisualSystemMemory::buildSynth()
{
    string strDir = GetCloudsDataPath(true) + "sound/textures/";
    ofDirectory sdir(strDir);
    string strAbsPath = ofToDataPath(strDir + "/CPUBeepsFastDrone_.aif", true);

    Tonic::SampleTable sample = Tonic::loadAudioFile(strAbsPath);
    
    Tonic::Generator sampleGen = Tonic::BufferPlayer().setBuffer(sample).trigger(1).loop(1);
    
    return sampleGen * 5;
}
Пример #4
1
float4 CGlobalRendering::CalculateSunDir(float startAngle) {
	float sang = PI - startAngle - initialSunAngle - gs->frameNum * 2.0f * PI / (GAME_SPEED * sunOrbitTime);

	float4 sdir(sunOrbitRad * cos(sang), sunOrbitHeight, sunOrbitRad * sin(sang));
	sdir = sunRotation.Mul(sdir);

	return sdir;
}
Пример #5
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;
}
Tonic::Generator CloudsVisualSystemConnectors::buildSynth()
{
    string strDir = GetCloudsDataPath(true)+"sound/textures";
    ofDirectory sdir(strDir);
    Tonic::SampleTable samples[1];
    for(int i=0; i<tonicSamples.size();i++){
        string strAbsPath = ofToDataPath(strDir + "/" + tonicSamples[i].soundFile, true);
        samples[i] = ofxAudioDecoderTonic(strAbsPath);
    }
    
    Tonic::Generator sampleGen1 = Tonic::BufferPlayer().setBuffer(samples[0]).loop(1).trigger(tonicSamples[0].soundTrigger);
    
    return sampleGen1 * volumeControl;
}
Пример #7
0
/** @param fname Name of file to load from (eg, an overlap matrix file)
@param vname Eg: "grid1" or "grid2" */
void Proj2::read_from_netcdf(
NcFile &nc,
NcVar *info_var,
std::string const &vname)
{
	sproj = std::string(get_att(info_var, vname.c_str())->as_string(0));
	if (sproj == "") {
		clear();
	} else {
		std::string sdir(std::string(get_att(info_var, (vname + ".direction").c_str())->as_string(0)));
		if (sdir == "xy2ll") direction = Direction::XY2LL;
		else if (sdir == "ll2xy") direction = Direction::LL2XY;
		else throw std::exception();
	}
}
Пример #8
0
TEST(OptimizationBfgsUpdate, BFGSUpdate_HInv_update) {
  typedef stan::optimization::BFGSUpdate_HInv<> QNUpdateT;
  typedef QNUpdateT::VectorT VectorT;

  const unsigned int nDim = 10;
  QNUpdateT bfgsUp;
  VectorT yk(nDim), sk(nDim), sdir(nDim);

  for (unsigned int i = 0; i < nDim; i++) {
    sk.setZero(nDim);
    yk.setZero(nDim);
    sk[i] = 1;
    yk[i] = 1;

    bfgsUp.update(yk,sk,i==0);
  }
}
Пример #9
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;
    }
  }
Пример #10
0
TEST(OptimizationBfgsUpdate, BFGSUpdate_HInv_search_direction) {
  typedef stan::optimization::BFGSUpdate_HInv<> QNUpdateT;
  typedef QNUpdateT::VectorT VectorT;

  const unsigned int nDim = 10;
  QNUpdateT bfgsUp;
  VectorT yk(nDim), sk(nDim), sdir(nDim);

  for (unsigned int i = 0; i < nDim; i++) {

    for (unsigned int j = 0; j <= i; j++) {
      sk.setZero(nDim);
      yk.setZero(nDim);
      sk[i - j] = 1;
      yk[i - j] = 1;

      bfgsUp.search_direction(sdir,yk);
      
    }
  }
}
float SpotLightCalculator::getLightAmount(const VC3 &position, const IStorm3D_Terrain &terrain, float rayHeight) const
{
	float squareRange = position.GetSquareRangeTo(data->position);
	if(squareRange > data->squareRange)
		return 0;

	VC2 pdir(position.x - data->position.x, position.z - data->position.z);
	VC2 sdir(data->direction.x, data->direction.z);

	float pAngle = pdir.CalculateAngle();
	float sAngle = sdir.CalculateAngle();
	float diff = pAngle - sAngle;
	//assert(diff

	if(diff < -3.1415f)
		diff += 3.1415f * 2;
	else if(diff > 3.1415f)
		diff -= 3.1415f * 2;

	if(fabsf(diff) / 3.1415f * 180.f > data->fov)
		return 0;

	return data->getAmount(position, -diff, terrain, rayHeight);
}
Пример #12
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;
}
Пример #13
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
}
Пример #14
0
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;
	}
}
Пример #15
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;
}
Пример #16
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;
}
Пример #17
0
//---------------------------------------------------------------------------//
// CalculaTangentes
//
//---------------------------------------------------------------------------//
void CObjeto3D::CalculaTangentes()
{
    TVector3 *pTan1 = NEW_ARRAY(TVector3, m_uNumVertices);
    //TVector3 *pTan2 = pTan1 + m_uNumVertices;
    memset(pTan1, 0, m_uNumVertices * sizeof(TVector3));

    for (int i = 0; i < m_uNumFaces; i++)
    {
        int i1 = m_pFaces[i].i0;
        int i2 = m_pFaces[i].i1;
        int i3 = m_pFaces[i].i2;

        const TVector3 &v1 = m_pVertices[i1];
        const TVector3 &v2 = m_pVertices[i2];
        const TVector3 &v3 = m_pVertices[i3];

        const TVector2 &w1 = m_pCacheUV[i*3+0];
        const TVector2 &w2 = m_pCacheUV[i*3+1];
        const TVector2 &w3 = m_pCacheUV[i*3+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);
        TVector3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
        //TVector3 tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);

        pTan1[i1].x += sdir.x;
        pTan1[i1].y += sdir.y;
        pTan1[i1].z += sdir.z;
        pTan1[i2].x += sdir.x;
        pTan1[i2].y += sdir.y;
        pTan1[i2].z += sdir.z;
        pTan1[i3].x += sdir.x;
        pTan1[i3].y += sdir.y;
        pTan1[i3].z += sdir.z;
        /*
        pTan2[i1].x += tdir.x; pTan2[i1].y += tdir.y; pTan2[i1].z += tdir.z;
        pTan2[i2].x += tdir.x; pTan2[i2].y += tdir.y; pTan2[i2].z += tdir.z;
        pTan2[i3].x += tdir.x; pTan2[i3].y += tdir.y; pTan2[i3].z += tdir.z;
        */
    }

    for (int i = 0; i < m_uNumVertices; i++)
    {
        TVector3 n = m_pVNormales[i];
        TVector3 t = pTan1[i];

        TVector3 r;
        float fDot = Vector_Dot(&n, &t);
        r.x = t.x - n.x * fDot;
        r.y = t.y - n.y * fDot;
        r.z = t.z - n.z * fDot;
        Vector_Unit (&m_pTangentes[i], &r);
        Vector_Cross(&m_pBinormales[i], &n, &m_pTangentes[i]);
    }

    DISPOSE_ARRAY(pTan1);
}
Пример #18
0
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;
  //  }
}
Пример #19
0
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;   
}
Пример #20
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;
}
Пример #21
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;
}
Пример #22
0
void OpenGL_Engine::getTangentSpace(const VertexVector *vertex, const TexCoords *texcoord, const FaceMaterialVector *faceMaterials, Normals const *normal, TexCoords3f **sTangent, TexCoords3f **tTangent)
{ // TODO: mem cleanup
	int id = vertex->getId();
	
	assert(id > 0, "vertex.id > 0");

	bool was = tangentSpaceCache.find(id) != tangentSpaceCache.end();

	*sTangent = &tangentSpaceCache[id].t;
	*tTangent = &tangentSpaceCache[id].b;

	if (!vertex->wasChanged() && was)
	{
		return;
	}

	if (!vertex || !texcoord || texcoord->size() != vertex->size()) return;

    unsigned int size = vertex->size();
//    tangentSpaceLight.resize(s); // TODO

/*	v3List *S, *T;
	S = new v3List(size);
	T = new v3List(size);
	v3List &s = *S;
	v3List &t = *T;
	
    for (unsigned int i=0; i<size; i++)
    {
        s[i].loadZero();
        t[i].loadZero();
    }

	for(FaceMaterialVector::const_iterator it = faceMaterials->begin(); it != faceMaterials->end(); it++)
	{
		Faces *triangle = it->triangles;
		

		for (unsigned int i=0; i<faces->triangles.size(); i++)
		{
			int a = faces->triangles[i].a[0];
			int b = faces->triangles[i].a[1];
			int c = faces->triangles[i].a[2];
			int e, f; // from e to f

			v2 me;
			v3  ve, ne;

			e = a;
			// vertex a (vector ab)
			me = texcoord->data[e]; ve = vertex->data[e];		ne = normal->data[e];

			f = b;  s[e] += getstangent(texcoord->data[f]-me, vertex->data[f] - ve, ne, v2(1.0, 0.0));
			// vertex a (vector ac)
			f = c;  s[e] += getstangent(texcoord->data[f]-me, vertex->data[f] - ve, ne, v2(1.0, 0.0));
			f = b;  t[e] += getstangent(texcoord->data[f]-me, vertex->data[f] - ve, ne, v2(0.0, -1.0));
			f = c;  t[e] += getstangent(texcoord->data[f]-me, vertex->data[f] - ve, ne, v2(0.0, -1.0));

			e = b;
			me = texcoord->data[e]; ve = vertex->data[e];		ne = normal->data[e];
			f = a;  s[e] += getstangent(texcoord->data[f]-me, vertex->data[f] - ve, ne, v2(1.0, 0.0));
			f = c;  s[e] += getstangent(texcoord->data[f]-me, vertex->data[f] - ve, ne, v2(1.0, 0.0));
			f = a;  t[e] += getstangent(texcoord->data[f]-me, vertex->data[f] - ve, ne, v2(0.0, -1.0));
			f = c;  t[e] += getstangent(texcoord->data[f]-me, vertex->data[f] - ve, ne, v2(0.0, -1.0));

			e = c;
			me = texcoord->data[e]; ve = vertex->data[e];		ne = normal->data[e];
			f = a;  s[e] += getstangent(texcoord->data[f]-me, vertex->data[f] - ve, ne, v2(1.0, 0.0));
			f = b;  s[e] += getstangent(texcoord->data[f]-me, vertex->data[f] - ve, ne, v2(1.0, 0.0));
			f = a;  t[e] += getstangent(texcoord->data[f]-me, vertex->data[f] - ve, ne, v2(0.0, -1.0));
			f = b;  t[e] += getstangent(texcoord->data[f]-me, vertex->data[f] - ve, ne, v2(0.0, -1.0));
		}
	}
    for (unsigned int i=0; i<size; i++)
    {
        s[i].normalize();
        t[i].normalize();
    }
	
	*sTangent = S;
	*tTangent = T;
	if(id > 0)
	{
		tangentSpaceCache[id].s = S;
		tangentSpaceCache[id].t = T;
	}
*/
	pvector<v3>& S = **sTangent;
	pvector<v3>& T = **tTangent;
	S.resize(size);
	T.resize(size);

	memset(&S[0], 0, size * sizeof(v3));
    
	for (FaceMaterialVector::const_iterator it = faceMaterials->begin(); it != faceMaterials->end(); it++)
	{
		Faces* faces = it->faces;
		
		for (size_t a=0; a < faces->triangles.size(); a++)
		{
			unsigned int i1 = faces->triangles[a].a[0];
			unsigned int i2 = faces->triangles[a].a[1];
			unsigned int i3 = faces->triangles[a].a[2];
        
			const v3& vertex1 = vertex->at(i1);
			const v3& vertex2 = vertex->at(i2);
			const v3& vertex3 = vertex->at(i3);
        
			const v2& w1 = texcoord->at(i1);
			const v2& w2 = texcoord->at(i2);
			const v2& w3 = texcoord->at(i3);
        
			float x1 = vertex2.x - vertex1.x;
			float x2 = vertex3.x - vertex1.x;
			float y1 = vertex2.y - vertex1.y;
			float y2 = vertex3.y - vertex1.y;
			float z1 = vertex2.z - vertex1.z;
			float z2 = vertex3.z - vertex1.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);
			v3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
					(t2 * z1 - t1 * z2) * r);
        
			S[i1] += sdir;
			S[i2] += sdir;
	        S[i3] += sdir;
	    }
	}


	for (long a = 0; a < (int)vertex->size(); a++)
    {
		const v3& n = normal->at(a);
        v3 t = S[a];
        
        // Gram-Schmidt orthogonalize
		t = (t - n * (n.dotProduct(t))).getNormalized();
		v3 b = t * n;

		S[a] = t;
		T[a] = b;
        
        // Calculate handedness
//        tangent[a].w = (Dot(Cross(n, t), tan2[a]) < 0.0F) ? -1.0F : 1.0F;
    }
};
Пример #23
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 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)));
    }
}
Пример #25
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;
    }
}
Пример #26
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 );
}