Logo Search packages:      
Sourcecode: lebiniou version File versions  Download package

infinity.h

/*
 *  Copyright 1994-2011 Olivier Girondel
 *
 *  This file is part of lebiniou.
 *
 *  lebiniou is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  lebiniou 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with lebiniou. If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __INFINITY_H
#define __INFINITY_H


00024 typedef struct {
  gfloat x,y;
} t_complex;

00028 typedef struct {
00029   guint32 coord ; /**< Coordinates of the top left pixel. */
00030   guint32 weight; /**< 32 bits = 4*8 = weights of the four corners */
} t_interpol;

00033 typedef struct {
00034   gint32 width;       /**< number of vectors */
00035   gint32 height;      /**< length of each vector */
00036   t_interpol *vector; /**< pointer to the vector field */
} vector_field_t;

00039 typedef struct {
  u_char nb_fct;
  void   (*new)(struct Context_s *);              /* constructor */
  t_complex (*fct)(t_complex, guint32, gint32, gint32);
  vector_field_t *vector_field;
} VectorField_t;

00046 struct args_s {
  guint32 f;
  guint32 height;
  VectorField_t *vf;
};


static void
compute_generate_sector(guint32 g, guint32 f, guint32 p1, guint32 p2,
                  guint32 debut, guint32 step, VectorField_t *vf)
{
  vector_field_t *vector_field = vf->vector_field;
  const guint32 width = (guint32)vector_field->width;
  const guint32 height = (guint32)vector_field->height;
  const guint32 prop_transmitted = 249;
  const guint32 b_add = g * width * height;
  t_interpol *vector = vector_field->vector;
  guint32 fin = debut + step;
  guint32 cx, cy;

  if (fin > height)
    fin = height;

  for (cy = debut; cy < fin; cy++)
    for (cx = 0; cx < width; cx++) {
      t_complex a;
      gfloat fpy;
      guint32 rw, lw, add;
      guint32 w1, w2, w3, w4;
      guint32 x, y;
          
      a.x = (gfloat)cx;
      a.y = (gfloat)cy;
      a = vf->fct(a, f, p1, p2);
      add = cx + cy * width;
      x = (guint32)(a.x);
      y = (guint32)(a.y);
      vector[b_add+add].coord = (x << 16) | y;

      fpy = a.y - floor (a.y);
      rw = (guint32)((a.x - floor (a.x)) * prop_transmitted);
      lw = prop_transmitted - rw;
      w4 = (guint32)(fpy * rw);
      w2 = rw - w4;
      w3 = (guint32)(fpy * lw);
      w1 = lw - w3; 
      vector[b_add + add].weight = \
      (w1 << 24) | (w2 << 16) | (w3 << 8) | w4;
    }
}


void
compute_generate_vector_field_loop(void *ptr)
{
  struct args_s *args = (struct args_s *)ptr;
  guint32 i;

  for (i = 0; i < args->height; i += 10)
    compute_generate_sector(args->f, args->f, 2, 2, i, 10, args->vf);

  xfree(args);
  pthread_exit(NULL);
}


void
compute_generate_vector_field(VectorField_t *vf)
{
  guint32 f, height;
  pthread_t *threads = NULL;

  threads = xcalloc(vf->nb_fct, sizeof(pthread_t));

  height = (guint32)vf->vector_field->height;

  printf("[i] infinity: Launching threads\n");
  for (f = 0; f < vf->nb_fct; f++) {
    struct args_s *args = xcalloc(1, sizeof(struct args_s));

    args->f = f;
    args->height = height;
    args->vf = vf;

    pthread_create(&threads[f], NULL, (void *(*)(void *))compute_generate_vector_field_loop, (void *)args);
  }

  printf("[i] infinity: Waiting for threads: ");
  for (f = 0; f < vf->nb_fct; f++) {
    pthread_join(threads[f], NULL);
    printf("%d ", f);
    fflush(stdout);
  }
  printf("\n[i] infinity: All threads exited\n");

  xfree(threads);
}


vector_field_t *
VectorField_vector_field_new(const u_char nb_fct)
{
  vector_field_t *field;
  
  field = g_new0(vector_field_t, 1);
  field->vector = g_new0(t_interpol, BUFFSIZE * nb_fct);
  field->width = WIDTH;
  field->height = HEIGHT;

  return field;
}


VectorField_t *
VectorField_new(const u_char nb_fct, t_complex (*fct)(t_complex, guint32, gint32, gint32))
{
  VectorField_t *vf = xcalloc(1, sizeof(VectorField_t));

  vf->nb_fct = nb_fct;
  vf->fct = fct;
  vf->vector_field = VectorField_vector_field_new(nb_fct);

  compute_generate_vector_field(vf);

  return vf;
}


void
VectorField_delete(VectorField_t *vf)
{
  assert(vf != NULL);

  g_free(vf->vector_field);
  xfree(vf);
}


void
VectorField_compute_surface(Context_t *ctx, t_interpol *vector, gint32 width, gint32 height) 
{
  gint32 i,j;
  gint32 add_dest = 0;
  guint32 add_src;
  t_interpol *interpol;
  Pixel_t *ptr_pix;
  guint32 color;
  Pixel_t *surface1 = active_buffer(ctx)->buffer;
  Pixel_t *surface2 = passive_buffer(ctx)->buffer;
  
  for (j = 0; j < height; j++)
    for (i = 0; i < width; i++) {
      interpol = &vector[add_dest];
      add_src = (interpol->coord & 0xFFFF) * width + (interpol->coord >> 16);
      ptr_pix = &((Pixel_t *)surface1)[add_src];
      color = ((guint32)(*(ptr_pix)) * (interpol->weight >> 24)
             + (guint32)(*(ptr_pix+1)) * ((interpol->weight & 0xFFFFFF) >> 16)
             + (guint32)(*(ptr_pix+width)) * ((interpol->weight & 0xFFFF) >> 8)
             + (guint32)(*(ptr_pix+width+1)) * (interpol->weight & 0xFF)) >> 8;
      if (color > 255)
      surface2[add_dest] = (Pixel_t)255;
      else
      surface2[add_dest] = (Pixel_t)color;
      add_dest++;
    }
}


void
VectorField_run(VectorField_t *vf, Context_t *ctx, u_long vector_index)
{
  vector_index *= BUFFSIZE;
  VectorField_compute_surface(ctx, &(vf->vector_field->vector[vector_index]),
                        vf->vector_field->width, vf->vector_field->height);
}

#endif /* __INFINITY_H */

Generated by  Doxygen 1.6.0   Back to index