Merge pull request #18 from tschw/19188

19188
This commit is contained in:
birarda 2013-04-04 18:24:45 -07:00
commit b017f9a454
12 changed files with 295 additions and 257 deletions

View file

@ -15,95 +15,93 @@
using namespace glm; using namespace glm;
FieldOfView::FieldOfView() FieldOfView::FieldOfView() :
: mat_orientation(mat4(1.0f)), _matOrientation(mat4(1.0f)),
vec_bounds_low(vec3(-1.0f,-1.0f,-1.0f)), _vecBoundsLow(vec3(-1.0f,-1.0f,-1.0f)),
vec_bounds_high(vec3(1.0f,1.0f,1.0f)), _vecBoundsHigh(vec3(1.0f,1.0f,1.0f)),
val_width(256.0f), _valWidth(256.0f),
val_height(256.0f), _valHeight(256.0f),
val_angle(0.61), _valAngle(0.61),
val_zoom(1.0f), _valZoom(1.0f),
enm_aspect_balancing(expose_less) _enmAspectBalancing(expose_less) {
{
} }
mat4 FieldOfView::getViewerScreenXform() const mat4 FieldOfView::getViewerScreenXform() const {
{
mat4 projection; mat4 projection;
vec3 low, high; vec3 low, high;
getFrustum(low, high); getFrustum(low, high);
// perspective projection? determine correct near distance // perspective projection? determine correct near distance
if (val_angle != 0.0f) if (_valAngle != 0.0f) {
{
projection = translate( projection = translate(
frustum(low.x, high.x, low.y, high.y, low.z, high.z), frustum(low.x, high.x, low.y, high.y, low.z, high.z),
vec3(0.f, 0.f, -low.z) ); vec3(0.f, 0.f, -low.z) );
} } else {
else
{
projection = ortho(low.x, high.x, low.y, high.y, low.z, high.z); projection = ortho(low.x, high.x, low.y, high.y, low.z, high.z);
} }
return projection; return projection;
} }
mat4 FieldOfView::getWorldViewerXform() const mat4 FieldOfView::getWorldViewerXform() const {
{
return translate(affineInverse(mat_orientation), return translate(affineInverse(_matOrientation),
vec3(0.0f, 0.0f, -vec_bounds_high.z) ); vec3(0.0f, 0.0f, -_vecBoundsHigh.z) );
} }
mat4 FieldOfView::getWorldScreenXform() const mat4 FieldOfView::getWorldScreenXform() const {
{
return translate( return translate(
getViewerScreenXform() * affineInverse(mat_orientation), getViewerScreenXform() * affineInverse(_matOrientation),
vec3(0.0f, 0.0f, -vec_bounds_high.z) ); vec3(0.0f, 0.0f, -_vecBoundsHigh.z) );
} }
mat4 FieldOfView::getViewerWorldXform() const mat4 FieldOfView::getViewerWorldXform() const {
{
vec3 n_translate = vec3(0.0f, 0.0f, vec_bounds_high.z); vec3 n_translate = vec3(0.0f, 0.0f, _vecBoundsHigh.z);
return translate( return translate(
translate(mat4(1.0f), n_translate) translate(mat4(1.0f), n_translate)
* mat_orientation, -n_translate ); * _matOrientation, -n_translate );
} }
float FieldOfView::getPixelSize() const float FieldOfView::getPixelSize() const {
{
vec3 low, high; vec3 low, high;
getFrustum(low, high); getFrustum(low, high);
return std::min( return std::min(
abs(high.x - low.x) / val_width, abs(high.x - low.x) / _valWidth,
abs(high.y - low.y) / val_height); abs(high.y - low.y) / _valHeight);
} }
void FieldOfView::getFrustum(vec3& low, vec3& high) const void FieldOfView::getFrustum(vec3& low, vec3& high) const {
{
low = vec_bounds_low; low = _vecBoundsLow;
high = vec_bounds_high; high = _vecBoundsHigh;
// start with uniform zoom // start with uniform zoom
float inv_zoom = 1.0f / val_zoom; float inv_zoom = 1.0f / _valZoom;
float adj_x = inv_zoom, adj_y = inv_zoom; float adj_x = inv_zoom, adj_y = inv_zoom;
// balance aspect // balance aspect
if (enm_aspect_balancing != stretch) if (_enmAspectBalancing != stretch) {
{
float f_aspect = (high.x - low.x) / (high.y - low.y); float f_aspect = (high.x - low.x) / (high.y - low.y);
float vp_aspect = val_width / val_height; float vp_aspect = _valWidth / _valHeight;
if ((_enmAspectBalancing == expose_more)
!= (f_aspect > vp_aspect)) {
if ((enm_aspect_balancing == expose_more)
!= (f_aspect > vp_aspect))
{
// expose_more -> f_aspect <= vp_aspect <=> adj >= 1 // expose_more -> f_aspect <= vp_aspect <=> adj >= 1
// expose_less -> f_aspect > vp_aspect <=> adj < 1 // expose_less -> f_aspect > vp_aspect <=> adj < 1
adj_x = vp_aspect / f_aspect; adj_x = vp_aspect / f_aspect;
}
else } else {
{
// expose_more -> f_aspect > vp_aspect <=> adj > 1 // expose_more -> f_aspect > vp_aspect <=> adj > 1
// expose_less -> f_aspect <= vp_aspect <=> adj <= 1 // expose_less -> f_aspect <= vp_aspect <=> adj <= 1
adj_y = f_aspect / vp_aspect; adj_y = f_aspect / vp_aspect;
@ -121,8 +119,8 @@ void FieldOfView::getFrustum(vec3& low, vec3& high) const
// calc and apply near distance based on near diagonal and perspective // calc and apply near distance based on near diagonal and perspective
float w = high.x - low.x, h = high.y - low.y; float w = high.x - low.x, h = high.y - low.y;
high.z -= low.z; high.z -= low.z;
low.z = val_angle == 0.0f ? 0.0f : low.z = _valAngle == 0.0f ? 0.0f :
sqrt(w*w+h*h) * 0.5f / tan(val_angle * 0.5f); sqrt(w*w+h*h) * 0.5f / tan(_valAngle * 0.5f);
high.z += low.z; high.z += low.z;
} }

View file

@ -11,39 +11,35 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
/** //
* Viewing parameter encapsulation. // Viewing parameter encapsulation.
*/ //
class FieldOfView class FieldOfView {
{
glm::mat4 mat_orientation; glm::mat4 _matOrientation;
glm::vec3 vec_bounds_low; glm::vec3 _vecBoundsLow;
glm::vec3 vec_bounds_high; glm::vec3 _vecBoundsHigh;
float val_width; float _valWidth;
float val_height; float _valHeight;
float val_angle; float _valAngle;
float val_zoom; float _valZoom;
int enm_aspect_balancing; int _enmAspectBalancing;
public: public:
FieldOfView(); FieldOfView();
// mutators // mutators
FieldOfView& setBounds(glm::vec3 const& low, glm::vec3 const& high) FieldOfView& setBounds(glm::vec3 const& low, glm::vec3 const& high) {
{ vec_bounds_low = low; vec_bounds_high = high; return *this; } _vecBoundsLow = low; _vecBoundsHigh = high; return *this; }
FieldOfView& setOrientation(glm::mat4 const& matrix) FieldOfView& setOrientation(glm::mat4 const& matrix) { _matOrientation = matrix; return *this; }
{ mat_orientation = matrix; return *this; }
FieldOfView& setPerspective(float angle) FieldOfView& setPerspective(float angle) { _valAngle = angle; return *this; }
{ val_angle = angle; return *this; }
FieldOfView& setResolution(unsigned width, unsigned height) FieldOfView& setResolution(unsigned width, unsigned height) { _valWidth = width; _valHeight = height; return *this; }
{ val_width = width; val_height = height; return *this; }
FieldOfView& setZoom(float factor) FieldOfView& setZoom(float factor) { _valZoom = factor; return *this; }
{ val_zoom = factor; return *this; }
enum aspect_balancing enum aspect_balancing
{ {
@ -52,76 +48,75 @@ class FieldOfView
stretch stretch
}; };
FieldOfView& setAspectBalancing(aspect_balancing v) FieldOfView& setAspectBalancing(aspect_balancing v) { _enmAspectBalancing = v; return *this; }
{ enm_aspect_balancing = v; return *this; }
// dumb accessors // dumb accessors
glm::mat4 const& getOrientation() const { return mat_orientation; } glm::mat4 const& getOrientation() const { return _matOrientation; }
float getWidthInPixels() const { return val_width; } float getWidthInPixels() const { return _valWidth; }
float getHeightInPixels() const { return val_height; } float getHeightInPixels() const { return _valHeight; }
float getPerspective() const { return val_angle; } float getPerspective() const { return _valAngle; }
// matrices // matrices
/** //
* Returns a full transformation matrix to project world coordinates // Returns a full transformation matrix to project world coordinates
* onto the screen. // onto the screen.
*/ //
glm::mat4 getWorldScreenXform() const; glm::mat4 getWorldScreenXform() const;
/** //
* Transforms world coordinates to viewer-relative coordinates. // Transforms world coordinates to viewer-relative coordinates.
* //
* This matrix can be used as the modelview matrix in legacy GL code // This matrix can be used as the modelview matrix in legacy GL code
* where the projection matrix is kept separately. // where the projection matrix is kept separately.
*/ //
glm::mat4 getWorldViewerXform() const; glm::mat4 getWorldViewerXform() const;
/** //
* Returns the transformation to of viewer-relative coordinates back // Returns the transformation to of viewer-relative coordinates back
* to world space. // to world space.
* //
* This matrix can be used to set up a coordinate system for avatar // This matrix can be used to set up a coordinate system for avatar
* rendering. // rendering.
*/ //
glm::mat4 getViewerWorldXform() const; glm::mat4 getViewerWorldXform() const;
/** //
* Returns the transformation of viewer-relative coordinates to the // Returns the transformation of viewer-relative coordinates to the
* screen. // screen.
* //
* This matrix can be used as the projection matrix in legacy GL code. // This matrix can be used as the projection matrix in legacy GL code.
*/ //
glm::mat4 getViewerScreenXform() const; glm::mat4 getViewerScreenXform() const;
// other useful information // other useful information
/** //
* Returns the size of a pixel in world space, that is the minimum // Returns the size of a pixel in world space, that is the minimum
* in respect to x/y screen directions. // in respect to x/y screen directions.
*/ //
float getPixelSize() const; float getPixelSize() const;
/** //
* Returns the frustum as used for the projection matrices. // Returns the frustum as used for the projection matrices.
* The result depdends on the bounds, eventually aspect correction // The result depdends on the bounds, eventually aspect correction
* for the current resolution, the perspective angle (specified in // for the current resolution, the perspective angle (specified in
* respect to diagonal) and zoom. // respect to diagonal) and zoom.
*/ //
void getFrustum(glm::vec3& low, glm::vec3& high) const; void getFrustum(glm::vec3& low, glm::vec3& high) const;
/** //
* Returns the z-offset from the origin to where orientation ia // Returns the z-offset from the origin to where orientation ia
* applied. // applied.
*/ //
float getTransformOffset() const { return vec_bounds_high.z; } float getTransformOffset() const { return _vecBoundsHigh.z; }
/** //
* Returns the aspect ratio. // Returns the aspect ratio.
*/ //
float getAspectRatio() const { return val_height / val_width; } float getAspectRatio() const { return _valHeight / _valWidth; }
}; };
#endif #endif

View file

@ -90,8 +90,8 @@ double diffclock(timeval *clock1,timeval *clock2)
return diffms; return diffms;
} }
void drawtext(int x, int y, float scale, float rotate, float thick, int mono, char *string, void drawtext(int x, int y, float scale, float rotate, float thick, int mono,
float r, float g, float b) char const* string, float r, float g, float b)
{ {
// //
// Draws text on screen as stroked so it can be resized // Draws text on screen as stroked so it can be resized

View file

@ -23,8 +23,8 @@ float angle_to(glm::vec3 head_pos, glm::vec3 source_pos, float render_yaw, float
float randFloat(); float randFloat();
void render_world_box(); void render_world_box();
void render_vector(glm::vec3 * vec); void render_vector(glm::vec3 * vec);
void drawtext(int x, int y, float scale, float rotate, float thick, int mono, char *string, void drawtext(int x, int y, float scale, float rotate, float thick, int mono,
float r=1.0, float g=1.0, float b=1.0); char const* string, float r=1.0, float g=1.0, float b=1.0);
void drawvec3(int x, int y, float scale, float rotate, float thick, int mono, glm::vec3 vec, void drawvec3(int x, int y, float scale, float rotate, float thick, int mono, glm::vec3 vec,
float r=1.0, float g=1.0, float b=1.0); float r=1.0, float g=1.0, float b=1.0);
double diffclock(timeval *clock1,timeval *clock2); double diffclock(timeval *clock1,timeval *clock2);

View file

@ -527,8 +527,6 @@ void display(void)
{ {
PerfStat("display"); PerfStat("display");
glEnable (GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LINE_SMOOTH); glEnable(GL_LINE_SMOOTH);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
@ -559,14 +557,12 @@ void display(void)
-myHead.getRenderPitch(), glm::vec3(1.0f,0.0f,0.0f)) ); -myHead.getRenderPitch(), glm::vec3(1.0f,0.0f,0.0f)) );
glLoadMatrixf( glm::value_ptr(fov.getWorldViewerXform()) ); glLoadMatrixf( glm::value_ptr(fov.getWorldViewerXform()) );
glRotatef(myHead.getRenderPitch(), 1, 0, 0);
glRotatef(myHead.getRenderYaw(), 0, 1, 0);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
if (::starsOn) { if (::starsOn) {
// should be the first rendering pass - w/o depth buffer / lighting
stars.render(fov); stars.render(fov);
} }
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
@ -670,8 +666,12 @@ void display(void)
if (display_levels) serialPort.renderLevels(WIDTH,HEIGHT); if (display_levels) serialPort.renderLevels(WIDTH,HEIGHT);
// Display miscellaneous text stats onscreen // Display miscellaneous text stats onscreen
if (stats_on) display_stats(); if (stats_on) {
glLineWidth(1.0f);
glPointSize(1.0f);
display_stats();
}
// Draw number of nearby people always // Draw number of nearby people always
char agents[100]; char agents[100];
sprintf(agents, "Agents nearby: %ld\n", agentList.getAgents().size()); sprintf(agents, "Agents nearby: %ld\n", agentList.getAgents().size());

View file

@ -96,18 +96,22 @@ namespace starfield {
Tiling tiling(k); Tiling tiling(k);
size_t nTiles = tiling.getTileCount(); size_t nTiles = tiling.getTileCount();
// REVISIT: could coalesce allocation for faster rebuild
// REVISIT: batch arrays are probably oversized, but - hey - they
// are not very large (unless for insane tiling) and we're better
// off safe than sorry
_arrData = new GpuVertex[n]; _arrData = new GpuVertex[n];
_arrTile = new Tile[nTiles + 1]; _arrTile = new Tile[nTiles + 1];
_arrBatchOffs = new GLint[nTiles]; _arrBatchOffs = new GLint[nTiles * 2];
_arrBatchCount = new GLsizei[nTiles]; _arrBatchCount = new GLsizei[nTiles * 2];
prepareVertexData(src, n, tiling, b, bMin); prepareVertexData(src, n, tiling, b, bMin);
this->glUpload(n); this->glUpload(n);
} }
~Renderer() ~Renderer() {
{
delete[] _arrData; delete[] _arrData;
delete[] _arrTile; delete[] _arrTile;
delete[] _arrBatchCount; delete[] _arrBatchCount;
@ -119,8 +123,7 @@ namespace starfield {
void render(float perspective, void render(float perspective,
float aspect, float aspect,
mat4 const& orientation, mat4 const& orientation,
BrightnessLevel minBright) BrightnessLevel minBright) {
{
// fprintf(stderr, " // fprintf(stderr, "
// Stars.cpp: rendering at minimal brightness %d\n", minBright); // Stars.cpp: rendering at minimal brightness %d\n", minBright);
@ -291,21 +294,31 @@ namespace starfield {
bool select(Tile* t) { bool select(Tile* t) {
if (t < _arrTile || t >= _itrTilesEnd || if (t < _arrTile || t >= _itrTilesEnd ||
!! (t->flags & Tile::visited)) { !! (t->flags & Tile::checked)) {
return false; // out of bounds or been here already
return false;
} }
if (! (t->flags & Tile::checked)) {
if (_refRenderer.visitTile(t)) // will check now and never again
t->flags |= Tile::render; t->flags |= Tile::checked;
if (_refRenderer.visitTile(t)) {
// good one -> remember (for batching) and propagate
t->flags |= Tile::render;
return true;
} }
return !! (t->flags & Tile::render); return false;
} }
void process(Tile* t) { bool process(Tile* t) {
t->flags |= Tile::visited; if (! (t->flags & Tile::visited)) {
t->flags |= Tile::visited;
return true;
}
return false;
} }
void right(Tile*& cursor) const { cursor += 1; } void right(Tile*& cursor) const { cursor += 1; }
@ -479,6 +492,9 @@ namespace starfield {
// fprintf(stderr, "Stars.cpp: Batch #%d - %d stars @ %d\n", i, // fprintf(stderr, "Stars.cpp: Batch #%d - %d stars @ %d\n", i,
// _arrBatchOffs[i], _arrBatchCount[i]); // _arrBatchOffs[i], _arrBatchCount[i]);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
// setup modelview matrix (identity) // setup modelview matrix (identity)
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glPushMatrix(); glPushMatrix();
@ -507,6 +523,7 @@ namespace starfield {
glBindVertexArray(0); glBindVertexArray(0);
glUseProgram(0); glUseProgram(0);
glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
glDisable(GL_POINT_SMOOTH);
glPopMatrix(); glPopMatrix();
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glPopMatrix(); glPopMatrix();

View file

@ -11,22 +11,22 @@
#include <math.h> #include <math.h>
struct Degrees struct Degrees {
{
static float pi() { return 180.0f; } static float pi() { return 180.0f; }
static float twicePi() { return 360.0f; } static float twicePi() { return 360.0f; }
static float halfPi() { return 90.0f; } static float halfPi() { return 90.0f; }
}; };
struct Radians struct Radians {
{
static float pi() { return 3.141592653589793f; } static float pi() { return 3.141592653589793f; }
static float twicePi() { return 6.283185307179586f; } static float twicePi() { return 6.283185307179586f; }
static float halfPi() { return 1.5707963267948966; } static float halfPi() { return 1.5707963267948966; }
}; };
struct Rotations struct Rotations {
{
static float pi() { return 0.5f; } static float pi() { return 0.5f; }
static float twicePi() { return 1.0f; } static float twicePi() { return 1.0f; }
static float halfPi() { return 0.25f; } static float halfPi() { return 0.25f; }
@ -36,8 +36,8 @@ struct Rotations
* Converts an angle from one unit to another. * Converts an angle from one unit to another.
*/ */
template< class UnitFrom, class UnitTo > template< class UnitFrom, class UnitTo >
float angleConvert(float a) float angleConvert(float a) {
{
return a * (UnitTo::halfPi() / UnitFrom::halfPi()); return a * (UnitTo::halfPi() / UnitFrom::halfPi());
} }
@ -46,8 +46,8 @@ float angleConvert(float a)
* Clamps an angle to the range of [-180; 180) degrees. * Clamps an angle to the range of [-180; 180) degrees.
*/ */
template< class Unit > template< class Unit >
float angleSignedNormal(float a) float angleSignedNormal(float a) {
{
float result = remainder(a, Unit::twicePi()); float result = remainder(a, Unit::twicePi());
if (result == Unit::pi()) if (result == Unit::pi())
result = -Unit::pi(); result = -Unit::pi();
@ -58,8 +58,8 @@ float angleSignedNormal(float a)
* Clamps an angle to the range of [0; 360) degrees. * Clamps an angle to the range of [0; 360) degrees.
*/ */
template< class Unit > template< class Unit >
float angleUnsignedNormal(float a) float angleUnsignedNormal(float a) {
{
return angleSignedNormal<Unit>(a - Unit::pi()) + Unit::pi(); return angleSignedNormal<Unit>(a - Unit::pi()) + Unit::pi();
} }
@ -72,16 +72,16 @@ float angleUnsignedNormal(float a)
* Both poles can be reached from any azimuthal direction. * Both poles can be reached from any azimuthal direction.
*/ */
template< class Unit > template< class Unit >
void angleHorizontalPolar(float& azimuth, float& altitude) void angleHorizontalPolar(float& azimuth, float& altitude) {
{
altitude = angleSignedNormal<Unit>(altitude); altitude = angleSignedNormal<Unit>(altitude);
if (altitude > Unit::halfPi()) if (altitude > Unit::halfPi()) {
{
altitude = Unit::pi() - altitude; altitude = Unit::pi() - altitude;
azimuth += Unit::pi(); azimuth += Unit::pi();
}
else if (altitude < -Unit::halfPi()) } else if (altitude < -Unit::halfPi()) {
{
altitude = -Unit::pi() - altitude; altitude = -Unit::pi() - altitude;
azimuth += Unit::pi(); azimuth += Unit::pi();
} }

View file

@ -11,6 +11,29 @@
/** /**
* Line scanning, iterative flood fill algorithm. * Line scanning, iterative flood fill algorithm.
*
* The strategy must obey the following contract:
*
* There is an associated cursor that represents a position on the image.
* The member functions 'left(C&)', 'right(C&)', 'up(C&)', and 'down(C&)'
* move it.
* The state of a cursor can be deferred to temporary storage (typically a
* stack or a queue) using the 'defer(C const&)' member function.
* Calling 'deferred(C&)' restores a cursor's state from temporary storage
* and removes it there.
* The 'select(C const&)' and 'process(C const&)' functions control the
* algorithm. The former is called to determine where to go. It may be
* called multiple times but does not have to (and should not) return
* 'true' more than once for a pixel to be selected (will cause memory
* overuse, otherwise). The latter will never be called for a given pixel
* unless previously selected. It may be called multiple times, in which
* case it should return 'true' upon successful processing and 'false'
* when an already processed pixel has been visited.
*
* Note: The terms "image" and "pixel" are used for illustratory purposes
* and mean "undirected graph with 4-connected 2D grid topology" and "node",
* respectively.
*
*/ */
template< class Strategy, typename Cursor > template< class Strategy, typename Cursor >
void floodFill(Cursor const& position, void floodFill(Cursor const& position,
@ -18,8 +41,8 @@ void floodFill(Cursor const& position,
template< class Strategy, typename Cursor > template< class Strategy, typename Cursor >
struct floodFill_impl : Strategy struct floodFill_impl : Strategy {
{
floodFill_impl(Strategy const& s) : Strategy(s) { } floodFill_impl(Strategy const& s) : Strategy(s) { }
using Strategy::select; using Strategy::select;
@ -33,16 +56,19 @@ struct floodFill_impl : Strategy
using Strategy::defer; using Strategy::defer;
using Strategy::deferred; using Strategy::deferred;
void go(Cursor position) void go(Cursor position) {
{
if (! select(position)) {
return;
}
Cursor higher, lower, h,l, i; Cursor higher, lower, h,l, i;
bool higherFound, lowerFound, hf, lf; bool higherFound, lowerFound, hf, lf;
do do {
{
if (! select(position))
continue;
process(position); if (! process(position)) {
continue;
}
higher = position; higherFound = false; higher = position; higherFound = false;
up(higher); yTest(higher, higherFound); up(higher); yTest(higher, higherFound);
@ -51,33 +77,39 @@ struct floodFill_impl : Strategy
i = position, h = higher, l = lower; i = position, h = higher, l = lower;
hf = higherFound, lf = lowerFound; hf = higherFound, lf = lowerFound;
do { right(i), right(h), right(l); yTest(h,hf); yTest(l,lf); } do {
while (selectAndProcess(i)); right(i), right(h), right(l); yTest(h,hf); yTest(l,lf);
} while (selectAndProcess(i));
i = position, h = higher, l = lower; i = position, h = higher, l = lower;
hf = higherFound, lf = lowerFound; hf = higherFound, lf = lowerFound;
do { left(i); left(h); left(l); yTest(h,hf); yTest(l,lf); } do {
while (selectAndProcess(i)); left(i); left(h); left(l); yTest(h,hf); yTest(l,lf);
}
while (deferred(position)); } while (selectAndProcess(i));
} while (deferred(position));
} }
bool selectAndProcess(Cursor const& i) bool selectAndProcess(Cursor const& i) {
{
if (select(i)) if (select(i)) {
{
process(i); process(i);
return true; return true;
} }
return false; return false;
} }
void yTest(Cursor const& i, bool& state) void yTest(Cursor const& i, bool& state) {
{
if (! select(i)) if (! select(i)) {
state = false; state = false;
else if (! state)
{ } else if (! state) {
state = true; state = true;
defer(i); defer(i);
} }
@ -85,8 +117,8 @@ struct floodFill_impl : Strategy
}; };
template< class Strategy, typename Cursor > template< class Strategy, typename Cursor >
void floodFill(Cursor const& p, Strategy const& s) void floodFill(Cursor const& p, Strategy const& s) {
{
floodFill_impl<Strategy,Cursor>(s).go(p); floodFill_impl<Strategy,Cursor>(s).go(p);
} }

View file

@ -25,30 +25,27 @@ void radix2InplaceSort( BidiIterator from, BidiIterator to,
template< class Scanner, typename Iterator > template< class Scanner, typename Iterator >
struct radix2InplaceSort_impl : Scanner struct radix2InplaceSort_impl : Scanner {
{
radix2InplaceSort_impl(Scanner const& s) : Scanner(s) { } radix2InplaceSort_impl(Scanner const& s) : Scanner(s) { }
using Scanner::advance; using Scanner::advance;
using Scanner::bit; using Scanner::bit;
void go(Iterator& from, Iterator& to, typename Scanner::state_type s) void go(Iterator& from, Iterator& to, typename Scanner::state_type s) {
{
Iterator l(from), r(to); Iterator l(from), r(to);
unsigned cl, cr; unsigned cl, cr;
using std::swap; using std::swap;
for (;;) while (true) {
{
// scan from left for set bit // scan from left for set bit
for (cl = cr = 0u; l != r ; ++l, ++cl) for (cl = cr = 0u; l != r ; ++l, ++cl)
if (bit(*l, s)) if (bit(*l, s)) {
{
// scan from the right for unset bit // scan from the right for unset bit
for (++cr; --r != l ;++cr) for (++cr; --r != l ;++cr)
if (! bit(*r, s)) if (! bit(*r, s)) {
{
// swap, continue scanning from left // swap, continue scanning from left
swap(*l, *r); swap(*l, *r);
break; break;
@ -58,22 +55,23 @@ struct radix2InplaceSort_impl : Scanner
} }
// on to the next digit, if any // on to the next digit, if any
if (! advance(s)) if (! advance(s)) {
return; return;
}
// recurse into smaller branch and prepare iterative // recurse into smaller branch and prepare iterative
// processing of the other // processing of the other
if (cl < cr) if (cl < cr) {
{
if (cl > 1u) go(from, l, s); if (cl > 1u) go(from, l, s);
else if (cr <= 1u) else if (cr <= 1u)
return; return;
l = from = r; l = from = r;
r = to; r = to;
}
else } else {
{
if (cr > 1u) go(r, to, s); if (cr > 1u) go(r, to, s);
else if (cl <= 1u) else if (cl <= 1u)
return; return;
@ -87,8 +85,8 @@ struct radix2InplaceSort_impl : Scanner
template< class Radix2Scanner, typename BidiIterator > template< class Radix2Scanner, typename BidiIterator >
void radix2InplaceSort( BidiIterator from, BidiIterator to, void radix2InplaceSort( BidiIterator from, BidiIterator to,
Radix2Scanner const& scanner) Radix2Scanner const& scanner) {
{
radix2InplaceSort_impl<Radix2Scanner, BidiIterator>(scanner) radix2InplaceSort_impl<Radix2Scanner, BidiIterator>(scanner)
.go(from, to, scanner.initial_state()); .go(from, to, scanner.initial_state());
} }

View file

@ -12,8 +12,8 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
namespace type_traits // those are needed for the declaration, see below namespace type_traits { // those are needed for the declaration, see below
{
// Note: There are better / more generally appicable implementations // Note: There are better / more generally appicable implementations
// in C++11, make_signed is missing in TR1 too - so I just use C++98 // in C++11, make_signed is missing in TR1 too - so I just use C++98
// hacks that get the job done... // hacks that get the job done...
@ -39,8 +39,8 @@ class Radix2IntegerScanner;
template< typename UInt > template< typename UInt >
class Radix2IntegerScanner< UInt, false > class Radix2IntegerScanner< UInt, false > {
{
UInt valMsb; UInt valMsb;
public: public:
@ -48,9 +48,8 @@ class Radix2IntegerScanner< UInt, false >
: valMsb(~UInt(0) &~ (~UInt(0) >> 1)) { } : valMsb(~UInt(0) &~ (~UInt(0) >> 1)) { }
explicit Radix2IntegerScanner(int bits) explicit Radix2IntegerScanner(int bits)
: valMsb(UInt(1u) << (bits - 1)) : valMsb(UInt(1u) << (bits - 1)) {
{ } }
typedef UInt state_type; typedef UInt state_type;
@ -67,12 +66,12 @@ class Radix2IntegerScanner< Int, true >
public: public:
Radix2IntegerScanner() Radix2IntegerScanner()
: valMsb(~state_type(0u) &~ (~state_type(0u) >> 1)) : valMsb(~state_type(0u) &~ (~state_type(0u) >> 1)) {
{ } }
explicit Radix2IntegerScanner(int bits) explicit Radix2IntegerScanner(int bits)
: valMsb(state_type(1u) << (bits - 1)) : valMsb(state_type(1u) << (bits - 1)) {
{ } }
typedef typename type_traits::make_unsigned<Int>::type state_type; typedef typename type_traits::make_unsigned<Int>::type state_type;

View file

@ -23,8 +23,8 @@ char const* const UrlReader::error_leftover_input = "UrlReader: Incomplete pro
#define hnd_curl static_cast<CURL*>(_ptrImpl) #define hnd_curl static_cast<CURL*>(_ptrImpl)
UrlReader::UrlReader() UrlReader::UrlReader()
: _ptrImpl(0l), _arrXtra(0l), _strError(0l) : _ptrImpl(0l), _arrXtra(0l), _strError(0l) {
{
_arrXtra = new(std::nothrow) char[max_read_ahead]; _arrXtra = new(std::nothrow) char[max_read_ahead];
if (! _arrXtra) { _strError = error_init_failed; return; } if (! _arrXtra) { _strError = error_init_failed; return; }
_ptrImpl = curl_easy_init(); _ptrImpl = curl_easy_init();
@ -34,15 +34,15 @@ UrlReader::UrlReader()
curl_easy_setopt(hnd_curl, CURLOPT_FILETIME, 1l); curl_easy_setopt(hnd_curl, CURLOPT_FILETIME, 1l);
} }
UrlReader::~UrlReader() UrlReader::~UrlReader() {
{
delete _arrXtra; delete _arrXtra;
if (! hnd_curl) return; if (! hnd_curl) return;
curl_easy_cleanup(hnd_curl); curl_easy_cleanup(hnd_curl);
} }
bool UrlReader::perform(char const* url, transfer_callback* cb) bool UrlReader::perform(char const* url, transfer_callback* cb) {
{
curl_easy_setopt(hnd_curl, CURLOPT_URL, url); curl_easy_setopt(hnd_curl, CURLOPT_URL, url);
curl_easy_setopt(hnd_curl, CURLOPT_WRITEFUNCTION, cb); curl_easy_setopt(hnd_curl, CURLOPT_WRITEFUNCTION, cb);
curl_easy_setopt(hnd_curl, CURLOPT_WRITEDATA, this); curl_easy_setopt(hnd_curl, CURLOPT_WRITEDATA, this);
@ -61,8 +61,8 @@ bool UrlReader::perform(char const* url, transfer_callback* cb)
} }
void UrlReader::getinfo(char const*& url, void UrlReader::getinfo(char const*& url,
char const*& type, int64_t& length, int64_t& stardate) char const*& type, int64_t& length, int64_t& stardate) {
{
curl_easy_getinfo(hnd_curl, CURLINFO_EFFECTIVE_URL, & url); curl_easy_getinfo(hnd_curl, CURLINFO_EFFECTIVE_URL, & url);
curl_easy_getinfo(hnd_curl, CURLINFO_CONTENT_TYPE, & type); curl_easy_getinfo(hnd_curl, CURLINFO_CONTENT_TYPE, & type);

View file

@ -17,8 +17,8 @@
* UrlReader class that encapsulates a context for sequential data retrieval * UrlReader class that encapsulates a context for sequential data retrieval
* via URLs. Use one per thread. * via URLs. Use one per thread.
*/ */
class UrlReader class UrlReader {
{
void* _ptrImpl; void* _ptrImpl;
char* _arrXtra; char* _arrXtra;
char const* _strError; char const* _strError;
@ -149,8 +149,7 @@ class UrlReader
}; };
template< class ContentStream > template< class ContentStream >
bool UrlReader::readUrl(char const* url, ContentStream& s) bool UrlReader::readUrl(char const* url, ContentStream& s) {
{
if (! _ptrImpl) return false; if (! _ptrImpl) return false;
_strError = success; _strError = success;
_ptrStream = & s; _ptrStream = & s;
@ -162,24 +161,24 @@ bool UrlReader::readUrl(char const* url, ContentStream& s)
inline char const* UrlReader::getError() const { return this->_strError; } inline char const* UrlReader::getError() const { return this->_strError; }
inline void UrlReader::setError(char const* static_c_string) inline void UrlReader::setError(char const* static_c_string) {
{
if (this->_strError == success) if (this->_strError == success)
this->_strError = static_c_string; this->_strError = static_c_string;
} }
template< class Stream > template< class Stream >
size_t UrlReader::callback_template( size_t UrlReader::callback_template(
char *input, size_t size, size_t nmemb, void* thiz) char *input, size_t size, size_t nmemb, void* thiz) {
{
size *= nmemb; size *= nmemb;
UrlReader* me = static_cast<UrlReader*>(thiz); UrlReader* me = static_cast<UrlReader*>(thiz);
Stream* stream = static_cast<Stream*>(me->_ptrStream); Stream* stream = static_cast<Stream*>(me->_ptrStream);
// first call? // first call?
if (me->_valXtraSize == ~size_t(0)) if (me->_valXtraSize == ~size_t(0)) {
{
me->_valXtraSize = 0u; me->_valXtraSize = 0u;
// extract meta information and call 'begin' // extract meta information and call 'begin'
char const* url, * type; char const* url, * type;
@ -190,14 +189,14 @@ size_t UrlReader::callback_template(
size_t input_offset = 0u; size_t input_offset = 0u;
for (;;) while (true) {
{
char* buffer = input + input_offset; char* buffer = input + input_offset;
size_t bytes = size - input_offset; size_t bytes = size - input_offset;
// data in extra buffer? // data in extra buffer?
if (me->_valXtraSize > 0) if (me->_valXtraSize > 0) {
{
// fill extra buffer with beginning of input // fill extra buffer with beginning of input
size_t fill = max_read_ahead - me->_valXtraSize; size_t fill = max_read_ahead - me->_valXtraSize;
if (bytes < fill) fill = bytes; if (bytes < fill) fill = bytes;
@ -210,36 +209,36 @@ size_t UrlReader::callback_template(
// call 'transfer' // call 'transfer'
size_t processed = stream->transfer(buffer, bytes); size_t processed = stream->transfer(buffer, bytes);
if (processed == abort) if (processed == abort) {
{
me->setError(error_aborted); me->setError(error_aborted);
return 0u; return 0u;
}
else if (! processed && ! input) } else if (! processed && ! input) {
{
me->setError(error_leftover_input); me->setError(error_leftover_input);
return 0u; return 0u;
} }
size_t unprocessed = bytes - processed; size_t unprocessed = bytes - processed;
// can switch to input buffer, now? // can switch to input buffer, now?
if (buffer == me->_arrXtra && unprocessed <= input_offset) if (buffer == me->_arrXtra && unprocessed <= input_offset) {
{
me->_valXtraSize = 0u; me->_valXtraSize = 0u;
input_offset -= unprocessed; input_offset -= unprocessed;
}
else // no? unprocessed data -> extra buffer } else { // no? unprocessed data -> extra buffer
{
if (unprocessed > max_read_ahead) if (unprocessed > max_read_ahead) {
{
me->setError(error_buffer_overflow); me->setError(error_buffer_overflow);
return 0; return 0;
} }
me->_valXtraSize = unprocessed; me->_valXtraSize = unprocessed;
memmove(me->_arrXtra, buffer + processed, unprocessed); memmove(me->_arrXtra, buffer + processed, unprocessed);
if (input_offset == size || buffer != me->_arrXtra) if (input_offset == size || buffer != me->_arrXtra) {
{
return size; return size;
} }
} }