<commit_before>/*
  Copyright (C) 2006 by <NAME>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free
  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/


#include "common.h"

#include "light.h"
#include "raytracer.h"
#include "kdtree.h"
#include "scene.h"

// Attenuation functions
static float LightAttnNone (float, const csVector4&);
static float LightAttnLinear (float, const csVector4&);
static float LightAttnInverse (float, const csVector4&);
static float LightAttnRealistic (float, const csVector4&);
static float LightAttnCLQ (float, const csVector4&);

static lighter::LightAttenuationFunc attnFuncTable[] = 
{
  LightAttnNone,
  LightAttnLinear,
  LightAttnInverse,
  LightAttnRealistic,
  LightAttnCLQ
};


namespace lighter
{

  Light::Light (Sector* o, bool deltaDistribution)
    : ownerSector (o), lightFrustum (csVector3 (0,0,0)),
    deltaDistribution (deltaDistribution),  pseudoDynamic (false), realLight (true)
  {
    lightFrustum.MakeInfinite ();
  }

  Light::~Light ()
  {

  }

  void Light::SetAttenuation (csLightAttenuationMode mode, const csVector4& constants)
  {
    attenuationMode = mode;
    attenuationConsts = constants;
    attenuationFunc = attnFuncTable[mode];
  }


  //--
  size_t VisibilityTester::rayID;

  VisibilityTester::VisibilityTester (Light* light, Object* obj) : 
    light (light), obj (obj)
  {    
  }

  void VisibilityTester::AddSegment (KDTree* tree, const csVector3& start, 
    const csVector3& end)
  {
    csVector3 dir = end-start;
    float d = dir.Norm ();

    AddSegment (tree, start, dir / d, d);
  }

  void VisibilityTester::AddSegment (KDTree* tree, const csVector3& start, 
    const csVector3& dir, float maxL)
  {
    Segment s;

    s.ray.origin = start;
    s.ray.direction = dir;
    s.ray.minLength = FLT_EPSILON*10.0f;
    s.ray.maxLength = maxL - FLT_EPSILON*10.0f;
    s.ray.ignoreFlags = KDPRIM_FLAG_NOSHADOW; // Ignore primitives that don't cast shadows
    s.ray.rayID = ++rayID; // Give unique IDs to rays; needed for the ray debugger.
    s.tree = tree;

    allSegments.Push (s);
  }

  VisibilityTester::OcclusionState VisibilityTester::Occlusion (
    const Primitive* ignorePrim)
  {
    HitCallback hitcb (*this);
    size_t lastHitCount = transparentHits.GetSize();

    bool haveAnyHit = false;

    // Start by testing if we have no hits or possibly hit a non-transparent one first
    for (size_t i = 0; i < allSegments.GetSize (); ++i)
    {
      Segment& s = allSegments[i];
      s.ray.ignorePrimitive = ignorePrim;

      HitPoint hit;
      if (Raytracer::TraceAnyHit (s.tree,s.ray, hit))
      {
        haveAnyHit = true;
        if (!(hit.kdFlags & KDPRIM_FLAG_TRANSPARENT))
        {
          // Non-transparent hit
          return occlOccluded;
        }
      }
    }

    // Didn't hit anything, cannot be anything transparent either
    if (!haveAnyHit)
    {
      return occlUnoccluded;
    }

    for (size_t i = 0; i < allSegments.GetSize (); ++i)
    {
      Segment& s = allSegments[i];
      s.ray.ignorePrimitive = ignorePrim;

      if (Raytracer::TraceAllHits (s.tree, s.ray, &hitcb))
      {
        if (transparentHits.GetSize() == 0) return occlOccluded;
      }

      if (transparentHits.GetSize() == lastHitCount)
        globalLighter->rayDebug.RegisterUnhit (light, obj, s.ray);
      lastHitCount = transparentHits.GetSize();<commit_msg>Also register hits from 'any hit' tests when debugging occlusion rays is enabled<commit_after>/*
  Copyright (C) 2006 by <NAME>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free
  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/


#include "common.h"

#include "light.h"
#include "raytracer.h"
#include "kdtree.h"
#include "scene.h"

// Attenuation functions
static float LightAttnNone (float, const csVector4&);
static float LightAttnLinear (float, const csVector4&);
static float LightAttnInverse (float, const csVector4&);
static float LightAttnRealistic (float, const csVector4&);
static float LightAttnCLQ (float, const csVector4&);

static lighter::LightAttenuationFunc attnFuncTable[] = 
{
  LightAttnNone,
  LightAttnLinear,
  LightAttnInverse,
  LightAttnRealistic,
  LightAttnCLQ
};


namespace lighter
{

  Light::Light (Sector* o, bool deltaDistribution)
    : ownerSector (o), lightFrustum (csVector3 (0,0,0)),
    deltaDistribution (deltaDistribution),  pseudoDynamic (false), realLight (true)
  {
    lightFrustum.MakeInfinite ();
  }

  Light::~Light ()
  {

  }

  void Light::SetAttenuation (csLightAttenuationMode mode, const csVector4& constants)
  {
    attenuationMode = mode;
    attenuationConsts = constants;
    attenuationFunc = attnFuncTable[mode];
  }


  //--
  size_t VisibilityTester::rayID;

  VisibilityTester::VisibilityTester (Light* light, Object* obj) : 
    light (light), obj (obj)
  {    
  }

  void VisibilityTester::AddSegment (KDTree* tree, const csVector3& start, 
    const csVector3& end)
  {
    csVector3 dir = end-start;
    float d = dir.Norm ();

    AddSegment (tree, start, dir / d, d);
  }

  void VisibilityTester::AddSegment (KDTree* tree, const csVector3& start, 
    const csVector3& dir, float maxL)
  {
    Segment s;

    s.ray.origin = start;
    s.ray.direction = dir;
    s.ray.minLength = FLT_EPSILON*10.0f;
    s.ray.maxLength = maxL - FLT_EPSILON*10.0f;
    s.ray.ignoreFlags = KDPRIM_FLAG_NOSHADOW; // Ignore primitives that don't cast shadows
    s.ray.rayID = ++rayID; // Give unique IDs to rays; needed for the ray debugger.
    s.tree = tree;

    allSegments.Push (s);
  }

  VisibilityTester::OcclusionState VisibilityTester::Occlusion (
    const Primitive* ignorePrim)
  {
    HitCallback hitcb (*this);
    size_t lastHitCount = transparentHits.GetSize();

    bool haveAnyHit = false;

    // Start by testing if we have no hits or possibly hit a non-transparent one first
    if (globalLighter->rayDebug.IsEnabled())
    {
      // Use hit call back to register ray hits for debugging
      for (size_t i = 0; i < allSegments.GetSize (); ++i)
      {
	Segment& s = allSegments[i];
	s.ray.ignorePrimitive = ignorePrim;
  
	if (Raytracer::TraceAnyHit (s.tree,s.ray, &hitcb))
	{
	  haveAnyHit = true;
	  if (transparentHits.GetSize() == lastHitCount)
	  {
	    // Non-transparent hit
	    return occlOccluded;
	  }
	}
      }
    }
    else
    {
      // No ray hit registration needed, so no callback needed either
      for (size_t i = 0; i < allSegments.GetSize (); ++i)
      {
	Segment& s = allSegments[i];
	s.ray.ignorePrimitive = ignorePrim;
  
	HitPoint hit;
	if (Raytracer::TraceAnyHit (s.tree,s.ray, hit))
	{
	  haveAnyHit = true;
	  if (!(hit.kdFlags & KDPRIM_FLAG_TRANSPARENT))
	  {
	    // Non-transparent hit
	    return occlOccluded;
	  }
	}
      }
    }

    // Didn't hit anything, cannot be anything transparent either
    if (!haveAnyHit)
    {
      return occlUnoccluded;
    }

    for (size_t i = 0; i < allSegments.GetSize (); ++i)
    {
      Segment& s = allSegments[i];
      s.ray.ignorePrimitive = ignorePrim;

      if (Raytracer::TraceAllHits (s.tree, s.ray, &hitcb))
      {
        if (transparentHits.GetSize() == 0) return occlOccluded;
      }

      if (transparentHits.GetSize() == lastHitCount)
        globalLighter->rayDebug.RegisterUnhit (light, obj, s.ray);
      lastHitCount = transparentHits.GetSize();
{'fraction_non_alphanumeric': 0.10104570555751381, 'fraction_numerical': 0.008812125484666901, 'mean_word_length': 3.26026026026026, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4095422', 'n_tokens_mistral': 2872, 'n_tokens_neox': 2734, 'n_words': 825}