pastebin

Paste #70124: lines.cpp

//lines.cpp

/*-- NOTE: You will have to manipulate this code to coorespond with the
            structures and stack implementation you chose to use.
	    Don't forget to put declarations in your .h files. --*/


/* The following (not including LookAt and Vertex3f) could either be
   implemented into your file or they can stand as a separate file called
   lines.c   It will be used for drawing pixels to the screen and
   for clipping. */
#include "lines.h"
#include <stdio.h>
#include <math.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <stdlib.h>


/* the clipping window */
static float xmin = 0.0;
static float xmax = 1.0;
static float ymin = 0.0;
static float ymax = 1.0;

/******************************************************************************
Draw a white line.

Entry:
  x0,y0 - first endpoint of line
  x1,y1 - second line endpoint
******************************************************************************/

void lines::draw_line(float x0, float y0, float x1, float y1)
{
  GLint viewport[4];
  int i;
  float x,y;
  float dx,dy;
  float xinc,yinc;
  float length=0.;
  int result;
  int width,height;

  /* set the clipping window */

  glGetIntegerv(GL_VIEWPORT, viewport);
  width = abs(viewport[2]-viewport[0]);
  height = abs(viewport[3]-viewport[1]);/*================================multiple definition of `draw_line(float, float, float, float)'==================================*/

  set_clip_window (0.0, 0.0, width - 0.51, height - 0.51);

  /* clip the line in 2D */
  result = clip_line (&x0, &y0, &x1, &y1);

  /* return if line is entirely outside the clip window */
  if (result == 0)
    return;

  /* incremental line drawing */

  dx = x1 - x0;
  dy = y1 - y0;

  /* determine whether horizontal or vertical change is larger */

  if (fabs(dx) > fabs(dy))
    length = fabs(dx);
  else
    length = fabs(dy);

  /* special case to avoid dividing by zero */

  if (length == 0) {
    glColor3f( 1.0, 1.0, 1.0 );
    glBegin(GL_POINTS);
    glVertex2i((int) floor(x0+0.5), (int) floor(y0+0.5));
    glEnd();

    return;
  }

  xinc = dx / length;
  yinc = dy / length;

  x = x0;
  y = y0;

  /* write "length" number of pixels along the line */

  for (i = 0; i <= length; i++) {
    glColor3f( 1.0, 1.0, 1.0 );
    glBegin(GL_POINTS);
    glVertex2i((int) floor(x+0.5), (int) floor(y+0.5));
    glEnd();


    x += xinc;
    y += yinc;
  }
  glFlush();
}


/******************************************************************************
Specify a clipping window.

Entry:
  x0,y0 - lower left boundaries of clipping window
  x1,y1 - upper right boundaries
******************************************************************************/

void lines::set_clip_window(float x0, float y0, float x1, float y1)
{
  xmin = x0;
  ymin = y0;

  xmax = x1;
  ymax = y1;
}


/******************************************************************************
Given a point P outside the window and the rise and run of a line, return
the intersection of line with window that is nearest P.

Entry:
  dx,dy - run and rise of line
  x,y   - the given point P

Exit:
  ix,iy - intersection point
  return 1 if there was a valid intersection, 0 if not
******************************************************************************/

int lines::clip_helper(
  float dx,
  float dy,
  float x,
  float y,
  float *ix,
  float *iy
)
{
  /* if line not vertical, check against left and right edges of window */

  if (dx != 0) {

    /* check against left edge */
    *iy = dy / dx * (xmin - x) + y;
    if (xmin >= x && *iy >= ymin && *iy <= ymax) {
      *ix = xmin;
      return (1);
    }

    /* check against right edge */
    *iy = dy / dx * (xmax - x) + y;
    if (xmax <= x && *iy >= ymin && *iy <= ymax) {
      *ix = xmax;
      return (1);
    }
  }

  /* if line not horizontal, check against top and bottom edges of window */

  if (dy != 0) {

    /* check against bottom edge */
    *ix = dx / dy * (ymin - y) + x;
    if (ymin >= y && *ix >= xmin && *ix <= xmax) {
      *iy = ymin;
      return (1);
    }

    /* check against top edge */
    *ix = dx / dy * (ymax - y) + x;
    if (ymax <= y && *ix >= xmin && *ix <= xmax) {
      *iy = ymax;
      return (1);
    }
  }

  /* if we get here, we found no intersection */
  return (0);
}


/******************************************************************************
Clip a line segment to a pre-specified window.

Entry:
  x0,y0 - first line segment endpoint
  x1,y1 - second endpoint

Exit:
  x0,y0,x1,y1 - clipped endpoint positions
  returns 1 if segment is at least partially in window,
  returns 0 if segment is entirely outside window
******************************************************************************/

