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