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

params3d.c

/*
 *  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/>.
 */

#include "params3d.h"
#include "brandom.h"

#define MAX_3D    10.0
#define NSAMPLES  36 /* for the sphere */
#define NSAMPLES2 ((float)(NSAMPLES))
#define TSTEP     (2.0 * M_PI / NSAMPLES2)
#define PSTEP     (M_PI / (NSAMPLES2-1))


/* These are the Quadrants also ;) */

/* oliv3 FIXME reorder so that we can traverse easily ?
 * like inverting a value in draw sphere optimized
 */
Point3d_t Cube3d[8] = {
  { { -1.0, +1.0, +1.0 } }, /* 0 */
  { { +1.0, +1.0, +1.0 } }, /* 1 */
  { { +1.0, -1.0, +1.0 } }, /* 2 */
  { { -1.0, -1.0, +1.0 } }, /* 3 */
  { { -1.0, +1.0, -1.0 } }, /* 4 */
  { { +1.0, +1.0, -1.0 } }, /* 5 */
  { { +1.0, -1.0, -1.0 } }, /* 6 */
  { { -1.0, -1.0, -1.0 } }  /* 7 */
};

Point3d_t Sphere3d[NSAMPLES][NSAMPLES];

/* #define RHO (sqrt (3.0)) */
#define RHO 1.732051


static void
init_sphere_3d(void)
{
  float theta, phi;
  u_short it = 0, ip = 0;

  for (theta = 0; it < NSAMPLES; theta += TSTEP, it++) {
    ip = 0;
    for (phi = 0; ip < NSAMPLES; phi += PSTEP, ip++) {
      Point3d_t *p = &Sphere3d[it][ip];
      
      p->pos.x = RHO * cosf(theta) * sinf(phi);
      p->pos.y = RHO * sinf(theta) * sinf(phi);
      p->pos.z = RHO * cosf(phi);
    }
  }
}


Params3d_t *
Params3d_new()
{
  Params3d_t *p = NULL;

  p = xcalloc(1, sizeof(Params3d_t));

  Params3d_init(p);

  return p;
}


void
Params3d_init(Params3d_t *p)
{
  int i;
      
  for (i = 0; i < 3; i++) {
    p->rotations[i] = 0;
    p->auto_rotate[i] = 0;
    p->rotate_amount[i] = ROT_STEP;
  }
  update(p);

  /* OK:    p->scale_factor = 120; */
  p->scale_factor = HHEIGHT/1.333;
  p->draw_boundary = 0;

  p->xs = p->xe = HWIDTH;
  p->ys = p->ye = HHEIGHT;

  init_sphere_3d();
  zero_3d(p);

  p->auto_rotate[Y_AXIS] = 1;
  p->rotate_amount[Y_AXIS] = 3 * ROT_STEP;

#ifdef Z_BUFFER
  Params3d_init_z_buffer();
#endif

  p->do_auto_rotate = 0;
  p->rotate_amount[X_AXIS] = 1 * ROT_STEP;
  p->rotate_amount[Y_AXIS] = 2 * ROT_STEP;
  p->rotate_amount[Z_AXIS] = 4 * ROT_STEP;
}


void
Params3d_delete(Params3d_t *p)
{
  xfree(p);
}


void
Params3d_randomize(Params3d_t *p)
{
  p->do_auto_rotate = 1;
  p->auto_rotate[X_AXIS] =  b_rand_boolean();
  p->auto_rotate[Y_AXIS] =  b_rand_boolean();
  p->auto_rotate[Z_AXIS] =  b_rand_boolean();
      
  if (!p->auto_rotate[X_AXIS] && !p->auto_rotate[Y_AXIS] && !p->auto_rotate[Z_AXIS]) {
    /* 2, c'est mieux qu'un :) */
    u_short idx = b_rand_int_range(0, 100) % 3;
    p->auto_rotate[idx] = p->auto_rotate[(idx+1) % 3] = 1;
  }
}


void
draw_sphere_3d(const Params3d_t *params3d, Buffer8_t *b, const Pixel_t color)
{
  u_short it, ip;
      
  for (it = 0; it < NSAMPLES; it++)
    for (ip = 0; ip < NSAMPLES; ip++)
      set_pixel_3d(params3d, b, &Sphere3d[it][ip], color);
}


void
draw_sphere_wireframe_3d(const Params3d_t *params3d, Buffer8_t *b, const Pixel_t color)
{
  u_short it, ip;

  for (it = 0; it < NSAMPLES-1; it++) {
    for (ip = 0; ip < NSAMPLES; ip++)
      draw_line_3d(params3d, b, &Sphere3d[it][ip], &Sphere3d[it+1][ip], color);
  }
  for (ip = 0; ip < NSAMPLES; ip++)
    draw_line_3d(params3d, b, &Sphere3d[0][ip], &Sphere3d[NSAMPLES-1][ip], color);
  for (it = 0; it < NSAMPLES; it++) {
    for (ip = 0; ip < NSAMPLES-1; ip++)
      draw_line_3d(params3d, b, &Sphere3d[it][ip], &Sphere3d[it][ip+1], color);
  }
}


/* not inlinable */
void
draw_cube_3d(const Params3d_t *p, Buffer8_t *b, const Pixel_t color)
{
  draw_line_3d(p, b, &Cube3d[7], &Cube3d[6], color);
  draw_line_3d(p, b, &Cube3d[7], &Cube3d[4], color);
  draw_line_3d(p, b, &Cube3d[7], &Cube3d[3], color);

  draw_line_3d(p, b, &Cube3d[5], &Cube3d[6], color); 
  draw_line_3d(p, b, &Cube3d[5], &Cube3d[4], color);
  draw_line_3d(p, b, &Cube3d[5], &Cube3d[1], color);

  draw_line_3d(p, b, &Cube3d[0], &Cube3d[4], color);
  draw_line_3d(p, b, &Cube3d[0], &Cube3d[3], color);
  draw_line_3d(p, b, &Cube3d[0], &Cube3d[1], color);

  draw_line_3d(p, b, &Cube3d[2], &Cube3d[6], color);
  draw_line_3d(p, b, &Cube3d[2], &Cube3d[3], color);
  draw_line_3d(p, b, &Cube3d[2], &Cube3d[1], color);
}


void
draw_line_3d(const Params3d_t *p, Buffer8_t *b, const Point3d_t *p1, const Point3d_t *p2, const Pixel_t color)
{
  Point2d_t pa, a1;
  Point2d_t pb, b1;
      
  pa = projection_perspective(p, p1);
  pb = projection_perspective(p, p2);
  a1 = pixel_ecran(p, &pa);
  b1 = pixel_ecran(p, &pb);

  draw_line(b, a1.x, a1.y, b1.x, b1.y, color);
}


void
Params3d_rotate(Params3d_t *p)
{
  float dx = (p->xe-p->xs)/(float)(WIDTH/8);
  float dy = (p->ye-p->ys)/(float)(HEIGHT/8);

  /* printf ("dx= %f, dy= %f\n", dx, dy); */
      
  p->rotations[Y_AXIS] += dx;
  p->rotations[X_AXIS] += dy;
      
  if (p->rotations[X_AXIS] > 2 * M_PI)
    p->rotations[X_AXIS] -= 2 * M_PI;
  else if (p->rotations[X_AXIS] < -2 * M_PI)
    p->rotations[X_AXIS] += 2 * M_PI;
      
  if (p->rotations[Z_AXIS] > 2 * M_PI)
    p->rotations[Z_AXIS] -= 2 * M_PI;
  else if (p->rotations[Z_AXIS] < -2 * M_PI)
    p->rotations[Z_AXIS] += 2 * M_PI;
      
  p->xs = p->xe;
  p->ys = p->ye;
      
  update(p);
}


void
Params3d_change_rotations(Params3d_t *p)
{
  int i, changed = 0;

  for (i = X_AXIS; i <= Z_AXIS; i++)
    if (p->auto_rotate[i]) {
      p->rotations[i] += p->rotate_amount[i];
      changed = 1;
    }
  if (changed)
    update(p);
}


#ifdef Z_BUFFER
void
Params3d_init_z_buffer()
{
  int i, j;
  
  for (j = 0; j < HEIGHT; j++)
    for (i = 0; i < WIDTH; i++)
      z_buffer[j][i] = -1e6;
}
#endif


void
update_x(Params3d_t *p)
{
  p->Cos[X_AXIS] = cosf(p->rotations[X_AXIS]);
  p->Sin[X_AXIS] = sinf(p->rotations[X_AXIS]);
}


void
update_y(Params3d_t *p)
{
  p->Cos[Y_AXIS] = cosf(p->rotations[Y_AXIS]);
  p->Sin[Y_AXIS] = sinf(p->rotations[Y_AXIS]);
}


void
update_z(Params3d_t *p)
{
  p->Cos[Z_AXIS] = cosf(p->rotations[Z_AXIS]);
  p->Sin[Z_AXIS] = sinf(p->rotations[Z_AXIS]);
}

Generated by  Doxygen 1.6.0   Back to index