int lines::clip_line(float *x0, float *y0, float *x1, float *y1)
{
  int count;
  float dx,dy;
  float xx0 = *x0;
  float yy0 = *y0;
  float xx1 = *x1;
  float yy1 = *y1;

  int code04 = (xx0 < xmin) ? 1 : 0;
  int code03 = (xx0 > xmax) ? 1 : 0;
  int code02 = (yy0 < ymin) ? 1 : 0;
  int code01 = (yy0 > ymax) ? 1 : 0;

  int code14 = (xx1 < xmin) ? 1 : 0;
  int code13 = (xx1 > xmax) ? 1 : 0;
  int code12 = (yy1 < ymin) ? 1 : 0;
  int code11 = (yy1 > ymax) ? 1 : 0;

  int sum0 = code01 + code02 + code03 + code04;
  int sum1 = code11 + code12 + code13 + code14;

  /* completely inside window? */
  if (sum0 == 0 && sum1 == 0)
    return (1);

  /* check for trivial invisibility (both endpoints on wrong side of */
  /* a single side of the window) */

  if (code01 && code11 || code02 && code12 || code03 && code13 ||
      code04 && code14) {
    return (0);
  }

  /* compute run and rise */
  dx = xx1 - xx0;
  dy = yy1 - yy0;

  /* case: only x0,y0 is inside window */
  if (sum0 == 0) {
    int dummy = clip_helper (dx, dy, xx1, yy1, &xx1, &yy1);
    *x0 = xx0;
    *y0 = yy0;
    *x1 = xx1;
    *y1 = yy1;
    return (1);
  }

  /* case: only x1,y1 is inside window */
  if (sum1 == 0) {
    int dummy = clip_helper (dx, dy, xx0, yy0, &xx0, &yy0);
    *x0 = xx0;
    *y0 = yy0;
    *x1 = xx1;
    *y1 = yy1;
    return (1);
  }

  /* neither endpoint is inside the window */

  count = 0;
  count += clip_helper (dx, dy, xx0, yy0, &xx0, &yy0);
  count += clip_helper (dx, dy, xx1, yy1, &xx1, &yy1);

  *x0 = xx0;
  *y0 = yy0;
  *x1 = xx1;
  *y1 = yy1;

  if (count)
    return (1);
  else
    return (0);
}


/******************************************************************************
Clip a line segment to front and back clipping planes.  These clip planes
are along the z-axis.  If your objects are on the negative z portion of
the axis, be sure to specify negative values for "near" and "far".

Entry:
  near,far - clip planes along z-axis
  x0,y0,z0 - first line segment endpoint
  x1,y1,z1 - second endpoint

Exit:
  x0,y0,z0,x1,y1,z1 - clipped endpoint positions
  returns 1 if segment is at least partially in window,
  returns 0 if segment is entirely outside window
******************************************************************************/

int lines::near_far_clip(
  float near,
  float far,
  float *x0,
  float *y0,
  float *z0,
  float *x1,
  float *y1,
  float *z1
)
{
  float temp;
  float fract;
  float xx0 = *x0;
  float yy0 = *y0;
  float zz0 = *z0;
  float xx1 = *x1;
  float yy1 = *y1;
  float zz1 = *z1;
  int code00,code01,code10,code11;

  /* make sure near < far */

  if (near > far) {
    temp = far;/*=============================================================================multiple definition of `near_far_clip(float, float, float*, float*, float*, float*, float*, float*)'*/
    far = near;
    near = temp;
  }

  /* figure out which endpoints are outside the clipping volume */

  code00 = (zz0 < near) ? 1 : 0;
  code01 = (zz0 > far)  ? 1 : 0;
  code10 = (zz1 < near) ? 1 : 0;
  code11 = (zz1 > far)  ? 1 : 0;

  /* return without clipping if all endpoints are inside clip volume */

  if (code00 + code01 + code10 + code11 == 0)
    return (1);  /* signals inside volume */

  /* if both endpoints are entirely out of clip volume, exit and signal this */

  if (code00 && code10 || code01 && code11)
    return (0);  /* signals outside volume */

  /* clip to near plane if necessary */

  if (code00) {
    fract = (near - zz0) / (zz1 - zz0);
    xx0 = xx0 + fract * (xx1 - xx0);
    yy0 = yy0 + fract * (yy1 - yy0);
    zz0 = near;
  }
  else if (code10) {
    fract = (near - zz1) / (zz0 - zz1);
    xx1 = xx1 + fract * (xx0 - xx1);
    yy1 = yy1 + fract * (yy0 - yy1);
    zz1 = near;
  }

  /* clip to far plane if necessary */

  if (code01) {
    fract = (far - zz0) / (zz1 - zz0);
    xx0 = xx0 + fract * (xx1 - xx0);
    yy0 = yy0 + fract * (yy1 - yy0);
    zz0 = far;
  }
  else if (code11) {
    fract = (far - zz1) / (zz0 - zz1);
    xx1 = xx1 + fract * (xx0 - xx1);
    yy1 = yy1 + fract * (yy0 - yy1);
    zz1 = far;
  }

  /* copy the clipped endpoints */

  *x0 = xx0;
  *y0 = yy0;
  *z0 = zz0;
  *x1 = xx1;
  *y1 = yy1;
  *z1 = zz1;

  /* signal that we're inside the clip volume */
  return (1);
}

/*=================== End of lines.c =====================================*/

New paste

  Language:
Private   — Wrap long lines  —  4 + 5 =   —  

About this pastebin

Welcome to the bulix.org / pastebin. Please don't use this pastebin for illegal purposes, defamation or kitten-squashing.

This pastebin is written using PHP and MySQL and relies on Alex Gorbatchev's syntax hhighlighter (JavaScript based). To avoid spam, you will be required to complete a small mathematical challenge when adding a new paste.

New! Try the pastebin command-line tool: paste.py (requires Python and python-beautifulsoup).

Powered by the Bulix.org Code Pastebin, by Maxime Petazzoni. View pastebin statistics.