// ray tracing of the sphere
// here we initialize the z-buffer's elements to -1.0 zBuffer that you find below
...
//
// rasterize a line
//
// line from p1 to p2 in LOCAL coordinates
Point3d p1 (-1.0, 0.0, 0.0);
Point3d p2 ( 1.0, 0.0, 0.0);
// transformations...
Matrix4d S = Matrix4d::scaling (5.0, 1.0, 1.0);
Matrix4d R1 = Matrix4d::rotation (0.5,'z');
Matrix4d R2 = Matrix4d::rotation (tau,'x');
Matrix4d T = Matrix4d::translation (0.0, 0.0, 8.0);
Matrix4d M = T*R2*R1*S;
p1 = M*p1;
p2 = M*p2;
// screen coordinates
double x1 = ( X + p1.x()/p1.z() ) / s - 0.5;
double y1 = ( Y - p1.y()/p1.z() ) / s - 0.5;
double x2 = ( X + p2.x()/p2.z() ) / s - 0.5;
double y2 = ( Y - p2.y()/p2.z() ) / s - 0.5;
//
// line rasterization algorithm with anti-aliasing and z-test
// (for lines with slope between -1 and 1)
//
int x = round(x1);
int y = round(y1);
double I0 = 1.0;
double m = (y2-y1) / (x2-x1);
bool up = true;
if (y2 < y1) {
m = -m;
I0 = 0.0;
up = false;
}
int nextY;
double z;
for ( ; x<=x2; x++) {
if (up)
nextY = y+1;
else
nextY = y-1;
// barycentric coordinates of the current point: (1-lambda, lambda),
// i.e.: x = (1-lambda) x1 + lambda x2
double lambda = (x-x1) / (x2-x1);
// perspectively correct linear interpolation of z-values
z = p1.z()*p2.z() / ( (1.0-lambda)*p2.z() + lambda*p1.z() );
if ( (zBuffer[x+y*w] < 0) || z < zBuffer[x+y*w] ) {
int I = (int) 255*I0;
image->setPixel( x, y, qRgb( 255-I, 255, 255-I ) );
image->setPixel( x, nextY, qRgb( I, 255, I ) );
}
if (m > I0) {
y = nextY;
I0 += 1.0;
}
I0 -= m;
}
// repaint canvas
repaint();
}