mirror of
https://github.com/lubosz/overte.git
synced 2025-04-23 16:14:01 +02:00
Merge branch 'fix_attachment_bug_with_recording' of github.com:Atlante45/hifi into radio_js
Conflicts: libraries/audio/src/AudioInjector.cpp
This commit is contained in:
commit
a4a5d71caa
14 changed files with 433 additions and 89 deletions
|
@ -75,7 +75,7 @@ InboundAudioStream::Settings AudioMixer::_streamSettings;
|
|||
|
||||
bool AudioMixer::_printStreamStats = false;
|
||||
|
||||
bool AudioMixer::_enableFilter = false;
|
||||
bool AudioMixer::_enableFilter = true;
|
||||
|
||||
AudioMixer::AudioMixer(const QByteArray& packet) :
|
||||
ThreadedAssignment(packet),
|
||||
|
@ -710,7 +710,9 @@ void AudioMixer::run() {
|
|||
}
|
||||
|
||||
const QString FILTER_KEY = "J-enable-filter";
|
||||
_enableFilter = audioGroupObject[FILTER_KEY].toBool();
|
||||
if (audioGroupObject[FILTER_KEY].isBool()) {
|
||||
_enableFilter = audioGroupObject[FILTER_KEY].toBool();
|
||||
}
|
||||
if (_enableFilter) {
|
||||
qDebug() << "Filter enabled";
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
"type": "checkbox",
|
||||
"label": "Enable Positional Filter",
|
||||
"help": "If enabled, positional audio stream uses lowpass filter",
|
||||
"default": false
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ var timerOffset;
|
|||
setupToolBar();
|
||||
|
||||
var timer = null;
|
||||
var slider = null;
|
||||
setupTimer();
|
||||
|
||||
var watchStop = false;
|
||||
|
@ -115,6 +116,30 @@ function setupTimer() {
|
|||
alpha: 1.0,
|
||||
visible: true
|
||||
});
|
||||
|
||||
slider = { x: 0, y: 0,
|
||||
w: 200, h: 20,
|
||||
pos: 0.0, // 0.0 <= pos <= 1.0
|
||||
};
|
||||
slider.background = Overlays.addOverlay("text", {
|
||||
text: "",
|
||||
backgroundColor: { red: 128, green: 128, blue: 128 },
|
||||
x: slider.x, y: slider.y,
|
||||
width: slider.w,
|
||||
height: slider.h,
|
||||
alpha: 1.0,
|
||||
visible: true
|
||||
});
|
||||
slider.foreground = Overlays.addOverlay("text", {
|
||||
text: "",
|
||||
backgroundColor: { red: 200, green: 200, blue: 200 },
|
||||
x: slider.x, y: slider.y,
|
||||
width: slider.pos * slider.w,
|
||||
height: slider.h,
|
||||
alpha: 1.0,
|
||||
visible: true
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function updateTimer() {
|
||||
|
@ -131,6 +156,16 @@ function updateTimer() {
|
|||
text: text
|
||||
})
|
||||
toolBar.changeSpacing(text.length * 8 + ((MyAvatar.isRecording()) ? 15 : 0), spacing);
|
||||
|
||||
if (MyAvatar.isRecording()) {
|
||||
slider.pos = 1.0;
|
||||
} else if (MyAvatar.playerLength() > 0) {
|
||||
slider.pos = MyAvatar.playerElapsed() / MyAvatar.playerLength();
|
||||
}
|
||||
|
||||
Overlays.editOverlay(slider.foreground, {
|
||||
width: slider.pos * slider.w
|
||||
});
|
||||
}
|
||||
|
||||
function formatTime(time) {
|
||||
|
@ -163,7 +198,19 @@ function moveUI() {
|
|||
Overlays.editOverlay(timer, {
|
||||
x: relative.x + timerOffset - ToolBar.SPACING,
|
||||
y: windowDimensions.y - relative.y - ToolBar.SPACING
|
||||
});
|
||||
});
|
||||
|
||||
slider.x = relative.x - ToolBar.SPACING;
|
||||
slider.y = windowDimensions.y - relative.y - slider.h - ToolBar.SPACING;
|
||||
|
||||
Overlays.editOverlay(slider.background, {
|
||||
x: slider.x,
|
||||
y: slider.y,
|
||||
});
|
||||
Overlays.editOverlay(slider.foreground, {
|
||||
x: slider.x,
|
||||
y: slider.y,
|
||||
});
|
||||
}
|
||||
|
||||
function mousePressEvent(event) {
|
||||
|
@ -188,7 +235,7 @@ function mousePressEvent(event) {
|
|||
}
|
||||
} else if (playIcon === toolBar.clicked(clickedOverlay) && !MyAvatar.isRecording()) {
|
||||
if (MyAvatar.isPlaying()) {
|
||||
MyAvatar.stopPlaying();
|
||||
MyAvatar.pausePlayer();
|
||||
toolBar.setAlpha(ALPHA_ON, recordIcon);
|
||||
toolBar.setAlpha(ALPHA_ON, saveIcon);
|
||||
toolBar.setAlpha(ALPHA_ON, loadIcon);
|
||||
|
@ -203,7 +250,7 @@ function mousePressEvent(event) {
|
|||
}
|
||||
} else if (playLoopIcon === toolBar.clicked(clickedOverlay) && !MyAvatar.isRecording()) {
|
||||
if (MyAvatar.isPlaying()) {
|
||||
MyAvatar.stopPlaying();
|
||||
MyAvatar.pausePlayer();
|
||||
toolBar.setAlpha(ALPHA_ON, recordIcon);
|
||||
toolBar.setAlpha(ALPHA_ON, saveIcon);
|
||||
toolBar.setAlpha(ALPHA_ON, loadIcon);
|
||||
|
@ -234,10 +281,30 @@ function mousePressEvent(event) {
|
|||
toolBar.setAlpha(ALPHA_ON, saveIcon);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
} else if (MyAvatar.playerLength() > 0 &&
|
||||
slider.x < event.x && event.x < slider.x + slider.w &&
|
||||
slider.y < event.y && event.y < slider.y + slider.h) {
|
||||
isSliding = true;
|
||||
slider.pos = (event.x - slider.x) / slider.w;
|
||||
MyAvatar.setPlayerTime(slider.pos * MyAvatar.playerLength());
|
||||
}
|
||||
}
|
||||
var isSliding = false;
|
||||
|
||||
function mouseMoveEvent(event) {
|
||||
if (isSliding) {
|
||||
slider.pos = (event.x - slider.x) / slider.w;
|
||||
if (slider.pos < 0.0 || slider.pos > 1.0) {
|
||||
MyAvatar.stopPlaying();
|
||||
slider.pos = 0.0;
|
||||
}
|
||||
MyAvatar.setPlayerTime(slider.pos * MyAvatar.playerLength());
|
||||
}
|
||||
}
|
||||
|
||||
function mouseReleaseEvent(event) {
|
||||
isSliding = false;
|
||||
}
|
||||
|
||||
function update() {
|
||||
var newDimensions = Controller.getViewportDimensions();
|
||||
|
@ -264,11 +331,15 @@ function scriptEnding() {
|
|||
if (MyAvatar.isPlaying()) {
|
||||
MyAvatar.stopPlaying();
|
||||
}
|
||||
toolBar.cleanup();
|
||||
Overlays.deleteOverlay(timer);
|
||||
toolBar.cleanup();
|
||||
Overlays.deleteOverlay(timer);
|
||||
Overlays.deleteOverlay(slider.background);
|
||||
Overlays.deleteOverlay(slider.foreground);
|
||||
}
|
||||
|
||||
Controller.mousePressEvent.connect(mousePressEvent);
|
||||
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
||||
Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
|
||||
Script.update.connect(update);
|
||||
Script.scriptEnding.connect(scriptEnding);
|
||||
|
||||
|
|
|
@ -1127,8 +1127,6 @@ function keyPressEvent(event) {
|
|||
} else if (event.text == "z") {
|
||||
undoSound.playRandom();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
trackKeyPressEvent(event); // used by preview support
|
||||
|
|
|
@ -17,13 +17,20 @@ const int SPLAT_COUNT = 4;
|
|||
// the splat textures
|
||||
uniform sampler2D diffuseMaps[SPLAT_COUNT];
|
||||
|
||||
// the model space normal
|
||||
varying vec3 normal;
|
||||
|
||||
// alpha values for the four splat textures
|
||||
varying vec4 alphaValues;
|
||||
|
||||
void main(void) {
|
||||
// determine the cube face to use for texture coordinate generation
|
||||
vec3 absNormal = abs(normal);
|
||||
vec2 parameters = step(absNormal.yy, absNormal.xz) * step(absNormal.zx, absNormal.xz);
|
||||
|
||||
// blend the splat textures
|
||||
gl_FragColor = (texture2D(diffuseMaps[0], gl_TexCoord[0].st) * alphaValues.x +
|
||||
texture2D(diffuseMaps[1], gl_TexCoord[1].st) * alphaValues.y +
|
||||
texture2D(diffuseMaps[2], gl_TexCoord[2].st) * alphaValues.z +
|
||||
texture2D(diffuseMaps[3], gl_TexCoord[3].st) * alphaValues.w);
|
||||
gl_FragColor = (texture2D(diffuseMaps[0], mix(gl_TexCoord[0].xw, gl_TexCoord[0].zy, parameters)) * alphaValues.x +
|
||||
texture2D(diffuseMaps[1], mix(gl_TexCoord[1].xw, gl_TexCoord[1].zy, parameters)) * alphaValues.y +
|
||||
texture2D(diffuseMaps[2], mix(gl_TexCoord[2].xw, gl_TexCoord[2].zy, parameters)) * alphaValues.z +
|
||||
texture2D(diffuseMaps[3], mix(gl_TexCoord[3].xw, gl_TexCoord[3].zy, parameters)) * alphaValues.w);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,9 @@ attribute vec4 materials;
|
|||
// the weights of each material
|
||||
attribute vec4 materialWeights;
|
||||
|
||||
// the model space normal
|
||||
varying vec3 normal;
|
||||
|
||||
// alpha values for the four splat textures
|
||||
varying vec4 alphaValues;
|
||||
|
||||
|
@ -36,12 +39,19 @@ void main(void) {
|
|||
// use the fixed-function position
|
||||
gl_Position = ftransform();
|
||||
|
||||
// pass along the normal
|
||||
normal = gl_Normal;
|
||||
|
||||
// pass along the scaled/offset texture coordinates
|
||||
vec4 textureSpacePosition = vec4(gl_Vertex.xz, 0.0, 1.0);
|
||||
gl_TexCoord[0] = textureSpacePosition * vec4(splatTextureScalesS[0], splatTextureScalesT[0], 0.0, 1.0);
|
||||
gl_TexCoord[1] = textureSpacePosition * vec4(splatTextureScalesS[1], splatTextureScalesT[1], 0.0, 1.0);
|
||||
gl_TexCoord[2] = textureSpacePosition * vec4(splatTextureScalesS[2], splatTextureScalesT[2], 0.0, 1.0);
|
||||
gl_TexCoord[3] = textureSpacePosition * vec4(splatTextureScalesS[3], splatTextureScalesT[3], 0.0, 1.0);
|
||||
vec4 textureSpacePosition = gl_Vertex.xyyz;
|
||||
gl_TexCoord[0] = textureSpacePosition * vec4(splatTextureScalesS[0], splatTextureScalesT[0],
|
||||
splatTextureScalesS[0], splatTextureScalesT[0]);
|
||||
gl_TexCoord[1] = textureSpacePosition * vec4(splatTextureScalesS[1], splatTextureScalesT[1],
|
||||
splatTextureScalesS[1], splatTextureScalesT[1]);
|
||||
gl_TexCoord[2] = textureSpacePosition * vec4(splatTextureScalesS[2], splatTextureScalesT[2],
|
||||
splatTextureScalesS[2], splatTextureScalesT[2]);
|
||||
gl_TexCoord[3] = textureSpacePosition * vec4(splatTextureScalesS[3], splatTextureScalesT[3],
|
||||
splatTextureScalesS[3], splatTextureScalesT[3]);
|
||||
|
||||
// compute the alpha values for each texture
|
||||
float value = materials[0];
|
||||
|
|
|
@ -25,7 +25,8 @@ AudioInjector::AudioInjector(QObject* parent) :
|
|||
QObject(parent),
|
||||
_sound(NULL),
|
||||
_options(),
|
||||
_shouldStop(false)
|
||||
_shouldStop(false),
|
||||
_currentSendPosition(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -97,17 +98,15 @@ void AudioInjector::injectAudio() {
|
|||
timer.start();
|
||||
int nextFrame = 0;
|
||||
|
||||
int currentSendPosition = 0;
|
||||
|
||||
int numPreAudioDataBytes = injectAudioPacket.size();
|
||||
bool shouldLoop = _options.getLoop();
|
||||
|
||||
// loop to send off our audio in NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL byte chunks
|
||||
quint16 outgoingInjectedAudioSequenceNumber = 0;
|
||||
while (currentSendPosition < soundByteArray.size() && !_shouldStop) {
|
||||
while (_currentSendPosition < soundByteArray.size() && !_shouldStop) {
|
||||
|
||||
int bytesToCopy = std::min(((_options.isStereo()) ? 2 : 1) * NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL,
|
||||
soundByteArray.size() - currentSendPosition);
|
||||
soundByteArray.size() - _currentSendPosition);
|
||||
memcpy(injectAudioPacket.data() + positionOptionOffset,
|
||||
&_options.getPosition(),
|
||||
sizeof(_options.getPosition()));
|
||||
|
@ -124,7 +123,7 @@ void AudioInjector::injectAudio() {
|
|||
|
||||
// copy the next NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL bytes to the packet
|
||||
memcpy(injectAudioPacket.data() + numPreAudioDataBytes,
|
||||
soundByteArray.data() + currentSendPosition, bytesToCopy);
|
||||
soundByteArray.data() + _currentSendPosition, bytesToCopy);
|
||||
|
||||
// grab our audio mixer from the NodeList, if it exists
|
||||
NodeList* nodeList = NodeList::getInstance();
|
||||
|
@ -134,22 +133,22 @@ void AudioInjector::injectAudio() {
|
|||
nodeList->writeDatagram(injectAudioPacket, audioMixer);
|
||||
outgoingInjectedAudioSequenceNumber++;
|
||||
|
||||
currentSendPosition += bytesToCopy;
|
||||
_currentSendPosition += bytesToCopy;
|
||||
|
||||
// send two packets before the first sleep so the mixer can start playback right away
|
||||
|
||||
if (currentSendPosition != bytesToCopy && currentSendPosition < soundByteArray.size()) {
|
||||
if (_currentSendPosition != bytesToCopy && _currentSendPosition < soundByteArray.size()) {
|
||||
// not the first packet and not done
|
||||
// sleep for the appropriate time
|
||||
int usecToSleep = (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - timer.nsecsElapsed() / 1000;
|
||||
|
||||
if (usecToSleep > 0) {
|
||||
usleep(usecToSleep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldLoop && currentSendPosition == soundByteArray.size()) {
|
||||
currentSendPosition = 0;
|
||||
if (shouldLoop && _currentSendPosition >= soundByteArray.size()) {
|
||||
_currentSendPosition = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,16 +26,20 @@ class AudioInjector : public QObject {
|
|||
public:
|
||||
AudioInjector(QObject* parent);
|
||||
AudioInjector(Sound* sound, const AudioInjectorOptions& injectorOptions);
|
||||
|
||||
int getCurrentSendPosition() const { return _currentSendPosition; }
|
||||
public slots:
|
||||
void injectAudio();
|
||||
void stop() { _shouldStop = true; }
|
||||
void setOptions(AudioInjectorOptions& options);
|
||||
void setCurrentSendPosition(int currentSendPosition) { _currentSendPosition = currentSendPosition; }
|
||||
signals:
|
||||
void finished();
|
||||
private:
|
||||
Sound* _sound;
|
||||
AudioInjectorOptions _options;
|
||||
bool _shouldStop;
|
||||
int _currentSendPosition;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(AudioInjector*)
|
||||
|
|
|
@ -587,18 +587,13 @@ bool AvatarData::hasReferential() {
|
|||
}
|
||||
|
||||
bool AvatarData::isPlaying() {
|
||||
if (!_player) {
|
||||
return false;
|
||||
}
|
||||
if (QThread::currentThread() != thread()) {
|
||||
bool result;
|
||||
QMetaObject::invokeMethod(this, "isPlaying", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(bool, result));
|
||||
return result;
|
||||
}
|
||||
return _player && _player->isPlaying();
|
||||
}
|
||||
|
||||
bool AvatarData::isPaused() {
|
||||
return _player && _player->isPaused();
|
||||
}
|
||||
|
||||
qint64 AvatarData::playerElapsed() {
|
||||
if (!_player) {
|
||||
return 0;
|
||||
|
@ -625,6 +620,14 @@ qint64 AvatarData::playerLength() {
|
|||
return _player->getRecording()->getLength();
|
||||
}
|
||||
|
||||
int AvatarData::playerCurrentFrame() {
|
||||
return (_player) ? _player->getCurrentFrame() : 0;
|
||||
}
|
||||
|
||||
int AvatarData::playerFrameNumber() {
|
||||
return (_player && _player->getRecording()) ? _player->getRecording()->getFrameNumber() : 0;
|
||||
}
|
||||
|
||||
void AvatarData::loadRecording(QString filename) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "loadRecording", Qt::BlockingQueuedConnection,
|
||||
|
@ -649,6 +652,18 @@ void AvatarData::startPlaying() {
|
|||
_player->startPlaying();
|
||||
}
|
||||
|
||||
void AvatarData::setPlayerFrame(int frame) {
|
||||
if (_player) {
|
||||
_player->setCurrentFrame(frame);
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarData::setPlayerTime(qint64 time) {
|
||||
if (_player) {
|
||||
_player->setCurrentTime(time);
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarData::setPlayFromCurrentLocation(bool playFromCurrentLocation) {
|
||||
if (_player) {
|
||||
_player->setPlayFromCurrentLocation(playFromCurrentLocation);
|
||||
|
@ -696,6 +711,19 @@ void AvatarData::play() {
|
|||
}
|
||||
}
|
||||
|
||||
void AvatarData::pausePlayer() {
|
||||
if (!_player) {
|
||||
return;
|
||||
}
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "pausePlayer", Qt::BlockingQueuedConnection);
|
||||
return;
|
||||
}
|
||||
if (_player) {
|
||||
_player->pausePlayer();
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarData::stopPlaying() {
|
||||
if (!_player) {
|
||||
return;
|
||||
|
|
|
@ -296,10 +296,16 @@ public slots:
|
|||
bool hasReferential();
|
||||
|
||||
bool isPlaying();
|
||||
bool isPaused();
|
||||
qint64 playerElapsed();
|
||||
qint64 playerLength();
|
||||
int playerCurrentFrame();
|
||||
int playerFrameNumber();
|
||||
|
||||
void loadRecording(QString filename);
|
||||
void startPlaying();
|
||||
void setPlayerFrame(int frame);
|
||||
void setPlayerTime(qint64 time);
|
||||
void setPlayFromCurrentLocation(bool playFromCurrentLocation);
|
||||
void setPlayerLoop(bool loop);
|
||||
void setPlayerUseDisplayName(bool useDisplayName);
|
||||
|
@ -307,6 +313,7 @@ public slots:
|
|||
void setPlayerUseHeadModel(bool useHeadModel);
|
||||
void setPlayerUseSkeletonModel(bool useSkeletonModel);
|
||||
void play();
|
||||
void pausePlayer();
|
||||
void stopPlaying();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <AudioRingBuffer.h>
|
||||
#include <GLMHelpers.h>
|
||||
#include <NodeList.h>
|
||||
#include <StreamUtils.h>
|
||||
|
@ -18,6 +19,8 @@
|
|||
|
||||
Player::Player(AvatarData* avatar) :
|
||||
_recording(new Recording()),
|
||||
_pausedFrame(-1),
|
||||
_timerOffset(0),
|
||||
_avatar(avatar),
|
||||
_audioThread(NULL),
|
||||
_playFromCurrentPosition(true),
|
||||
|
@ -36,16 +39,26 @@ bool Player::isPlaying() const {
|
|||
return _timer.isValid();
|
||||
}
|
||||
|
||||
bool Player::isPaused() const {
|
||||
return (_pausedFrame != -1);
|
||||
}
|
||||
|
||||
qint64 Player::elapsed() const {
|
||||
if (isPlaying()) {
|
||||
return _timer.elapsed();
|
||||
return _timerOffset + _timer.elapsed();
|
||||
} else if (isPaused()) {
|
||||
return _timerOffset;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Player::startPlaying() {
|
||||
if (_recording && _recording->getFrameNumber() > 0) {
|
||||
if (!_recording || _recording->getFrameNumber() <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isPaused()) {
|
||||
_currentContext.globalTimestamp = usecTimestampNow();
|
||||
_currentContext.domain = NodeList::getInstance()->getDomainHandler().getHostname();
|
||||
_currentContext.position = _avatar->getPosition();
|
||||
|
@ -97,9 +110,17 @@ void Player::startPlaying() {
|
|||
_avatar->setForceFaceshiftConnected(true);
|
||||
|
||||
qDebug() << "Recorder::startPlaying()";
|
||||
setupAudioThread();
|
||||
_currentFrame = 0;
|
||||
_timerOffset = 0;
|
||||
_timer.start();
|
||||
} else {
|
||||
qDebug() << "Recorder::startPlaying(): Unpause";
|
||||
setupAudioThread();
|
||||
_timer.start();
|
||||
|
||||
setCurrentFrame(_pausedFrame);
|
||||
_pausedFrame = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,6 +128,7 @@ void Player::stopPlaying() {
|
|||
if (!isPlaying()) {
|
||||
return;
|
||||
}
|
||||
_pausedFrame = -1;
|
||||
_timer.invalidate();
|
||||
cleanupAudioThread();
|
||||
_avatar->clearJointsData();
|
||||
|
@ -130,6 +152,15 @@ void Player::stopPlaying() {
|
|||
qDebug() << "Recorder::stopPlaying()";
|
||||
}
|
||||
|
||||
void Player::pausePlayer() {
|
||||
_timerOffset = elapsed();
|
||||
_timer.invalidate();
|
||||
cleanupAudioThread();
|
||||
|
||||
_pausedFrame = _currentFrame;
|
||||
qDebug() << "Recorder::pausePlayer()";
|
||||
}
|
||||
|
||||
void Player::setupAudioThread() {
|
||||
_audioThread = new QThread();
|
||||
_options.setPosition(_avatar->getPosition());
|
||||
|
@ -156,6 +187,7 @@ void Player::loopRecording() {
|
|||
cleanupAudioThread();
|
||||
setupAudioThread();
|
||||
_currentFrame = 0;
|
||||
_timerOffset = 0;
|
||||
_timer.restart();
|
||||
}
|
||||
|
||||
|
@ -166,10 +198,13 @@ void Player::loadFromFile(const QString& file) {
|
|||
_recording = RecordingPointer(new Recording());
|
||||
}
|
||||
readRecordingFromFile(_recording, file);
|
||||
|
||||
_pausedFrame = -1;
|
||||
}
|
||||
|
||||
void Player::loadRecording(RecordingPointer recording) {
|
||||
_recording = recording;
|
||||
_pausedFrame = -1;
|
||||
}
|
||||
|
||||
void Player::play() {
|
||||
|
@ -213,6 +248,77 @@ void Player::play() {
|
|||
_injector->setOptions(_options);
|
||||
}
|
||||
|
||||
void Player::setCurrentFrame(int currentFrame) {
|
||||
if (_recording && (currentFrame < 0 || currentFrame >= _recording->getFrameNumber())) {
|
||||
stopPlaying();
|
||||
return;
|
||||
}
|
||||
|
||||
_currentFrame = currentFrame;
|
||||
_timerOffset = _recording->getFrameTimestamp(_currentFrame);
|
||||
|
||||
if (isPlaying()) {
|
||||
_timer.start();
|
||||
setAudionInjectorPosition();
|
||||
} else {
|
||||
_pausedFrame = currentFrame;
|
||||
}
|
||||
}
|
||||
|
||||
void Player::setCurrentTime(qint64 currentTime) {
|
||||
if (currentTime < 0 || currentTime >= _recording->getLength()) {
|
||||
stopPlaying();
|
||||
return;
|
||||
}
|
||||
|
||||
// Find correct frame
|
||||
int lowestBound = 0;
|
||||
int highestBound = _recording->getFrameNumber() - 1;
|
||||
while (lowestBound + 1 != highestBound) {
|
||||
assert(lowestBound < highestBound);
|
||||
|
||||
int bestGuess = lowestBound +
|
||||
(highestBound - lowestBound) *
|
||||
(float)(currentTime - _recording->getFrameTimestamp(lowestBound)) /
|
||||
(float)(_recording->getFrameTimestamp(highestBound) - _recording->getFrameTimestamp(lowestBound));
|
||||
|
||||
if (_recording->getFrameTimestamp(bestGuess) <= currentTime) {
|
||||
if (currentTime < _recording->getFrameTimestamp(bestGuess + 1)) {
|
||||
lowestBound = bestGuess;
|
||||
highestBound = bestGuess + 1;
|
||||
} else {
|
||||
lowestBound = bestGuess + 1;
|
||||
}
|
||||
} else {
|
||||
if (_recording->getFrameTimestamp(bestGuess - 1) <= currentTime) {
|
||||
lowestBound = bestGuess - 1;
|
||||
highestBound = bestGuess;
|
||||
} else {
|
||||
highestBound = bestGuess - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_currentFrame = lowestBound;
|
||||
_timerOffset = _recording->getFrameTimestamp(lowestBound);
|
||||
|
||||
if (isPlaying()) {
|
||||
_timer.start();
|
||||
setAudionInjectorPosition();
|
||||
} else {
|
||||
_pausedFrame = lowestBound;
|
||||
}
|
||||
}
|
||||
|
||||
void Player::setAudionInjectorPosition() {
|
||||
int MSEC_PER_SEC = 1000;
|
||||
int SAMPLE_SIZE = 2; // 16 bits
|
||||
int CHANNEL_COUNT = 1;
|
||||
int FRAME_SIZE = SAMPLE_SIZE * CHANNEL_COUNT;
|
||||
int currentAudioFrame = elapsed() * FRAME_SIZE * (SAMPLE_RATE / MSEC_PER_SEC);
|
||||
_injector->setCurrentSendPosition(currentAudioFrame);
|
||||
}
|
||||
|
||||
void Player::setPlayFromCurrentLocation(bool playFromCurrentLocation) {
|
||||
_playFromCurrentPosition = playFromCurrentLocation;
|
||||
}
|
||||
|
@ -227,7 +333,7 @@ bool Player::computeCurrentFrame() {
|
|||
}
|
||||
|
||||
while (_currentFrame < _recording->getFrameNumber() - 1 &&
|
||||
_recording->getFrameTimestamp(_currentFrame) < _timer.elapsed()) {
|
||||
_recording->getFrameTimestamp(_currentFrame) < elapsed()) {
|
||||
++_currentFrame;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,17 +30,23 @@ public:
|
|||
Player(AvatarData* avatar);
|
||||
|
||||
bool isPlaying() const;
|
||||
bool isPaused() const;
|
||||
qint64 elapsed() const;
|
||||
|
||||
RecordingPointer getRecording() const { return _recording; }
|
||||
int getCurrentFrame() const { return _currentFrame; }
|
||||
|
||||
public slots:
|
||||
void startPlaying();
|
||||
void stopPlaying();
|
||||
void pausePlayer();
|
||||
void loadFromFile(const QString& file);
|
||||
void loadRecording(RecordingPointer recording);
|
||||
void play();
|
||||
|
||||
void setCurrentFrame(int currentFrame);
|
||||
void setCurrentTime(qint64 currentTime);
|
||||
|
||||
void setPlayFromCurrentLocation(bool playFromCurrentPosition);
|
||||
void setLoop(bool loop) { _loop = loop; }
|
||||
void useAttachements(bool useAttachments) { _useAttachments = useAttachments; }
|
||||
|
@ -52,11 +58,14 @@ private:
|
|||
void setupAudioThread();
|
||||
void cleanupAudioThread();
|
||||
void loopRecording();
|
||||
void setAudionInjectorPosition();
|
||||
bool computeCurrentFrame();
|
||||
|
||||
QElapsedTimer _timer;
|
||||
RecordingPointer _recording;
|
||||
int _currentFrame;
|
||||
int _pausedFrame;
|
||||
qint64 _timerOffset;
|
||||
|
||||
QSharedPointer<AudioInjector> _injector;
|
||||
AudioInjectorOptions _options;
|
||||
|
@ -64,7 +73,6 @@ private:
|
|||
AvatarData* _avatar;
|
||||
QThread* _audioThread;
|
||||
|
||||
|
||||
RecordingContext _currentContext;
|
||||
bool _playFromCurrentPosition;
|
||||
bool _loop;
|
||||
|
@ -72,7 +80,6 @@ private:
|
|||
bool _useDisplayName;
|
||||
bool _useHeadURL;
|
||||
bool _useSkeletonURL;
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_Player_h
|
|
@ -9,6 +9,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <AudioRingBuffer.h>
|
||||
#include <GLMHelpers.h>
|
||||
#include <NetworkAccessManager.h>
|
||||
#include <NodeList.h>
|
||||
|
@ -60,6 +61,9 @@ qint32 Recording::getFrameTimestamp(int i) const {
|
|||
if (i >= _timestamps.size()) {
|
||||
return getLength();
|
||||
}
|
||||
if (i < 0) {
|
||||
return 0;
|
||||
}
|
||||
return _timestamps[i];
|
||||
}
|
||||
|
||||
|
@ -781,7 +785,6 @@ RecordingPointer readRecordingFromRecFile(RecordingPointer recording, const QStr
|
|||
fileStream >> audioArray;
|
||||
|
||||
// Cut down audio if necessary
|
||||
int SAMPLE_RATE = 48000; // 48 kHz
|
||||
int SAMPLE_SIZE = 2; // 16 bits
|
||||
int MSEC_PER_SEC = 1000;
|
||||
int audioLength = recording->getLength() * SAMPLE_SIZE * (SAMPLE_RATE / MSEC_PER_SEC);
|
||||
|
|
|
@ -667,8 +667,9 @@ int VoxelMaterialBoxEditVisitor::visit(MetavoxelInfo& info) {
|
|||
return DEFAULT_ORDER;
|
||||
}
|
||||
VoxelColorDataPointer colorPointer = info.inputValues.at(0).getInlineValue<VoxelColorDataPointer>();
|
||||
QVector<QRgb> colorContents = (colorPointer && colorPointer->getSize() == VOXEL_BLOCK_SAMPLES) ?
|
||||
QVector<QRgb> oldColorContents = (colorPointer && colorPointer->getSize() == VOXEL_BLOCK_SAMPLES) ?
|
||||
colorPointer->getContents() : QVector<QRgb>(VOXEL_BLOCK_VOLUME);
|
||||
QVector<QRgb> colorContents = oldColorContents;
|
||||
|
||||
Box overlap = info.getBounds().getIntersection(_region);
|
||||
float scale = VOXEL_BLOCK_SIZE / info.size;
|
||||
|
@ -725,32 +726,92 @@ int VoxelMaterialBoxEditVisitor::visit(MetavoxelInfo& info) {
|
|||
for (int x = hermiteMinX, hermiteMaxX = x + hermiteSizeX - 1; x <= hermiteMaxX; x++,
|
||||
hermiteDestX += VoxelHermiteData::EDGE_COUNT) {
|
||||
// internal edges are set to zero; border edges (when non-terminal) are set to the intersection values
|
||||
hermiteDestX[0] = 0x0;
|
||||
if ((x == hermiteMinX || x == hermiteMaxX) && x != VOXEL_BLOCK_SIZE) {
|
||||
const QRgb* color = colorContents.constData() + z * VOXEL_BLOCK_AREA + y * VOXEL_BLOCK_SAMPLES + x;
|
||||
int offset = z * VOXEL_BLOCK_AREA + y * VOXEL_BLOCK_SAMPLES + x;
|
||||
const QRgb* color = colorContents.constData() + offset;
|
||||
int alpha0 = qAlpha(color[0]);
|
||||
if (alpha0 != qAlpha(color[1])) {
|
||||
hermiteDestX[0] = qRgba(alpha0 == 0 ? -NORMAL_MAX : NORMAL_MAX, 0, 0,
|
||||
((x == hermiteMinX ? overlap.minimum.x : overlap.maximum.x) - x) * EIGHT_BIT_MAXIMUM);
|
||||
int alpha1 = qAlpha(color[1]);
|
||||
if (alpha0 != alpha1) {
|
||||
const QRgb* oldColor = oldColorContents.constData() + offset;
|
||||
if (qAlpha(oldColor[0]) == alpha0 && qAlpha(oldColor[1]) == alpha1) {
|
||||
if (x == hermiteMinX) {
|
||||
int alpha = (overlap.minimum.x - x) * EIGHT_BIT_MAXIMUM;
|
||||
if (alpha <= qAlpha(hermiteDestX[0])) {
|
||||
hermiteDestX[0] = qRgba(alpha0 == 0 ? -NORMAL_MAX : NORMAL_MAX, 0, 0, alpha);
|
||||
}
|
||||
} else {
|
||||
int alpha = (overlap.maximum.x - x) * EIGHT_BIT_MAXIMUM;
|
||||
if (alpha >= qAlpha(hermiteDestX[0])) {
|
||||
hermiteDestX[0] = qRgba(alpha0 == 0 ? -NORMAL_MAX : NORMAL_MAX, 0, 0, alpha);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
hermiteDestX[0] = qRgba(alpha0 == 0 ? -NORMAL_MAX : NORMAL_MAX, 0, 0,
|
||||
((x == hermiteMinX ? overlap.minimum.x : overlap.maximum.x) - x) * EIGHT_BIT_MAXIMUM);
|
||||
}
|
||||
} else {
|
||||
hermiteDestX[0] = 0x0;
|
||||
}
|
||||
} else {
|
||||
hermiteDestX[0] = 0x0;
|
||||
}
|
||||
hermiteDestX[1] = 0x0;
|
||||
if ((y == hermiteMinY || y == hermiteMaxY) && y != VOXEL_BLOCK_SIZE) {
|
||||
const QRgb* color = colorContents.constData() + z * VOXEL_BLOCK_AREA + y * VOXEL_BLOCK_SAMPLES + x;
|
||||
int offset = z * VOXEL_BLOCK_AREA + y * VOXEL_BLOCK_SAMPLES + x;
|
||||
const QRgb* color = colorContents.constData() + offset;
|
||||
int alpha0 = qAlpha(color[0]);
|
||||
if (alpha0 != qAlpha(color[VOXEL_BLOCK_SAMPLES])) {
|
||||
hermiteDestX[1] = qRgba(0, alpha0 == 0 ? -NORMAL_MAX : NORMAL_MAX, 0,
|
||||
((y == hermiteMinY ? overlap.minimum.y : overlap.maximum.y) - y) * EIGHT_BIT_MAXIMUM);
|
||||
int alpha2 = qAlpha(color[VOXEL_BLOCK_SAMPLES]);
|
||||
if (alpha0 != alpha2) {
|
||||
const QRgb* oldColor = oldColorContents.constData() + offset;
|
||||
if (qAlpha(oldColor[0]) == alpha0 && qAlpha(oldColor[VOXEL_BLOCK_SAMPLES]) == alpha2) {
|
||||
if (y == hermiteMinY) {
|
||||
int alpha = (overlap.minimum.y - y) * EIGHT_BIT_MAXIMUM;
|
||||
if (alpha <= qAlpha(hermiteDestX[1])) {
|
||||
hermiteDestX[1] = qRgba(0, alpha0 == 0 ? -NORMAL_MAX : NORMAL_MAX, 0, alpha);
|
||||
}
|
||||
} else {
|
||||
int alpha = (overlap.maximum.y - y) * EIGHT_BIT_MAXIMUM;
|
||||
if (alpha >= qAlpha(hermiteDestX[1])) {
|
||||
hermiteDestX[1] = qRgba(0, alpha0 == 0 ? -NORMAL_MAX : NORMAL_MAX, 0, alpha);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
hermiteDestX[1] = qRgba(0, alpha0 == 0 ? -NORMAL_MAX : NORMAL_MAX, 0,
|
||||
((y == hermiteMinY ? overlap.minimum.y : overlap.maximum.y) - y) * EIGHT_BIT_MAXIMUM);
|
||||
}
|
||||
} else {
|
||||
hermiteDestX[1] = 0x0;
|
||||
}
|
||||
} else {
|
||||
hermiteDestX[1] = 0x0;
|
||||
}
|
||||
hermiteDestX[2] = 0x0;
|
||||
if ((z == hermiteMinZ || z == hermiteMaxZ) && z != VOXEL_BLOCK_SIZE) {
|
||||
const QRgb* color = colorContents.constData() + z * VOXEL_BLOCK_AREA + y * VOXEL_BLOCK_SAMPLES + x;
|
||||
int offset = z * VOXEL_BLOCK_AREA + y * VOXEL_BLOCK_SAMPLES + x;
|
||||
const QRgb* color = colorContents.constData() + offset;
|
||||
int alpha0 = qAlpha(color[0]);
|
||||
if (alpha0 != qAlpha(color[VOXEL_BLOCK_AREA])) {
|
||||
hermiteDestX[2] = qRgba(0, 0, alpha0 == 0 ? -NORMAL_MAX : NORMAL_MAX,
|
||||
((z == hermiteMinZ ? overlap.minimum.z : overlap.maximum.z) - z) * EIGHT_BIT_MAXIMUM);
|
||||
int alpha4 = qAlpha(color[VOXEL_BLOCK_AREA]);
|
||||
if (alpha0 != alpha4) {
|
||||
const QRgb* oldColor = oldColorContents.constData() + offset;
|
||||
if (qAlpha(oldColor[0]) == alpha0 && qAlpha(oldColor[VOXEL_BLOCK_AREA]) == alpha4) {
|
||||
if (z == hermiteMinZ) {
|
||||
int alpha = (overlap.minimum.z - z) * EIGHT_BIT_MAXIMUM;
|
||||
if (alpha <= qAlpha(hermiteDestX[2])) {
|
||||
hermiteDestX[2] = qRgba(0, 0, alpha0 == 0 ? -NORMAL_MAX : NORMAL_MAX, alpha);
|
||||
}
|
||||
} else {
|
||||
int alpha = (overlap.maximum.z - z) * EIGHT_BIT_MAXIMUM;
|
||||
if (alpha >= qAlpha(hermiteDestX[2])) {
|
||||
hermiteDestX[2] = qRgba(0, 0, alpha0 == 0 ? -NORMAL_MAX : NORMAL_MAX, alpha);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
hermiteDestX[2] = qRgba(0, 0, alpha0 == 0 ? -NORMAL_MAX : NORMAL_MAX,
|
||||
((z == hermiteMinZ ? overlap.minimum.z : overlap.maximum.z) - z) * EIGHT_BIT_MAXIMUM);
|
||||
}
|
||||
} else {
|
||||
hermiteDestX[2] = 0x0;
|
||||
}
|
||||
} else {
|
||||
hermiteDestX[2] = 0x0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -864,8 +925,9 @@ int VoxelMaterialSphereEditVisitor::visit(MetavoxelInfo& info) {
|
|||
return DEFAULT_ORDER;
|
||||
}
|
||||
VoxelColorDataPointer colorPointer = info.inputValues.at(0).getInlineValue<VoxelColorDataPointer>();
|
||||
QVector<QRgb> colorContents = (colorPointer && colorPointer->getSize() == VOXEL_BLOCK_SAMPLES) ?
|
||||
QVector<QRgb> oldColorContents = (colorPointer && colorPointer->getSize() == VOXEL_BLOCK_SAMPLES) ?
|
||||
colorPointer->getContents() : QVector<QRgb>(VOXEL_BLOCK_VOLUME);
|
||||
QVector<QRgb> colorContents = oldColorContents;
|
||||
|
||||
Box overlap = info.getBounds().getIntersection(_bounds);
|
||||
float scale = VOXEL_BLOCK_SIZE / info.size;
|
||||
|
@ -883,6 +945,7 @@ int VoxelMaterialSphereEditVisitor::visit(MetavoxelInfo& info) {
|
|||
float relativeRadiusSquared = relativeRadius * relativeRadius;
|
||||
|
||||
QRgb rgb = _color.rgba();
|
||||
bool flipped = (qAlpha(rgb) == 0);
|
||||
glm::vec3 position(0.0f, 0.0f, minZ);
|
||||
for (QRgb* destZ = colorContents.data() + minZ * VOXEL_BLOCK_AREA + minY * VOXEL_BLOCK_SAMPLES + minX,
|
||||
*endZ = destZ + sizeZ * VOXEL_BLOCK_AREA; destZ != endZ; destZ += VOXEL_BLOCK_AREA, position.z++) {
|
||||
|
@ -932,78 +995,117 @@ int VoxelMaterialSphereEditVisitor::visit(MetavoxelInfo& info) {
|
|||
hermiteDestX += VoxelHermiteData::EDGE_COUNT) {
|
||||
// at each intersected non-terminal edge, we check for a transition and, if one is detected, we assign the
|
||||
// crossing and normal values based on intersection with the sphere
|
||||
hermiteDestX[0] = 0x0;
|
||||
glm::vec3 offset(x - relativeCenter.x, y - relativeCenter.y, z - relativeCenter.z);
|
||||
glm::vec3 vector(x - relativeCenter.x, y - relativeCenter.y, z - relativeCenter.z);
|
||||
if (x != VOXEL_BLOCK_SIZE) {
|
||||
const QRgb* color = colorContents.constData() + z * VOXEL_BLOCK_AREA + y * VOXEL_BLOCK_SAMPLES + x;
|
||||
int offset = z * VOXEL_BLOCK_AREA + y * VOXEL_BLOCK_SAMPLES + x;
|
||||
const QRgb* color = colorContents.constData() + offset;
|
||||
int alpha0 = qAlpha(color[0]);
|
||||
if (alpha0 != qAlpha(color[1])) {
|
||||
float radicand = relativeRadiusSquared - offset.y * offset.y - offset.z * offset.z;
|
||||
int alpha1 = qAlpha(color[1]);
|
||||
if (alpha0 != alpha1) {
|
||||
float radicand = relativeRadiusSquared - vector.y * vector.y - vector.z * vector.z;
|
||||
float parameter = 0.5f;
|
||||
if (radicand >= 0.0f) {
|
||||
float root = glm::sqrt(radicand);
|
||||
parameter = -offset.x - root;
|
||||
parameter = -vector.x - root;
|
||||
if (parameter < 0.0f || parameter > 1.0f) {
|
||||
parameter = glm::clamp(-offset.x + root, 0.0f, 1.0f);
|
||||
parameter = glm::clamp(-vector.x + root, 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
glm::vec3 normal = offset + glm::vec3(parameter, 0.0f, 0.0f);
|
||||
glm::vec3 normal = vector + glm::vec3(parameter, 0.0f, 0.0f);
|
||||
float length = glm::length(normal);
|
||||
if (length > EPSILON) {
|
||||
normal /= length;
|
||||
} else {
|
||||
normal = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||
}
|
||||
hermiteDestX[0] = packNormal(normal, parameter * EIGHT_BIT_MAXIMUM);
|
||||
const QRgb* oldColor = oldColorContents.constData() + offset;
|
||||
if (qAlpha(oldColor[0]) == alpha0 && qAlpha(oldColor[1]) == alpha1) {
|
||||
int alpha = parameter * EIGHT_BIT_MAXIMUM;
|
||||
if (normal.x < 0.0f ? alpha <= qAlpha(hermiteDestX[0]) : alpha >= qAlpha(hermiteDestX[0])) {
|
||||
hermiteDestX[0] = packNormal(flipped ? -normal : normal, alpha);
|
||||
}
|
||||
} else {
|
||||
hermiteDestX[0] = packNormal(flipped ? -normal : normal, parameter * EIGHT_BIT_MAXIMUM);
|
||||
}
|
||||
} else {
|
||||
hermiteDestX[0] = 0x0;
|
||||
}
|
||||
} else {
|
||||
hermiteDestX[0] = 0x0;
|
||||
}
|
||||
hermiteDestX[1] = 0x0;
|
||||
if (y != VOXEL_BLOCK_SIZE) {
|
||||
const QRgb* color = colorContents.constData() + z * VOXEL_BLOCK_AREA + y * VOXEL_BLOCK_SAMPLES + x;
|
||||
int offset = z * VOXEL_BLOCK_AREA + y * VOXEL_BLOCK_SAMPLES + x;
|
||||
const QRgb* color = colorContents.constData() + offset;
|
||||
int alpha0 = qAlpha(color[0]);
|
||||
if (alpha0 != qAlpha(color[VOXEL_BLOCK_SAMPLES])) {
|
||||
float radicand = relativeRadiusSquared - offset.x * offset.x - offset.z * offset.z;
|
||||
int alpha2 = qAlpha(color[VOXEL_BLOCK_SAMPLES]);
|
||||
if (alpha0 != alpha2) {
|
||||
float radicand = relativeRadiusSquared - vector.x * vector.x - vector.z * vector.z;
|
||||
float parameter = 0.5f;
|
||||
if (radicand >= 0.0f) {
|
||||
float root = glm::sqrt(radicand);
|
||||
parameter = -offset.y - root;
|
||||
parameter = -vector.y - root;
|
||||
if (parameter < 0.0f || parameter > 1.0f) {
|
||||
parameter = glm::clamp(-offset.y + root, 0.0f, 1.0f);
|
||||
parameter = glm::clamp(-vector.y + root, 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
glm::vec3 normal = offset + glm::vec3(parameter, 0.0f, 0.0f);
|
||||
glm::vec3 normal = vector + glm::vec3(parameter, 0.0f, 0.0f);
|
||||
float length = glm::length(normal);
|
||||
if (length > EPSILON) {
|
||||
normal /= length;
|
||||
} else {
|
||||
normal = glm::vec3(1.0f, 0.0f, 0.0f);
|
||||
}
|
||||
hermiteDestX[1] = packNormal(normal, parameter * EIGHT_BIT_MAXIMUM);
|
||||
const QRgb* oldColor = oldColorContents.constData() + offset;
|
||||
if (qAlpha(oldColor[0]) == alpha0 && qAlpha(oldColor[VOXEL_BLOCK_SAMPLES]) == alpha2) {
|
||||
int alpha = parameter * EIGHT_BIT_MAXIMUM;
|
||||
if (normal.y < 0.0f ? alpha <= qAlpha(hermiteDestX[1]) : alpha >= qAlpha(hermiteDestX[1])) {
|
||||
hermiteDestX[1] = packNormal(flipped ? -normal : normal, alpha);
|
||||
}
|
||||
} else {
|
||||
hermiteDestX[1] = packNormal(flipped ? -normal : normal, parameter * EIGHT_BIT_MAXIMUM);
|
||||
}
|
||||
} else {
|
||||
hermiteDestX[1] = 0x0;
|
||||
}
|
||||
} else {
|
||||
hermiteDestX[1] = 0x0;
|
||||
}
|
||||
hermiteDestX[2] = 0x0;
|
||||
if (z != VOXEL_BLOCK_SIZE) {
|
||||
const QRgb* color = colorContents.constData() + z * VOXEL_BLOCK_AREA + y * VOXEL_BLOCK_SAMPLES + x;
|
||||
int offset = z * VOXEL_BLOCK_AREA + y * VOXEL_BLOCK_SAMPLES + x;
|
||||
const QRgb* color = colorContents.constData() + offset;
|
||||
int alpha0 = qAlpha(color[0]);
|
||||
if (alpha0 != qAlpha(color[VOXEL_BLOCK_AREA])) {
|
||||
float radicand = relativeRadiusSquared - offset.x * offset.x - offset.y * offset.y;
|
||||
int alpha4 = qAlpha(color[VOXEL_BLOCK_AREA]);
|
||||
if (alpha0 != alpha4) {
|
||||
float radicand = relativeRadiusSquared - vector.x * vector.x - vector.y * vector.y;
|
||||
float parameter = 0.5f;
|
||||
if (radicand >= 0.0f) {
|
||||
float root = glm::sqrt(radicand);
|
||||
parameter = -offset.z - root;
|
||||
parameter = -vector.z - root;
|
||||
if (parameter < 0.0f || parameter > 1.0f) {
|
||||
parameter = glm::clamp(-offset.z + root, 0.0f, 1.0f);
|
||||
parameter = glm::clamp(-vector.z + root, 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
glm::vec3 normal = offset + glm::vec3(parameter, 0.0f, 0.0f);
|
||||
glm::vec3 normal = vector + glm::vec3(parameter, 0.0f, 0.0f);
|
||||
float length = glm::length(normal);
|
||||
if (length > EPSILON) {
|
||||
normal /= length;
|
||||
} else {
|
||||
normal = glm::vec3(1.0f, 0.0f, 0.0f);
|
||||
}
|
||||
hermiteDestX[2] = packNormal(normal, parameter * EIGHT_BIT_MAXIMUM);
|
||||
const QRgb* oldColor = oldColorContents.constData() + offset;
|
||||
if (qAlpha(oldColor[0]) == alpha0 && qAlpha(oldColor[VOXEL_BLOCK_AREA]) == alpha4) {
|
||||
int alpha = parameter * EIGHT_BIT_MAXIMUM;
|
||||
if (normal.z < 0.0f ? alpha <= qAlpha(hermiteDestX[2]) : alpha >= qAlpha(hermiteDestX[2])) {
|
||||
hermiteDestX[2] = packNormal(flipped ? -normal : normal, alpha);
|
||||
}
|
||||
} else {
|
||||
hermiteDestX[2] = packNormal(flipped ? -normal : normal, parameter * EIGHT_BIT_MAXIMUM);
|
||||
}
|
||||
} else {
|
||||
hermiteDestX[2] = 0x0;
|
||||
}
|
||||
} else {
|
||||
hermiteDestX[2] = 0x0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue