<commit_before>/*
 * Eclectic Sheep
 *
 * Copyright (C) 2012  Intel Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 */

#include <string.h>
#include <stdlib.h>

#include <cogl/cogl.h>
#include <SDL.h>

#include "es-entity.h"
#include "es-components.h"

#ifndef COGL_VERSION_CHECK
#define COGL_VERSION_CHECK(a,b,c) (FALSE)
#endif

#define USER_ENTITY 2
#define N_ENTITIES  4

typedef struct
{
  CoglFramebuffer *fb;
  gboolean quit;

  Entity entities[N_ENTITIES];
  Entity *selected_entity;
  Entity *main_camera;
  Entity *light;

  /* shadow mapping */
  CoglOffscreen *shadow_fb;
  CoglTexture2D *shadow_color;
  CoglTexture   *shadow_map;

  CoglPipeline *shadow_color_tex;
  CoglPipeline *shadow_map_tex;

  /* debug */
  CoglTexture *uv_debug;
} Cube;

static Cube cube;
static CoglContext *context;
static GTimer *timer;

CoglContext *
es_get_cogl_context (void)
{
  return context;
}

CoglPipeline *
es_get_root_pipeline (void)
{
  return es_entity_get_pipeline (&cube.entities[USER_ENTITY]);
}

/* in micro seconds  */
int64_t
es_get_current_time (void)
{
  return (int64_t) (g_timer_elapsed (timer, NULL) * 1e6);
}

static CoglPipeline *
create_texture_pipeline (CoglTexture *texture)
{
  static CoglPipeline *template = NULL, *new_pipeline;

  if (G_UNLIKELY (template == NULL))
    {
      template = cogl_pipeline_new (context);
      cogl_pipeline_set_layer_null_texture (template, 0, COGL_TEXTURE_TYPE_2D);
    }

  new_pipeline = cogl_pipeline_copy (template);
  cogl_pipeline_set_layer_texture (new_pipeline, 0, texture);

  return new_pipeline;
}


static void
compute_light_shadow_matrix (CoglMatrix *light_matrix,
                             CoglMatrix *light_projection,
                             CoglMatrix *light_view)
{
  /* Move the unit cube from [-1,1] to [0,1], column major order */
  float bias[16] = {
    .5f, .0f, .0f, .0f,
    .0f, .5f, .0f, .0f,
    .0f, .0f, .5f, .0f,
    .5f, .5f, .5f, 1.f
  };

  cogl_matrix_init_from_array (light_matrix, bias);
  cogl_matrix_multiply (light_matrix, light_matrix, light_projection);
  cogl_matrix_multiply (light_matrix, light_matrix, light_view);
}

static void
draw_entities (Cube            *cube,
               CoglFramebuffer *fb,
               Entity          *camera,
               gboolean         shadow_pass)
{
  CoglMatrix *transform, inverse;
  int i;

  transform = es_entity_get_transform (camera);
  cogl_matrix_get_inverse (transform, &inverse);
  if (shadow_pass)
    {
      cogl_framebuffer_identity_matrix (fb);
      cogl_framebuffer_scale (fb, 1, -1, 1);
      cogl_framebuffer_transform (fb, &inverse);
    }
  else
    {
      cogl_framebuffer_set_modelview_matrix (fb, &inverse);
    }
  es_entity_draw (camera, fb);

  for (i = 1; i < N_ENTITIES; i++)
    {
      Entity *entity;

      entity = &cube->entities[i];

      if (shadow_pass && !entity_cast_shadow (entity))
        continue;

      cogl_framebuffer_push_matrix (fb);

      transform = es_entity_get_transform (entity);
      cogl_framebuffer_transform (fb, transform);

      es_entity_draw (entity, fb);

      cogl_framebuffer_pop_matrix (fb);
    }
}

