New camera model; Cleanup; Bashing head :against desk

This commit is contained in:
Zach Fox 2017-06-08 14:36:38 -07:00
parent 3884287c41
commit fd50434d86
5 changed files with 113 additions and 72 deletions

View file

@ -1,8 +1,20 @@
//
// SecondaryCamera.cpp
// interface/src
//
// Created by Samuel Gateau, Howard Stearns, and Zach Fox on 2017-06-08.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "SecondaryCamera.h"
#include <TextureCache.h>
#include <gpu/Context.h>
using RenderArgsPointer = std::shared_ptr<RenderArgs>;
void MainRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred) {
task.addJob<RenderShadowTask>("RenderShadowTask", cullFunctor);
@ -15,19 +27,18 @@ void MainRenderTask::build(JobModel& task, const render::Varying& inputs, render
}
}
#include <TextureCache.h>
using RenderArgsPointer = std::shared_ptr<RenderArgs>;
void SecondaryCameraRenderTaskConfig::resetSize(int width, int height) { // Carefully adjust the framebuffer / texture.
void SecondaryCameraRenderTaskConfig::resetSize(int width, int height) { // FIXME: Add an arg here for "destinationFramebuffer"
bool wasEnabled = isEnabled();
setEnabled(false);
auto textureCache = DependencyManager::get<TextureCache>();
textureCache->resetSpectatorCameraFramebuffer(width, height);
textureCache->resetSpectatorCameraFramebuffer(width, height); // FIXME: Call the correct reset function based on the "destinationFramebuffer" arg
setEnabled(wasEnabled);
}
void SecondaryCameraRenderTaskConfig::resetSizeSpectatorCamera(int width, int height) { // Carefully adjust the framebuffer / texture.
resetSize(width, height);
}
class BeginSecondaryCameraFrame { // Changes renderContext for our framebuffer and and view.
glm::vec3 _position{};
glm::quat _orientation{};
@ -39,36 +50,36 @@ public:
}
void configure(const Config& config) {
// Why does this run all the time, even when not enabled? Should we check and bail?
//qDebug() << "FIXME pos" << config.position << "orient" << config.orientation;
_position = config.position;
_orientation = config.orientation;
if (config.enabled || config.alwaysEnabled) {
_position = config.position;
_orientation = config.orientation;
}
}
void run(const render::RenderContextPointer& renderContext, RenderArgsPointer& cachedArgs) {
auto args = renderContext->args;
auto textureCache = DependencyManager::get<TextureCache>();
auto destFramebuffer = textureCache->getSpectatorCameraFramebuffer();
// Caching/restoring the old values doesn't seem to be needed. Is it because we happen to be last in the pipeline (which would be a bug waiting to happen)?
_cachedArgsPointer->_blitFramebuffer = args->_blitFramebuffer;
_cachedArgsPointer->_viewport = args->_viewport;
_cachedArgsPointer->_displayMode = args->_displayMode;
args->_blitFramebuffer = destFramebuffer;
args->_viewport = glm::ivec4(0, 0, destFramebuffer->getWidth(), destFramebuffer->getHeight());
args->_viewport = glm::ivec4(0, 0, destFramebuffer->getWidth(), destFramebuffer->getHeight());
args->_displayMode = RenderArgs::MONO;
gpu::FramebufferPointer destFramebuffer;
destFramebuffer = textureCache->getSpectatorCameraFramebuffer(); // FIXME: Change the destination based on some unimplemented config var
if (destFramebuffer) {
// Caching/restoring the old values doesn't seem to be needed. Is it because we happen to be last in the pipeline (which would be a bug waiting to happen)?
_cachedArgsPointer->_blitFramebuffer = args->_blitFramebuffer;
_cachedArgsPointer->_viewport = args->_viewport;
_cachedArgsPointer->_displayMode = args->_displayMode;
args->_blitFramebuffer = destFramebuffer;
args->_viewport = glm::ivec4(0, 0, destFramebuffer->getWidth(), destFramebuffer->getHeight());
args->_displayMode = RenderArgs::MONO;
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
batch.disableContextStereo();
});
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
batch.disableContextStereo();
});
auto srcViewFrustum = args->getViewFrustum();
srcViewFrustum.setPosition(_position);
srcViewFrustum.setOrientation(_orientation);
//srcViewFrustum.calculate(); // do we need this? I don't think so
//qDebug() << "FIXME pos" << _position << "orient" << _orientation << "frust pos" << srcViewFrustum.getPosition() << "orient" << srcViewFrustum.getOrientation() << "direct" << srcViewFrustum.getDirection();
args->pushViewFrustum(srcViewFrustum);
cachedArgs = _cachedArgsPointer;
auto srcViewFrustum = args->getViewFrustum();
srcViewFrustum.setPosition(_position);
srcViewFrustum.setOrientation(_orientation);
args->pushViewFrustum(srcViewFrustum);
cachedArgs = _cachedArgsPointer;
}
}
protected:

View file

@ -1,3 +1,14 @@
//
// SecondaryCamera.h
// interface/src
//
// Created by Samuel Gateau, Howard Stearns, and Zach Fox on 2017-06-08.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#pragma once
#ifndef hifi_SecondaryCamera_h
#define hifi_SecondaryCamera_h
@ -34,10 +45,12 @@ class SecondaryCameraRenderTaskConfig : public render::Task::Config {
Q_OBJECT
public:
SecondaryCameraRenderTaskConfig() : render::Task::Config(false) {}
private:
void resetSize(int width, int height);
signals:
void dirty();
public slots:
void resetSize(int width, int height);
void resetSizeSpectatorCamera(int width, int height);
};
class SecondaryCameraRenderTask {

View file

@ -50,7 +50,8 @@ Q_LOGGING_CATEGORY(trace_resource_parse_image_ktx, "trace.resource.parse.image.k
const std::string TextureCache::KTX_DIRNAME { "ktx_cache" };
const std::string TextureCache::KTX_EXT { "ktx" };
const std::string TextureCache::SPECTATOR_CAMERA_FRAME_URL { "resource://spectatorCameraFrame" };
static const QString RESOURCE_SCHEME = "resource";
static const QUrl SPECTATOR_CAMERA_FRAME_URL("resource://spectatorCameraFrame");
static const float SKYBOX_LOAD_PRIORITY { 10.0f }; // Make sure skybox loads first
static const float HIGH_MIPS_LOAD_PRIORITY { 9.0f }; // Make sure high mips loads after skybox but before models
@ -182,9 +183,8 @@ ScriptableResource* TextureCache::prefetch(const QUrl& url, int type, int maxNum
}
NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels) {
if (url == QUrl(SPECTATOR_CAMERA_FRAME_URL.c_str())) {
return getSpectatorCameraNetworkTexture();
if (url.scheme() == RESOURCE_SCHEME) {
return getResourceTexture(url);
}
TextureExtra extra = { type, content, maxNumPixels };
return ResourceCache::getResource(url, QUrl(), &extra).staticCast<NetworkTexture>();
@ -885,31 +885,30 @@ void ImageReader::read() {
}
NetworkTexturePointer TextureCache::getSpectatorCameraNetworkTexture() {
if (!_spectatorCameraNetworkTexture) {
_spectatorCameraNetworkTexture.reset(new NetworkTexture(QUrl(SPECTATOR_CAMERA_FRAME_URL.c_str())));
auto texture = getSpectatorCameraTexture();
_spectatorCameraNetworkTexture->setImage(texture, texture->getWidth(), texture->getHeight());
NetworkTexturePointer TextureCache::getResourceTexture(QUrl resourceTextureUrl) {
gpu::TexturePointer texture;
if (resourceTextureUrl == SPECTATOR_CAMERA_FRAME_URL) {
if (!_spectatorCameraNetworkTexture) {
_spectatorCameraNetworkTexture.reset(new NetworkTexture(resourceTextureUrl));
}
texture = _spectatorCameraFramebuffer->getRenderBuffer(0);
if (texture) {
_spectatorCameraNetworkTexture->setImage(texture, texture->getWidth(), texture->getHeight());
return _spectatorCameraNetworkTexture;
}
}
return _spectatorCameraNetworkTexture;
}
const gpu::TexturePointer& TextureCache::getSpectatorCameraTexture() {
if (!_spectatorCameraTexture) {
getSpectatorCameraFramebuffer();
}
return _spectatorCameraTexture;
return NetworkTexturePointer();
}
const gpu::FramebufferPointer& TextureCache::getSpectatorCameraFramebuffer() {
if (!_spectatorCameraFramebuffer) {
resetSpectatorCameraFramebuffer(2048, 1024);
}
return _spectatorCameraFramebuffer;
}
void TextureCache::resetSpectatorCameraFramebuffer(int width, int height) {
_spectatorCameraFramebuffer.reset(gpu::Framebuffer::create("spectatorCamera", gpu::Element::COLOR_SRGBA_32, 2048, 1024));
_spectatorCameraTexture = _spectatorCameraFramebuffer->getRenderBuffer(0);
_spectatorCameraFramebuffer.reset(gpu::Framebuffer::create("spectatorCamera", gpu::Element::COLOR_SRGBA_32, width, height));
_spectatorCameraNetworkTexture.reset();
}

View file

@ -171,8 +171,7 @@ public:
/// SpectatorCamera rendering targets.
NetworkTexturePointer getSpectatorCameraNetworkTexture();
const gpu::TexturePointer& getSpectatorCameraTexture();
NetworkTexturePointer getResourceTexture(QUrl resourceTextureUrl);
const gpu::FramebufferPointer& getSpectatorCameraFramebuffer();
void resetSpectatorCameraFramebuffer(int width, int height);
@ -193,7 +192,6 @@ private:
static const std::string KTX_DIRNAME;
static const std::string KTX_EXT;
static const std::string SPECTATOR_CAMERA_FRAME_URL;
KTXCache _ktxCache;
// Map from image hashes to texture weak pointers
@ -206,10 +204,8 @@ private:
gpu::TexturePointer _blueTexture;
gpu::TexturePointer _blackTexture;
gpu::FramebufferPointer _spectatorCameraFramebuffer;
gpu::TexturePointer _spectatorCameraTexture;
NetworkTexturePointer _spectatorCameraNetworkTexture;
gpu::FramebufferPointer _spectatorCameraFramebuffer;
};
#endif // hifi_TextureCache_h

View file

@ -28,7 +28,7 @@
// Spectator camera utility functions and variables.
//
function inFrontOf(distance, position, orientation) {
return Vec3.sum(position || MyAvatar.position,
return Vec3.sum(position || Vec3.sum(MyAvatar.position, { x: 0, y: 0.3, z: 0 }),
Vec3.multiply(distance, Quat.getForward(orientation || MyAvatar.orientation)));
}
var aroundY = Quat.fromPitchYawRollDegrees(0, 180, 0);
@ -46,6 +46,8 @@
// camera: The in-world entity that corresponds to the spectator camera.
// cameraIsDynamic: "false" for now while we figure out why dynamic, parented overlays
// drift with respect to their parent
// lastCameraPosition: Holds the last known camera position
// lastCameraRotation: Holds the last known camera rotation
//
// Arguments:
// None
@ -59,11 +61,18 @@
var viewFinderOverlay = false;
var camera = false;
var cameraIsDynamic = false;
var lastCameraPosition = false;
var lastCameraRotation = false;
function updateRenderFromCamera() {
var cameraData = Entities.getEntityProperties(camera, ['position', 'rotation']);
// FIXME: don't muck with config if properties haven't changed.
beginSpectatorFrameRenderConfig.position = cameraData.position;
beginSpectatorFrameRenderConfig.orientation = cameraData.rotation;
if (JSON.stringify(lastCameraPosition) !== JSON.stringify(cameraData.position)) {
lastCameraPosition = cameraData.position;
beginSpectatorFrameRenderConfig.position = lastCameraPosition;
}
if (JSON.stringify(lastCameraRotation) !== JSON.stringify(cameraData.rotation)) {
lastCameraRotation = cameraData.rotation;
beginSpectatorFrameRenderConfig.orientation = lastCameraRotation;
}
if (cameraIsDynamic) {
// BUG: image3d overlays don't retain their locations properly when parented to a dynamic object
Overlays.editOverlay(viewFinderOverlay, { orientation: flip(cameraData.rotation) });
@ -88,33 +97,46 @@
function spectatorCameraOn() {
// Set the special texture size based on the window in which it will eventually be displayed.
var size = Controller.getViewportDimensions(); // FIXME: Need a signal to hook into when the dimensions change.
spectatorFrameRenderConfig.resetSize(size.x, size.y);
spectatorFrameRenderConfig.resetSizeSpectatorCamera(size.x, size.y);
spectatorFrameRenderConfig.enabled = beginSpectatorFrameRenderConfig.enabled = true;
var cameraRotation = MyAvatar.orientation, cameraPosition = inFrontOf(2);
Script.update.connect(updateRenderFromCamera);
isUpdateRenderWired = true;
camera = Entities.addEntity({
type: 'Box',
dimensions: { x: 0.4, y: 0.2, z: 0.4 },
userData: '{"grabbableKey":{"grabbable":true}}',
dynamic: cameraIsDynamic,
color: { red: 255, green: 0, blue: 0 },
name: 'SpectatorCamera',
position: cameraPosition, // Put the camera in front of me so that I can find it.
rotation: cameraRotation
"angularDamping": 0.98000001907348633,
"collisionsWillMove": 1,
"damping": 0.98000001907348633,
"dimensions": {
"x": 0.2338641881942749,
"y": 0.407032310962677,
"z": 0.38702544569969177
},
"dynamic": cameraIsDynamic,
"modelURL": "http://hifi-content.s3.amazonaws.com/alan/dev/spectator-camera.fbx",
"queryAACube": {
"scale": 0.60840487480163574,
"x": -0.30420243740081787,
"y": -0.30420243740081787,
"z": -0.30420243740081787
},
"rotation": cameraRotation,
"position": cameraPosition,
"shapeType": "simple-compound",
"type": "Model",
"userData": "{\"grabbableKey\":{\"grabbable\":true}}"
}, true);
// Put an image3d overlay on the near face, as a viewFinder.
viewFinderOverlay = Overlays.addOverlay("image3d", {
url: "resource://spectatorCameraFrame",
parentID: camera,
alpha: 1,
position: inFrontOf(-0.25, cameraPosition, cameraRotation),
position: inFrontOf(0, Vec3.sum(cameraPosition, { x: 0, y: 0.15, z: 0 }), cameraRotation),
// FIXME: We shouldn't need the flip and the negative scale.
// e.g., This isn't necessary using an ordinary .jpg with lettering, above.
// Must be something about the view frustum projection matrix?
// But don't go changing that in (c++ code) without getting all the way to a desktop display!
orientation: flip(cameraRotation),
scale: -0.35,
scale: -0.16,
});
setDisplay(monitorShowsCameraView);
}