mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 17:14:59 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into view_frustum_work
This commit is contained in:
commit
309eb08490
15 changed files with 695 additions and 825 deletions
|
@ -1,126 +0,0 @@
|
|||
//
|
||||
// FieldOfView.cpp
|
||||
// interface
|
||||
//
|
||||
// Created by Tobias Schwinger on 3/21/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "FieldOfView.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <algorithm>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/matrix_inverse.hpp>
|
||||
|
||||
using namespace glm;
|
||||
|
||||
FieldOfView::FieldOfView() :
|
||||
_matOrientation(mat4(1.0f)),
|
||||
_vecBoundsLow(vec3(-1.0f,-1.0f,-1.0f)),
|
||||
_vecBoundsHigh(vec3(1.0f,1.0f,1.0f)),
|
||||
_valWidth(256.0f),
|
||||
_valHeight(256.0f),
|
||||
_valAngle(0.61),
|
||||
_valZoom(1.0f),
|
||||
_enmAspectBalancing(expose_less) {
|
||||
}
|
||||
|
||||
mat4 FieldOfView::getViewerScreenXform() const {
|
||||
|
||||
mat4 projection;
|
||||
vec3 low, high;
|
||||
getFrustum(low, high);
|
||||
|
||||
// perspective projection? determine correct near distance
|
||||
if (_valAngle != 0.0f) {
|
||||
|
||||
projection = translate(
|
||||
frustum(low.x, high.x, low.y, high.y, low.z, high.z),
|
||||
vec3(0.f, 0.f, -low.z) );
|
||||
} else {
|
||||
|
||||
projection = ortho(low.x, high.x, low.y, high.y, low.z, high.z);
|
||||
}
|
||||
|
||||
return projection;
|
||||
}
|
||||
|
||||
mat4 FieldOfView::getWorldViewerXform() const {
|
||||
|
||||
return translate(affineInverse(_matOrientation),
|
||||
vec3(0.0f, 0.0f, -_vecBoundsHigh.z) );
|
||||
}
|
||||
|
||||
mat4 FieldOfView::getWorldScreenXform() const {
|
||||
|
||||
return translate(
|
||||
getViewerScreenXform() * affineInverse(_matOrientation),
|
||||
vec3(0.0f, 0.0f, -_vecBoundsHigh.z) );
|
||||
}
|
||||
|
||||
mat4 FieldOfView::getViewerWorldXform() const {
|
||||
|
||||
vec3 n_translate = vec3(0.0f, 0.0f, _vecBoundsHigh.z);
|
||||
|
||||
return translate(
|
||||
translate(mat4(1.0f), n_translate)
|
||||
* _matOrientation, -n_translate );
|
||||
}
|
||||
|
||||
float FieldOfView::getPixelSize() const {
|
||||
|
||||
vec3 low, high;
|
||||
getFrustum(low, high);
|
||||
|
||||
return std::min(
|
||||
abs(high.x - low.x) / _valWidth,
|
||||
abs(high.y - low.y) / _valHeight);
|
||||
}
|
||||
|
||||
void FieldOfView::getFrustum(vec3& low, vec3& high) const {
|
||||
|
||||
low = _vecBoundsLow;
|
||||
high = _vecBoundsHigh;
|
||||
|
||||
// start with uniform zoom
|
||||
float inv_zoom = 1.0f / _valZoom;
|
||||
float adj_x = inv_zoom, adj_y = inv_zoom;
|
||||
|
||||
// balance aspect
|
||||
if (_enmAspectBalancing != stretch) {
|
||||
|
||||
float f_aspect = (high.x - low.x) / (high.y - low.y);
|
||||
float vp_aspect = _valWidth / _valHeight;
|
||||
|
||||
if ((_enmAspectBalancing == expose_more)
|
||||
!= (f_aspect > vp_aspect)) {
|
||||
|
||||
// expose_more -> f_aspect <= vp_aspect <=> adj >= 1
|
||||
// expose_less -> f_aspect > vp_aspect <=> adj < 1
|
||||
adj_x = vp_aspect / f_aspect;
|
||||
|
||||
} else {
|
||||
|
||||
// expose_more -> f_aspect > vp_aspect <=> adj > 1
|
||||
// expose_less -> f_aspect <= vp_aspect <=> adj <= 1
|
||||
adj_y = f_aspect / vp_aspect;
|
||||
}
|
||||
}
|
||||
|
||||
// scale according to zoom / aspect correction
|
||||
float ax = (low.x + high.x) / 2.0f, ay = (low.y + high.y) / 2.0f;
|
||||
low.x = (low.x - ax) * adj_x + ax;
|
||||
high.x = (high.x - ax) * adj_x + ax;
|
||||
low.y = (low.y - ay) * adj_y + ay;
|
||||
high.y = (high.y - ay) * adj_y + ay;
|
||||
low.z = (low.z - high.z) * inv_zoom + high.z;
|
||||
|
||||
// calc and apply near distance based on near diagonal and perspective
|
||||
float w = high.x - low.x, h = high.y - low.y;
|
||||
high.z -= low.z;
|
||||
low.z = _valAngle == 0.0f ? 0.0f :
|
||||
sqrt(w*w+h*h) * 0.5f / tan(_valAngle * 0.5f);
|
||||
high.z += low.z;
|
||||
}
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
//
|
||||
// FieldOfView.h
|
||||
// interface
|
||||
//
|
||||
// Created by Tobias Schwinger on 3/21/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __interface__FieldOfView__
|
||||
#define __interface__FieldOfView__
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
//
|
||||
// Viewing parameter encapsulation.
|
||||
//
|
||||
class FieldOfView {
|
||||
|
||||
glm::mat4 _matOrientation;
|
||||
glm::vec3 _vecBoundsLow;
|
||||
glm::vec3 _vecBoundsHigh;
|
||||
float _valWidth;
|
||||
float _valHeight;
|
||||
float _valAngle;
|
||||
float _valZoom;
|
||||
int _enmAspectBalancing;
|
||||
public:
|
||||
|
||||
FieldOfView();
|
||||
|
||||
// mutators
|
||||
|
||||
FieldOfView& setBounds(glm::vec3 const& low, glm::vec3 const& high) {
|
||||
_vecBoundsLow = low; _vecBoundsHigh = high; return *this; }
|
||||
|
||||
FieldOfView& setOrientation(glm::mat4 const& matrix) { _matOrientation = matrix; return *this; }
|
||||
|
||||
FieldOfView& setPerspective(float angle) { _valAngle = angle; return *this; }
|
||||
|
||||
FieldOfView& setResolution(unsigned width, unsigned height) { _valWidth = width; _valHeight = height; return *this; }
|
||||
|
||||
FieldOfView& setZoom(float factor) { _valZoom = factor; return *this; }
|
||||
|
||||
enum aspect_balancing
|
||||
{
|
||||
expose_more,
|
||||
expose_less,
|
||||
stretch
|
||||
};
|
||||
|
||||
FieldOfView& setAspectBalancing(aspect_balancing v) { _enmAspectBalancing = v; return *this; }
|
||||
|
||||
// dumb accessors
|
||||
|
||||
glm::mat4 const& getOrientation() const { return _matOrientation; }
|
||||
float getWidthInPixels() const { return _valWidth; }
|
||||
float getHeightInPixels() const { return _valHeight; }
|
||||
float getPerspective() const { return _valAngle; }
|
||||
|
||||
// matrices
|
||||
|
||||
//
|
||||
// Returns a full transformation matrix to project world coordinates
|
||||
// onto the screen.
|
||||
//
|
||||
glm::mat4 getWorldScreenXform() const;
|
||||
|
||||
//
|
||||
// Transforms world coordinates to viewer-relative coordinates.
|
||||
//
|
||||
// This matrix can be used as the modelview matrix in legacy GL code
|
||||
// where the projection matrix is kept separately.
|
||||
//
|
||||
glm::mat4 getWorldViewerXform() const;
|
||||
|
||||
//
|
||||
// Returns the transformation to of viewer-relative coordinates back
|
||||
// to world space.
|
||||
//
|
||||
// This matrix can be used to set up a coordinate system for avatar
|
||||
// rendering.
|
||||
//
|
||||
glm::mat4 getViewerWorldXform() const;
|
||||
|
||||
//
|
||||
// Returns the transformation of viewer-relative coordinates to the
|
||||
// screen.
|
||||
//
|
||||
// This matrix can be used as the projection matrix in legacy GL code.
|
||||
//
|
||||
glm::mat4 getViewerScreenXform() const;
|
||||
|
||||
|
||||
// other useful information
|
||||
|
||||
//
|
||||
// Returns the size of a pixel in world space, that is the minimum
|
||||
// in respect to x/y screen directions.
|
||||
//
|
||||
float getPixelSize() const;
|
||||
|
||||
//
|
||||
// Returns the frustum as used for the projection matrices.
|
||||
// The result depdends on the bounds, eventually aspect correction
|
||||
// for the current resolution, the perspective angle (specified in
|
||||
// respect to diagonal) and zoom.
|
||||
//
|
||||
void getFrustum(glm::vec3& low, glm::vec3& high) const;
|
||||
|
||||
//
|
||||
// Returns the z-offset from the origin to where orientation ia
|
||||
// applied.
|
||||
//
|
||||
float getTransformOffset() const { return _vecBoundsHigh.z; }
|
||||
|
||||
//
|
||||
// Returns the aspect ratio.
|
||||
//
|
||||
float getAspectRatio() const { return _valHeight / _valWidth; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -22,8 +22,7 @@
|
|||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
#include <glm/gtx/quaternion.hpp> //looks like we might not need this
|
||||
|
||||
enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH};
|
||||
|
||||
|
@ -85,12 +84,13 @@ struct AvatarBone
|
|||
glm::vec3 springyPosition; // used for special effects (a 'flexible' variant of position)
|
||||
glm::dvec3 springyVelocity; // used for special effects ( the velocity of the springy position)
|
||||
float springBodyTightness; // how tightly the springy position tries to stay on the position
|
||||
glm::quat rotation; // this will eventually replace yaw, pitch and roll (and maybe orienttion)
|
||||
glm::quat rotation; // this will eventually replace yaw, pitch and roll (and maybe orientation)
|
||||
float yaw; // the yaw Euler angle of the bone rotation off the parent
|
||||
float pitch; // the pitch Euler angle of the bone rotation off the parent
|
||||
float roll; // the roll Euler angle of the bone rotation off the parent
|
||||
Orientation orientation; // three orthogonal normals determined by yaw, pitch, roll
|
||||
float length; // the length of the bone
|
||||
float radius; // used for detecting collisions for certain physical effects
|
||||
};
|
||||
|
||||
struct Avatar
|
||||
|
@ -111,9 +111,9 @@ class Head : public AvatarData {
|
|||
void reset();
|
||||
void UpdateGyros(float frametime, SerialInterface * serialInterface, int head_mirror, glm::vec3 * gravity);
|
||||
void setNoise (float mag) { noise = mag; }
|
||||
void setPitch(float p) {Pitch = p; }
|
||||
void setYaw(float y) {Yaw = y; }
|
||||
void setRoll(float r) {Roll = r; };
|
||||
void setPitch(float p) {_headPitch = p; }
|
||||
void setYaw(float y) {_headYaw = y; }
|
||||
void setRoll(float r) {_headRoll = r; };
|
||||
void setScale(float s) {scale = s; };
|
||||
void setRenderYaw(float y) {renderYaw = y;}
|
||||
void setRenderPitch(float p) {renderPitch = p;}
|
||||
|
@ -121,14 +121,14 @@ class Head : public AvatarData {
|
|||
float getRenderPitch() {return renderPitch;}
|
||||
void setLeanForward(float dist);
|
||||
void setLeanSideways(float dist);
|
||||
void addPitch(float p) {Pitch -= p; }
|
||||
void addYaw(float y){Yaw -= y; }
|
||||
void addRoll(float r){Roll += r; }
|
||||
void addPitch(float p) {_headPitch -= p; }
|
||||
void addYaw(float y){_headYaw -= y; }
|
||||
void addRoll(float r){_headRoll += r; }
|
||||
void addLean(float x, float z);
|
||||
float getPitch() {return Pitch;}
|
||||
float getRoll() {return Roll;}
|
||||
float getYaw() {return Yaw;}
|
||||
float getLastMeasuredYaw() {return YawRate;}
|
||||
float getPitch() {return _headPitch;}
|
||||
float getRoll() {return _headRoll;}
|
||||
float getYaw() {return _headYaw;}
|
||||
float getLastMeasuredYaw() {return _headYawRate;}
|
||||
|
||||
float getBodyYaw() {return _bodyYaw;};
|
||||
void addBodyYaw(float y) {_bodyYaw += y;};
|
||||
|
@ -180,12 +180,12 @@ class Head : public AvatarData {
|
|||
private:
|
||||
bool _isMine;
|
||||
float noise;
|
||||
float Pitch;
|
||||
float Yaw;
|
||||
float Roll;
|
||||
float PitchRate;
|
||||
float YawRate;
|
||||
float RollRate;
|
||||
float _headPitch;
|
||||
float _headYaw;
|
||||
float _headRoll;
|
||||
float _headPitchRate;
|
||||
float _headYawRate;
|
||||
float _headRollRate;
|
||||
float EyeballPitch[2];
|
||||
float EyeballYaw[2];
|
||||
float EyebrowPitch[2];
|
||||
|
@ -212,7 +212,9 @@ class Head : public AvatarData {
|
|||
float averageLoudness;
|
||||
float audioAttack;
|
||||
float browAudioLift;
|
||||
|
||||
|
||||
glm::vec3 _TEST_bigSpherePosition;
|
||||
float _TEST_bigSphereRadius;
|
||||
|
||||
//temporary - placeholder for real other avs
|
||||
glm::vec3 DEBUG_otherAvatarListPosition [ NUM_OTHER_AVATARS ];
|
||||
|
@ -253,12 +255,12 @@ class Head : public AvatarData {
|
|||
//-----------------------------
|
||||
// private methods...
|
||||
//-----------------------------
|
||||
void initializeAvatar();
|
||||
void initializeSkeleton();
|
||||
void updateSkeleton();
|
||||
void initializeBodySprings();
|
||||
void updateBodySprings( float deltaTime );
|
||||
void calculateBoneLengths();
|
||||
void updateBigSphereCollisionTest( float deltaTime );
|
||||
void readSensors();
|
||||
};
|
||||
|
||||
|
|
|
@ -28,9 +28,9 @@
|
|||
#define ACCEL_Z 5
|
||||
|
||||
// Gyro sensors, in coodinate system of head/airplane
|
||||
#define PITCH_RATE 1
|
||||
#define YAW_RATE 0
|
||||
#define ROLL_RATE 2
|
||||
#define HEAD_PITCH_RATE 1
|
||||
#define HEAD_YAW_RATE 0
|
||||
#define HEAD_ROLL_RATE 2
|
||||
|
||||
class SerialInterface {
|
||||
public:
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
//
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
#include "FieldOfView.h"
|
||||
#include "Stars.h"
|
||||
|
||||
#define __interface__Starfield_impl__
|
||||
|
@ -23,8 +22,8 @@ Stars::~Stars() {
|
|||
delete _ptrController;
|
||||
}
|
||||
|
||||
bool Stars::readInput(const char* url, unsigned limit) {
|
||||
return _ptrController->readInput(url, limit);
|
||||
bool Stars::readInput(const char* url, const char* cacheFile, unsigned limit) {
|
||||
return _ptrController->readInput(url, cacheFile, limit);
|
||||
}
|
||||
|
||||
bool Stars::setResolution(unsigned k) {
|
||||
|
@ -35,8 +34,9 @@ float Stars::changeLOD(float fraction, float overalloc, float realloc) {
|
|||
return float(_ptrController->changeLOD(fraction, overalloc, realloc));
|
||||
}
|
||||
|
||||
void Stars::render(FieldOfView const& fov) {
|
||||
_ptrController->render(fov.getPerspective(), fov.getAspectRatio(), fov.getOrientation());
|
||||
void Stars::render(float fovDiagonal, float aspect, glm::mat4 const& view) {
|
||||
|
||||
_ptrController->render(fovDiagonal, aspect, glm::affineInverse(view));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#ifndef __interface__Stars__
|
||||
#define __interface__Stars__
|
||||
|
||||
#include "FieldOfView.h"
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
namespace starfield { class Controller; }
|
||||
|
||||
|
@ -31,13 +31,13 @@ class Stars {
|
|||
* The limit parameter allows to reduce the number of stars
|
||||
* that are loaded, keeping the brightest ones.
|
||||
*/
|
||||
bool readInput(const char* url, unsigned limit = 200000);
|
||||
bool readInput(const char* url, const char* cacheFile = 0l, unsigned limit = 200000);
|
||||
|
||||
/**
|
||||
* Renders the starfield from a local viewer's perspective.
|
||||
* The parameter specifies the field of view.
|
||||
*/
|
||||
void render(FieldOfView const& fov);
|
||||
void render(float fovDiagonal, float aspect, glm::mat4 const& view);
|
||||
|
||||
/**
|
||||
* Sets the resolution for FOV culling.
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
#include "Audio.h"
|
||||
#endif
|
||||
|
||||
#include "FieldOfView.h"
|
||||
#include "AngleUtil.h"
|
||||
#include "Stars.h"
|
||||
|
||||
#include "MenuRow.h"
|
||||
|
@ -96,6 +96,7 @@ int headMirror = 1; // Whether to mirror own head when viewing
|
|||
int WIDTH = 1200; // Window size
|
||||
int HEIGHT = 800;
|
||||
int fullscreen = 0;
|
||||
float aspectRatio = 1.0f;
|
||||
|
||||
bool wantColorRandomizer = true; // for addSphere and load file
|
||||
|
||||
|
@ -109,12 +110,8 @@ Camera viewFrustumOffsetCamera; // The camera we use to sometimes show the v
|
|||
|
||||
// Starfield information
|
||||
char starFile[] = "https://s3-us-west-1.amazonaws.com/highfidelity/stars.txt";
|
||||
FieldOfView fov;
|
||||
char starCacheFile[] = "cachedStars.txt";
|
||||
Stars stars;
|
||||
#ifdef STARFIELD_KEYS
|
||||
int starsTiles = 20;
|
||||
double starsLod = 1.0;
|
||||
#endif
|
||||
|
||||
bool showingVoxels = true;
|
||||
|
||||
|
@ -170,8 +167,8 @@ int headMouseX, headMouseY;
|
|||
int mouseX, mouseY; // Where is the mouse
|
||||
|
||||
// Mouse location at start of last down click
|
||||
int mouseStartX;// = WIDTH / 2;
|
||||
int mouseStartY;// = HEIGHT / 2;
|
||||
int mouseStartX = WIDTH / 2;
|
||||
int mouseStartY = HEIGHT / 2;
|
||||
int mousePressed = 0; // true if mouse has been pressed (clear when finished)
|
||||
|
||||
Menu menu; // main menu
|
||||
|
@ -302,7 +299,7 @@ void init(void)
|
|||
headMouseX = WIDTH/2;
|
||||
headMouseY = HEIGHT/2;
|
||||
|
||||
stars.readInput(starFile, 0);
|
||||
stars.readInput(starFile, starCacheFile, 0);
|
||||
|
||||
// Initialize Field values
|
||||
field = Field();
|
||||
|
@ -382,8 +379,8 @@ void updateAvatarHand(float deltaTime) {
|
|||
//
|
||||
void updateAvatar(float frametime)
|
||||
{
|
||||
float gyroPitchRate = serialPort.getRelativeValue(PITCH_RATE);
|
||||
float gyroYawRate = serialPort.getRelativeValue(YAW_RATE);
|
||||
float gyroPitchRate = serialPort.getRelativeValue(HEAD_PITCH_RATE);
|
||||
float gyroYawRate = serialPort.getRelativeValue(HEAD_YAW_RATE );
|
||||
|
||||
myAvatar.UpdateGyros(frametime, &serialPort, headMirror, &gravity);
|
||||
|
||||
|
@ -765,18 +762,12 @@ void display(void)
|
|||
glRotatef ( whichCamera.getYaw(), 0, 1, 0 );
|
||||
glTranslatef( -whichCamera.getPosition().x, -whichCamera.getPosition().y, -whichCamera.getPosition().z );
|
||||
|
||||
|
||||
|
||||
|
||||
//quick test for camera ortho-normal sanity check...
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (::starsOn) {
|
||||
// should be the first rendering pass - w/o depth buffer / lighting
|
||||
stars.render(fov);
|
||||
|
||||
glm::mat4 view;
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, glm::value_ptr(view));
|
||||
stars.render(angleConvert<Degrees,Radians>(whichCamera.getFieldOfView()), aspectRatio, view);
|
||||
}
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
|
@ -842,7 +833,6 @@ void display(void)
|
|||
// brad's frustum for debugging
|
||||
if (::frustumOn) render_view_frustum();
|
||||
|
||||
|
||||
//Render my own avatar
|
||||
myAvatar.render(true);
|
||||
}
|
||||
|
@ -1278,13 +1268,6 @@ void key(unsigned char k, int x, int y)
|
|||
if (k == ' ') reset_sensors();
|
||||
if (k == 't') renderPitchRate -= KEYBOARD_PITCH_RATE;
|
||||
if (k == 'g') renderPitchRate += KEYBOARD_PITCH_RATE;
|
||||
#ifdef STARFIELD_KEYS
|
||||
if (k == 'u') stars.setResolution(starsTiles += 1);
|
||||
if (k == 'j') stars.setResolution(starsTiles = max(starsTiles-1,1));
|
||||
if (k == 'i') if (starsLod < 1.0) starsLod = stars.changeLOD(1.01);
|
||||
if (k == 'k') if (starsLod > 0.01) starsLod = stars.changeLOD(0.99);
|
||||
if (k == 'r') stars.readInput(starFile, 0);
|
||||
#endif
|
||||
if (k == 'a') myAvatar.setDriveKeys(ROT_LEFT, 1);
|
||||
if (k == 'd') myAvatar.setDriveKeys(ROT_RIGHT, 1);
|
||||
}
|
||||
|
@ -1335,22 +1318,21 @@ void idle(void) {
|
|||
// Only run simulation code if more than IDLE_SIMULATE_MSECS have passed since last time
|
||||
|
||||
if (diffclock(&lastTimeIdle, &check) > IDLE_SIMULATE_MSECS) {
|
||||
// If mouse is being dragged, update hand movement in the avatar
|
||||
//if ( mousePressed == 1 )
|
||||
|
||||
if ( myAvatar.getMode() == AVATAR_MODE_COMMUNICATING ) {
|
||||
//if ( myAvatar.getMode() == AVATAR_MODE_COMMUNICATING ) {
|
||||
float leftRight = ( mouseX - mouseStartX ) / (float)WIDTH;
|
||||
float downUp = ( mouseY - mouseStartY ) / (float)HEIGHT;
|
||||
float backFront = 0.0;
|
||||
glm::vec3 handMovement( leftRight, downUp, backFront );
|
||||
myAvatar.setHandMovement( handMovement );
|
||||
}
|
||||
/*}
|
||||
else {
|
||||
mouseStartX = mouseX;
|
||||
mouseStartY = mouseY;
|
||||
//mouseStartX = (float)WIDTH / 2.0f;
|
||||
//mouseStartY = (float)HEIGHT / 2.0f;
|
||||
}
|
||||
*/
|
||||
|
||||
//--------------------------------------------------------
|
||||
// when the mouse is being pressed, an 'action' is being
|
||||
|
@ -1364,14 +1346,13 @@ void idle(void) {
|
|||
}
|
||||
|
||||
//
|
||||
// Sample hardware, update view frustum if needed, send avatar data to mixer/agents
|
||||
// Sample hardware, update view frustum if needed, Lsend avatar data to mixer/agents
|
||||
//
|
||||
updateAvatar( 1.f/FPS );
|
||||
|
||||
|
||||
//test
|
||||
/*
|
||||
for(std::vector<Agent>::iterator agent = agentList.getAgents().begin(); agent != agentList.getAgents().end(); agent++)
|
||||
//loop through all the other avatars and simulate them.
|
||||
AgentList * agentList = AgentList::getInstance();
|
||||
for(std::vector<Agent>::iterator agent = agentList->getAgents().begin(); agent != agentList->getAgents().end(); agent++)
|
||||
{
|
||||
if (agent->getLinkedData() != NULL)
|
||||
{
|
||||
|
@ -1379,7 +1360,7 @@ void idle(void) {
|
|||
agentHead->simulate(1.f/FPS);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
updateAvatarHand(1.f/FPS);
|
||||
|
||||
|
@ -1404,7 +1385,7 @@ void reshape(int width, int height)
|
|||
{
|
||||
WIDTH = width;
|
||||
HEIGHT = height;
|
||||
float aspectRatio = ((float)width/(float)height); // based on screen resize
|
||||
aspectRatio = ((float)width/(float)height); // based on screen resize
|
||||
|
||||
float fov;
|
||||
float nearClip;
|
||||
|
@ -1432,14 +1413,6 @@ void reshape(int width, int height)
|
|||
|
||||
glMatrixMode(GL_PROJECTION); //hello
|
||||
|
||||
// XXXBHG - Note: this is Tobias's code for loading the perspective matrix. At Philip's suggestion, I'm removing
|
||||
// it and putting back our old code that simply loaded the fov, ratio, and near/far clips. But I'm keeping this here
|
||||
// for reference for now.
|
||||
//fov.setResolution(width, height)
|
||||
// .setBounds(glm::vec3(-0.5f,-0.5f,-500.0f), glm::vec3(0.5f, 0.5f, 0.1f) )
|
||||
// .setPerspective(0.7854f);
|
||||
//glLoadMatrixf(glm::value_ptr(fov.getViewerScreenXform()));
|
||||
|
||||
glLoadIdentity();
|
||||
|
||||
// XXXBHG - If we're in view frustum mode, then we need to do this little bit of hackery so that
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
#define STARFIELD_LOW_MEMORY 0 // set to 1 not to use 16-bit types
|
||||
#endif
|
||||
|
||||
#ifndef STARFIELD_DEBUG_LOD
|
||||
#define STARFIELD_DEBUG_LOD 0 // set to 1 to peek behind the scenes
|
||||
#ifndef STARFIELD_DEBUG_CULLING
|
||||
#define STARFIELD_DEBUG_CULLING 0 // set to 1 to peek behind the scenes
|
||||
#endif
|
||||
|
||||
#ifndef STARFIELD_MULTITHREADING
|
||||
|
@ -64,7 +64,6 @@
|
|||
#include <glm/gtc/matrix_inverse.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/matrix_access.hpp>
|
||||
#include <glm/gtc/swizzle.hpp>
|
||||
|
||||
#include "UrlReader.h"
|
||||
#include "AngleUtil.h"
|
||||
|
@ -80,13 +79,11 @@ namespace starfield {
|
|||
using glm::vec4;
|
||||
using glm::dot;
|
||||
using glm::normalize;
|
||||
using glm::swizzle;
|
||||
using glm::X;
|
||||
using glm::Y;
|
||||
using glm::Z;
|
||||
using glm::W;
|
||||
using glm::mat4;
|
||||
using glm::column;
|
||||
using glm::row;
|
||||
|
||||
using namespace std;
|
||||
|
|
|
@ -109,11 +109,11 @@ namespace starfield {
|
|||
_ptrRenderer(0l) {
|
||||
}
|
||||
|
||||
bool readInput(const char* url, unsigned limit)
|
||||
bool readInput(const char* url, const char* cacheFile, unsigned limit)
|
||||
{
|
||||
InputVertices vertices;
|
||||
|
||||
if (! Loader().loadVertices(vertices, url, limit))
|
||||
if (! Loader().loadVertices(vertices, url, cacheFile, limit))
|
||||
return false;
|
||||
|
||||
BrightnessLevels brightness;
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace starfield {
|
|||
public:
|
||||
|
||||
bool loadVertices(
|
||||
InputVertices& destination, char const* url, unsigned limit)
|
||||
InputVertices& destination, char const* url, char const* cacheFile, unsigned limit)
|
||||
{
|
||||
_ptrVertices = & destination;
|
||||
_valLimit = limit;
|
||||
|
@ -43,7 +43,7 @@ namespace starfield {
|
|||
#endif
|
||||
_strUrl = url; // in case we fail early
|
||||
|
||||
if (! UrlReader::readUrl(url, *this))
|
||||
if (! UrlReader::readUrl(url, *this, cacheFile))
|
||||
{
|
||||
fprintf(stderr, "%s:%d: %s\n",
|
||||
_strUrl, _valLineNo, getError());
|
||||
|
|
|
@ -149,7 +149,7 @@ namespace starfield {
|
|||
matrix[3][2] = 0.0f;
|
||||
|
||||
// extract local z vector
|
||||
vec3 ahead = swizzle<X,Y,Z>( column(matrix, 2) );
|
||||
vec3 ahead = vec3(matrix[2]);
|
||||
|
||||
float azimuth = atan2(ahead.x,-ahead.z) + Radians::pi();
|
||||
float altitude = atan2(-ahead.y, hypotf(ahead.x, ahead.z));
|
||||
|
@ -163,7 +163,7 @@ namespace starfield {
|
|||
// fprintf(stderr, "Stars.cpp: starting on tile #%d\n", tileIndex);
|
||||
|
||||
|
||||
#if STARFIELD_DEBUG_LOD
|
||||
#if STARFIELD_DEBUG_CULLING
|
||||
mat4 matrix_debug = glm::translate(
|
||||
glm::frustum(-hw, hw, -hh, hh, nearClip, 10.0f),
|
||||
vec3(0.0f, 0.0f, -4.0f)) * glm::affineInverse(matrix);
|
||||
|
@ -173,7 +173,7 @@ namespace starfield {
|
|||
* glm::affineInverse(matrix);
|
||||
|
||||
this->_itrOutIndex = (unsigned*) _arrBatchOffs;
|
||||
this->_vecWxform = swizzle<X,Y,Z>(row(matrix, 3));
|
||||
this->_vecWxform = vec3(row(matrix, 3));
|
||||
this->_valHalfPersp = halfPersp;
|
||||
this->_valMinBright = minBright;
|
||||
|
||||
|
@ -181,13 +181,13 @@ namespace starfield {
|
|||
_arrTile, _arrTile + _objTiling.getTileCount(),
|
||||
(Tile**) _arrBatchCount));
|
||||
|
||||
#if STARFIELD_DEBUG_LOD
|
||||
#if STARFIELD_DEBUG_CULLING
|
||||
# define matrix matrix_debug
|
||||
#endif
|
||||
this->glBatch(glm::value_ptr(matrix), prepareBatch(
|
||||
(unsigned*) _arrBatchOffs, _itrOutIndex) );
|
||||
|
||||
#if STARFIELD_DEBUG_LOD
|
||||
#if STARFIELD_DEBUG_CULLING
|
||||
# undef matrix
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
|
|||
memcpy(destinationBuffer, &_handPosition, sizeof(float) * 3);
|
||||
destinationBuffer += sizeof(float) * 3;
|
||||
|
||||
//std::cout << _bodyPosition.x << ", " << _bodyPosition.y << ", " << _bodyPosition.z << "\n";
|
||||
std::cout << _handPosition.x << ", " << _handPosition.y << ", " << _handPosition.z << "\n";
|
||||
|
||||
return destinationBuffer - bufferStart;
|
||||
}
|
||||
|
|
|
@ -6,13 +6,17 @@
|
|||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#include "UrlReader.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NOCURL_IN_WINDOWS
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef NOCURL_IN_WINDOWS
|
||||
#include <curl/curl.h>
|
||||
size_t const UrlReader::max_read_ahead = CURL_MAX_WRITE_SIZE;
|
||||
|
@ -21,6 +25,7 @@ size_t const UrlReader::max_read_ahead = 0;
|
|||
#endif
|
||||
|
||||
char const* const UrlReader::success = "UrlReader: Success!";
|
||||
char const* const UrlReader::success_cached = "UrlReader:: Using local file.";
|
||||
char const* const UrlReader::error_init_failed = "UrlReader: Initialization failed.";
|
||||
char const* const UrlReader::error_aborted = "UrlReader: Processing error.";
|
||||
char const* const UrlReader::error_buffer_overflow = "UrlReader: Buffer overflow.";
|
||||
|
@ -29,7 +34,7 @@ char const* const UrlReader::error_leftover_input = "UrlReader: Incomplete pro
|
|||
#define hnd_curl static_cast<CURL*>(_ptrImpl)
|
||||
|
||||
UrlReader::UrlReader()
|
||||
: _ptrImpl(0l), _arrXtra(0l), _strError(0l) {
|
||||
: _ptrImpl(0l), _arrXtra(0l), _strError(0l), _arrCacheRdBuf(0l) {
|
||||
|
||||
_arrXtra = new(std::nothrow) char[max_read_ahead];
|
||||
if (! _arrXtra) { _strError = error_init_failed; return; }
|
||||
|
@ -39,12 +44,14 @@ UrlReader::UrlReader()
|
|||
curl_easy_setopt(hnd_curl, CURLOPT_NOSIGNAL, 1l);
|
||||
curl_easy_setopt(hnd_curl, CURLOPT_FAILONERROR, 1l);
|
||||
curl_easy_setopt(hnd_curl, CURLOPT_FILETIME, 1l);
|
||||
curl_easy_setopt(hnd_curl, CURLOPT_ENCODING, "");
|
||||
#endif
|
||||
}
|
||||
|
||||
UrlReader::~UrlReader() {
|
||||
|
||||
delete _arrXtra;
|
||||
delete[] _arrXtra;
|
||||
delete[] _arrCacheRdBuf;
|
||||
#ifndef NOCURL_IN_WINDOWS
|
||||
if (! hnd_curl) return;
|
||||
curl_easy_cleanup(hnd_curl);
|
||||
|
@ -78,14 +85,42 @@ void UrlReader::getinfo(char const*& url,
|
|||
char const*& type, int64_t& length, int64_t& stardate) {
|
||||
#ifndef NOCURL_IN_WINDOWS
|
||||
|
||||
double clen;
|
||||
long time;
|
||||
curl_easy_getinfo(hnd_curl, CURLINFO_FILETIME, & time);
|
||||
|
||||
// check caching file time whether we actually want to download anything
|
||||
if (_strCacheFile != 0l) {
|
||||
struct stat s;
|
||||
stat(_strCacheFile, & s);
|
||||
if (time > s.st_mtime) {
|
||||
// file on server is newer -> update cache file
|
||||
_ptrCacheFile = fopen(_strCacheFile, "wb");
|
||||
if (_ptrCacheFile != 0l) {
|
||||
_valCacheMode = cache_write;
|
||||
}
|
||||
} else {
|
||||
// file on server is older -> use cache file
|
||||
if (! _arrCacheRdBuf) {
|
||||
_arrCacheRdBuf = new (std::nothrow) char[max_read_ahead];
|
||||
if (! _arrCacheRdBuf) {
|
||||
_valCacheMode = no_cache;
|
||||
}
|
||||
}
|
||||
_ptrCacheFile = fopen(_strCacheFile, "rb");
|
||||
if (_ptrCacheFile != 0l) {
|
||||
_valCacheMode = cache_read;
|
||||
}
|
||||
_strError = success_cached;
|
||||
}
|
||||
}
|
||||
|
||||
curl_easy_getinfo(hnd_curl, CURLINFO_EFFECTIVE_URL, & url);
|
||||
curl_easy_getinfo(hnd_curl, CURLINFO_CONTENT_TYPE, & type);
|
||||
|
||||
double clen;
|
||||
curl_easy_getinfo(hnd_curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, & clen);
|
||||
length = static_cast<int64_t>(clen);
|
||||
|
||||
long time;
|
||||
curl_easy_getinfo(hnd_curl, CURLINFO_FILETIME, & time);
|
||||
stardate = time;
|
||||
#endif
|
||||
|
|
|
@ -12,119 +12,132 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* UrlReader class that encapsulates a context for sequential data retrieval
|
||||
* via URLs. Use one per thread.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
//
|
||||
// UrlReader class that encapsulates a context for sequential data retrieval
|
||||
// via URLs. Use one per thread.
|
||||
//
|
||||
class UrlReader {
|
||||
|
||||
enum CacheMode { no_cache, cache_write, cache_read };
|
||||
|
||||
void* _ptrImpl;
|
||||
char* _arrXtra;
|
||||
char const* _strError;
|
||||
void* _ptrStream;
|
||||
char const* _strCacheFile;
|
||||
FILE* _ptrCacheFile;
|
||||
char* _arrCacheRdBuf;
|
||||
CacheMode _valCacheMode;
|
||||
size_t _valXtraSize;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor - performs initialization, never throws.
|
||||
*/
|
||||
//
|
||||
// Constructor - performs initialization, never throws.
|
||||
//
|
||||
UrlReader();
|
||||
|
||||
/**
|
||||
* Destructor - frees resources, never throws.
|
||||
*/
|
||||
//
|
||||
// Destructor - frees resources, never throws.
|
||||
//
|
||||
~UrlReader();
|
||||
|
||||
/**
|
||||
* Reads data from an URL and forwards it to the instance of a class
|
||||
* fulfilling the ContentStream concept.
|
||||
*
|
||||
* The call protocol on the ContentStream is detailed as follows:
|
||||
*
|
||||
* 1. begin(char const* url,
|
||||
* char const* content_type, uint64_t bytes, uint64_t stardate)
|
||||
*
|
||||
* All information except 'url' is optional; 'content_type' can
|
||||
* be a null pointer - 'bytes' and 'stardate' can be equal to
|
||||
* to 'unavailable'.
|
||||
*
|
||||
* 2. transfer(char* buffer, size_t bytes)
|
||||
*
|
||||
* Called until all data has been received. The number of bytes
|
||||
* actually processed should be returned.
|
||||
* Unprocessed data is stored in an extra buffer whose size is
|
||||
* given by the constant UrlReader::max_read_ahead - it can be
|
||||
* assumed to be reasonably large for on-the-fly parsing.
|
||||
*
|
||||
* 3. end(bool ok)
|
||||
*
|
||||
* Called at the end of the transfer.
|
||||
*
|
||||
* Returns the same success code
|
||||
*/
|
||||
//
|
||||
// Reads data from an URL and forwards it to the instance of a class
|
||||
// fulfilling the ContentStream concept.
|
||||
//
|
||||
// The call protocol on the ContentStream is detailed as follows:
|
||||
//
|
||||
// 1. begin(char const* url,
|
||||
// char const* content_type, uint64_t bytes, uint64_t stardate)
|
||||
//
|
||||
// All information except 'url' is optional; 'content_type' can
|
||||
// be a null pointer - 'bytes' and 'stardate' can be equal to
|
||||
// to 'unavailable'.
|
||||
//
|
||||
// 2. transfer(char* buffer, size_t bytes)
|
||||
//
|
||||
// Called until all data has been received. The number of bytes
|
||||
// actually processed should be returned.
|
||||
// Unprocessed data is stored in an extra buffer whose size is
|
||||
// given by the constant UrlReader::max_read_ahead - it can be
|
||||
// assumed to be reasonably large for on-the-fly parsing.
|
||||
//
|
||||
// 3. end(bool ok)
|
||||
//
|
||||
// Called at the end of the transfer.
|
||||
//
|
||||
// Returns the same success code
|
||||
//
|
||||
template< class ContentStream >
|
||||
bool readUrl(char const* url, ContentStream& s);
|
||||
bool readUrl(char const* url, ContentStream& s, char const* cacheFile = 0l);
|
||||
|
||||
/**
|
||||
* Returns a pointer to a static C-string that describes the error
|
||||
* condition.
|
||||
*/
|
||||
//
|
||||
// Returns a pointer to a static C-string that describes the error
|
||||
// condition.
|
||||
//
|
||||
inline char const* getError() const;
|
||||
|
||||
/**
|
||||
* Can be called by the stream to set a user-defined error string.
|
||||
*/
|
||||
//
|
||||
// Can be called by the stream to set a user-defined error string.
|
||||
//
|
||||
inline void setError(char const* static_c_string);
|
||||
|
||||
/**
|
||||
* Pointer to the C-string returned by a call to 'readUrl' when no
|
||||
* error occurred.
|
||||
*/
|
||||
//
|
||||
// Pointer to the C-string returned by a call to 'readUrl' when no
|
||||
// error occurred.
|
||||
//
|
||||
static char const* const success;
|
||||
|
||||
/**
|
||||
* Pointer to the C-string returned by a call to 'readUrl' when the
|
||||
* initialization has failed.
|
||||
*/
|
||||
//
|
||||
// Pointer to the C-string returned by a call to 'readUrl' when no
|
||||
// error occurred and a local file has been read instead of the
|
||||
// network stream.
|
||||
//
|
||||
static char const* const success_cached;
|
||||
|
||||
//
|
||||
// Pointer to the C-string returned by a call to 'readUrl' when the
|
||||
// initialization has failed.
|
||||
//
|
||||
static char const* const error_init_failed;
|
||||
|
||||
/**
|
||||
* Pointer to the C-string returned by a call to 'readUrl' when the
|
||||
* transfer has been aborted by the client.
|
||||
*/
|
||||
//
|
||||
// Pointer to the C-string returned by a call to 'readUrl' when the
|
||||
// transfer has been aborted by the client.
|
||||
//
|
||||
static char const* const error_aborted;
|
||||
|
||||
/**
|
||||
* Pointer to the C-string returned by a call to 'readUrl' when
|
||||
* leftover input from incomplete processing caused a buffer
|
||||
* overflow.
|
||||
*/
|
||||
//
|
||||
// Pointer to the C-string returned by a call to 'readUrl' when
|
||||
// leftover input from incomplete processing caused a buffer
|
||||
// overflow.
|
||||
//
|
||||
static char const* const error_buffer_overflow;
|
||||
|
||||
/**
|
||||
* Pointer to the C-string return by a call to 'readUrl' when the
|
||||
* input provided was not completely consumed.
|
||||
*/
|
||||
//
|
||||
// Pointer to the C-string return by a call to 'readUrl' when the
|
||||
// input provided was not completely consumed.
|
||||
//
|
||||
static char const* const error_leftover_input;
|
||||
|
||||
/**
|
||||
* Constant of the maximum number of bytes that are buffered
|
||||
* between invocations of 'transfer'.
|
||||
*/
|
||||
//
|
||||
// Constant of the maximum number of bytes that are buffered
|
||||
// between invocations of 'transfer'.
|
||||
//
|
||||
static size_t const max_read_ahead;
|
||||
|
||||
/**
|
||||
* Constant representing absent information in the call to the
|
||||
* 'begin' member function of the target stream.
|
||||
*/
|
||||
//
|
||||
// Constant representing absent information in the call to the
|
||||
// 'begin' member function of the target stream.
|
||||
//
|
||||
static int const unavailable = -1;
|
||||
|
||||
/**
|
||||
* Constant for requesting to abort the current transfer when
|
||||
* returned by the 'transfer' member function of the target stream.
|
||||
*/
|
||||
//
|
||||
// Constant for requesting to abort the current transfer when
|
||||
// returned by the 'transfer' member function of the target stream.
|
||||
//
|
||||
static size_t const abort = ~0u;
|
||||
|
||||
private:
|
||||
|
@ -143,38 +156,105 @@ class UrlReader {
|
|||
|
||||
// synthesized callback
|
||||
|
||||
template< class Stream >
|
||||
static size_t callback_template(
|
||||
char *input, size_t size, size_t nmemb, void* thiz);
|
||||
template< class Stream > static size_t callback_template(char *input, size_t size,
|
||||
size_t nmemb, void* thiz);
|
||||
|
||||
template< class Stream > size_t feedBuffered(Stream* stream,
|
||||
char* input, size_t size);
|
||||
};
|
||||
|
||||
template< class ContentStream >
|
||||
bool UrlReader::readUrl(char const* url, ContentStream& s) {
|
||||
bool UrlReader::readUrl(char const* url, ContentStream& s, char const* cacheFile) {
|
||||
if (! _ptrImpl) return false;
|
||||
_strCacheFile = cacheFile;
|
||||
_ptrCacheFile = 0l;
|
||||
_valCacheMode = no_cache; // eventually set later
|
||||
_strError = success;
|
||||
_ptrStream = & s;
|
||||
_valXtraSize = ~size_t(0);
|
||||
this->perform(url, & callback_template<ContentStream>);
|
||||
s.end(_strError == success);
|
||||
return _strError == success;
|
||||
if (_ptrCacheFile != 0l) {
|
||||
fclose(_ptrCacheFile);
|
||||
}
|
||||
return _strError == success || _strError == success_cached;
|
||||
}
|
||||
|
||||
inline char const* UrlReader::getError() const { return this->_strError; }
|
||||
|
||||
inline void UrlReader::setError(char const* static_c_string) {
|
||||
inline void UrlReader::setError(char const* staticCstring) {
|
||||
|
||||
if (this->_strError == success)
|
||||
this->_strError = static_c_string;
|
||||
if (this->_strError == success || this->_strError == success_cached)
|
||||
this->_strError = staticCstring;
|
||||
}
|
||||
|
||||
template< class Stream >
|
||||
size_t UrlReader::callback_template(
|
||||
char *input, size_t size, size_t nmemb, void* thiz) {
|
||||
size_t UrlReader::feedBuffered(Stream* stream, char* input, size_t size) {
|
||||
size_t inputOffset = 0u;
|
||||
|
||||
size *= nmemb;
|
||||
while (true) {
|
||||
|
||||
char* buffer = input + inputOffset;
|
||||
size_t bytes = size - inputOffset;
|
||||
|
||||
// data in extra buffer?
|
||||
if (_valXtraSize > 0) {
|
||||
|
||||
// fill extra buffer with beginning of input
|
||||
size_t fill = max_read_ahead - _valXtraSize;
|
||||
if (bytes < fill) fill = bytes;
|
||||
memcpy(_arrXtra + _valXtraSize, buffer, fill);
|
||||
// use extra buffer for next transfer
|
||||
buffer = _arrXtra;
|
||||
bytes = _valXtraSize + fill;
|
||||
inputOffset += fill;
|
||||
}
|
||||
|
||||
// call 'transfer'
|
||||
size_t processed = stream->transfer(buffer, bytes);
|
||||
if (processed == abort) {
|
||||
|
||||
setError(error_aborted);
|
||||
return 0u;
|
||||
|
||||
} else if (! processed && ! input) {
|
||||
|
||||
setError(error_leftover_input);
|
||||
return 0u;
|
||||
}
|
||||
size_t unprocessed = bytes - processed;
|
||||
|
||||
// can switch to input buffer, now?
|
||||
if (buffer == _arrXtra && unprocessed <= inputOffset) {
|
||||
|
||||
_valXtraSize = 0u;
|
||||
inputOffset -= unprocessed;
|
||||
|
||||
} else { // no? unprocessed data -> extra buffer
|
||||
|
||||
if (unprocessed > max_read_ahead) {
|
||||
|
||||
setError(error_buffer_overflow);
|
||||
return 0;
|
||||
}
|
||||
_valXtraSize = unprocessed;
|
||||
memmove(_arrXtra, buffer + processed, unprocessed);
|
||||
|
||||
if (inputOffset == size || buffer != _arrXtra) {
|
||||
|
||||
return size;
|
||||
}
|
||||
}
|
||||
} // while
|
||||
}
|
||||
|
||||
template< class Stream >
|
||||
size_t UrlReader::callback_template(char *input, size_t size, size_t nmemb, void* thiz) {
|
||||
|
||||
size_t result = 0u;
|
||||
UrlReader* me = static_cast<UrlReader*>(thiz);
|
||||
Stream* stream = static_cast<Stream*>(me->_ptrStream);
|
||||
size *= nmemb;
|
||||
|
||||
// first call?
|
||||
if (me->_valXtraSize == ~size_t(0)) {
|
||||
|
@ -184,65 +264,28 @@ size_t UrlReader::callback_template(
|
|||
char const* url, * type;
|
||||
int64_t length, stardate;
|
||||
me->getinfo(url, type, length, stardate);
|
||||
stream->begin(url, type, length, stardate);
|
||||
if (me->_valCacheMode != cache_read) {
|
||||
stream->begin(url, type, length, stardate);
|
||||
}
|
||||
}
|
||||
do {
|
||||
// will have to repeat from here when reading a local file
|
||||
|
||||
size_t input_offset = 0u;
|
||||
|
||||
while (true) {
|
||||
|
||||
char* buffer = input + input_offset;
|
||||
size_t bytes = size - input_offset;
|
||||
|
||||
// data in extra buffer?
|
||||
if (me->_valXtraSize > 0) {
|
||||
|
||||
// fill extra buffer with beginning of input
|
||||
size_t fill = max_read_ahead - me->_valXtraSize;
|
||||
if (bytes < fill) fill = bytes;
|
||||
memcpy(me->_arrXtra + me->_valXtraSize, buffer, fill);
|
||||
// use extra buffer for next transfer
|
||||
buffer = me->_arrXtra;
|
||||
bytes = me->_valXtraSize + fill;
|
||||
input_offset += fill;
|
||||
// read from cache file?
|
||||
if (me->_valCacheMode == cache_read) {
|
||||
// change input buffer and start
|
||||
input = me->_arrCacheRdBuf;
|
||||
size = fread(input, 1, max_read_ahead, me->_ptrCacheFile);
|
||||
nmemb = 1;
|
||||
} else if (me->_valCacheMode == cache_write) {
|
||||
fwrite(input, 1, size, me->_ptrCacheFile);
|
||||
}
|
||||
|
||||
// call 'transfer'
|
||||
size_t processed = stream->transfer(buffer, bytes);
|
||||
if (processed == abort) {
|
||||
result = me->feedBuffered(stream, input, size);
|
||||
|
||||
me->setError(error_aborted);
|
||||
return 0u;
|
||||
} while (me->_valCacheMode == cache_read && result != 0 && ! feof(me->_ptrCacheFile));
|
||||
|
||||
} else if (! processed && ! input) {
|
||||
|
||||
me->setError(error_leftover_input);
|
||||
return 0u;
|
||||
}
|
||||
size_t unprocessed = bytes - processed;
|
||||
|
||||
// can switch to input buffer, now?
|
||||
if (buffer == me->_arrXtra && unprocessed <= input_offset) {
|
||||
|
||||
me->_valXtraSize = 0u;
|
||||
input_offset -= unprocessed;
|
||||
|
||||
} else { // no? unprocessed data -> extra buffer
|
||||
|
||||
if (unprocessed > max_read_ahead) {
|
||||
|
||||
me->setError(error_buffer_overflow);
|
||||
return 0;
|
||||
}
|
||||
me->_valXtraSize = unprocessed;
|
||||
memmove(me->_arrXtra, buffer + processed, unprocessed);
|
||||
|
||||
if (input_offset == size || buffer != me->_arrXtra) {
|
||||
|
||||
return size;
|
||||
}
|
||||
}
|
||||
} // for
|
||||
return me->_valCacheMode != cache_read ? result : 0;
|
||||
}
|
||||
|
||||
#endif /* defined(__hifi__UrlReader__) */
|
||||
|
|
Loading…
Reference in a new issue