static void
draw (Cube *cube)
{
  int i;
  int64_t time; /* micro seconds */
  CoglFramebuffer *shadow_fb;

  /*
   * update entities
   */

  time = es_get_current_time ();

  for (i = 0; i < N_ENTITIES; i++)
    {
      Entity *entity = &cube->entities[i];

      es_entity_update (entity, time);
    }

  /*
   * render the shadow map
   */

  shadow_fb = COGL_FRAMEBUFFER (cube->shadow_fb);

  /* update the light matrix uniform */
  {
    CoglMatrix light_shadow_matrix, light_projection, light_view;
    CoglPipeline *pipeline;

    int location;

    cogl_framebuffer_get_projection_matrix (shadow_fb, &light_projection);
    cogl_framebuffer_get_modelview_matrix (shadow_fb, &light_view);
    compute_light_shadow_matrix (&light_shadow_matrix,
                                 &light_projection,
                                 &light_view);

    pipeline = es_entity_get_pipeline (&cube->entities[USER_ENTITY]);
    location = cogl_pipeline_get_uniform_location (pipeline,
                                                   "light_shadow_matrix");
    cogl_pipeline_set_uniform_matrix (pipeline,
                                      location,
                                      4, 1,
                                      FALSE,
                                      cogl_matrix_get_array (&light_shadow_matrix));

    pipeline = es_entity_get_pipeline (&cube->entities[USER_ENTITY + 1]);
    location = cogl_pipeline_get_uniform_location (pipeline,
                                                   "light_shadow_matrix");
    cogl_pipeline_set_uniform_matrix (pipeline,
                                      location,
                                      4, 1,
                                      FALSE,
                                      cogl_matrix_get_array (&light_shadow_matrix));
  }

  draw_entities (cube, shadow_fb, cube->light, TRUE /* shadow pass */);

  /*<commit_msg>main: Fix the way we compute the light view matrix uniform<commit_after>/*
 * Eclectic Sheep
 *
 * Copyright (C) 2012  Intel Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 */

#include <string.h>
#include <stdlib.h>

#include <cogl/cogl.h>
#include <SDL.h>

#include "es-entity.h"
#include "es-components.h"

#ifndef COGL_VERSION_CHECK
#define COGL_VERSION_CHECK(a,b,c) (FALSE)
#endif

#define USER_ENTITY 2
#define N_ENTITIES  4

typedef struct
{
  CoglFramebuffer *fb;
  gboolean quit;

  Entity entities[N_ENTITIES];
  Entity *selected_entity;
  Entity *main_camera;
  Entity *light;

  /* shadow mapping */
  CoglOffscreen *shadow_fb;
  CoglTexture2D *shadow_color;
  CoglTexture   *shadow_map;

  CoglPipeline *shadow_color_tex;
  CoglPipeline *shadow_map_tex;

  /* debug */
  CoglTexture *uv_debug;
} Cube;

static Cube cube;
static CoglContext *context;
static GTimer *timer;

CoglContext *
es_get_cogl_context (void)
{
  return context;
}

CoglPipeline *
es_get_root_pipeline (void)
{
  return es_entity_get_pipeline (&cube.entities[USER_ENTITY]);
}

/* in micro seconds  */
int64_t
es_get_current_time (void)
{
  return (int64_t) (g_timer_elapsed (timer, NULL) * 1e6);
}

static CoglPipeline *
create_texture_pipeline (CoglTexture *texture)
{
  static CoglPipeline *template = NULL, *new_pipeline;

  if (G_UNLIKELY (template == NULL))
    {
      template = cogl_pipeline_new (context);
      cogl_pipeline_set_layer_null_texture (template, 0, COGL_TEXTURE_TYPE_2D);
    }

  new_pipeline = cogl_pipeline_copy (template);
  cogl_pipeline_set_layer_texture (new_pipeline, 0, texture);

  return new_pipeline;
}


static void
compute_light_shadow_matrix (CoglMatrix *light_matrix,
                             CoglMatrix *light_projection,
                             CoglMatrix *light_view)
{
  /* Move the unit cube from [-1,1] to [0,1], column major order */
  float bias[16] = {
    .5f, .0f, .0f, .0f,
    .0f, .5f, .0f, .0f,
    .0f, .0f, .5f, .0f,
    .5f, .5f, .5f, 1.f
  };

  cogl_matrix_init_from_array (light_matrix, bias);
  cogl_matrix_multiply (light_matrix, light_matrix, light_projection);
  cogl_matrix_multiply (light_matrix, light_matrix, light_view);
}

static void
draw_entities (Cube            *cube,
               CoglFramebuffer *fb,
               Entity          *camera,
               gboolean         shadow_pass)
{
  CoglMatrix *transform, inverse;
  int i;

  transform = es_entity_get_transform (camera);
  cogl_matrix_get_inverse (transform, &inverse);
  if (shadow_pass)
    {
      cogl_framebuffer_identity_matrix (fb);
      cogl_framebuffer_scale (fb, 1, -1, 1);
      cogl_framebuffer_transform (fb, &inverse);
    }
  else
    {
      cogl_framebuffer_set_modelview_matrix (fb, &inverse);
    }
  es_entity_draw (camera, fb);

  for (i = 1; i < N_ENTITIES; i++)
    {
      Entity *entity;

      entity = &cube->entities[i];

      if (shadow_pass && !entity_cast_shadow (entity))
        continue;

      cogl_framebuffer_push_matrix (fb);

      transform = es_entity_get_transform (entity);
      cogl_framebuffer_transform (fb, transform);

      es_entity_draw (entity, fb);

      cogl_framebuffer_pop_matrix (fb);
    }
}

static void
draw (Cube *cube)
{
  int i;
  int64_t time; /* micro seconds */
  CoglFramebuffer *shadow_fb;

  /*
   * update entities
   */

  time = es_get_current_time ();

  for (i = 0; i < N_ENTITIES; i++)
    {
      Entity *entity = &cube->entities[i];

      es_entity_update (entity, time);
    }

  /*
   * render the shadow map
   */

  shadow_fb = COGL_FRAMEBUFFER (cube->shadow_fb);

  /* update the light matrix uniform */
  {
    CoglMatrix light_shadow_matrix, light_projection, *light_transform,
               light_view;
    CoglPipeline *pipeline;

    int location;

    cogl_framebuffer_get_projection_matrix (shadow_fb, &light_projection);
    light_transform = es_entity_get_transform (cube->light);
    cogl_matrix_get_inverse (light_transform, &light_view);
    compute_light_shadow_matrix (&light_shadow_matrix,
                                 &light_projection,
                                 &light_view);

    pipeline = es_entity_get_pipeline (&cube->entities[USER_ENTITY]);
    location = cogl_pipeline_get_uniform_location (pipeline,
                                                   "light_shadow_matrix");
    cogl_pipeline_set_uniform_matrix (pipeline,
                                      location,
                                      4, 1,
                                      FALSE,
                                      cogl_matrix_get_array (&light_shadow_matrix));

    pipeline = es_entity_get_pipeline (&cube->entities[USER_ENTITY + 1]);
    location = cogl_pipeline_get_uniform_location (pipeline,
                                                   "light_shadow_matrix");
    cogl_pipeline_set_uniform_matrix (pipeline,
                                      location,
                                      4, 1,
                                      FALSE,
                                      cogl_matrix_get_array (&light_shadow_matrix));
  }

  draw_entities (cube, shadow_fb, cube->light, TRUE /* shadow pass */);

  /*
{'fraction_non_alphanumeric': 0.09201918883558657, 'fraction_numerical': 0.00907108591365024, 'mean_word_length': 2.567517112632234, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 26, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 28, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4758374', 'n_tokens_mistral': 3813, 'n_tokens_neox': 3631, 'n_words': 896}