@Override public boolean next(PixelRayBuffer b) {
		if( totalSamples == targetSamples ) return false;
		
		b.vectorSize = (int)Math.min(targetSamples - totalSamples, b.maxVectorSize);
		if( screenX == null || screenX.length < b.vectorSize ) {
			screenX = new double[b.vectorSize];
			screenY = new double[b.vectorSize];
		}
		
		int i;
		for( i=0; i<b.vectorSize; ++i, ++x ) {
			if( x >= imageWidth ) {
				x = 0; ++y;
			}
			if( y >= imageHeight ) {
				y = 0;
			}
			
			b.index[i] = x + y*imageWidth;
			screenX[i] = (x + rand.nextDouble()) * (viewX1 - viewX0) / imageWidth  + viewX0;
			screenY[i] = (y + rand.nextDouble()) * (viewY1 - viewY0) / imageHeight + viewY0;
		}
		
		projection.project(b.vectorSize, screenX, screenY, b.ox, b.oy, b.oz, b.dx, b.dy, b.dz);
		
		for( i=0; i<b.vectorSize; ++i ) {
			// Apply transformation!!
			   pixelOffset.set(b.ox[i], b.oy[i], b.oz[i]);
			pixelDirection.set(b.dx[i], b.dy[i], b.dz[i]);
			MatrixMath.multiply( cameraTransform, pixelOffset, rayOffset );
			MatrixMath.multiplyRotationOnly( cameraTransform, pixelDirection, rayDirection );
			b.ox[i] =    rayOffset.x; b.oy[i] =    rayOffset.y; b.oz[i] =    rayOffset.z;
			b.dx[i] = rayDirection.x; b.dy[i] = rayDirection.y; b.dz[i] = rayDirection.z;
		}
		
		totalSamples += b.vectorSize; 
		return true;
	}