Exemplo n.º 1
0
/*!
SLRay::refractMC scatters a ray around perfect transmissive direction according 
to translucency (for higher translucency the ray is less scattered).
This is used for path tracing and distributed ray tracing as well as for photon 
scattering. The direction is calculated the same as with specular scattering
(see reflectMC). The created direction is along z-axis and then transformed to 
lie along transmissive direction with rotationMatrix rotMat. The rotation 
matrix must be precalculated (stays the same for each ray sample, needs to be 
be calculated only once)
*/
void SLRay::refractMC(SLRay* refracted,SLMat3f rotMat)
{  SLfloat eta1, eta2;
   SLVec3f randVec;
   SLfloat translucency = hitMat->translucency();

   //scatter within transmissive lobe
   eta1 = (SLfloat)random->Random(); 
   eta2 = SL_2PI*(SLfloat)random->Random();
   SLfloat f1=sqrt(1.0f-pow(eta1,2.0f/(translucency+1.0f)));

   //transform to cartesian
   randVec.set( f1*cos(eta2),
                f1*sin(eta2),
                pow(eta1,1.0f/(translucency+1.0f)));

   //ray needs to be reset if already hit a shape
   if(refracted->hitShape)
   {  refracted->length = SL_FLOAT_MAX;
      refracted->hitShape = 0;
      refracted->hitPoint = SLVec3f::ZERO;
      refracted->hitNormal = SLVec3f::ZERO;
   }
   
   refracted->setDir(rotMat*randVec);
}
Exemplo n.º 2
0
/*!
SLCurveBezier::subdivideRender adds points along the curve to the point vector
renderPoints by recursively subdividing the curve with the Casteljau scheme.
*/
void SLCurveBezier::subdivideRender(SLVVec3f &renderPoints,
                                    const SLMat4f &wm,
                                    SLfloat epsilon,
                                    const SLVec3f& P0, const SLVec3f& P1, 
                                    const SLVec3f& P2, const SLVec3f& P3)
{
    // add first point transformed by wm if not already in the list
    if (renderPoints.size()==0)
        renderPoints.push_back(wm.multVec(P0));
    else if (P0 != renderPoints[renderPoints.size()-1])
        renderPoints.push_back(wm.multVec(P0));
   
    // check to see if basically straight
    SLfloat Lmin = P0.distance(P3);
    SLfloat Lmax = P0.distance(P1) + P1.distance(P2) + P2.distance(P3);
    SLfloat diff = Lmin - Lmax;
    if (diff*diff < epsilon) return;

    // otherwise get control points for subdivision
    SLVec3f L1  = (P0 + P1) * 0.5f;
    SLVec3f H   = (P1 + P2) * 0.5f;
    SLVec3f L2  = (L1 + H)  * 0.5f;
    SLVec3f R2  = (P2 + P3) * 0.5f;
    SLVec3f R1  = (H  + R2) * 0.5f;
    SLVec3f mid = (L2 + R1) * 0.5f;

    // subdivide
    subdivideRender(renderPoints, wm, epsilon, P0, L1, L2, mid);
    subdivideRender(renderPoints, wm, epsilon, mid, R1, R2, P3);
}
Exemplo n.º 3
0
/*!
SLSphere::SLSphere ctor for spheric revolution object around the z-axis.
*/
SLSphere::SLSphere(SLfloat sphereRadius,
                     SLint stacks, 
                     SLint slices,
                     SLstring name,
                     SLMaterial* mat) : SLRevolver(name)
{
    assert(slices >= 3 && "Error: Not enough slices.");
    assert(slices >  0 && "Error: Not enough stacks.");
   
    _radius = sphereRadius;
    _stacks = stacks;

    _slices = slices;
    _smoothFirst = true;
    _smoothLast  = true;
    _revAxis.set(0,0,1);
    _revPoints.reserve(stacks+1);

    SLfloat theta = -SL_PI;
    SLfloat phi   = 0;
    SLfloat dTheta= SL_PI / stacks;
   
    for (SLint i=0; i<=stacks; ++i)
    {   SLVec3f p;
        p.fromSpherical(sphereRadius, theta, phi);
        _revPoints.push_back(p);
        theta += dTheta;
    }
   
    buildMesh(mat);
}
Exemplo n.º 4
0
/*!
SLCamera::calcMinMax calculates the axis alligned minimum and maximum point of
the camera position and the 4 near clipping plane points.
*/
void SLCamera::calcMinMax(SLVec3f &minV, SLVec3f &maxV)
{
    SLVec3f P[5];
    SLfloat tanFov = tan(_fov*SL_DEG2RAD*0.5f);
    SLfloat tN = tanFov * _clipNear; //top near
    SLfloat rN = tN * _aspect;       //right near

    // frustum pyramid lines
    P[0].set(0,0,0);

    // around near clipping plane
    P[1].set( rN, tN,-_clipNear);
    P[2].set( rN,-tN,-_clipNear);
    P[3].set(-rN,-tN,-_clipNear);
    P[4].set(-rN, tN,-_clipNear);

    // init min & max points
    minV.set( FLT_MAX,  FLT_MAX,  FLT_MAX);
    maxV.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);

    // calc min and max point of all vertices
    for (SLuint i=0; i<5; ++i)
    {   if (P[i].x < minV.x) minV.x = P[i].x;
        if (P[i].x > maxV.x) maxV.x = P[i].x;
        if (P[i].y < minV.y) minV.y = P[i].y;
        if (P[i].y > maxV.y) maxV.y = P[i].y;
        if (P[i].z < minV.z) minV.z = P[i].z;
        if (P[i].z > maxV.z) maxV.z = P[i].z;
    }
}
Exemplo n.º 5
0
/*!
SLRay::reflectMC scatters a ray around perfect specular direction according to 
shininess (for higher shininess the ray is less scattered). This is used for 
path tracing and distributed ray tracing as well as for photon scattering. 
The direction is calculated according to MCCABE. The created direction is 
along z-axis and then transformed to lie along specular direction with 
rotationMatrix rotMat. The rotation matrix must be precalculated (stays the 
same for each ray sample, needs to be be calculated only once)
*/
bool SLRay::reflectMC(SLRay* reflected,SLMat3f rotMat)
{  SLfloat eta1, eta2;
   SLVec3f randVec;
   SLfloat shininess = hitMat->shininess();

   //scatter within specular lobe
   eta1 = (SLfloat)random->Random();
   eta2 = SL_2PI*(SLfloat)random->Random();
   SLfloat f1 = sqrt(1.0f-pow(eta1, 2.0f/(shininess+1.0f)));

   //tranform to cartesian
   randVec.set(f1 * cos(eta2),
               f1 * sin(eta2),
               pow(eta1, 1.0f/(shininess+1.0f)));

   //ray needs to be reset if already hit a shape
   if(reflected->hitShape)
   {  reflected->length = SL_FLOAT_MAX;
      reflected->hitShape = 0;
      reflected->hitPoint = SLVec3f::ZERO;
      reflected->hitNormal = SLVec3f::ZERO;
   }
   
   //apply rotation
   reflected->setDir(rotMat*randVec);
   
   //true if in direction of normal
   return (hitNormal * reflected->dir >= 0.0f);
}
Exemplo n.º 6
0
/*!
SLRay::diffuseMC scatters a ray around hit normal (cosine distribution).
This is only used for photonmapping(russian roulette).
The random direction lies around z-Axis and is then transformed by a rotation 
matrix to lie along the normal. The direction is calculated according to MCCABE
*/
void SLRay::diffuseMC(SLRay* scattered)
{
   SLVec3f randVec;
   SLfloat eta1,eta2,eta1sqrt;

   scattered->setDir(hitNormal);
   scattered->origin = hitPoint;
   scattered->depth = depth+1;
   depthReached = scattered->depth;
   
   // for reflectance the start material stays the same
   scattered->originMat = hitMat;
   scattered->originShape = hitShape;
   scattered->type = REFLECTED;

   //calculate rotation matrix
   SLMat3f rotMat;
   SLVec3f rotAxis((SLVec3f(0.0,0.0,1.0) ^ scattered->dir).normalize());
   SLfloat rotAngle=acos(scattered->dir.z); //z*scattered.dir()
   rotMat.rotation(rotAngle*180.0f/SL_PI, rotAxis);

   //cosine distribution
   eta1 = (SLfloat)random->Random(); 
   eta2 = SL_2PI*(SLfloat)random->Random();
   eta1sqrt = sqrt(1-eta1);
   //transform to cartesian
   randVec.set(eta1sqrt * cos(eta2),
               eta1sqrt * sin(eta2),
               sqrt(eta1));

   scattered->setDir(rotMat*randVec);
}
Exemplo n.º 7
0
/*!Creates photons (ray with power) from a point light source and sends 
it into the scene. 
Note that a point light has no cosine distribution and no surface area
*/
void SLPhotonMapper::photonEmission(SLLight* light)
{
   SLfloat eta1,eta2,f1,f2;
   SLVec3f C,N;
   SLVec3f power;
      
   C = light->positionWS();

   //because point lights have no surface use only radiance for power of emitted photons
   power.set(light->diffuse().r,light->diffuse().g,light->diffuse().b);

   //progress
   SLlong maxPhotons=_mapCaustic->maxStoredPhotons()+_mapGlobal->maxStoredPhotons();
   SLlong curPhotons=_mapCaustic->storedPhotons()+_mapGlobal->storedPhotons();;
   
   SLlong emitted=0;

   //shoot the photons as long as maps are not full
   while(emitted<light->photons() && !(_mapCaustic->isFull()&&(_mapGlobal->isFull())))
   {
      //progress
      if(emitted%1000==0)
      {  curPhotons=_mapCaustic->storedPhotons()+_mapGlobal->storedPhotons();
         printf("\b\b\b\b%3.0f%%",(SLfloat)curPhotons/(SLfloat)maxPhotons*100.0f);
      }

      //create spherical random direction
      eta1=_random->Random();eta2=_random->Random();
      f1 = SL_2PI*eta2;
      f2 = 2.0f * sqrt(eta1 * (1-eta1));

      //direction in cartesian coordinates
      N.set(cos(f1)*f2, sin(f1)*f2, (1.0-2.0*eta1));
      
      //create and emit photon
      SLRay scattered(C,N,PRIMARY, (SLShape*)light, SL_FLOAT_MAX, 1);
      photonScatter(&scattered,power,LIGHT);

      emitted++;
      //scaling of stored photons is necessary if one of the maps was filled by this photon
      //(because emission of photons continues in order to fill the other map)
      if(_mapCaustic->isFull() && !_mapCausticGotFull)
      {  _mapCausticGotFull = true;
         _mapCaustic->scalePhotonPower(1.0f/SLfloat(emitted));
      }
      if(_mapGlobal->isFull() && !_mapGlobalGotFull)
      {  _mapGlobalGotFull = true;
         _mapGlobal->scalePhotonPower(1.0f/SLfloat(emitted));
      }

   }

   //scale all stored photons of this light source
   if(emitted)
   {  SLRay::emittedPhotons+=emitted;
      _mapCaustic->scalePhotonPower(1.0f/SLfloat(emitted));
      _mapGlobal->scalePhotonPower(1.0f/SLfloat(emitted));
   }
}
Exemplo n.º 8
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.º 9
0
/*! 
SLMesh::calcMinMax calculates the axis alligned minimum and maximum point
*/
void SLMesh::calcMinMax(SLVec3f &minV, SLVec3f &maxV)
{  // init min & max points
   minV.set( FLT_MAX,  FLT_MAX,  FLT_MAX);
   maxV.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);

   // calc min and max point of all vertices
   for (SLuint i=0; i<numV; ++i)
   {  if (P[i].x < minV.x) minV.x = P[i].x;
      if (P[i].x > maxV.x) maxV.x = P[i].x;
      if (P[i].y < minV.y) minV.y = P[i].y;
      if (P[i].y > maxV.y) maxV.y = P[i].y;
      if (P[i].z < minV.z) minV.z = P[i].z;
      if (P[i].z > maxV.z) maxV.z = P[i].z;
   } 
}
Exemplo n.º 10
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.º 11
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.º 12
0
/*!
SLCurveBezier::subdivideLength calculates length of Bezier curve by recursive
midpoint subdivision.
*/
SLfloat SLCurveBezier::subdivideLength(const SLVec3f& P0, 
                                       const SLVec3f& P1, 
                                       const SLVec3f& P2, 
                                       const SLVec3f& P3)
{
    // check to see if basically straight
    SLfloat Lmin = P0.distance(P3);
    SLfloat Lmax = P0.distance(P1) + P1.distance(P2) + P2.distance(P3);
    SLfloat diff = Lmin - Lmax;

    if (diff*diff < 1.0e-3f)
        return 0.5f*(Lmin + Lmax);

    // otherwise get control points for subdivision
    SLVec3f L1  = (P0 + P1) * 0.5f;
    SLVec3f H   = (P1 + P2) * 0.5f;
    SLVec3f L2  = (L1 + H ) * 0.5f;
    SLVec3f R2  = (P2 + P3) * 0.5f;
    SLVec3f R1  = (H  + R2) * 0.5f;
    SLVec3f mid = (L2 + R1) * 0.5f;

    // subdivide
    return subdivideLength(P0, L1, L2, mid) + subdivideLength(mid, R1, R2, P3);
}
Exemplo n.º 13
0
//-----------------------------------------------------------------------------
//! Gets called whenever the mouse is moved.
SLbool SLCamera::onMouseMove(const SLMouseButton button, 
                             const SLint x, const SLint y, const SLKey mod)
{  
    if (button == ButtonLeft) //================================================
    {   
        // new vars needed
        SLVec3f position = this->translation();
        SLVec3f forward =  this->forward();
        SLVec3f right =    this->right();
        SLVec3f up =       this->up();

        // The lookAt point
        SLVec3f laP = position + _focalDist * forward;

         
        // Determine rotation point as the center of the AABB of the hitNode
        SLVec3f rtP;
        if (_lookAtRay.length < FLT_MAX && _lookAtRay.hitNode)
             rtP = _lookAtRay.hitNode->aabb()->centerWS();
        else rtP = laP;
              
        // Determine rot angles around x- & y-axis
        SLfloat dY = (y-_oldTouchPos1.y) * _rotFactor;
        SLfloat dX = (x-_oldTouchPos1.x) * _rotFactor;

        if (_camAnim==turntableYUp) //.......................................
        {
            SLMat4f rot;
            rot.translate(rtP);
            rot.rotate(-dX, SLVec3f(0,1,0));
            rot.rotate(-dY, right);
            rot.translate(-rtP);
			
            _om.setMatrix(rot * _om);
            needWMUpdate();
        }
        else if (_camAnim==turntableZUp) //..................................
        {
            SLMat4f rot;
            rot.translate(rtP);
            rot.rotate(dX, SLVec3f(0,0,1));
            rot.rotate(dY, right);
            rot.translate(-rtP);
         
            _om.setMatrix(rot * _om);
            needWMUpdate();
        }
        else if (_camAnim==walkingYUp) //....................................
        {
            dY *= 0.5f; 
            dX *= 0.5f; 
            
            SLMat4f rot;
            rot.rotate(-dX, SLVec3f(0, 1, 0));
            rot.rotate(-dY, right);

            forward.set(rot.multVec(forward));
            lookAt(position + forward);
        }
        else if (_camAnim==walkingZUp) //....................................
        {
            dY *= 0.5f; 
            dX *= 0.5f; 
            
            SLMat4f rot;
            rot.rotate(-dX, SLVec3f(0, 0, 1));
            rot.rotate(-dY, right);

            forward.set(rot.multVec(forward));
            lookAt(position + forward, SLVec3f(0, 0, 1));
        }
        
        _oldTouchPos1.set((SLfloat)x,(SLfloat)y);
    } 
    else
    if (button == ButtonMiddle) //==============================================
    {   if (_camAnim==turntableYUp || _camAnim==turntableZUp)
        {  
            // Calculate the fraction delta of the mouse movement
            SLVec2f dMouse(x-_oldTouchPos1.x, _oldTouchPos1.y-y);
            dMouse.x /= (SLfloat)_scrW;
            dMouse.y /= (SLfloat)_scrH;
         
            // Scale the mouse delta by the lookAt distance
            SLfloat lookAtDist;
            if (_lookAtRay.length < FLT_MAX)
                lookAtDist = _lookAtRay.length;
            else lookAtDist = _focalDist;

            // scale factor depending on the space sice at focal dist
            SLfloat spaceH = tan(SL_DEG2RAD*_fov/2) * lookAtDist * 2.0f;
            SLfloat spaceW = spaceH * _aspect;

            dMouse.x *= spaceW;
            dMouse.y *= spaceH;
         
            if (mod==KeyCtrl)
            {
                translate(SLVec3f(-dMouse.x, 0, dMouse.y), TS_Object);

            } else
            {
                translate(SLVec3f(-dMouse.x, -dMouse.y, 0), TS_Object);
            }
            _oldTouchPos1.set((SLfloat)x,(SLfloat)y);
        }
    } //========================================================================
    return true;
}
Exemplo n.º 14
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.º 15
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;
    }
}
Exemplo n.º 16
0
/*!
onInit initializes the global variables and builds the shader program. It
should be called after a window with a valid OpenGL context is present.
*/
void onInit()
{  
    // Set light parameters
    _globalAmbi.set(0.0f, 0.0f, 0.0f);
    _lightPos.set( 0.0f, 0.0f, 100.0f);
    _lightDir.set( 0.0f, 0.0f,-1.0f);
    _lightAmbient.set( 0.1f, 0.1f, 0.1f);
    _lightDiffuse.set( 1.0f, 1.0f, 1.0f);
    _lightSpecular.set( 1.0f, 1.0f, 1.0f);
    _matAmbient.set( 1.0f, 1.0f, 1.0f);
    _matDiffuse.set( 1.0f, 1.0f, 1.0f);
    _matSpecular.set( 1.0f, 1.0f, 1.0f);
    _matEmissive.set( 0.0f, 0.0f, 0.0f);
    _matShininess = 100.0f;

    // backwards movement of the camera
    _camZ = -3.0f;

    // Mouse rotation parameters
    _rotX = 0;
    _rotY = 0;
    _deltaX = 0;
    _deltaY = 0;
    _mouseLeftDown = false;

    // Load textures
    _textureID = glUtils::buildTexture("../_data/images/textures/earth2048_C.jpg");

    // Load, compile & link shaders
    _shaderVertID = glUtils::buildShader("../_data/shaders/ADSTex.vert", GL_VERTEX_SHADER);
    _shaderFragID = glUtils::buildShader("../_data/shaders/ADSTex.frag", GL_FRAGMENT_SHADER);
    _shaderProgID = glUtils::buildProgram(_shaderVertID, _shaderFragID);

    // Activate the shader program
    glUseProgram(_shaderProgID);

    // Get the variable locations (identifiers) within the vertex & pixel shader programs
    _pLoc            = glGetAttribLocation (_shaderProgID, "a_position");
    _nLoc            = glGetAttribLocation (_shaderProgID, "a_normal");
    _tLoc            = glGetAttribLocation (_shaderProgID, "a_texCoord");
    _mvMatrixLoc     = glGetUniformLocation(_shaderProgID, "u_mvMatrix");
    _mvpMatrixLoc    = glGetUniformLocation(_shaderProgID, "u_mvpMatrix");
    _nMatrixLoc      = glGetUniformLocation(_shaderProgID, "u_nMatrix");
    _globalAmbiLoc   = glGetUniformLocation(_shaderProgID, "u_globalAmbi");
    _lightPosVSLoc   = glGetUniformLocation(_shaderProgID, "u_lightPosVS");
    _lightDirVSLoc   = glGetUniformLocation(_shaderProgID, "u_lightDirVS");
    _lightAmbientLoc = glGetUniformLocation(_shaderProgID, "u_lightAmbient");
    _lightDiffuseLoc = glGetUniformLocation(_shaderProgID, "u_lightDiffuse");
    _lightSpecularLoc= glGetUniformLocation(_shaderProgID, "u_lightSpecular");
    _matAmbientLoc   = glGetUniformLocation(_shaderProgID, "u_matAmbient");
    _matDiffuseLoc   = glGetUniformLocation(_shaderProgID, "u_matDiffuse");
    _matSpecularLoc  = glGetUniformLocation(_shaderProgID, "u_matSpecular");
    _matEmissiveLoc  = glGetUniformLocation(_shaderProgID, "u_matEmissive");
    _matShininessLoc = glGetUniformLocation(_shaderProgID, "u_matShininess");
    _texture0Loc     = glGetUniformLocation(_shaderProgID, "u_texture0");

    // Build object
    buildSquare();

    // Set some OpenGL states
    glClearColor(0.0f, 0.0f, 0.0f, 1);  // Set the background color
    glEnable(GL_DEPTH_TEST);            // Enables depth test
    glEnable(GL_CULL_FACE);             // Enables the culling of back faces
    GETGLERROR;                         // Check for OpenGL errors
}
Exemplo n.º 17
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;
    }
}