mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-07-24 11:04:43 +02:00
commit
b017f9a454
12 changed files with 295 additions and 257 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue