Esempio n. 1
0
bool LightSquare::getLight( const TWorld &world, const TRay &ray, TRay &lightRay ) {
  // If point not in light volume, return false (no diffuse component)
  if ( !isLighten( ray.intersection.pointWorldSpace ) )
    return false;

  if ( !globalSettings::shadowOn )
    return true;

  stats.increase( TStatistic::STATISTIC_LIGHT_RAY );

  // Compute vector from intersection to light
  lightRay.direction = location - ray.intersection.pointWorldSpace;
  float dist2 = lightRay.direction.magnitudeSquared(); // get vector length

//--TODO  // test attenuation
//--TODO  float att = brightness;
//--TODO  if ( attenuation )
//--TODO    att = ( brightness / ( 1.0f + dist2 ) );
//--TODO  if ( att < lightAttenuation )
//--TODO    return false;

  lightRay.direction *= fastInvSqrt( dist2 ); // normalize vector
  lightRay.origin = ray.intersection.pointWorldSpace + lightRay.direction * 0.1f; // origin is intersection
  lightRay.reverseDirection = inverseVector( lightRay.direction );
  lightRay.target = location;
  lightRay.kind = TRay::RAY_SHADOW;

  // Compute amount of shadow receive  0: full shadow   1: no shadow
  if ( world.findFirstIntersection( lightRay, ray.intersection, dist2, shadowCache ) )
    return false;

  return true;
}
Esempio n. 2
0
float LightSquare::getAmountShadow( const TWorld &world, const TRay &ray ) {
  float shadow = 0.0f;

  // for each dot light in square: create a light ray and compute intersection
  TRay shadowRay;
  TPoint3 *dotGridIdx = dotGrid;
  for ( int i = 0; i < numDots; i++ ) {
    // create a lightRay from dot in grid to intersection
    shadowRay.direction = *dotGridIdx - ray.intersection.pointWorldSpace;
    float dist2 = shadowRay.direction.magnitudeSquared();

//--TODO    // test attenuation
//--TODO    float att = brightness;
//--TODO    if ( attenuation )
//--TODO      att = ( brightness / ( 1.0f + dist2 ) );
//--TODO    if ( att < lightAttenuation ) {
//--TODO      dotGridIdx++; // next dot in grid
//--TODO      continue;
//--TODO    }

    shadowRay.direction *= fastInvSqrt( dist2 ); // normalize vector
    shadowRay.origin = ray.intersection.pointWorldSpace + shadowRay.direction * 0.1f; // origin is intersection
    shadowRay.reverseDirection = inverseVector( shadowRay.direction );
    shadowRay.target = *dotGridIdx;
    shadowRay.kind = TRay::RAY_SHADOW;
    
//--    // if shadow: add 0.0f
//--    if ( world.findFirstIntersection( shadowRay, ray.intersection, dist2, shadowCache ) )
//--      shadowCache = shadowRay.intersectionObject; // store object in cache
//--    // if no shadow: add 1.0f
//--    else
//--      shadow += 1.0f;
    // if no shadow: add 1.0f, shadow cache is updated in findFirstIntersection
    if ( !world.findFirstIntersection( shadowRay, ray.intersection, dist2, shadowCache ) )
      shadow += 1.0f;
    // if shadow: add 0.0f

    dotGridIdx++; // next dot in grid
  }
  return shadow * oneOverNumDots;
}
Esempio n. 3
0
bool
Particle::update()
{
    if (!mMap) return false;

    if (mLifetimeLeft == 0)
    {
        mAlive = false;
    }

    if (mAlive)
    {
        //calculate particle movement
        if (mMomentum != 1.0f)
        {
            mVelocity *= mMomentum;
        }

        if (mTarget && mAcceleration != 0.0f)
        {
            Vector dist = mPos - mTarget->getPosition();
            dist.x *= SIN45;
            float invHypotenuse;

            switch (Particle::fastPhysics)
            {
                case 1:
                    invHypotenuse = fastInvSqrt(
                        dist.x * dist.x + dist.y * dist.y + dist.z * dist.z);
                    break;
                case 2:
                    invHypotenuse = 2.0f /
                        fabs(dist.x) + fabs(dist.y) + fabs(dist.z);
                    break;
                default:
                    invHypotenuse = 1.0f / sqrt(
                        dist.x * dist.x + dist.y * dist.y + dist.z * dist.z);
                    break;
            }

            if (invHypotenuse)
            {
                if (mInvDieDistance > 0.0f && invHypotenuse > mInvDieDistance)
                {
                    mAlive = false;
                }
                float accFactor = invHypotenuse * mAcceleration;
                mVelocity -= dist * accFactor;
            }
        }

        if (mRandomnes > 0)
        {
            mVelocity.x += (rand()%mRandomnes - rand()%mRandomnes) / 1000.0f;
            mVelocity.y += (rand()%mRandomnes - rand()%mRandomnes) / 1000.0f;
            mVelocity.z += (rand()%mRandomnes - rand()%mRandomnes) / 1000.0f;
        }

        mVelocity.z -= mGravity;

        // Update position
        mPos.x += mVelocity.x;
        mPos.y += mVelocity.y * SIN45;
        mPos.z += mVelocity.z * SIN45;

        // Update other stuff
        if (mLifetimeLeft > 0)
        {
            mLifetimeLeft--;
        }
        mLifetimePast++;

        if (mPos.z > PARTICLE_SKY || mPos.z < 0.0f)
        {
            if (mBounce > 0.0f)
            {
                mPos.z *= -mBounce;
                mVelocity *= mBounce;
                mVelocity.z = -mVelocity.z;
            }
            else {
                mAlive = false;
            }
        }

        // Update child emitters
        if (mLifetimePast%Particle::emitterSkip == 0)
        {
            for (   EmitterIterator e = mChildEmitters.begin();
                    e != mChildEmitters.end();
                    e++
                )
            {
                Particles newParticles = (*e)->createParticles();
                for (   ParticleIterator p = newParticles.begin();
                        p != newParticles.end();
                        p++
                    )
                {
                    (*p)->moveBy(mPos.x, mPos.y, mPos.z);
                    mChildParticles.push_back (*p);
                }
            }
        }
    }

    // Update child particles
    for (ParticleIterator p = mChildParticles.begin();
         p != mChildParticles.end();)
    {
        if ((*p)->update())
        {
            p++;
        } else {
            delete (*p);
            p = mChildParticles.erase(p);
        }
    }

    if (!mAlive && mChildParticles.empty() && mAutoDelete)
    {
        return false;
    }

    return true;
}
Esempio n. 4
0
bool LightSquare::computeLighting( const TWorld &world, const TRay &ray,
				   TLighting &lighting ) {
  lighting.light = this;
  lighting.visible = isLighten( ray.intersection.pointWorldSpace );
  // If point not in light volume, return false (no diffuse component)
  if ( !lighting.visible )
    return false;

  const TFinish *finish = ray.intersection.texture->finish;

  // reset lighting
  lighting.shadow = 0.0f;
  lighting.diffuse = 0.0f;
  lighting.specular = 0.0f;
  lighting.phong = 0.0f;
  float att = 0.0f;

  TRay lightRay;
  TPoint3 *dotGridIdx = dotGrid;
  for ( int i = 0; i < numDots; i++, dotGridIdx++ ) {
    // create a lightRay from dot in grid to intersection
    lightRay.direction = *dotGridIdx - ray.intersection.pointWorldSpace;
    float dist2 = lightRay.direction.magnitudeSquared();
    lightRay.direction *= fastInvSqrt( dist2 ); // normalize vector
    lightRay.origin = ray.intersection.pointWorldSpace + lightRay.direction * 0.1f; // origin is intersection
    lightRay.reverseDirection = inverseVector( lightRay.direction );
    lightRay.target = *dotGridIdx;

    stats.increase( TStatistic::STATISTIC_LIGHT_RAY );

    // TODO
    att += brightness;
    
    // if shadow: proceed with next lightRay
    if ( world.findFirstIntersection( lightRay, ray.intersection, dist2, shadowCache ) )
      continue;
    // if no shadow: add 1.0f (no shadow) to lighting.shadow
    lighting.shadow += 1.0f;

    stats.increase( TStatistic::STATISTIC_DIFFUSE );
    
    // Diffuse
    if ( finish->diffuseFactor > 0.0f ) {
      float angleLight = ray.intersection.normal | lightRay.direction;
      if ( angleLight > 0.0f )
	//--float intensity = powf( angleLight, finish->brilliance ); // FIXME
	lighting.diffuse += angleLight * finish->diffuseFactor;
    }
    
    // Specular
    if ( finish->specularFactor > 0.0f ) {
      TVector3 H = lightRay.direction - ray.direction; H.normalize();
      float angleSpecular = H | ray.intersection.normal;
      if ( angleSpecular > 0.0f ) {
	float intensity = powf( angleSpecular, finish->specularRoughness );
	lighting.specular += intensity * finish->specularFactor;
      }
    }
    
    // Phong
    if ( finish->phongFactor > 0.0f ) {
      TVector3 R = reflectVector( ray.direction, ray.intersection.normal );
      float anglePhong = R | lightRay.direction;
      if ( anglePhong > 0.0f ) {
	float intensity = powf( anglePhong, finish->phongSize );
	lighting.phong += intensity * finish->phongFactor;
      }
    }
  }

  // If full shadow, return false (no diffuse component)
  if ( lighting.shadow <= 0.0f )
    return false;

  // att, shadow, diffuse, specular and phong must be scaled by oneOverNumDots (=N)
  // att * N * shadow * N * ( diffuse * N + specular * N + phong * N )
  // = N*N * ( att * shadow * ( N * ( diffuse + specular + phong ) )
  // = N*N*N * ( att * shadow * ( diffuse + specular + phong ) )
  lighting.color = color * ( (oneOverNumDots*oneOverNumDots*oneOverNumDots) * att * lighting.shadow * ( lighting.diffuse + lighting.specular + lighting.phong ) );
  return true;
}
Esempio n. 5
0
bool LightSquare::computeLighting( const TWorld &world, const TRay &ray,
				   TLighting &lighting ) {
  lighting.light = this;
  lighting.visible = isLighten( ray.intersection.pointWorldSpace );
  // If point not in light volume, return false (no diffuse component)
  if ( !lighting.visible )
    return false;

  stats.increase( TStatistic::STATISTIC_LIGHT_RAY );

  // Compute vector from intersection to light
  TRay lightRay;
  lightRay.direction = location - ray.intersection.pointWorldSpace;
  float dist2 = lightRay.direction.magnitudeSquared(); // get vector length

  // test attenuation
  float att = brightness;
//--TODO  if ( attenuation )
//--TODO    att = ( brightness / ( 1.0f + dist2 ) );
//--TODO  if ( att < lightAttenuation )
//--TODO    return false;

  lightRay.direction *= fastInvSqrt( dist2 ); // normalize vector
  //--  lightRay.origin = ray.intersection.pointWorldSpace + lightRay.direction * 0.1f; // origin is intersection
  //--  lightRay.reverseDirection = inverseVector( lightRay.direction );
  //--  lightRay.target = location;
  lightRay.kind = TRay::RAY_SHADOW;

  // Shadow
//--  if ( globalSettings::shadowOn
//--       && world.findFirstIntersection( lightRay, ray.intersection, dist2, shadowCache ) ) {
//--    // If full shadow, return false (no diffuse component)
//--    lighting.shadow = 0.0f; // shadow
//--    return false;
//--  }
//--  else
//--    lighting.shadow = 1.0f; // no shadow
  if ( globalSettings::shadowOn ) {
    lighting.shadow = getAmountShadow( world, ray );
    // If full shadow, return false (no diffuse component)
    if ( lighting.shadow <= 0.0f )
      return false;
  }
  else lighting.shadow = 1.0f;

  const TFinish *finish = ray.intersection.texture->finish;

  stats.increase( TStatistic::STATISTIC_DIFFUSE );

  // Diffuse
  lighting.diffuse = 0.0f;
  if ( finish->diffuseFactor > 0.0f ) {
    // FIXME: create a light ray for each dot in square and compute average value
    // we compute angle between lightRay (from intersection to center of square)
    // this "trick" is a good approximation if dotSize is small
    float angleLight = ray.intersection.normal | lightRay.direction;
    if ( angleLight > 0.0f )
      //--float intensity = powf( angleLight, finish->brilliance ); // FIXME
      lighting.diffuse = angleLight * finish->diffuseFactor;
  }

  // Specular
  lighting.specular = 0.0f;
  if ( finish->specularFactor > 0.0f ) {
    TVector3 H = lightRay.direction - ray.direction; H.normalize();
    float angleSpecular = H | ray.intersection.normal;
    if ( angleSpecular > 0.0f ) {
      float intensity = powf( angleSpecular, finish->specularRoughness );
      lighting.specular = intensity * finish->specularFactor;
    }
  }

  // Phong
  lighting.phong = 0.0f;
  if ( finish->phongFactor > 0.0f ) {
    TVector3 R = reflectVector( ray.direction, ray.intersection.normal );
    float anglePhong = R | lightRay.direction;
    if ( anglePhong > 0.0f ) {
      float intensity = powf( anglePhong, finish->phongSize );
      lighting.phong = intensity * finish->phongFactor;
    }
  }

  lighting.color = color * ( att * lighting.shadow * ( lighting.diffuse + lighting.specular + lighting.phong ) );
  return true;
}
Esempio n. 6
0
bool Particle::update()
{
    if (!mMap)
        return false;

    if (mLifetimeLeft == 0 && mAlive == ALIVE)
        mAlive = DEAD_TIMEOUT;

    Vector oldPos = mPos;

    if (mAlive == ALIVE)
    {
        //calculate particle movement
        if (mMomentum != 1.0f)
        {
            mVelocity *= mMomentum;
        }

        if (mTarget && mAcceleration != 0.0f)
        {
            Vector dist = mPos - mTarget->getPosition();
            dist.x *= SIN45;
            float invHypotenuse;

            switch (Particle::fastPhysics)
            {
                case 1:
                    invHypotenuse = fastInvSqrt(
                        dist.x * dist.x + dist.y * dist.y + dist.z * dist.z);
                    break;
                case 2:
                    invHypotenuse = 2.0f /
                        fabs(dist.x) + fabs(dist.y) + fabs(dist.z);
                    break;
                default:
                    invHypotenuse = 1.0f / sqrt(
                        dist.x * dist.x + dist.y * dist.y + dist.z * dist.z);
                    break;
            }

            if (invHypotenuse)
            {
                if (mInvDieDistance > 0.0f && invHypotenuse > mInvDieDistance)
                {
                    mAlive = DEAD_IMPACT;
                }
                float accFactor = invHypotenuse * mAcceleration;
                mVelocity -= dist * accFactor;
            }
        }

        if (mRandomness > 0)
        {
            mVelocity.x += (rand()%mRandomness - rand()%mRandomness) / 1000.0f;
            mVelocity.y += (rand()%mRandomness - rand()%mRandomness) / 1000.0f;
            mVelocity.z += (rand()%mRandomness - rand()%mRandomness) / 1000.0f;
        }

        mVelocity.z -= mGravity;

        // Update position
        mPos.x += mVelocity.x;
        mPos.y += mVelocity.y * SIN45;
        mPos.z += mVelocity.z * SIN45;

        // Update other stuff
        if (mLifetimeLeft > 0)
        {
            mLifetimeLeft--;
        }
        mLifetimePast++;

        if (mPos.z < 0.0f)
        {
            if (mBounce > 0.0f)
            {
                mPos.z *= -mBounce;
                mVelocity *= mBounce;
                mVelocity.z = -mVelocity.z;
            }
            else
            {
                mAlive = DEAD_FLOOR;
            }
        }
        else if (mPos.z > PARTICLE_SKY)
        {
                mAlive = DEAD_SKY;
        }

        // Update child emitters
        if ((mLifetimePast-1)%Particle::emitterSkip == 0)
        {
            for (EmitterIterator e = mChildEmitters.begin();
                 e != mChildEmitters.end(); e++)
            {
                Particles newParticles = (*e)->createParticles(mLifetimePast);
                for (ParticleIterator p = newParticles.begin();
                     p != newParticles.end(); p++)
                {
                    (*p)->moveBy(mPos);
                    mChildParticles.push_back (*p);
                }
            }
        }
    }

    // create death effect when the particle died
    if (mAlive != ALIVE && mAlive != DEAD_LONG_AGO)
    {
        if ((mAlive & mDeathEffectConditions) > 0x00  && !mDeathEffect.empty())
        {
            Particle* deathEffect = particleEngine->addEffect(mDeathEffect, 0, 0);
            deathEffect->moveBy(mPos);
        }
        mAlive = DEAD_LONG_AGO;
    }

    Vector change = mPos - oldPos;

    // Update child particles

    for (ParticleIterator p = mChildParticles.begin();
         p != mChildParticles.end();)
    {
        //move particle with its parent if desired
        if ((*p)->doesFollow())
        {
            (*p)->moveBy(change);
        }
        //update particle
        if ((*p)->update())
        {
            p++;
        }
        else
        {
            delete (*p);
            p = mChildParticles.erase(p);
        }
    }
    if (mAlive != ALIVE && mChildParticles.empty() && mAutoDelete)
    {
        return false;
    }

    return true;
}