mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 03:44:02 +02:00
New camera model; Cleanup; Bashing head :against desk
This commit is contained in:
parent
3884287c41
commit
fd50434d86
5 changed files with 113 additions and 72 deletions
|
@ -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:
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue