Exemplo n.º 1
0
/*!
SLMesh::preShade calculates the rest of the intersection information 
after the final hit point is determined. Should be called just before the 
shading when the final intersection point of the closest triangle was found.
*/
void SLMesh::preShade(SLRay* ray)
{
   SLFace* hit = ray->hitTriangle;
   
   // calculate the hit point in world space
   ray->hitPoint.set(ray->origin + ray->length * ray->dir);
      
   // calculate the interpolated normal with vertex normals in object space
   ray->hitNormal.set(N[hit->iA] * (1-(ray->hitU+ray->hitV)) + 
                      N[hit->iB] * ray->hitU + 
                      N[hit->iC] * ray->hitV);
                      
   // transform normal back to world space
   ray->hitNormal.set(ray->hitShape->wmN() * ray->hitNormal);
                 
   // invert normal if the ray is inside a shape
   if (!ray->isOutside) ray->hitNormal *= -1;
   
   // for shading the normal is expected to be unit length
   ray->hitNormal.normalize();
   
   // calculate interpolated texture coordinates
   SLVGLTexture& textures = ray->hitMat->textures();
   if (textures.size() > 0)
   {  SLVec2f Tu(Tc[hit->iB] - Tc[hit->iA]);
      SLVec2f Tv(Tc[hit->iC] - Tc[hit->iA]);
      SLVec2f tc(Tc[hit->iA] + ray->hitU*Tu + ray->hitV*Tv);
      ray->hitTexCol.set(textures[0]->getTexelf(tc.x,tc.y));
      
      // bumpmapping
      if (textures.size() > 1)
      {  if (T)
         {  
            // calculate the interpolated tangent with vertex tangent in object space
            SLVec4f hitT(T[hit->iA] * (1-(ray->hitU+ray->hitV)) + 
                         T[hit->iB] * ray->hitU + 
                         T[hit->iC] * ray->hitV);
                         
            SLVec3f T3(hitT.x,hitT.y,hitT.z);         // tangent with 3 components
            T3.set(ray->hitShape->wmN() * T3);        // transform tangent back to world space
            SLVec2f d = textures[1]->dsdt(tc.x,tc.y);  // slope of bumpmap at tc
            SLVec3f N = ray->hitNormal;               // unperturbated normal
            SLVec3f B(N^T3);                          // binormal tangent B
            B *= T[hit->iA].w;                        // correct handedness
            SLVec3f D(d.x*T3 + d.y*B);                // perturbation vector D
            N+=D;
            N.normalize();
            ray->hitNormal.set(N);
         }
      }
   }
}
Exemplo n.º 2
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.º 3
0
SLfloat SLLightRect::shadowTestMC(SLRay* ray, // ray of hit point
                                  const SLVec3f& L, // vector from hit point to light
                                  const SLfloat lightDist) // distance to light
{
    SLVec3f SP; // vector hit point to sample point in world coords

    SLfloat randX = rnd01();
    SLfloat randY = rnd01();

    // choose random point on rect as sample
    SP.set(updateAndGetWM().multVec(SLVec3f((randX*_width)-(_width*0.5f), (randY*_height)-(_height*0.5f), 0)) - ray->hitPoint);
    SLfloat SPDist = SP.length();
    SP.normalize();
    SLRay shadowRay(SPDist, SP, ray);

    SLScene::current->root3D()->hitRec(&shadowRay);

    if (shadowRay.length >= SPDist - FLT_EPSILON)
        return 1.0f;
    else
        return 0.0f;
}
Exemplo n.º 4
0
/*! SLCamera::camUpdate does the smooth transition for the walk animation. It
is called in every frame. It moves the camera after the key was released and
smoothly stops the motion by decreasing the speed every frame.
*/
SLbool SLCamera::camUpdate(SLfloat elapsedTimeMS)
{  
    if (_velocity == SLVec3f::ZERO && _moveDir == SLVec3f::ZERO)
        return false;

    SLfloat dtS = elapsedTimeMS * 0.001f;

    SLbool braking = false;
    if (_moveDir != SLVec3f::ZERO)
    {   
        // x and z movement direction vector should be projected on the x,z plane while
        // but still in local space
        // the y movement direction should alway be in world space
        SLVec3f f = forward();
        f.y = 0;
        f.normalize();

        SLVec3f r = right();
        r.y = 0;
        r.normalize();

        _acceleration = f * -_moveDir.z + r * _moveDir.x;
        _acceleration.y = _moveDir.y;
        _acceleration.normalize();
        _acceleration *= _moveAccel;

    } // accelerate in the opposite velocity to brake
    else
    {  
        _acceleration = -_velocity.normalized() * _brakeAccel;
        braking = true;
    }
    
    // accelerate
    SLfloat velMag = _velocity.length();
    SLVec3f increment = _acceleration * dtS; // all units in m/s, convert MS to S
    
    // early out if we're braking and the velocity would fall < 0
    if (braking && increment.lengthSqr() > _velocity.lengthSqr())
    {
        _velocity.set(SLVec3f::ZERO);
        return false;
    }

    _velocity += increment - _drag * _velocity * dtS; 
    velMag = _velocity.length();

    // don't go over max speed
    if (velMag > _maxSpeed)
        _velocity = _velocity.normalized() * _maxSpeed;

    // final delta movement vector
    SLVec3f delta = _velocity * dtS;

    // adjust for scaling (if the character is shrinked or enlarged)
    delta *= _unitScaling;

    translate(delta, TS_World);
    
    return true;
    
    //SL_LOG("cs: %3.2f | %3.2f, %3.2f, %3.2f\n", _velocity.length(), _acceleration.x, _acceleration.y, _acceleration.z);

    /* OLD CODE BELOW
    // ToDo: The recursive update traversal is not yet implemented
    if (_maxSpeed != SLVec3f::ZERO || _curSpeed != SLVec3f::ZERO)
    {  
        // delta speed during acceleration/slow down
        SLfloat ds = _speedLimit / 20.0f;
      
        // Accelerate
        if (_maxSpeed.x>0 && _curSpeed.x<_maxSpeed.x) _curSpeed.x += ds; else
        if (_maxSpeed.x<0 && _curSpeed.x>_maxSpeed.x) _curSpeed.x -= ds;
        if (_maxSpeed.y>0 && _curSpeed.y<_maxSpeed.y) _curSpeed.y += ds; else
        if (_maxSpeed.y<0 && _curSpeed.y>_maxSpeed.y) _curSpeed.y -= ds;      
        if (_maxSpeed.z>0 && _curSpeed.z<_maxSpeed.z) _curSpeed.z += ds; else
        if (_maxSpeed.z<0 && _curSpeed.z>_maxSpeed.z) _curSpeed.z -= ds;
      
        if (_curSpeed.z == 0.0f) {
            int i = 0;
        }

        // Slow down
        if (_maxSpeed.z == 0)
        {   if (_curSpeed.z > 0) 
            {  _curSpeed.z -= ds;
                if (_curSpeed.z < 0) _curSpeed.z = 0.0f;
            } else
            if (_curSpeed.z < 0) 
            {  _curSpeed.z += ds;
                if (_curSpeed.z > 0) _curSpeed.z = 0.0f;
            }
        }
        if (_maxSpeed.x == 0)
        {   if (_curSpeed.x < 0) 
            {  _curSpeed.x += ds;
                if (_curSpeed.x > 0) _curSpeed.x = 0.0f;
            } else 
            if (_curSpeed.x > 0) 
            {  _curSpeed.x -= ds;
                if (_curSpeed.x < 0) _curSpeed.x = 0.0f;
            }
        }
        if (_maxSpeed.y == 0)
        {   if (_curSpeed.y < 0) 
            {  _curSpeed.y += ds;
                if (_curSpeed.y > 0) _curSpeed.y = 0.0f;
            } else 
            if (_curSpeed.y > 0) 
            {  _curSpeed.y -= ds;
                if (_curSpeed.y < 0) _curSpeed.y = 0.0f;
            }
        }
      
        SL_LOG("cs: %3.1f, %3.1f, %3.1f\n", _curSpeed.x, _curSpeed.y, _curSpeed.z);
        SLfloat temp = _curSpeed.length();

        _curSpeed = updateAndGetWM().mat3() * _curSpeed;
        _curSpeed.y = 0;
        _curSpeed.normalize();
        _curSpeed *= temp;

        forward();

        SLVec3f delta(_curSpeed * elapsedTimeMS / 1000.0f);

        translate(delta, TS_World);
      
        return true;
    }
    return false;*/
}
Exemplo n.º 5
0
/*!
SLLightRect::shadowTest returns 0.0 if the hit point is completely shaded and 
1.0 if it is 100% lighted. A return value inbetween is calculate by the ratio 
of the shadow rays not blocked to the total number of casted shadow rays.
*/
SLfloat SLLightRect::shadowTest(SLRay* ray, // ray of hit point
                               const SLVec3f& L, // vector from hit point to light
                               const SLfloat lightDist) // distance to light
{  
    if (_samples.x==1 && _samples.y==1)
    {  
        // define shadow ray
        SLRay shadowRay(lightDist, L, ray);
            
        SLScene::current->root3D()->hitRec(&shadowRay);

        return (shadowRay.length < lightDist) ? 0.0f : 1.0f;
    } 
    else // do light sampling for soft shadows
    {   SLfloat dw = (SLfloat)_width/(SLfloat)_samples.x; // width of a sample cell
        SLfloat dl = (SLfloat)_height/(SLfloat)_samples.y;// length of a sample cell
        SLint   x, y, hx=_samples.x/2, hy=_samples.y/2;
        SLint   samples = _samples.x*_samples.y;
        SLbool* isSampled = new SLbool[samples];
        SLbool  importantPointsAreLighting = true;
        SLfloat lighted = 0.0f; // return value
        SLfloat invSamples = 1.0f/(SLfloat)(samples);
        SLVec3f SP; // vector hitpoint to samplepoint in world coords

        for (y=0; y<_samples.y; ++y)
        {   for (x=0; x<_samples.x; ++x)
            {  SLint iSP = y*_samples.x + x;
            isSampled[iSP]=false;
            }
        }

        /*
        Important sample points (X) on a 7 by 5 rectangular light.
        If all of them are lighting the hitpoint the sample points
        in between (O) are not tested anymore.

             0   1   2   3   4   5   6         
           +---+---+---+---+---+---+---+
        0  | X | . | . | X | . | . | X |
           +---+---+---+---+---+---+---+
        1  | . | . | . | . | . | . | . |
           +---+---+---+---+---+---+---+
        2  | X | . | . | X | . | . | X |
           +---+---+---+---+---+---+---+
        3  | . | . | . | . | . | . | . |
           +---+---+---+---+---+---+---+
        4  | X | . | . | X | . | . | X |
           +---+---+---+---+---+---+---+
        */

        // Double loop for the important sample points
        for (y=-hy; y<=hy; y+=hy)
        {   for (x=-hx; x<=hx; x+=hx)
            {  SLint iSP = (y+hy)*_samples.x + x+hx;
            isSampled[iSP]=true;
            
            SP.set(updateAndGetWM().multVec(SLVec3f(x*dw, y*dl, 0)) - ray->hitPoint);
            SLfloat SPDist = SP.length();
            SP.normalize();
            SLRay shadowRay(SPDist, SP, ray);

            SLScene::current->root3D()->hitRec(&shadowRay);
            
            if (shadowRay.length >= SPDist-FLT_EPSILON) 
                lighted += invSamples; // sum up the light
            else 
                importantPointsAreLighting = false;
            }
        }

        if (importantPointsAreLighting)
            lighted = 1.0f;
        else
        {  // Double loop for the samplepoints inbetween
            for (y=-hy; y<=hy; ++y)
            {   for (x=-hx; x<=hx; ++x)
                {  SLint iSP = (y+hy)*_samples.x + x+hx;
                    if (!isSampled[iSP])
                    {   SP.set(updateAndGetWM().multVec(SLVec3f(x*dw, y*dl, 0)) - ray->hitPoint);
                        SLfloat SPDist = SP.length();
                        SP.normalize();
                        SLRay shadowRay(SPDist, SP, ray);

                        SLScene::current->root3D()->hitRec(&shadowRay);
                  
                        // sum up the light
                        if (shadowRay.length >= SPDist-FLT_EPSILON) 
                            lighted += invSamples;
                    }
                }
            }
        }
        if (isSampled) delete [] isSampled;
        return lighted;
    }
}