Exemplo n.º 1
0
/*!
Rotates the object so that it's forward vector is pointing towards the 'target' 
point. Default forward is -Z. The 'relativeTo' parameter defines in what space
the 'target' parameter is to be interpreted in. 
*/
void SLNode::lookAt(const SLVec3f& target, const SLVec3f& up, 
                    SLTransformSpace relativeTo)
{
    SLVec3f pos = translation();
    SLVec3f dir;
    SLVec3f localUp = up;

    if (relativeTo == TS_world && _parent)
    {
        SLVec3f localTarget = _parent->updateAndGetWMI() * target;
        localUp = _parent->updateAndGetWMI().mat3() * up;
        dir = localTarget - translation();
    }
    else if (relativeTo == TS_object)
        dir = _om * target - translation();
    else
        dir = target - translation();

    dir.normalize();
    
    SLfloat cosAngle = localUp.dot(dir);
    
    // dir and up are parallel and facing in the same direction 
    // or facing in opposite directions.
    // in this case we just rotate the up vector by 90° around
    // our current right vector
    // @todo This check might make more sense to be in Mat3.posAtUp
    if (fabs(cosAngle-1.0) <= FLT_EPSILON || fabs(cosAngle+1.0) <= FLT_EPSILON)
    {
        SLMat3f rot;
        rot.rotation(-90.0f, right());

        localUp = rot * localUp;
    }

    _om.posAtUp(pos, pos+dir, localUp);

    needUpdate();
}
Exemplo n.º 2
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;
    }
}