diff --git a/examples/PlayRecordingOnAC.js b/examples/PlayRecordingOnAC.js index a68e60a6fa..76f00ab9cd 100644 --- a/examples/PlayRecordingOnAC.js +++ b/examples/PlayRecordingOnAC.js @@ -12,12 +12,15 @@ var filename = "http://your.recording.url"; var playFromCurrentLocation = true; +var loop = true; Avatar.faceModelURL = "http://public.highfidelity.io/models/heads/EvilPhilip_v7.fst"; Avatar.skeletonModelURL = "http://public.highfidelity.io/models/skeletons/Philip_Carl_Body_A-Pose.fst"; // Set position here if playFromCurrentLocation is true Avatar.position = { x:1, y: 1, z: 1 }; +Avatar.orientation = Quat.fromPitchYawRollDegrees(0, 0, 0); +Avatar.scale = 1.0; Agent.isAvatar = true; @@ -30,7 +33,9 @@ function update(event) { return; } if (count == 0) { - Avatar.startPlaying(playFromCurrentLocation); + Avatar.setPlayFromCurrentLocation(playFromCurrentLocation); + Avatar.setPlayerLoop(loop); + Avatar.startPlaying(); Avatar.play(); Vec3.print("Playing from ", Avatar.position); diff --git a/examples/Recorder.js b/examples/Recorder.js index cf4b422926..7ecf0e2640 100644 --- a/examples/Recorder.js +++ b/examples/Recorder.js @@ -12,6 +12,8 @@ Script.include("toolBars.js"); var recordingFile = "recording.rec"; +var playFromCurrentLocation = true; +var loop = true; var windowDimensions = Controller.getViewportDimensions(); var TOOL_ICON_URL = "http://s3-us-west-1.amazonaws.com/highfidelity-public/images/tools/"; @@ -139,8 +141,6 @@ function moveUI() { function mousePressEvent(event) { clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); - print("Status: isPlaying=" + MyAvatar.isPlaying() + ", isRecording=" + MyAvatar.isRecording()); - if (recordIcon === toolBar.clicked(clickedOverlay) && !MyAvatar.isPlaying()) { if (!MyAvatar.isRecording()) { MyAvatar.startRecording(); @@ -154,19 +154,23 @@ function mousePressEvent(event) { if (MyAvatar.isPlaying()) { MyAvatar.stopPlaying(); } else { - MyAvatar.setPlayFromCurrentLocation(true); - MyAvatar.setPlayerLoop(true); + MyAvatar.setPlayFromCurrentLocation(playFromCurrentLocation); + MyAvatar.setPlayerLoop(loop); MyAvatar.startPlaying(true); } } else if (saveIcon === toolBar.clicked(clickedOverlay)) { if (!MyAvatar.isRecording()) { recordingFile = Window.save("Save recording to file", ".", "*.rec"); - MyAvatar.saveRecording(recordingFile); + if (recordingFile != null) { + MyAvatar.saveRecording(recordingFile); + } } } else if (loadIcon === toolBar.clicked(clickedOverlay)) { if (!MyAvatar.isRecording()) { recordingFile = Window.browse("Load recorcding from file", ".", "*.rec"); - MyAvatar.loadRecording(recordingFile); + if (recordingFile != "null") { + MyAvatar.loadRecording(recordingFile); + } } } else { diff --git a/examples/editModels.js b/examples/editModels.js index 411431791c..fc093b5446 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -1116,7 +1116,7 @@ var toolBar = (function () { browseModelsButton, loadURLMenuItem, loadFileMenuItem, - menuItemWidth = 90, + menuItemWidth = 125, menuItemOffset, menuItemHeight, menuItemMargin = 5, diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 1d97dc94fc..85287d03b5 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -880,22 +880,24 @@ void HeightfieldBuffer::render(bool cursor) { DefaultMetavoxelRendererImplementation::getShadowLightHeightfieldProgram().bind(); DefaultMetavoxelRendererImplementation::getShadowLightHeightfieldProgram().setUniformValue( DefaultMetavoxelRendererImplementation::getShadowLightHeightScaleLocation(), 1.0f / _heightSize); - + glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0); + DefaultMetavoxelRendererImplementation::getShadowMapHeightfieldProgram().bind(); + } else if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) { DefaultMetavoxelRendererImplementation::getCascadedShadowLightHeightfieldProgram().bind(); DefaultMetavoxelRendererImplementation::getCascadedShadowLightHeightfieldProgram().setUniformValue( DefaultMetavoxelRendererImplementation::getCascadedShadowLightHeightScaleLocation(), 1.0f / _heightSize); - + glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0); + DefaultMetavoxelRendererImplementation::getCascadedShadowMapHeightfieldProgram().bind(); + } else { DefaultMetavoxelRendererImplementation::getLightHeightfieldProgram().bind(); DefaultMetavoxelRendererImplementation::getLightHeightfieldProgram().setUniformValue( - DefaultMetavoxelRendererImplementation::getBaseHeightScaleLocation(), 1.0f / _heightSize); + DefaultMetavoxelRendererImplementation::getLightHeightScaleLocation(), 1.0f / _heightSize); + glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0); + DefaultMetavoxelRendererImplementation::getHeightfieldProgram().bind(); } - glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0); - - DefaultMetavoxelRendererImplementation::getHeightfieldProgram().bind(); - glDisable(GL_POLYGON_OFFSET_FILL); glDisable(GL_BLEND); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); @@ -1050,8 +1052,8 @@ void DefaultMetavoxelRendererImplementation::init() { _baseHeightfieldProgram.bind(); _baseHeightfieldProgram.setUniformValue("heightMap", 0); _baseHeightfieldProgram.setUniformValue("diffuseMap", 1); - _baseHeightScaleLocation = _heightfieldProgram.uniformLocation("heightScale"); - _baseColorScaleLocation = _heightfieldProgram.uniformLocation("colorScale"); + _baseHeightScaleLocation = _baseHeightfieldProgram.uniformLocation("heightScale"); + _baseColorScaleLocation = _baseHeightfieldProgram.uniformLocation("colorScale"); _baseHeightfieldProgram.release(); _splatHeightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + diff --git a/libraries/avatars/src/Recorder.cpp b/libraries/avatars/src/Recorder.cpp index 69cde6560e..70568a3487 100644 --- a/libraries/avatars/src/Recorder.cpp +++ b/libraries/avatars/src/Recorder.cpp @@ -10,7 +10,9 @@ // #include +#include +#include #include #include #include @@ -57,6 +59,25 @@ Recording::~Recording() { delete _audio; } +int Recording::getLength() const { + if (_timestamps.isEmpty()) { + return 0; + } + return _timestamps.last(); +} + +qint32 Recording::getFrameTimestamp(int i) const { + if (i >= _timestamps.size()) { + return getLength(); + } + return _timestamps[i]; +} + +const RecordingFrame& Recording::getFrame(int i) const { + assert(i < _timestamps.size()); + return _frames[i]; +} + void Recording::addFrame(int timestamp, RecordingFrame &frame) { _timestamps << timestamp; _frames << frame; @@ -492,18 +513,40 @@ void writeRecordingToFile(RecordingPointer recording, QString filename) { } RecordingPointer readRecordingFromFile(RecordingPointer recording, QString filename) { - qDebug() << "Reading recording from " << filename << "."; + QElapsedTimer timer; + timer.start(); + + QByteArray byteArray; + QUrl url(filename); + if (url.scheme() == "http" || url.scheme() == "https" || url.scheme() == "ftp") { + qDebug() << "Downloading recording at" << url; + NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(url)); + QEventLoop loop; + QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); + loop.exec(); + if (reply->error() != QNetworkReply::NoError) { + qDebug() << "Error while downloading recording: " << reply->error(); + reply->deleteLater(); + return recording; + } + byteArray = reply->readAll(); + reply->deleteLater(); + } else { + qDebug() << "Reading recording from " << filename << "."; + QFile file(filename); + if (!file.open(QIODevice::ReadOnly)){ + return recording; + } + byteArray = file.readAll(); + file.close(); + } + if (!recording) { recording.reset(new Recording()); } - QElapsedTimer timer; - QFile file(filename); - if (!file.open(QIODevice::ReadOnly)){ - return recording; - } - timer.start(); - QDataStream fileStream(&file); + QDataStream fileStream(byteArray); fileStream >> recording->_timestamps; RecordingFrame baseFrame; @@ -603,7 +646,7 @@ RecordingPointer readRecordingFromFile(RecordingPointer recording, QString filen recording->addAudioPacket(audioArray); - qDebug() << "Read " << file.size() << " bytes in " << timer.elapsed() << " ms."; + qDebug() << "Read " << byteArray.size() << " bytes in " << timer.elapsed() << " ms."; return recording; } diff --git a/libraries/avatars/src/Recorder.h b/libraries/avatars/src/Recorder.h index 1f41672749..447c3eabe8 100644 --- a/libraries/avatars/src/Recorder.h +++ b/libraries/avatars/src/Recorder.h @@ -81,11 +81,11 @@ public: ~Recording(); bool isEmpty() const { return _timestamps.isEmpty(); } - int getLength() const { return _timestamps.last(); } // in ms + int getLength() const; // in ms int getFrameNumber() const { return _frames.size(); } - qint32 getFrameTimestamp(int i) const { return _timestamps[i]; } - const RecordingFrame& getFrame(int i) const { return _frames[i]; } + qint32 getFrameTimestamp(int i) const; + const RecordingFrame& getFrame(int i) const; Sound* getAudio() const { return _audio; } protected: @@ -97,7 +97,6 @@ private: QVector _timestamps; QVector _frames; - bool _stereo; Sound* _audio; friend class Recorder;