mirror of
https://github.com/overte-org/overte.git
synced 2025-04-19 14:44:39 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi
This commit is contained in:
commit
1a6acdc5b7
52 changed files with 548 additions and 500 deletions
|
@ -123,7 +123,7 @@ var RainSquall = function (properties) {
|
|||
function setUp() {
|
||||
if (debug) {
|
||||
squallCircle = Overlays.addOverlay("circle3d", {
|
||||
size: { x: 2 * squallRadius, y: 2 * squallRadius },
|
||||
size: { x: squallRadius, y: squallRadius },
|
||||
color: SQUALL_CIRCLE_COLOR,
|
||||
alpha: SQUALL_CIRCLE_ALPHA,
|
||||
solid: true,
|
||||
|
|
|
@ -392,7 +392,8 @@ SelectionDisplay = (function () {
|
|||
|
||||
var grabberSpotLightCircle = Overlays.addOverlay("circle3d", {
|
||||
color: lightOverlayColor,
|
||||
isSolid: false
|
||||
isSolid: false,
|
||||
visible: false
|
||||
});
|
||||
var grabberSpotLightLineT = Overlays.addOverlay("line3d", spotLightLineProperties);
|
||||
var grabberSpotLightLineB = Overlays.addOverlay("line3d", spotLightLineProperties);
|
||||
|
@ -409,17 +410,20 @@ SelectionDisplay = (function () {
|
|||
var grabberPointLightCircleX = Overlays.addOverlay("circle3d", {
|
||||
rotation: Quat.fromPitchYawRollDegrees(0, 90, 0),
|
||||
color: lightOverlayColor,
|
||||
isSolid: false
|
||||
isSolid: false,
|
||||
visible: false
|
||||
});
|
||||
var grabberPointLightCircleY = Overlays.addOverlay("circle3d", {
|
||||
rotation: Quat.fromPitchYawRollDegrees(90, 0, 0),
|
||||
color: lightOverlayColor,
|
||||
isSolid: false
|
||||
isSolid: false,
|
||||
visible: false
|
||||
});
|
||||
var grabberPointLightCircleZ = Overlays.addOverlay("circle3d", {
|
||||
rotation: Quat.fromPitchYawRollDegrees(0, 0, 0),
|
||||
color: lightOverlayColor,
|
||||
isSolid: false
|
||||
isSolid: false,
|
||||
visible: false
|
||||
});
|
||||
var grabberPointLightT = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
||||
var grabberPointLightB = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
||||
|
@ -546,7 +550,7 @@ SelectionDisplay = (function () {
|
|||
|
||||
var rotateOverlayTarget = Overlays.addOverlay("circle3d", {
|
||||
position: { x:0, y: 0, z: 0},
|
||||
size: rotateOverlayTargetSize * 2,
|
||||
size: rotateOverlayTargetSize,
|
||||
color: { red: 0, green: 0, blue: 0 },
|
||||
alpha: 0.0,
|
||||
solid: true,
|
||||
|
@ -1186,7 +1190,7 @@ SelectionDisplay = (function () {
|
|||
});
|
||||
Overlays.editOverlay(grabberSpotLightCircle, {
|
||||
position: NEAR,
|
||||
dimensions: { x: distance * 2, y: distance * 2, z: 1 },
|
||||
dimensions: { x: distance, y: distance, z: 1 },
|
||||
lineWidth: 1.5,
|
||||
rotation: rotation,
|
||||
visible: true,
|
||||
|
@ -1258,19 +1262,19 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(grabberPointLightCircleX, {
|
||||
position: position,
|
||||
rotation: Quat.multiply(rotation, Quat.fromPitchYawRollDegrees(0, 90, 0)),
|
||||
dimensions: { x: properties.dimensions.z, y: properties.dimensions.z, z: 1 },
|
||||
dimensions: { x: properties.dimensions.z / 2.0, y: properties.dimensions.z / 2.0, z: 1 },
|
||||
visible: true,
|
||||
});
|
||||
Overlays.editOverlay(grabberPointLightCircleY, {
|
||||
position: position,
|
||||
rotation: Quat.multiply(rotation, Quat.fromPitchYawRollDegrees(90, 0, 0)),
|
||||
dimensions: { x: properties.dimensions.z, y: properties.dimensions.z, z: 1 },
|
||||
dimensions: { x: properties.dimensions.z / 2.0, y: properties.dimensions.z / 2.0, z: 1 },
|
||||
visible: true,
|
||||
});
|
||||
Overlays.editOverlay(grabberPointLightCircleZ, {
|
||||
position: position,
|
||||
rotation: rotation,
|
||||
dimensions: { x: properties.dimensions.z, y: properties.dimensions.z, z: 1 },
|
||||
dimensions: { x: properties.dimensions.z / 2.0, y: properties.dimensions.z / 2.0, z: 1 },
|
||||
visible: true,
|
||||
});
|
||||
|
||||
|
@ -1966,7 +1970,7 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(rotateOverlayInner,
|
||||
{
|
||||
visible: true,
|
||||
size: innerRadius * 2,
|
||||
size: innerRadius,
|
||||
innerRadius: 0.9,
|
||||
startAt: 0,
|
||||
endAt: 360,
|
||||
|
@ -1976,7 +1980,7 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(rotateOverlayOuter,
|
||||
{
|
||||
visible: true,
|
||||
size: outerRadius * 2,
|
||||
size: outerRadius,
|
||||
innerRadius: 0.9,
|
||||
startAt: 0,
|
||||
endAt: 360,
|
||||
|
@ -1986,7 +1990,7 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(rotateOverlayCurrent,
|
||||
{
|
||||
visible: true,
|
||||
size: outerRadius * 2,
|
||||
size: outerRadius,
|
||||
startAt: 0,
|
||||
endAt: 0,
|
||||
innerRadius: 0.9,
|
||||
|
@ -2064,13 +2068,13 @@ SelectionDisplay = (function () {
|
|||
if (snapToInner) {
|
||||
Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 });
|
||||
Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder });
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius * 2,
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius,
|
||||
majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0,
|
||||
majorTickMarksLength: -0.25, minorTickMarksLength: 0, });
|
||||
} else {
|
||||
Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 });
|
||||
Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder });
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius * 2,
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius,
|
||||
majorTickMarksAngle: 45.0, minorTickMarksAngle: 5,
|
||||
majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, });
|
||||
}
|
||||
|
@ -2095,7 +2099,7 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(rotateOverlayInner,
|
||||
{
|
||||
visible: true,
|
||||
size: innerRadius * 2,
|
||||
size: innerRadius,
|
||||
innerRadius: 0.9,
|
||||
startAt: 0,
|
||||
endAt: 360,
|
||||
|
@ -2105,7 +2109,7 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(rotateOverlayOuter,
|
||||
{
|
||||
visible: true,
|
||||
size: outerRadius * 2,
|
||||
size: outerRadius,
|
||||
innerRadius: 0.9,
|
||||
startAt: 0,
|
||||
endAt: 360,
|
||||
|
@ -2115,7 +2119,7 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(rotateOverlayCurrent,
|
||||
{
|
||||
visible: true,
|
||||
size: outerRadius * 2,
|
||||
size: outerRadius,
|
||||
startAt: 0,
|
||||
endAt: 0,
|
||||
innerRadius: 0.9,
|
||||
|
@ -2186,13 +2190,13 @@ SelectionDisplay = (function () {
|
|||
if (snapToInner) {
|
||||
Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 });
|
||||
Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder });
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius * 2,
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius,
|
||||
majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0,
|
||||
majorTickMarksLength: -0.25, minorTickMarksLength: 0, });
|
||||
} else {
|
||||
Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 });
|
||||
Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder });
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius * 2,
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius,
|
||||
majorTickMarksAngle: 45.0, minorTickMarksAngle: 5,
|
||||
majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, });
|
||||
}
|
||||
|
@ -2216,7 +2220,7 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(rotateOverlayInner,
|
||||
{
|
||||
visible: true,
|
||||
size: innerRadius * 2,
|
||||
size: innerRadius,
|
||||
innerRadius: 0.9,
|
||||
startAt: 0,
|
||||
endAt: 360,
|
||||
|
@ -2226,7 +2230,7 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(rotateOverlayOuter,
|
||||
{
|
||||
visible: true,
|
||||
size: outerRadius * 2,
|
||||
size: outerRadius,
|
||||
innerRadius: 0.9,
|
||||
startAt: 0,
|
||||
endAt: 360,
|
||||
|
@ -2236,7 +2240,7 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(rotateOverlayCurrent,
|
||||
{
|
||||
visible: true,
|
||||
size: outerRadius * 2,
|
||||
size: outerRadius,
|
||||
startAt: 0,
|
||||
endAt: 0,
|
||||
innerRadius: 0.9,
|
||||
|
@ -2306,13 +2310,13 @@ SelectionDisplay = (function () {
|
|||
if (snapToInner) {
|
||||
Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 });
|
||||
Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder });
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius * 2,
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius,
|
||||
majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0,
|
||||
majorTickMarksLength: -0.25, minorTickMarksLength: 0, });
|
||||
} else {
|
||||
Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 });
|
||||
Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder });
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius * 2,
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius,
|
||||
majorTickMarksAngle: 45.0, minorTickMarksAngle: 5,
|
||||
majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, });
|
||||
}
|
||||
|
|
|
@ -3306,6 +3306,11 @@ namespace render {
|
|||
|
||||
|
||||
void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool selfAvatarOnly, bool billboard) {
|
||||
|
||||
// FIXME: This preRender call is temporary until we create a separate render::scene for the mirror rendering.
|
||||
// Then we can move this logic into the Avatar::simulate call.
|
||||
_myAvatar->preRender(renderArgs);
|
||||
|
||||
activeRenderingThread = QThread::currentThread();
|
||||
PROFILE_RANGE(__FUNCTION__);
|
||||
PerformanceTimer perfTimer("display");
|
||||
|
|
|
@ -445,10 +445,10 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, boo
|
|||
_skeletonModel.renderJointCollisionShapes(0.7f);
|
||||
}
|
||||
|
||||
if (renderHead && shouldRenderHead(renderArgs, cameraPosition)) {
|
||||
if (renderHead && shouldRenderHead(renderArgs)) {
|
||||
getHead()->getFaceModel().renderJointCollisionShapes(0.7f);
|
||||
}
|
||||
if (renderBounding && shouldRenderHead(renderArgs, cameraPosition)) {
|
||||
if (renderBounding && shouldRenderHead(renderArgs)) {
|
||||
_skeletonModel.renderBoundingCollisionShapes(0.7f);
|
||||
}
|
||||
|
||||
|
@ -533,6 +533,7 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
|
|||
}
|
||||
|
||||
void Avatar::fixupModelsInScene() {
|
||||
|
||||
// check to see if when we added our models to the scene they were ready, if they were not ready, then
|
||||
// fix them up in the scene
|
||||
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
||||
|
@ -581,7 +582,7 @@ void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool
|
|||
getHead()->render(renderArgs, 1.0f, renderFrustum, postLighting);
|
||||
}
|
||||
|
||||
bool Avatar::shouldRenderHead(const RenderArgs* renderArgs, const glm::vec3& cameraPosition) const {
|
||||
bool Avatar::shouldRenderHead(const RenderArgs* renderArgs) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -237,7 +237,7 @@ protected:
|
|||
Transform calculateDisplayNameTransform(const ViewFrustum& frustum, float fontSize) const;
|
||||
void renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum) const;
|
||||
virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel = 0.0f);
|
||||
virtual bool shouldRenderHead(const RenderArgs* renderArgs, const glm::vec3& cameraPosition) const;
|
||||
virtual bool shouldRenderHead(const RenderArgs* renderArgs) const;
|
||||
virtual void fixupModelsInScene();
|
||||
|
||||
void simulateAttachments(float deltaTime);
|
||||
|
|
|
@ -128,20 +128,13 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
|
|||
const float AVERAGE_SACCADE_INTERVAL = 6.0f;
|
||||
const float MICROSACCADE_MAGNITUDE = 0.002f;
|
||||
const float SACCADE_MAGNITUDE = 0.04f;
|
||||
const float MAXIMUM_SACCADE_SPEED = 0.8f;
|
||||
|
||||
if (randFloat() < deltaTime / AVERAGE_MICROSACCADE_INTERVAL) {
|
||||
_saccadeTarget = MICROSACCADE_MAGNITUDE * randVector();
|
||||
} else if (randFloat() < deltaTime / AVERAGE_SACCADE_INTERVAL) {
|
||||
_saccadeTarget = SACCADE_MAGNITUDE * randVector();
|
||||
}
|
||||
|
||||
glm::vec3 saccadeDelta = (_saccadeTarget - _saccade) * 0.5f;
|
||||
float speed = glm::length(saccadeDelta) / deltaTime;
|
||||
if (speed > MAXIMUM_SACCADE_SPEED) {
|
||||
saccadeDelta = saccadeDelta * MAXIMUM_SACCADE_SPEED / speed;
|
||||
}
|
||||
_saccade += saccadeDelta;
|
||||
_saccade += (_saccadeTarget - _saccade) * 0.5f;
|
||||
|
||||
// Detect transition from talking to not; force blink after that and a delay
|
||||
bool forceBlink = false;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <GeometryUtil.h>
|
||||
#include <NodeList.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <PathUtils.h>
|
||||
#include <PerfStat.h>
|
||||
#include <ShapeCollider.h>
|
||||
#include <SharedUtil.h>
|
||||
|
@ -96,8 +97,12 @@ MyAvatar::MyAvatar() :
|
|||
_feetTouchFloor(true),
|
||||
_isLookingAtLeftEye(true),
|
||||
_realWorldFieldOfView("realWorldFieldOfView",
|
||||
DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES)
|
||||
DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES),
|
||||
_firstPersonSkeletonModel(this),
|
||||
_prevShouldDrawHead(true)
|
||||
{
|
||||
_firstPersonSkeletonModel.setIsFirstPerson(true);
|
||||
|
||||
ShapeCollider::initDispatchTable();
|
||||
for (int i = 0; i < MAX_DRIVE_KEYS; i++) {
|
||||
_driveKeys[i] = 0.0f;
|
||||
|
@ -131,6 +136,7 @@ QByteArray MyAvatar::toByteArray() {
|
|||
|
||||
void MyAvatar::reset() {
|
||||
_skeletonModel.reset();
|
||||
_firstPersonSkeletonModel.reset();
|
||||
getHead()->reset();
|
||||
|
||||
_targetVelocity = glm::vec3(0.0f);
|
||||
|
@ -189,6 +195,7 @@ void MyAvatar::simulate(float deltaTime) {
|
|||
{
|
||||
PerformanceTimer perfTimer("skeleton");
|
||||
_skeletonModel.simulate(deltaTime);
|
||||
_firstPersonSkeletonModel.simulate(deltaTime);
|
||||
}
|
||||
|
||||
if (!_skeletonModel.hasSkeleton()) {
|
||||
|
@ -986,16 +993,35 @@ QString MyAvatar::getModelDescription() const {
|
|||
}
|
||||
|
||||
void MyAvatar::setFaceModelURL(const QUrl& faceModelURL) {
|
||||
|
||||
Avatar::setFaceModelURL(faceModelURL);
|
||||
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
||||
getHead()->getFaceModel().setVisibleInScene(_prevShouldDrawHead, scene);
|
||||
_billboardValid = false;
|
||||
}
|
||||
|
||||
void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
||||
|
||||
Avatar::setSkeletonModelURL(skeletonModelURL);
|
||||
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
||||
_billboardValid = false;
|
||||
|
||||
if (_useFullAvatar) {
|
||||
_skeletonModel.setVisibleInScene(_prevShouldDrawHead, scene);
|
||||
|
||||
const QUrl DEFAULT_SKELETON_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_body.fst");
|
||||
_firstPersonSkeletonModel.setURL(_skeletonModelURL, DEFAULT_SKELETON_MODEL_URL, true, !isMyAvatar());
|
||||
_firstPersonSkeletonModel.setVisibleInScene(!_prevShouldDrawHead, scene);
|
||||
} else {
|
||||
_skeletonModel.setVisibleInScene(true, scene);
|
||||
|
||||
_firstPersonSkeletonModel.setVisibleInScene(false, scene);
|
||||
_firstPersonSkeletonModel.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName) {
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "useFullAvatarURL", Qt::BlockingQueuedConnection,
|
||||
Q_ARG(const QUrl&, fullAvatarURL),
|
||||
|
@ -1177,17 +1203,13 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName, const g
|
|||
void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel) {
|
||||
|
||||
if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
||||
return; // wait until both models are loaded
|
||||
return; // wait until all models are loaded
|
||||
}
|
||||
|
||||
// check to see if when we added our models to the scene they were ready, if they were not ready, then
|
||||
// fix them up in the scene
|
||||
fixupModelsInScene();
|
||||
|
||||
const glm::vec3 cameraPos = Application::getInstance()->getCamera()->getPosition();
|
||||
|
||||
// Render head so long as the camera isn't inside it
|
||||
if (shouldRenderHead(renderArgs, cameraPos)) {
|
||||
if (shouldRenderHead(renderArgs)) {
|
||||
getHead()->render(renderArgs, 1.0f, renderFrustum, postLighting);
|
||||
}
|
||||
if (postLighting) {
|
||||
|
@ -1195,12 +1217,51 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bo
|
|||
}
|
||||
}
|
||||
|
||||
void MyAvatar::setVisibleInSceneIfReady(Model* model, render::ScenePointer scene, bool visible) {
|
||||
if (model->isActive() && model->isRenderable()) {
|
||||
model->setVisibleInScene(visible, scene);
|
||||
}
|
||||
}
|
||||
|
||||
void MyAvatar::preRender(RenderArgs* renderArgs) {
|
||||
|
||||
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
||||
const bool shouldDrawHead = shouldRenderHead(renderArgs);
|
||||
|
||||
_skeletonModel.initWhenReady(scene);
|
||||
if (_useFullAvatar) {
|
||||
_firstPersonSkeletonModel.initWhenReady(scene);
|
||||
}
|
||||
|
||||
if (shouldDrawHead != _prevShouldDrawHead) {
|
||||
if (_useFullAvatar) {
|
||||
if (shouldDrawHead) {
|
||||
_skeletonModel.setVisibleInScene(true, scene);
|
||||
_firstPersonSkeletonModel.setVisibleInScene(false, scene);
|
||||
} else {
|
||||
_skeletonModel.setVisibleInScene(false, scene);
|
||||
_firstPersonSkeletonModel.setVisibleInScene(true, scene);
|
||||
}
|
||||
} else {
|
||||
getHead()->getFaceModel().setVisibleInScene(shouldDrawHead, scene);
|
||||
}
|
||||
|
||||
}
|
||||
_prevShouldDrawHead = shouldDrawHead;
|
||||
}
|
||||
|
||||
const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f;
|
||||
|
||||
bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs, const glm::vec3& cameraPosition) const {
|
||||
bool MyAvatar::cameraInsideHead() const {
|
||||
const Head* head = getHead();
|
||||
return (renderArgs->_renderMode != RenderArgs::NORMAL_RENDER_MODE) || (Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON) ||
|
||||
(glm::length(cameraPosition - head->getEyePosition()) > RENDER_HEAD_CUTOFF_DISTANCE * _scale);
|
||||
const glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition();
|
||||
return glm::length(cameraPosition - head->getEyePosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * _scale);
|
||||
}
|
||||
|
||||
bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const {
|
||||
return ((renderArgs->_renderMode != RenderArgs::DEFAULT_RENDER_MODE) ||
|
||||
(Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON) ||
|
||||
!cameraInsideHead());
|
||||
}
|
||||
|
||||
void MyAvatar::updateOrientation(float deltaTime) {
|
||||
|
|
|
@ -35,11 +35,12 @@ public:
|
|||
void reset();
|
||||
void update(float deltaTime);
|
||||
void simulate(float deltaTime);
|
||||
void preRender(RenderArgs* renderArgs);
|
||||
void updateFromTrackers(float deltaTime);
|
||||
|
||||
virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, bool postLighting = false) override;
|
||||
virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel = 0.0f) override;
|
||||
virtual bool shouldRenderHead(const RenderArgs* renderArgs, const glm::vec3& cameraPosition) const override;
|
||||
virtual bool shouldRenderHead(const RenderArgs* renderArgs) const override;
|
||||
void renderDebugBodyPoints();
|
||||
|
||||
// setters
|
||||
|
@ -206,10 +207,14 @@ signals:
|
|||
|
||||
private:
|
||||
|
||||
bool cameraInsideHead() const;
|
||||
|
||||
// These are made private for MyAvatar so that you will use the "use" methods instead
|
||||
virtual void setFaceModelURL(const QUrl& faceModelURL);
|
||||
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
|
||||
|
||||
void setVisibleInSceneIfReady(Model* model, render::ScenePointer scene, bool visiblity);
|
||||
|
||||
glm::vec3 _gravity;
|
||||
|
||||
float _driveKeys[MAX_DRIVE_KEYS];
|
||||
|
@ -265,6 +270,10 @@ private:
|
|||
QString _headModelName;
|
||||
QString _bodyModelName;
|
||||
QString _fullAvatarModelName;
|
||||
|
||||
// used for rendering when in first person view or when in an HMD.
|
||||
SkeletonModel _firstPersonSkeletonModel;
|
||||
bool _prevShouldDrawHead;
|
||||
};
|
||||
|
||||
#endif // hifi_MyAvatar_h
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "Menu.h"
|
||||
#include "SkeletonModel.h"
|
||||
#include "Util.h"
|
||||
#include "InterfaceLogging.h"
|
||||
|
||||
enum StandingFootState {
|
||||
LEFT_FOOT,
|
||||
|
@ -38,7 +39,8 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) :
|
|||
_standingFoot(NO_FOOT),
|
||||
_standingOffset(0.0f),
|
||||
_clampedFootPosition(0.0f),
|
||||
_headClipDistance(DEFAULT_NEAR_CLIP)
|
||||
_headClipDistance(DEFAULT_NEAR_CLIP),
|
||||
_isFirstPerson(false)
|
||||
{
|
||||
assert(_owningAvatar);
|
||||
_enableShapes = true;
|
||||
|
@ -98,7 +100,7 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
|
|||
setRotation(_owningAvatar->getOrientation() * refOrientation);
|
||||
setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningAvatar->getScale());
|
||||
setBlendshapeCoefficients(_owningAvatar->getHead()->getBlendshapeCoefficients());
|
||||
|
||||
|
||||
Model::simulate(deltaTime, fullUpdate);
|
||||
|
||||
if (!isActive() || !_owningAvatar->isMyAvatar()) {
|
||||
|
@ -140,6 +142,11 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
|
|||
applyPalmData(geometry.rightHandJointIndex, hand->getPalms()[rightPalmIndex]);
|
||||
}
|
||||
|
||||
if (_isFirstPerson) {
|
||||
cauterizeHead();
|
||||
updateClusterMatrices();
|
||||
}
|
||||
|
||||
_boundingShape.setTranslation(_translation + _rotation * _boundingShapeLocalOffset);
|
||||
_boundingShape.setRotation(_rotation);
|
||||
}
|
||||
|
@ -806,3 +813,57 @@ void SkeletonModel::renderBoundingCollisionShapes(float alpha) {
|
|||
bool SkeletonModel::hasSkeleton() {
|
||||
return isActive() ? _geometry->getFBXGeometry().rootJointIndex != -1 : false;
|
||||
}
|
||||
|
||||
void SkeletonModel::initHeadBones() {
|
||||
_headBones.clear();
|
||||
const FBXGeometry& fbxGeometry = _geometry->getFBXGeometry();
|
||||
const int neckJointIndex = fbxGeometry.neckJointIndex;
|
||||
std::queue<int> q;
|
||||
q.push(neckJointIndex);
|
||||
_headBones.push_back(neckJointIndex);
|
||||
|
||||
// fbxJoints only hold links to parents not children, so we have to do a bit of extra work here.
|
||||
while (q.size() > 0) {
|
||||
int jointIndex = q.front();
|
||||
for (int i = 0; i < fbxGeometry.joints.size(); i++) {
|
||||
const FBXJoint& fbxJoint = fbxGeometry.joints[i];
|
||||
if (jointIndex == fbxJoint.parentIndex) {
|
||||
_headBones.push_back(i);
|
||||
q.push(i);
|
||||
}
|
||||
}
|
||||
q.pop();
|
||||
}
|
||||
}
|
||||
|
||||
void SkeletonModel::invalidateHeadBones() {
|
||||
_headBones.clear();
|
||||
}
|
||||
|
||||
void SkeletonModel::cauterizeHead() {
|
||||
if (isActive()) {
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
const int neckJointIndex = geometry.neckJointIndex;
|
||||
if (neckJointIndex > 0 && neckJointIndex < _jointStates.size()) {
|
||||
|
||||
// lazy init of headBones
|
||||
if (_headBones.size() == 0) {
|
||||
initHeadBones();
|
||||
}
|
||||
|
||||
// preserve the translation for the neck
|
||||
glm::vec4 trans = _jointStates[neckJointIndex].getTransform()[3];
|
||||
glm::vec4 zero(0, 0, 0, 0);
|
||||
for (const int &i : _headBones) {
|
||||
JointState& joint = _jointStates[i];
|
||||
glm::mat4 newXform(zero, zero, zero, trans);
|
||||
joint.setTransform(newXform);
|
||||
joint.setVisibleTransform(newXform);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SkeletonModel::onInvalidate() {
|
||||
invalidateHeadBones();
|
||||
}
|
||||
|
|
|
@ -112,6 +112,11 @@ public:
|
|||
|
||||
float getHeadClipDistance() const { return _headClipDistance; }
|
||||
|
||||
void setIsFirstPerson(bool value) { _isFirstPerson = value; }
|
||||
bool getIsFirstPerson() const { return _isFirstPerson; }
|
||||
|
||||
virtual void onInvalidate() override;
|
||||
|
||||
signals:
|
||||
|
||||
void skeletonLoaded();
|
||||
|
@ -132,7 +137,11 @@ protected:
|
|||
void maybeUpdateLeanRotation(const JointState& parentState, JointState& state);
|
||||
void maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
|
||||
void maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
|
||||
|
||||
|
||||
void cauterizeHead();
|
||||
void initHeadBones();
|
||||
void invalidateHeadBones();
|
||||
|
||||
private:
|
||||
|
||||
void renderJointConstraints(int jointIndex);
|
||||
|
@ -164,6 +173,9 @@ private:
|
|||
glm::vec3 _clampedFootPosition;
|
||||
|
||||
float _headClipDistance; // Near clip distance to use if no separate head model
|
||||
|
||||
bool _isFirstPerson;
|
||||
std::vector<int> _headBones;
|
||||
};
|
||||
|
||||
#endif // hifi_SkeletonModel_h
|
||||
|
|
|
@ -16,15 +16,12 @@
|
|||
#include "Application.h"
|
||||
#include "Base3DOverlay.h"
|
||||
|
||||
const glm::vec3 DEFAULT_POSITION = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
const float DEFAULT_LINE_WIDTH = 1.0f;
|
||||
const bool DEFAULT_IS_SOLID = false;
|
||||
const bool DEFAULT_IS_DASHED_LINE = false;
|
||||
|
||||
Base3DOverlay::Base3DOverlay() :
|
||||
_position(DEFAULT_POSITION),
|
||||
_lineWidth(DEFAULT_LINE_WIDTH),
|
||||
_rotation(),
|
||||
_isSolid(DEFAULT_IS_SOLID),
|
||||
_isDashedLine(DEFAULT_IS_DASHED_LINE),
|
||||
_ignoreRayIntersection(false),
|
||||
|
@ -35,9 +32,8 @@ Base3DOverlay::Base3DOverlay() :
|
|||
|
||||
Base3DOverlay::Base3DOverlay(const Base3DOverlay* base3DOverlay) :
|
||||
Overlay(base3DOverlay),
|
||||
_position(base3DOverlay->_position),
|
||||
_transform(base3DOverlay->_transform),
|
||||
_lineWidth(base3DOverlay->_lineWidth),
|
||||
_rotation(base3DOverlay->_rotation),
|
||||
_isSolid(base3DOverlay->_isSolid),
|
||||
_isDashedLine(base3DOverlay->_isDashedLine),
|
||||
_ignoreRayIntersection(base3DOverlay->_ignoreRayIntersection),
|
||||
|
@ -46,14 +42,6 @@ Base3DOverlay::Base3DOverlay(const Base3DOverlay* base3DOverlay) :
|
|||
{
|
||||
}
|
||||
|
||||
Base3DOverlay::~Base3DOverlay() {
|
||||
}
|
||||
|
||||
// TODO: Implement accurate getBounds() implementations
|
||||
AABox Base3DOverlay::getBounds() const {
|
||||
return AABox(_position, glm::vec3(1.0f));
|
||||
}
|
||||
|
||||
void Base3DOverlay::setProperties(const QScriptValue& properties) {
|
||||
Overlay::setProperties(properties);
|
||||
|
||||
|
@ -151,13 +139,13 @@ void Base3DOverlay::setProperties(const QScriptValue& properties) {
|
|||
|
||||
QScriptValue Base3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "position" || property == "start" || property == "p1" || property == "point") {
|
||||
return vec3toScriptValue(_scriptEngine, _position);
|
||||
return vec3toScriptValue(_scriptEngine, getPosition());
|
||||
}
|
||||
if (property == "lineWidth") {
|
||||
return _lineWidth;
|
||||
}
|
||||
if (property == "rotation") {
|
||||
return quatToScriptValue(_scriptEngine, _rotation);
|
||||
return quatToScriptValue(_scriptEngine, getRotation());
|
||||
}
|
||||
if (property == "isSolid" || property == "isFilled" || property == "solid" || property == "filed") {
|
||||
return _isSolid;
|
||||
|
|
|
@ -11,10 +11,7 @@
|
|||
#ifndef hifi_Base3DOverlay_h
|
||||
#define hifi_Base3DOverlay_h
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
#include <BoxBase.h>
|
||||
#include <Transform.h>
|
||||
|
||||
#include "Overlay.h"
|
||||
|
||||
|
@ -24,32 +21,38 @@ class Base3DOverlay : public Overlay {
|
|||
public:
|
||||
Base3DOverlay();
|
||||
Base3DOverlay(const Base3DOverlay* base3DOverlay);
|
||||
~Base3DOverlay();
|
||||
|
||||
// getters
|
||||
virtual bool is3D() const { return true; }
|
||||
const glm::vec3& getPosition() const { return _position; }
|
||||
const glm::vec3& getCenter() const { return _position; } // TODO: consider implementing registration points in this class
|
||||
const glm::vec3& getPosition() const { return _transform.getTranslation(); }
|
||||
const glm::quat& getRotation() const { return _transform.getRotation(); }
|
||||
const glm::vec3& getScale() const { return _transform.getScale(); }
|
||||
|
||||
// TODO: consider implementing registration points in this class
|
||||
const glm::vec3& getCenter() const { return getPosition(); }
|
||||
|
||||
float getLineWidth() const { return _lineWidth; }
|
||||
bool getIsSolid() const { return _isSolid; }
|
||||
bool getIsDashedLine() const { return _isDashedLine; }
|
||||
bool getIsSolidLine() const { return !_isDashedLine; }
|
||||
const glm::quat& getRotation() const { return _rotation; }
|
||||
bool getIgnoreRayIntersection() const { return _ignoreRayIntersection; }
|
||||
bool getDrawInFront() const { return _drawInFront; }
|
||||
bool getDrawOnHUD() const { return _drawOnHUD; }
|
||||
|
||||
// setters
|
||||
void setPosition(const glm::vec3& position) { _position = position; }
|
||||
void setPosition(const glm::vec3& value) { _transform.setTranslation(value); }
|
||||
void setRotation(const glm::quat& value) { _transform.setRotation(value); }
|
||||
void setScale(float value) { _transform.setScale(value); }
|
||||
void setScale(const glm::vec3& value) { _transform.setScale(value); }
|
||||
|
||||
void setLineWidth(float lineWidth) { _lineWidth = lineWidth; }
|
||||
void setIsSolid(bool isSolid) { _isSolid = isSolid; }
|
||||
void setIsDashedLine(bool isDashedLine) { _isDashedLine = isDashedLine; }
|
||||
void setRotation(const glm::quat& value) { _rotation = value; }
|
||||
void setIgnoreRayIntersection(bool value) { _ignoreRayIntersection = value; }
|
||||
void setDrawInFront(bool value) { _drawInFront = value; }
|
||||
void setDrawOnHUD(bool value) { _drawOnHUD = value; }
|
||||
|
||||
virtual AABox getBounds() const;
|
||||
virtual AABox getBounds() const = 0;
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
@ -62,9 +65,9 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
glm::vec3 _position;
|
||||
Transform _transform;
|
||||
|
||||
float _lineWidth;
|
||||
glm::quat _rotation;
|
||||
bool _isSolid;
|
||||
bool _isDashedLine;
|
||||
bool _ignoreRayIntersection;
|
||||
|
|
|
@ -9,26 +9,20 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Application.h"
|
||||
#include "GeometryUtil.h"
|
||||
#include "PlaneShape.h"
|
||||
|
||||
#include "BillboardOverlay.h"
|
||||
|
||||
BillboardOverlay::BillboardOverlay() :
|
||||
_fromImage(),
|
||||
_scale(1.0f),
|
||||
_isFacingAvatar(true)
|
||||
{
|
||||
#include "Application.h"
|
||||
#include "GeometryUtil.h"
|
||||
|
||||
BillboardOverlay::BillboardOverlay() {
|
||||
_isLoaded = false;
|
||||
}
|
||||
|
||||
BillboardOverlay::BillboardOverlay(const BillboardOverlay* billboardOverlay) :
|
||||
Base3DOverlay(billboardOverlay),
|
||||
Planar3DOverlay(billboardOverlay),
|
||||
_url(billboardOverlay->_url),
|
||||
_texture(billboardOverlay->_texture),
|
||||
_fromImage(billboardOverlay->_fromImage),
|
||||
_scale(billboardOverlay->_scale),
|
||||
_isFacingAvatar(billboardOverlay->_isFacingAvatar)
|
||||
{
|
||||
}
|
||||
|
@ -46,8 +40,8 @@ void BillboardOverlay::render(RenderArgs* args) {
|
|||
glm::quat rotation;
|
||||
if (_isFacingAvatar) {
|
||||
// rotate about vertical to face the camera
|
||||
rotation = Application::getInstance()->getCamera()->getRotation();
|
||||
rotation *= glm::angleAxis(glm::pi<float>(), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
rotation = args->_viewFrustum->getOrientation();
|
||||
rotation *= glm::angleAxis(glm::pi<float>(), IDENTITY_UP);
|
||||
rotation *= getRotation();
|
||||
} else {
|
||||
rotation = getRotation();
|
||||
|
@ -89,11 +83,9 @@ void BillboardOverlay::render(RenderArgs* args) {
|
|||
auto batch = args->_batch;
|
||||
|
||||
if (batch) {
|
||||
Transform transform;
|
||||
transform.setTranslation(_position);
|
||||
transform.setRotation(rotation);
|
||||
transform.setScale(_scale);
|
||||
|
||||
Transform transform = _transform;
|
||||
transform.postScale(glm::vec3(getDimensions(), 1.0f));
|
||||
|
||||
batch->setModelTransform(transform);
|
||||
batch->setUniformTexture(0, _texture->getGPUTexture());
|
||||
|
||||
|
@ -111,10 +103,10 @@ void BillboardOverlay::render(RenderArgs* args) {
|
|||
glBindTexture(GL_TEXTURE_2D, _texture->getID());
|
||||
|
||||
glPushMatrix(); {
|
||||
glTranslatef(_position.x, _position.y, _position.z);
|
||||
glTranslatef(getPosition().x, getPosition().y, getPosition().z);
|
||||
glm::vec3 axis = glm::axis(rotation);
|
||||
glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
|
||||
glScalef(_scale, _scale, _scale);
|
||||
glScalef(_dimensions.x, _dimensions.y, 1.0f);
|
||||
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
|
||||
glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha));
|
||||
|
@ -130,7 +122,7 @@ void BillboardOverlay::render(RenderArgs* args) {
|
|||
}
|
||||
|
||||
void BillboardOverlay::setProperties(const QScriptValue &properties) {
|
||||
Base3DOverlay::setProperties(properties);
|
||||
Planar3DOverlay::setProperties(properties);
|
||||
|
||||
QScriptValue urlValue = properties.property("url");
|
||||
if (urlValue.isValid()) {
|
||||
|
@ -171,11 +163,6 @@ void BillboardOverlay::setProperties(const QScriptValue &properties) {
|
|||
}
|
||||
}
|
||||
|
||||
QScriptValue scaleValue = properties.property("scale");
|
||||
if (scaleValue.isValid()) {
|
||||
_scale = scaleValue.toVariant().toFloat();
|
||||
}
|
||||
|
||||
QScriptValue isFacingAvatarValue = properties.property("isFacingAvatar");
|
||||
if (isFacingAvatarValue.isValid()) {
|
||||
_isFacingAvatar = isFacingAvatarValue.toVariant().toBool();
|
||||
|
@ -189,14 +176,11 @@ QScriptValue BillboardOverlay::getProperty(const QString& property) {
|
|||
if (property == "subImage") {
|
||||
return qRectToScriptValue(_scriptEngine, _fromImage);
|
||||
}
|
||||
if (property == "scale") {
|
||||
return _scale;
|
||||
}
|
||||
if (property == "isFacingAvatar") {
|
||||
return _isFacingAvatar;
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
return Planar3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
void BillboardOverlay::setURL(const QString& url) {
|
||||
|
@ -212,13 +196,11 @@ bool BillboardOverlay::findRayIntersection(const glm::vec3& origin, const glm::v
|
|||
float& distance, BoxFace& face) {
|
||||
|
||||
if (_texture) {
|
||||
glm::quat rotation;
|
||||
glm::quat rotation = getRotation();
|
||||
if (_isFacingAvatar) {
|
||||
// rotate about vertical to face the camera
|
||||
rotation = Application::getInstance()->getCamera()->getRotation();
|
||||
rotation *= glm::angleAxis(glm::pi<float>(), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
} else {
|
||||
rotation = _rotation;
|
||||
}
|
||||
|
||||
// Produce the dimensions of the billboard based on the image's aspect ratio and the overlay's scale.
|
||||
|
@ -226,9 +208,9 @@ bool BillboardOverlay::findRayIntersection(const glm::vec3& origin, const glm::v
|
|||
float width = isNull ? _texture->getWidth() : _fromImage.width();
|
||||
float height = isNull ? _texture->getHeight() : _fromImage.height();
|
||||
float maxSize = glm::max(width, height);
|
||||
glm::vec2 dimensions = _scale * glm::vec2(width / maxSize, height / maxSize);
|
||||
glm::vec2 dimensions = _dimensions * glm::vec2(width / maxSize, height / maxSize);
|
||||
|
||||
return findRayRectangleIntersection(origin, direction, rotation, _position, dimensions, distance);
|
||||
return findRayRectangleIntersection(origin, direction, rotation, getPosition(), dimensions, distance);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -12,14 +12,11 @@
|
|||
#ifndef hifi_BillboardOverlay_h
|
||||
#define hifi_BillboardOverlay_h
|
||||
|
||||
#include <QScopedPointer>
|
||||
#include <QUrl>
|
||||
|
||||
#include <TextureCache.h>
|
||||
|
||||
#include "Base3DOverlay.h"
|
||||
#include "Planar3DOverlay.h"
|
||||
|
||||
class BillboardOverlay : public Base3DOverlay {
|
||||
class BillboardOverlay : public Planar3DOverlay {
|
||||
Q_OBJECT
|
||||
public:
|
||||
BillboardOverlay();
|
||||
|
@ -29,7 +26,6 @@ public:
|
|||
|
||||
// setters
|
||||
void setURL(const QString& url);
|
||||
void setScale(float scale) { _scale = scale; }
|
||||
void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
|
@ -48,8 +44,7 @@ private:
|
|||
|
||||
QRect _fromImage; // where from in the image to sample
|
||||
|
||||
float _scale;
|
||||
bool _isFacingAvatar;
|
||||
bool _isFacingAvatar = true;
|
||||
};
|
||||
|
||||
#endif // hifi_BillboardOverlay_h
|
||||
|
|
|
@ -8,16 +8,12 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
#include "Circle3DOverlay.h"
|
||||
|
||||
#include <DeferredLightingEffect.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <GlowEffect.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <StreamUtils.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
#include "Circle3DOverlay.h"
|
||||
|
||||
Circle3DOverlay::Circle3DOverlay() :
|
||||
_startAt(0.0f),
|
||||
|
@ -66,9 +62,6 @@ Circle3DOverlay::Circle3DOverlay(const Circle3DOverlay* circle3DOverlay) :
|
|||
{
|
||||
}
|
||||
|
||||
Circle3DOverlay::~Circle3DOverlay() {
|
||||
}
|
||||
|
||||
void Circle3DOverlay::render(RenderArgs* args) {
|
||||
if (!_visible) {
|
||||
return; // do nothing if we're not visible
|
||||
|
@ -103,15 +96,13 @@ void Circle3DOverlay::render(RenderArgs* args) {
|
|||
_lastColor = colorX;
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
||||
Transform transform;
|
||||
transform.setTranslation(getCenter());
|
||||
transform.setRotation(getRotation());
|
||||
transform.setScale(glm::vec3(getDimensions(), 0.01f) / 2.0f);
|
||||
|
||||
|
||||
Q_ASSERT(args->_batch);
|
||||
auto& batch = *args->_batch;
|
||||
batch._glLineWidth(_lineWidth);
|
||||
|
||||
auto transform = _transform;
|
||||
transform.postScale(glm::vec3(getDimensions(), 1.0f));
|
||||
batch.setModelTransform(transform);
|
||||
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, false, false);
|
||||
|
||||
|
@ -402,12 +393,12 @@ bool Circle3DOverlay::findRayIntersection(const glm::vec3& origin,
|
|||
|
||||
if (intersects) {
|
||||
glm::vec3 hitPosition = origin + (distance * direction);
|
||||
glm::vec3 localHitPosition = glm::inverse(_rotation) * (hitPosition - _position);
|
||||
localHitPosition.y = localHitPosition.y * _dimensions.x / _dimensions.y; // Scale to make circular
|
||||
glm::vec3 localHitPosition = glm::inverse(getRotation()) * (hitPosition - getPosition());
|
||||
localHitPosition.y = localHitPosition.y * getDimensions().x / getDimensions().y; // Scale to make circular
|
||||
|
||||
float distanceToHit = glm::length(localHitPosition);
|
||||
float innerRadius = _dimensions.x / 2.0f * _innerRadius;
|
||||
float outerRadius = _dimensions.x / 2.0f * _outerRadius;
|
||||
float innerRadius = getDimensions().x / 2.0f * _innerRadius;
|
||||
float outerRadius = getDimensions().x / 2.0f * _outerRadius;
|
||||
|
||||
intersects = innerRadius <= distanceToHit && distanceToHit <= outerRadius;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
#ifndef hifi_Circle3DOverlay_h
|
||||
#define hifi_Circle3DOverlay_h
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include "Planar3DOverlay.h"
|
||||
|
||||
class Circle3DOverlay : public Planar3DOverlay {
|
||||
|
@ -19,7 +22,7 @@ class Circle3DOverlay : public Planar3DOverlay {
|
|||
public:
|
||||
Circle3DOverlay();
|
||||
Circle3DOverlay(const Circle3DOverlay* circle3DOverlay);
|
||||
~Circle3DOverlay();
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
|
|
@ -19,17 +19,11 @@
|
|||
#include "Application.h"
|
||||
#include "Cube3DOverlay.h"
|
||||
|
||||
Cube3DOverlay::Cube3DOverlay() : _borderSize(0) {
|
||||
}
|
||||
|
||||
Cube3DOverlay::Cube3DOverlay(const Cube3DOverlay* cube3DOverlay) :
|
||||
Volume3DOverlay(cube3DOverlay)
|
||||
{
|
||||
}
|
||||
|
||||
Cube3DOverlay::~Cube3DOverlay() {
|
||||
}
|
||||
|
||||
void Cube3DOverlay::render(RenderArgs* args) {
|
||||
if (!_visible) {
|
||||
return; // do nothing if we're not visible
|
||||
|
|
|
@ -17,9 +17,9 @@ class Cube3DOverlay : public Volume3DOverlay {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Cube3DOverlay();
|
||||
Cube3DOverlay() {}
|
||||
Cube3DOverlay(const Cube3DOverlay* cube3DOverlay);
|
||||
~Cube3DOverlay();
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
virtual Cube3DOverlay* createClone() const;
|
||||
|
|
|
@ -9,28 +9,29 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include "Grid3DOverlay.h"
|
||||
|
||||
#include <PathUtils.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Grid3DOverlay.h"
|
||||
|
||||
ProgramObject Grid3DOverlay::_gridProgram;
|
||||
|
||||
Grid3DOverlay::Grid3DOverlay() : Base3DOverlay(),
|
||||
Grid3DOverlay::Grid3DOverlay() :
|
||||
_minorGridWidth(1.0),
|
||||
_majorGridEvery(5) {
|
||||
}
|
||||
|
||||
Grid3DOverlay::Grid3DOverlay(const Grid3DOverlay* grid3DOverlay) :
|
||||
Base3DOverlay(grid3DOverlay),
|
||||
Planar3DOverlay(grid3DOverlay),
|
||||
_minorGridWidth(grid3DOverlay->_minorGridWidth),
|
||||
_majorGridEvery(grid3DOverlay->_majorGridEvery)
|
||||
{
|
||||
}
|
||||
|
||||
Grid3DOverlay::~Grid3DOverlay() {
|
||||
}
|
||||
|
||||
void Grid3DOverlay::render(RenderArgs* args) {
|
||||
if (!_visible) {
|
||||
return; // do nothing if we're not visible
|
||||
|
@ -41,7 +42,7 @@ void Grid3DOverlay::render(RenderArgs* args) {
|
|||
const float MAX_COLOR = 255.0f;
|
||||
|
||||
// center the grid around the camera position on the plane
|
||||
glm::vec3 rotated = glm::inverse(_rotation) * Application::getInstance()->getCamera()->getPosition();
|
||||
glm::vec3 rotated = glm::inverse(getRotation()) * Application::getInstance()->getCamera()->getPosition();
|
||||
|
||||
float spacing = _minorGridWidth;
|
||||
|
||||
|
@ -53,7 +54,7 @@ void Grid3DOverlay::render(RenderArgs* args) {
|
|||
|
||||
if (batch) {
|
||||
Transform transform;
|
||||
transform.setRotation(_rotation);
|
||||
transform.setRotation(getRotation());
|
||||
|
||||
|
||||
// Minor grid
|
||||
|
@ -61,7 +62,7 @@ void Grid3DOverlay::render(RenderArgs* args) {
|
|||
batch->_glLineWidth(1.0f);
|
||||
auto position = glm::vec3(_minorGridWidth * (floorf(rotated.x / spacing) - MINOR_GRID_DIVISIONS / 2),
|
||||
spacing * (floorf(rotated.y / spacing) - MINOR_GRID_DIVISIONS / 2),
|
||||
_position.z);
|
||||
getPosition().z);
|
||||
float scale = MINOR_GRID_DIVISIONS * spacing;
|
||||
|
||||
transform.setTranslation(position);
|
||||
|
@ -78,7 +79,7 @@ void Grid3DOverlay::render(RenderArgs* args) {
|
|||
spacing *= _majorGridEvery;
|
||||
auto position = glm::vec3(spacing * (floorf(rotated.x / spacing) - MAJOR_GRID_DIVISIONS / 2),
|
||||
spacing * (floorf(rotated.y / spacing) - MAJOR_GRID_DIVISIONS / 2),
|
||||
_position.z);
|
||||
getPosition().z);
|
||||
float scale = MAJOR_GRID_DIVISIONS * spacing;
|
||||
|
||||
transform.setTranslation(position);
|
||||
|
@ -161,7 +162,7 @@ void Grid3DOverlay::render(RenderArgs* args) {
|
|||
}
|
||||
|
||||
void Grid3DOverlay::setProperties(const QScriptValue& properties) {
|
||||
Base3DOverlay::setProperties(properties);
|
||||
Planar3DOverlay::setProperties(properties);
|
||||
|
||||
if (properties.property("minorGridWidth").isValid()) {
|
||||
_minorGridWidth = properties.property("minorGridWidth").toVariant().toFloat();
|
||||
|
@ -180,7 +181,7 @@ QScriptValue Grid3DOverlay::getProperty(const QString& property) {
|
|||
return _majorGridEvery;
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
return Planar3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
Grid3DOverlay* Grid3DOverlay::createClone() const {
|
||||
|
|
|
@ -15,20 +15,16 @@
|
|||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <ProgramObject.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "Base3DOverlay.h"
|
||||
#include "Planar3DOverlay.h"
|
||||
|
||||
class Grid3DOverlay : public Base3DOverlay {
|
||||
class Grid3DOverlay : public Planar3DOverlay {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Grid3DOverlay();
|
||||
Grid3DOverlay(const Grid3DOverlay* grid3DOverlay);
|
||||
~Grid3DOverlay();
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
|
|
|
@ -8,17 +8,11 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QSvgRenderer>
|
||||
#include "ImageOverlay.h"
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "ImageOverlay.h"
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
ImageOverlay::ImageOverlay() :
|
||||
_imageURL(),
|
||||
|
@ -38,9 +32,6 @@ ImageOverlay::ImageOverlay(const ImageOverlay* imageOverlay) :
|
|||
{
|
||||
}
|
||||
|
||||
ImageOverlay::~ImageOverlay() {
|
||||
}
|
||||
|
||||
// TODO: handle setting image multiple times, how do we manage releasing the bound texture?
|
||||
void ImageOverlay::setImageURL(const QUrl& url) {
|
||||
_imageURL = url;
|
||||
|
|
|
@ -15,17 +15,11 @@
|
|||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QImage>
|
||||
#include <QNetworkReply>
|
||||
#include <QRect>
|
||||
#include <QScriptValue>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
#include <NetworkAccessManager.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <TextureCache.h>
|
||||
|
||||
#include "Overlay.h"
|
||||
#include "Overlay2D.h"
|
||||
|
||||
class ImageOverlay : public Overlay2D {
|
||||
|
@ -34,7 +28,7 @@ class ImageOverlay : public Overlay2D {
|
|||
public:
|
||||
ImageOverlay();
|
||||
ImageOverlay(const ImageOverlay* imageOverlay);
|
||||
~ImageOverlay();
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
// getters
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <GlowEffect.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
#include "Line3DOverlay.h"
|
||||
|
||||
|
@ -33,13 +34,12 @@ Line3DOverlay::~Line3DOverlay() {
|
|||
}
|
||||
|
||||
AABox Line3DOverlay::getBounds() const {
|
||||
auto start = _position + _start;
|
||||
auto end = _position + _end;
|
||||
|
||||
auto min = glm::min(start, end);
|
||||
auto max = glm::max(start, end);
|
||||
|
||||
return AABox(min, max - min);
|
||||
auto extents = Extents{};
|
||||
extents.addPoint(_start);
|
||||
extents.addPoint(_end);
|
||||
extents.transform(_transform);
|
||||
|
||||
return AABox(extents);
|
||||
}
|
||||
|
||||
void Line3DOverlay::render(RenderArgs* args) {
|
||||
|
@ -55,14 +55,11 @@ void Line3DOverlay::render(RenderArgs* args) {
|
|||
auto batch = args->_batch;
|
||||
|
||||
if (batch) {
|
||||
Transform transform;
|
||||
transform.setTranslation(_position);
|
||||
transform.setRotation(_rotation);
|
||||
batch->setModelTransform(transform);
|
||||
batch->setModelTransform(_transform);
|
||||
|
||||
if (getIsDashedLine()) {
|
||||
// TODO: add support for color to renderDashedLine()
|
||||
DependencyManager::get<GeometryCache>()->renderDashedLine(*batch, _position, _end, colorv4, _geometryCacheID);
|
||||
DependencyManager::get<GeometryCache>()->renderDashedLine(*batch, _start, _end, colorv4, _geometryCacheID);
|
||||
} else {
|
||||
DependencyManager::get<GeometryCache>()->renderLine(*batch, _start, _end, colorv4, _geometryCacheID);
|
||||
}
|
||||
|
@ -87,7 +84,7 @@ void Line3DOverlay::render(RenderArgs* args) {
|
|||
|
||||
if (getIsDashedLine()) {
|
||||
// TODO: add support for color to renderDashedLine()
|
||||
DependencyManager::get<GeometryCache>()->renderDashedLine(_position, _end, colorv4, _geometryCacheID);
|
||||
DependencyManager::get<GeometryCache>()->renderDashedLine(_start, _end, colorv4, _geometryCacheID);
|
||||
} else {
|
||||
DependencyManager::get<GeometryCache>()->renderLine(_start, _end, colorv4, _geometryCacheID);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ public:
|
|||
Line3DOverlay(const Line3DOverlay* line3DOverlay);
|
||||
~Line3DOverlay();
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual AABox getBounds() const override;
|
||||
virtual AABox getBounds() const;
|
||||
|
||||
// getters
|
||||
const glm::vec3& getStart() const { return _start; }
|
||||
|
|
|
@ -24,10 +24,6 @@ LocalModelsOverlay::LocalModelsOverlay(const LocalModelsOverlay* localModelsOver
|
|||
Volume3DOverlay(localModelsOverlay),
|
||||
_entityTreeRenderer(localModelsOverlay->_entityTreeRenderer)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
LocalModelsOverlay::~LocalModelsOverlay() {
|
||||
}
|
||||
|
||||
void LocalModelsOverlay::update(float deltatime) {
|
||||
|
@ -46,7 +42,7 @@ void LocalModelsOverlay::render(RenderArgs* args) {
|
|||
glPushMatrix(); {
|
||||
Application* app = Application::getInstance();
|
||||
glm::vec3 oldTranslation = app->getViewMatrixTranslation();
|
||||
app->setViewMatrixTranslation(oldTranslation + _position);
|
||||
app->setViewMatrixTranslation(oldTranslation + getPosition());
|
||||
_entityTreeRenderer->render(args);
|
||||
Application::getInstance()->setViewMatrixTranslation(oldTranslation);
|
||||
} glPopMatrix();
|
||||
|
|
|
@ -21,7 +21,6 @@ class LocalModelsOverlay : public Volume3DOverlay {
|
|||
public:
|
||||
LocalModelsOverlay(EntityTreeRenderer* entityTreeRenderer);
|
||||
LocalModelsOverlay(const LocalModelsOverlay* localModelsOverlay);
|
||||
~LocalModelsOverlay();
|
||||
|
||||
virtual void update(float deltatime);
|
||||
virtual void render(RenderArgs* args);
|
||||
|
|
|
@ -9,15 +9,15 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ModelOverlay.h"
|
||||
|
||||
#include <Application.h>
|
||||
#include <GlowEffect.h>
|
||||
|
||||
#include "ModelOverlay.h"
|
||||
|
||||
ModelOverlay::ModelOverlay()
|
||||
: _model(),
|
||||
_modelTextures(QVariantMap()),
|
||||
_scale(1.0f),
|
||||
_updateModel(false)
|
||||
{
|
||||
_model.init();
|
||||
|
@ -25,12 +25,10 @@ ModelOverlay::ModelOverlay()
|
|||
}
|
||||
|
||||
ModelOverlay::ModelOverlay(const ModelOverlay* modelOverlay) :
|
||||
Base3DOverlay(modelOverlay),
|
||||
Volume3DOverlay(modelOverlay),
|
||||
_model(),
|
||||
_modelTextures(QVariantMap()),
|
||||
_url(modelOverlay->_url),
|
||||
_rotation(modelOverlay->_rotation),
|
||||
_scale(modelOverlay->_scale),
|
||||
_updateModel(false)
|
||||
{
|
||||
_model.init();
|
||||
|
@ -45,8 +43,9 @@ void ModelOverlay::update(float deltatime) {
|
|||
_updateModel = false;
|
||||
|
||||
_model.setSnapModelToCenter(true);
|
||||
_model.setRotation(_rotation);
|
||||
_model.setTranslation(_position);
|
||||
_model.setScale(getScale());
|
||||
_model.setRotation(getRotation());
|
||||
_model.setTranslation(getPosition());
|
||||
_model.setURL(_url);
|
||||
_model.simulate(deltatime, true);
|
||||
} else {
|
||||
|
@ -56,13 +55,13 @@ void ModelOverlay::update(float deltatime) {
|
|||
}
|
||||
|
||||
bool ModelOverlay::addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
|
||||
Base3DOverlay::addToScene(overlay, scene, pendingChanges);
|
||||
Volume3DOverlay::addToScene(overlay, scene, pendingChanges);
|
||||
_model.addToScene(scene, pendingChanges);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ModelOverlay::removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
|
||||
Base3DOverlay::removeFromScene(overlay, scene, pendingChanges);
|
||||
Volume3DOverlay::removeFromScene(overlay, scene, pendingChanges);
|
||||
_model.removeFromScene(scene, pendingChanges);
|
||||
}
|
||||
|
||||
|
@ -100,54 +99,26 @@ void ModelOverlay::render(RenderArgs* args) {
|
|||
}
|
||||
|
||||
void ModelOverlay::setProperties(const QScriptValue &properties) {
|
||||
Base3DOverlay::setProperties(properties);
|
||||
auto position = getPosition();
|
||||
auto rotation = getRotation();
|
||||
auto scale = getDimensions();
|
||||
|
||||
Volume3DOverlay::setProperties(properties);
|
||||
|
||||
if (position != getPosition() || rotation != getRotation() || scale != getDimensions()) {
|
||||
_model.setScaleToFit(true, getScale());
|
||||
_updateModel = true;
|
||||
}
|
||||
|
||||
QScriptValue urlValue = properties.property("url");
|
||||
if (urlValue.isValid()) {
|
||||
_url = urlValue.toVariant().toString();
|
||||
if (urlValue.isValid() && urlValue.isString()) {
|
||||
_url = urlValue.toString();
|
||||
_updateModel = true;
|
||||
_isLoaded = false;
|
||||
}
|
||||
|
||||
QScriptValue scaleValue = properties.property("scale");
|
||||
if (scaleValue.isValid()) {
|
||||
_scale = scaleValue.toVariant().toFloat();
|
||||
_model.setScaleToFit(true, _scale);
|
||||
_updateModel = true;
|
||||
}
|
||||
|
||||
QScriptValue rotationValue = properties.property("rotation");
|
||||
if (rotationValue.isValid()) {
|
||||
QScriptValue x = rotationValue.property("x");
|
||||
QScriptValue y = rotationValue.property("y");
|
||||
QScriptValue z = rotationValue.property("z");
|
||||
QScriptValue w = rotationValue.property("w");
|
||||
if (x.isValid() && y.isValid() && z.isValid() && w.isValid()) {
|
||||
_rotation.x = x.toVariant().toFloat();
|
||||
_rotation.y = y.toVariant().toFloat();
|
||||
_rotation.z = z.toVariant().toFloat();
|
||||
_rotation.w = w.toVariant().toFloat();
|
||||
}
|
||||
_updateModel = true;
|
||||
}
|
||||
|
||||
QScriptValue dimensionsValue = properties.property("dimensions");
|
||||
if (dimensionsValue.isValid()) {
|
||||
QScriptValue x = dimensionsValue.property("x");
|
||||
QScriptValue y = dimensionsValue.property("y");
|
||||
QScriptValue z = dimensionsValue.property("z");
|
||||
if (x.isValid() && y.isValid() && z.isValid()) {
|
||||
glm::vec3 dimensions;
|
||||
dimensions.x = x.toVariant().toFloat();
|
||||
dimensions.y = y.toVariant().toFloat();
|
||||
dimensions.z = z.toVariant().toFloat();
|
||||
_model.setScaleToFit(true, dimensions);
|
||||
}
|
||||
_updateModel = true;
|
||||
}
|
||||
|
||||
QScriptValue texturesValue = properties.property("textures");
|
||||
if (texturesValue.isValid()) {
|
||||
if (texturesValue.isValid() && texturesValue.toVariant().canConvert(QVariant::Map)) {
|
||||
QVariantMap textureMap = texturesValue.toVariant().toMap();
|
||||
foreach(const QString& key, textureMap.keys()) {
|
||||
|
||||
|
@ -161,22 +132,12 @@ void ModelOverlay::setProperties(const QScriptValue &properties) {
|
|||
_modelTextures[key] = newTextureURL; // Keep local track of textures for getProperty()
|
||||
}
|
||||
}
|
||||
|
||||
if (properties.property("position").isValid()) {
|
||||
_updateModel = true;
|
||||
}
|
||||
}
|
||||
|
||||
QScriptValue ModelOverlay::getProperty(const QString& property) {
|
||||
if (property == "url") {
|
||||
return _url.toString();
|
||||
}
|
||||
if (property == "scale") {
|
||||
return _scale;
|
||||
}
|
||||
if (property == "rotation") {
|
||||
return quatToScriptValue(_scriptEngine, _rotation);
|
||||
}
|
||||
if (property == "dimensions") {
|
||||
return vec3toScriptValue(_scriptEngine, _model.getScaleToFitDimensions());
|
||||
}
|
||||
|
@ -192,7 +153,7 @@ QScriptValue ModelOverlay::getProperty(const QString& property) {
|
|||
}
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
return Volume3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
bool ModelOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
|
||||
#include <Model.h>
|
||||
|
||||
#include "Base3DOverlay.h"
|
||||
#include "Volume3DOverlay.h"
|
||||
|
||||
class ModelOverlay : public Base3DOverlay {
|
||||
class ModelOverlay : public Volume3DOverlay {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ModelOverlay();
|
||||
|
@ -41,9 +41,6 @@ private:
|
|||
QVariantMap _modelTextures;
|
||||
|
||||
QUrl _url;
|
||||
glm::quat _rotation;
|
||||
float _scale;
|
||||
|
||||
bool _updateModel;
|
||||
};
|
||||
|
||||
|
|
|
@ -8,12 +8,13 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include "Overlay.h"
|
||||
|
||||
#include <NumericalConstants.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
static const xColor DEFAULT_OVERLAY_COLOR = { 255, 255, 255 };
|
||||
static const float DEFAULT_ALPHA = 0.7f;
|
||||
|
||||
Overlay::Overlay() :
|
||||
_renderItemID(render::Item::INVALID_ITEM_ID),
|
||||
|
|
|
@ -14,18 +14,11 @@
|
|||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QRect>
|
||||
#include <QScriptValue>
|
||||
#include <QString>
|
||||
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <SharedUtil.h> // for xColor
|
||||
#include <RenderArgs.h>
|
||||
#include <AABox.h>
|
||||
#include <render/Scene.h>
|
||||
|
||||
const xColor DEFAULT_OVERLAY_COLOR = { 255, 255, 255 };
|
||||
const float DEFAULT_ALPHA = 0.7f;
|
||||
class QScriptEngine;
|
||||
class QScriptValue;
|
||||
|
||||
class Overlay : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -37,7 +30,6 @@ public:
|
|||
};
|
||||
|
||||
typedef std::shared_ptr<Overlay> Pointer;
|
||||
|
||||
typedef render::Payload<Overlay> Payload;
|
||||
typedef std::shared_ptr<render::Item::PayloadInterface> PayloadPointer;
|
||||
|
||||
|
@ -47,6 +39,8 @@ public:
|
|||
void init(QScriptEngine* scriptEngine);
|
||||
virtual void update(float deltatime) {}
|
||||
virtual void render(RenderArgs* args) = 0;
|
||||
|
||||
virtual AABox getBounds() const = 0;
|
||||
|
||||
virtual bool addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
|
||||
virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
|
||||
|
|
|
@ -8,16 +8,9 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "Overlay2D.h"
|
||||
|
||||
|
||||
Overlay2D::Overlay2D() {
|
||||
}
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
Overlay2D::Overlay2D(const Overlay2D* overlay2D) :
|
||||
Overlay(overlay2D),
|
||||
|
@ -25,7 +18,9 @@ Overlay2D::Overlay2D(const Overlay2D* overlay2D) :
|
|||
{
|
||||
}
|
||||
|
||||
Overlay2D::~Overlay2D() {
|
||||
AABox Overlay2D::getBounds() const {
|
||||
return AABox(glm::vec3(_bounds.x(), _bounds.y(), 0.0f),
|
||||
glm::vec3(_bounds.width(), _bounds.height(), 0.01f));
|
||||
}
|
||||
|
||||
void Overlay2D::setProperties(const QScriptValue& properties) {
|
||||
|
@ -40,7 +35,7 @@ void Overlay2D::setProperties(const QScriptValue& properties) {
|
|||
boundsRect.setHeight(bounds.property("height").toVariant().toInt());
|
||||
setBounds(boundsRect);
|
||||
} else {
|
||||
QRect oldBounds = getBounds();
|
||||
QRect oldBounds = _bounds;
|
||||
QRect newBounds = oldBounds;
|
||||
|
||||
if (properties.property("x").isValid()) {
|
||||
|
|
|
@ -15,10 +15,6 @@
|
|||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QRect>
|
||||
#include <QScriptValue>
|
||||
#include <QString>
|
||||
|
||||
#include <SharedUtil.h> // for xColor
|
||||
|
||||
#include "Overlay.h"
|
||||
|
||||
|
@ -26,9 +22,10 @@ class Overlay2D : public Overlay {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Overlay2D();
|
||||
Overlay2D() {}
|
||||
Overlay2D(const Overlay2D* overlay2D);
|
||||
~Overlay2D();
|
||||
|
||||
virtual AABox getBounds() const;
|
||||
|
||||
virtual bool is3D() const { return false; }
|
||||
|
||||
|
@ -37,8 +34,8 @@ public:
|
|||
int getY() const { return _bounds.y(); }
|
||||
int getWidth() const { return _bounds.width(); }
|
||||
int getHeight() const { return _bounds.height(); }
|
||||
const QRect& getBounds() const { return _bounds; }
|
||||
|
||||
const QRect& getBoundingRect() const { return _bounds; }
|
||||
|
||||
// setters
|
||||
void setX(int x) { _bounds.setX(x); }
|
||||
void setY(int y) { _bounds.setY(y); }
|
||||
|
|
|
@ -8,14 +8,13 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Overlays.h"
|
||||
|
||||
#include <QScriptValueIterator>
|
||||
|
||||
#include <limits>
|
||||
#include <typeinfo>
|
||||
|
||||
#include <Application.h>
|
||||
#include <avatar/AvatarManager.h>
|
||||
#include <LODManager.h>
|
||||
#include <render/Scene.h>
|
||||
|
||||
#include "BillboardOverlay.h"
|
||||
|
@ -25,7 +24,6 @@
|
|||
#include "Line3DOverlay.h"
|
||||
#include "LocalModelsOverlay.h"
|
||||
#include "ModelOverlay.h"
|
||||
#include "Overlays.h"
|
||||
#include "Rectangle3DOverlay.h"
|
||||
#include "Sphere3DOverlay.h"
|
||||
#include "Grid3DOverlay.h"
|
||||
|
@ -37,7 +35,6 @@ Overlays::Overlays() : _nextOverlayID(1) {
|
|||
}
|
||||
|
||||
Overlays::~Overlays() {
|
||||
|
||||
{
|
||||
QWriteLocker lock(&_lock);
|
||||
QWriteLocker deleteLock(&_deleteLock);
|
||||
|
@ -99,9 +96,6 @@ void Overlays::cleanupOverlaysToDelete() {
|
|||
|
||||
void Overlays::renderHUD(RenderArgs* renderArgs) {
|
||||
QReadLocker lock(&_lock);
|
||||
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
|
||||
foreach(Overlay::Pointer thisOverlay, _overlaysHUD) {
|
||||
if (thisOverlay->is3D()) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
@ -284,7 +278,7 @@ unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) {
|
|||
} else {
|
||||
Overlay2D* thisOverlay = static_cast<Overlay2D*>(i.value().get());
|
||||
if (thisOverlay->getVisible() && thisOverlay->isLoaded() &&
|
||||
thisOverlay->getBounds().contains(pointCopy.x, pointCopy.y, false)) {
|
||||
thisOverlay->getBoundingRect().contains(pointCopy.x, pointCopy.y, false)) {
|
||||
return thisID;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,13 +11,13 @@
|
|||
#ifndef hifi_Overlays_h
|
||||
#define hifi_Overlays_h
|
||||
|
||||
#include <QString>
|
||||
#include <QReadWriteLock>
|
||||
#include <QScriptValue>
|
||||
#include <QSignalMapper>
|
||||
|
||||
#include "Base3DOverlay.h"
|
||||
#include "Overlay.h"
|
||||
|
||||
class PickRay;
|
||||
|
||||
class OverlayPropertyResult {
|
||||
public:
|
||||
OverlayPropertyResult();
|
||||
|
@ -48,9 +48,11 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, R
|
|||
|
||||
class Overlays : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Overlays();
|
||||
~Overlays();
|
||||
|
||||
void init();
|
||||
void update(float deltatime);
|
||||
void renderHUD(RenderArgs* renderArgs);
|
||||
|
|
|
@ -35,8 +35,8 @@
|
|||
|
||||
namespace render {
|
||||
template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay) {
|
||||
if (overlay->is3D() && !static_cast<Base3DOverlay*>(overlay.get())->getDrawOnHUD()) {
|
||||
if (static_cast<Base3DOverlay*>(overlay.get())->getDrawInFront()) {
|
||||
if (overlay->is3D() && !std::dynamic_pointer_cast<Base3DOverlay>(overlay)->getDrawOnHUD()) {
|
||||
if (std::dynamic_pointer_cast<Base3DOverlay>(overlay)->getDrawInFront()) {
|
||||
return ItemKey::Builder().withTypeShape().withLayered().build();
|
||||
} else {
|
||||
return ItemKey::Builder::opaqueShape();
|
||||
|
@ -46,12 +46,7 @@ namespace render {
|
|||
}
|
||||
}
|
||||
template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay) {
|
||||
if (overlay->is3D()) {
|
||||
return static_cast<Base3DOverlay*>(overlay.get())->getBounds();
|
||||
} else {
|
||||
QRect bounds = static_cast<Overlay2D*>(overlay.get())->getBounds();
|
||||
return AABox(glm::vec3(bounds.x(), bounds.y(), 0.0f), glm::vec3(bounds.width(), bounds.height(), 0.1f));
|
||||
}
|
||||
return overlay->getBounds();
|
||||
}
|
||||
template <> int payloadGetLayer(const Overlay::Pointer& overlay) {
|
||||
// MAgic number while we are defining the layering mechanism:
|
||||
|
@ -59,7 +54,7 @@ namespace render {
|
|||
const int LAYER_3D_FRONT = 1;
|
||||
const int LAYER_3D = 0;
|
||||
if (overlay->is3D()) {
|
||||
return (static_cast<Base3DOverlay*>(overlay.get())->getDrawInFront() ? LAYER_3D_FRONT : LAYER_3D);
|
||||
return (std::dynamic_pointer_cast<Base3DOverlay>(overlay)->getDrawInFront() ? LAYER_3D_FRONT : LAYER_3D);
|
||||
} else {
|
||||
return LAYER_2D;
|
||||
}
|
||||
|
|
|
@ -8,32 +8,24 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <PlaneShape.h>
|
||||
#include <RayIntersectionInfo.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <StreamUtils.h>
|
||||
|
||||
#include "GeometryUtil.h"
|
||||
|
||||
#include "Planar3DOverlay.h"
|
||||
|
||||
const float DEFAULT_SIZE = 1.0f;
|
||||
|
||||
Planar3DOverlay::Planar3DOverlay() :
|
||||
_dimensions(glm::vec2(DEFAULT_SIZE, DEFAULT_SIZE))
|
||||
{
|
||||
}
|
||||
#include <Extents.h>
|
||||
#include <GeometryUtil.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
Planar3DOverlay::Planar3DOverlay(const Planar3DOverlay* planar3DOverlay) :
|
||||
Base3DOverlay(planar3DOverlay),
|
||||
_dimensions(planar3DOverlay->_dimensions)
|
||||
Base3DOverlay(planar3DOverlay)
|
||||
{
|
||||
}
|
||||
|
||||
Planar3DOverlay::~Planar3DOverlay() {
|
||||
AABox Planar3DOverlay::getBounds() const {
|
||||
auto halfDimensions = glm::vec3{_dimensions / 2.0f, 0.01f};
|
||||
|
||||
auto extents = Extents{-halfDimensions, halfDimensions};
|
||||
extents.transform(_transform);
|
||||
|
||||
return AABox(extents);
|
||||
}
|
||||
|
||||
void Planar3DOverlay::setProperties(const QScriptValue& properties) {
|
||||
|
@ -86,7 +78,7 @@ void Planar3DOverlay::setProperties(const QScriptValue& properties) {
|
|||
|
||||
QScriptValue Planar3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "dimensions" || property == "scale" || property == "size") {
|
||||
return vec2toScriptValue(_scriptEngine, _dimensions);
|
||||
return vec2toScriptValue(_scriptEngine, getDimensions());
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
|
@ -94,5 +86,5 @@ QScriptValue Planar3DOverlay::getProperty(const QString& property) {
|
|||
|
||||
bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face) {
|
||||
return findRayRectangleIntersection(origin, direction, _rotation, _position, _dimensions, distance);
|
||||
return findRayRectangleIntersection(origin, direction, getRotation(), getPosition(), getDimensions(), distance);
|
||||
}
|
||||
|
|
|
@ -14,34 +14,28 @@
|
|||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <QScriptValue>
|
||||
|
||||
#include "Base3DOverlay.h"
|
||||
|
||||
class Planar3DOverlay : public Base3DOverlay {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Planar3DOverlay();
|
||||
Planar3DOverlay() {}
|
||||
Planar3DOverlay(const Planar3DOverlay* planar3DOverlay);
|
||||
~Planar3DOverlay();
|
||||
|
||||
// getters
|
||||
const glm::vec2& getDimensions() const { return _dimensions; }
|
||||
|
||||
// setters
|
||||
void setSize(float size) { _dimensions = glm::vec2(size, size); }
|
||||
|
||||
AABox getBounds() const;
|
||||
|
||||
glm::vec2 getDimensions() const { return _dimensions; }
|
||||
void setDimensions(float value) { _dimensions = glm::vec2(value); }
|
||||
void setDimensions(const glm::vec2& value) { _dimensions = value; }
|
||||
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face);
|
||||
|
||||
|
||||
protected:
|
||||
glm::vec2 _dimensions;
|
||||
glm::vec2 _dimensions{1.0f, 1.0f};
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -11,12 +11,12 @@
|
|||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include "Rectangle3DOverlay.h"
|
||||
|
||||
#include <GeometryCache.h>
|
||||
#include <GlowEffect.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "Rectangle3DOverlay.h"
|
||||
|
||||
Rectangle3DOverlay::Rectangle3DOverlay() :
|
||||
_geometryCacheID(DependencyManager::get<GeometryCache>()->allocateID())
|
||||
{
|
||||
|
|
|
@ -17,17 +17,12 @@
|
|||
#include "Sphere3DOverlay.h"
|
||||
#include "Application.h"
|
||||
|
||||
Sphere3DOverlay::Sphere3DOverlay() {
|
||||
}
|
||||
|
||||
Sphere3DOverlay::Sphere3DOverlay(const Sphere3DOverlay* Sphere3DOverlay) :
|
||||
Volume3DOverlay(Sphere3DOverlay)
|
||||
{
|
||||
}
|
||||
|
||||
Sphere3DOverlay::~Sphere3DOverlay() {
|
||||
}
|
||||
|
||||
void Sphere3DOverlay::render(RenderArgs* args) {
|
||||
if (!_visible) {
|
||||
return; // do nothing if we're not visible
|
||||
|
@ -42,11 +37,8 @@ void Sphere3DOverlay::render(RenderArgs* args) {
|
|||
auto batch = args->_batch;
|
||||
|
||||
if (batch) {
|
||||
Transform transform;
|
||||
transform.setTranslation(_position);
|
||||
transform.setRotation(_rotation);
|
||||
transform.setScale(_dimensions);
|
||||
|
||||
Transform transform = _transform;
|
||||
transform.postScale(getDimensions());
|
||||
batch->setModelTransform(transform);
|
||||
DependencyManager::get<GeometryCache>()->renderSphere(*batch, 1.0f, SLICES, SLICES, sphereColor, _isSolid);
|
||||
} else {
|
||||
|
|
|
@ -17,9 +17,9 @@ class Sphere3DOverlay : public Volume3DOverlay {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Sphere3DOverlay();
|
||||
Sphere3DOverlay() {}
|
||||
Sphere3DOverlay(const Sphere3DOverlay* Sphere3DOverlay);
|
||||
~Sphere3DOverlay();
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
virtual Sphere3DOverlay* createClone() const;
|
||||
|
|
|
@ -11,14 +11,17 @@
|
|||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include "Application.h"
|
||||
#include "Text3DOverlay.h"
|
||||
|
||||
#include <RenderDeferredTask.h>
|
||||
#include <TextRenderer3D.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 };
|
||||
const float DEFAULT_BACKGROUND_ALPHA = 0.7f;
|
||||
const float DEFAULT_MARGIN = 0.1f;
|
||||
const int FIXED_FONT_POINT_SIZE = 40;
|
||||
const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 80.0f; // this is a ratio determined through experimentation
|
||||
const float LINE_SCALE_RATIO = 1.2f;
|
||||
|
||||
|
@ -32,6 +35,7 @@ Text3DOverlay::Text3DOverlay() :
|
|||
_bottomMargin(DEFAULT_MARGIN),
|
||||
_isFacingAvatar(false)
|
||||
{
|
||||
_textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE);
|
||||
}
|
||||
|
||||
Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) :
|
||||
|
@ -46,6 +50,7 @@ Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) :
|
|||
_bottomMargin(text3DOverlay->_bottomMargin),
|
||||
_isFacingAvatar(text3DOverlay->_isFacingAvatar)
|
||||
{
|
||||
_textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE);
|
||||
}
|
||||
|
||||
Text3DOverlay::~Text3DOverlay() {
|
||||
|
@ -77,58 +82,58 @@ void Text3DOverlay::render(RenderArgs* args) {
|
|||
return; // do nothing if we're not visible
|
||||
}
|
||||
|
||||
auto batch = args->_batch;
|
||||
|
||||
if (batch) {
|
||||
glm::quat rotation;
|
||||
|
||||
if (_isFacingAvatar) {
|
||||
// rotate about vertical to face the camera
|
||||
rotation = Application::getInstance()->getCamera()->getRotation();
|
||||
} else {
|
||||
rotation = getRotation();
|
||||
}
|
||||
|
||||
Transform transform;
|
||||
transform.setTranslation(_position);
|
||||
transform.setRotation(rotation);
|
||||
|
||||
batch->setModelTransform(transform);
|
||||
|
||||
const float MAX_COLOR = 255.0f;
|
||||
xColor backgroundColor = getBackgroundColor();
|
||||
glm::vec4 quadColor(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR,
|
||||
getBackgroundAlpha());
|
||||
|
||||
glm::vec2 dimensions = getDimensions();
|
||||
glm::vec2 halfDimensions = dimensions * 0.5f;
|
||||
|
||||
const float SLIGHTLY_BEHIND = -0.005f;
|
||||
|
||||
glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND);
|
||||
glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND);
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(*batch, topLeft, bottomRight, quadColor);
|
||||
|
||||
// Same font properties as textSize()
|
||||
float maxHeight = (float)_textRenderer->computeExtent("Xy").y * LINE_SCALE_RATIO;
|
||||
|
||||
float scaleFactor = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight;
|
||||
|
||||
glm::vec2 clipMinimum(0.0f, 0.0f);
|
||||
glm::vec2 clipDimensions((dimensions.x - (_leftMargin + _rightMargin)) / scaleFactor,
|
||||
(dimensions.y - (_topMargin + _bottomMargin)) / scaleFactor);
|
||||
|
||||
transform.setTranslation(_position);
|
||||
transform.postTranslate(glm::vec3(-(halfDimensions.x - _leftMargin) , halfDimensions.y - _topMargin, 0.01f));
|
||||
transform.setScale(scaleFactor);
|
||||
batch->setModelTransform(transform);
|
||||
|
||||
glm::vec4 textColor = { _color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, getAlpha() };
|
||||
_textRenderer->draw(*batch, 0, 0, _text, textColor);
|
||||
|
||||
batch->setPipeline(DrawOverlay3D::getOpaquePipeline());
|
||||
|
||||
Q_ASSERT(args->_batch);
|
||||
auto& batch = *args->_batch;
|
||||
|
||||
glm::quat rotation;
|
||||
|
||||
if (_isFacingAvatar) {
|
||||
// rotate about vertical to face the camera
|
||||
rotation = args->_viewFrustum->getOrientation();
|
||||
} else {
|
||||
rotation = getRotation();
|
||||
}
|
||||
|
||||
|
||||
Transform transform;
|
||||
transform.setTranslation(getPosition());
|
||||
transform.setRotation(rotation);
|
||||
transform.setScale(getScale());
|
||||
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
const float MAX_COLOR = 255.0f;
|
||||
xColor backgroundColor = getBackgroundColor();
|
||||
glm::vec4 quadColor(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR,
|
||||
getBackgroundAlpha());
|
||||
|
||||
glm::vec2 dimensions = getDimensions();
|
||||
glm::vec2 halfDimensions = dimensions * 0.5f;
|
||||
|
||||
const float SLIGHTLY_BEHIND = -0.005f;
|
||||
|
||||
glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND);
|
||||
glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND);
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, quadColor);
|
||||
|
||||
// Same font properties as textSize()
|
||||
float maxHeight = (float)_textRenderer->computeExtent("Xy").y * LINE_SCALE_RATIO;
|
||||
|
||||
float scaleFactor = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight;
|
||||
|
||||
glm::vec2 clipMinimum(0.0f, 0.0f);
|
||||
glm::vec2 clipDimensions((dimensions.x - (_leftMargin + _rightMargin)) / scaleFactor,
|
||||
(dimensions.y - (_topMargin + _bottomMargin)) / scaleFactor);
|
||||
|
||||
transform.setTranslation(getPosition());
|
||||
transform.postTranslate(glm::vec3(-(halfDimensions.x - _leftMargin) , halfDimensions.y - _topMargin, 0.01f));
|
||||
transform.setScale(scaleFactor);
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
glm::vec4 textColor = { _color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, getAlpha() };
|
||||
_textRenderer->draw(batch, 0, 0, _text, textColor);
|
||||
|
||||
batch.setPipeline(DrawOverlay3D::getOpaquePipeline());
|
||||
}
|
||||
|
||||
void Text3DOverlay::setProperties(const QScriptValue& properties) {
|
||||
|
|
|
@ -16,12 +16,9 @@
|
|||
|
||||
#include <QString>
|
||||
|
||||
#include <RenderArgs.h>
|
||||
#include <TextRenderer3D.h>
|
||||
|
||||
#include "Planar3DOverlay.h"
|
||||
|
||||
const int FIXED_FONT_POINT_SIZE = 40;
|
||||
class TextRenderer3D;
|
||||
|
||||
class Text3DOverlay : public Planar3DOverlay {
|
||||
Q_OBJECT
|
||||
|
@ -60,7 +57,7 @@ public:
|
|||
virtual Text3DOverlay* createClone() const;
|
||||
|
||||
private:
|
||||
TextRenderer3D* _textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE);
|
||||
TextRenderer3D* _textRenderer = nullptr;
|
||||
|
||||
QString _text;
|
||||
xColor _backgroundColor;
|
||||
|
|
|
@ -11,11 +11,14 @@
|
|||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include "TextOverlay.h"
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <TextRenderer.h>
|
||||
|
||||
#include "TextOverlay.h"
|
||||
|
||||
TextOverlay::TextOverlay() :
|
||||
_backgroundColor(DEFAULT_BACKGROUND_COLOR),
|
||||
|
|
|
@ -14,14 +14,10 @@
|
|||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QRect>
|
||||
#include <QScriptValue>
|
||||
#include <QString>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
#include <TextRenderer.h>
|
||||
|
||||
#include "Overlay.h"
|
||||
#include "Overlay2D.h"
|
||||
|
||||
const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 };
|
||||
|
@ -30,6 +26,8 @@ const int DEFAULT_MARGIN = 10;
|
|||
const int DEFAULT_FONTSIZE = 11;
|
||||
const int DEFAULT_FONT_WEIGHT = 50;
|
||||
|
||||
class TextRenderer;
|
||||
|
||||
class TextOverlay : public Overlay2D {
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -8,32 +8,22 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtx/transform.hpp>
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <AABox.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <StreamUtils.h>
|
||||
|
||||
#include "Volume3DOverlay.h"
|
||||
|
||||
const float DEFAULT_SIZE = 1.0f;
|
||||
|
||||
Volume3DOverlay::Volume3DOverlay() :
|
||||
_dimensions(glm::vec3(DEFAULT_SIZE, DEFAULT_SIZE, DEFAULT_SIZE))
|
||||
{
|
||||
}
|
||||
#include <Extents.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
Volume3DOverlay::Volume3DOverlay(const Volume3DOverlay* volume3DOverlay) :
|
||||
Base3DOverlay(volume3DOverlay),
|
||||
_dimensions(volume3DOverlay->_dimensions)
|
||||
Base3DOverlay(volume3DOverlay)
|
||||
{
|
||||
}
|
||||
|
||||
Volume3DOverlay::~Volume3DOverlay() {
|
||||
AABox Volume3DOverlay::getBounds() const {
|
||||
auto extents = Extents{_localBoundingBox};
|
||||
extents.rotate(getRotation());
|
||||
extents.shiftBy(getPosition());
|
||||
|
||||
return AABox(extents);
|
||||
}
|
||||
|
||||
void Volume3DOverlay::setProperties(const QScriptValue& properties) {
|
||||
|
@ -58,26 +48,30 @@ void Volume3DOverlay::setProperties(const QScriptValue& properties) {
|
|||
QScriptValue z = dimensions.property("z");
|
||||
|
||||
|
||||
if (x.isValid() && y.isValid() && z.isValid()) {
|
||||
newDimensions.x = x.toVariant().toFloat();
|
||||
newDimensions.y = y.toVariant().toFloat();
|
||||
newDimensions.z = z.toVariant().toFloat();
|
||||
if (x.isValid() && x.isNumber() &&
|
||||
y.isValid() && y.isNumber() &&
|
||||
z.isValid() && z.isNumber()) {
|
||||
newDimensions.x = x.toNumber();
|
||||
newDimensions.y = y.toNumber();
|
||||
newDimensions.z = z.toNumber();
|
||||
validDimensions = true;
|
||||
} else {
|
||||
QScriptValue width = dimensions.property("width");
|
||||
QScriptValue height = dimensions.property("height");
|
||||
QScriptValue depth = dimensions.property("depth");
|
||||
if (width.isValid() && height.isValid() && depth.isValid()) {
|
||||
newDimensions.x = width.toVariant().toFloat();
|
||||
newDimensions.y = height.toVariant().toFloat();
|
||||
newDimensions.z = depth.toVariant().toFloat();
|
||||
if (width.isValid() && width.isNumber() &&
|
||||
height.isValid() && height.isNumber() &&
|
||||
depth.isValid() && depth.isNumber()) {
|
||||
newDimensions.x = width.toNumber();
|
||||
newDimensions.y = height.toNumber();
|
||||
newDimensions.z = depth.toNumber();
|
||||
validDimensions = true;
|
||||
}
|
||||
}
|
||||
|
||||
// size, scale, dimensions is special, it might just be a single scalar, check that here
|
||||
if (!validDimensions && dimensions.isNumber()) {
|
||||
float size = dimensions.toVariant().toFloat();
|
||||
float size = dimensions.toNumber();
|
||||
newDimensions.x = size;
|
||||
newDimensions.y = size;
|
||||
newDimensions.z = size;
|
||||
|
@ -92,7 +86,7 @@ void Volume3DOverlay::setProperties(const QScriptValue& properties) {
|
|||
|
||||
QScriptValue Volume3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "dimensions" || property == "scale" || property == "size") {
|
||||
return vec3toScriptValue(_scriptEngine, _dimensions);
|
||||
return vec3toScriptValue(_scriptEngine, getDimensions());
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
|
@ -100,24 +94,14 @@ QScriptValue Volume3DOverlay::getProperty(const QString& property) {
|
|||
|
||||
bool Volume3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face) {
|
||||
|
||||
// extents is the entity relative, scaled, centered extents of the entity
|
||||
glm::vec3 position = getPosition();
|
||||
glm::mat4 rotation = glm::mat4_cast(getRotation());
|
||||
glm::mat4 translation = glm::translate(position);
|
||||
glm::mat4 entityToWorldMatrix = translation * rotation;
|
||||
glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix);
|
||||
|
||||
glm::vec3 dimensions = _dimensions;
|
||||
glm::vec3 corner = dimensions * -0.5f; // since we're going to do the ray picking in the overlay frame of reference
|
||||
AABox overlayFrameBox(corner, dimensions);
|
||||
glm::mat4 worldToEntityMatrix;
|
||||
_transform.getInverseMatrix(worldToEntityMatrix);
|
||||
|
||||
glm::vec3 overlayFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f));
|
||||
glm::vec3 overlayFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f));
|
||||
|
||||
// we can use the AABox's ray intersection by mapping our origin and direction into the overlays frame
|
||||
// and testing intersection there.
|
||||
if (overlayFrameBox.findRayIntersection(overlayFrameOrigin, overlayFrameDirection, distance, face)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return _localBoundingBox.findRayIntersection(overlayFrameOrigin, overlayFrameDirection, distance, face);
|
||||
}
|
||||
|
|
|
@ -14,36 +14,29 @@
|
|||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <QScriptValue>
|
||||
|
||||
#include "Base3DOverlay.h"
|
||||
|
||||
class Volume3DOverlay : public Base3DOverlay {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Volume3DOverlay();
|
||||
Volume3DOverlay() {}
|
||||
Volume3DOverlay(const Volume3DOverlay* volume3DOverlay);
|
||||
~Volume3DOverlay();
|
||||
|
||||
// getters
|
||||
const glm::vec3& getCenter() const { return _position; } // TODO: consider adding registration point!!
|
||||
glm::vec3 getCorner() const { return _position - (_dimensions * 0.5f); } // TODO: consider adding registration point!!
|
||||
const glm::vec3& getDimensions() const { return _dimensions; }
|
||||
|
||||
// setters
|
||||
void setSize(float size) { _dimensions = glm::vec3(size, size, size); }
|
||||
void setDimensions(const glm::vec3& value) { _dimensions = value; }
|
||||
|
||||
virtual AABox getBounds() const;
|
||||
|
||||
const glm::vec3& getDimensions() const { return _localBoundingBox.getDimensions(); }
|
||||
void setDimensions(float value) { _localBoundingBox.setBox(glm::vec3(-value / 2.0f), value); }
|
||||
void setDimensions(const glm::vec3& value) { _localBoundingBox.setBox(-value / 2.0f, value); }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face);
|
||||
|
||||
|
||||
protected:
|
||||
glm::vec3 _dimensions;
|
||||
// Centered local bounding box
|
||||
AABox _localBoundingBox;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -30,8 +30,7 @@
|
|||
const float DEFAULT_KEYHOLE_RADIUS = 3.0f;
|
||||
const float DEFAULT_FIELD_OF_VIEW_DEGREES = 45.0f;
|
||||
const float DEFAULT_ASPECT_RATIO = 16.0f/9.0f;
|
||||
//const float DEFAULT_NEAR_CLIP = 0.08f;
|
||||
const float DEFAULT_NEAR_CLIP = 0.25f;
|
||||
const float DEFAULT_NEAR_CLIP = 0.08f;
|
||||
const float DEFAULT_FAR_CLIP = (float)TREE_SCALE;
|
||||
|
||||
class ViewFrustum {
|
||||
|
|
|
@ -106,6 +106,9 @@ public:
|
|||
glm::quat computeParentRotation() const;
|
||||
glm::quat computeVisibleParentRotation() const;
|
||||
|
||||
void setTransform(const glm::mat4& transform) { _transform = transform; }
|
||||
void setVisibleTransform(const glm::mat4& transform) { _visibleTransform = transform; }
|
||||
|
||||
private:
|
||||
void setRotationInConstrainedFrameInternal(const glm::quat& targetRotation);
|
||||
/// debug helper function
|
||||
|
|
|
@ -1102,9 +1102,11 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo
|
|||
_readyWhenAdded = false; // reset out render items.
|
||||
_needsReload = true;
|
||||
invalidCalculatedMeshBoxes();
|
||||
|
||||
|
||||
_url = url;
|
||||
|
||||
onInvalidate();
|
||||
|
||||
// if so instructed, keep the current geometry until the new one is loaded
|
||||
_nextBaseGeometry = _nextGeometry = DependencyManager::get<GeometryCache>()->getGeometry(url, fallback, delayLoad);
|
||||
_nextLODHysteresis = NetworkGeometry::NO_HYSTERESIS;
|
||||
|
@ -1368,6 +1370,7 @@ void Model::simulate(float deltaTime, bool fullUpdate) {
|
|||
// because ray picking needs valid boxes to work
|
||||
_calculatedMeshBoxesValid = false;
|
||||
_calculatedMeshTrianglesValid = false;
|
||||
onInvalidate();
|
||||
|
||||
// check for scale to fit
|
||||
if (_scaleToFit && !_scaledToFit) {
|
||||
|
@ -1380,6 +1383,26 @@ void Model::simulate(float deltaTime, bool fullUpdate) {
|
|||
}
|
||||
}
|
||||
|
||||
void Model::updateClusterMatrices() {
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
glm::mat4 modelToWorld = glm::mat4_cast(_rotation);
|
||||
for (int i = 0; i < _meshStates.size(); i++) {
|
||||
MeshState& state = _meshStates[i];
|
||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||
if (_showTrueJointTransforms) {
|
||||
for (int j = 0; j < mesh.clusters.size(); j++) {
|
||||
const FBXCluster& cluster = mesh.clusters.at(j);
|
||||
state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getTransform() * cluster.inverseBindMatrix;
|
||||
}
|
||||
} else {
|
||||
for (int j = 0; j < mesh.clusters.size(); j++) {
|
||||
const FBXCluster& cluster = mesh.clusters.at(j);
|
||||
state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getVisibleTransform() * cluster.inverseBindMatrix;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Model::simulateInternal(float deltaTime) {
|
||||
// update the world space transforms for all joints
|
||||
|
||||
|
@ -2120,6 +2143,34 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f
|
|||
}
|
||||
}
|
||||
|
||||
bool Model::initWhenReady(render::ScenePointer scene) {
|
||||
if (isActive() && isRenderable() && !_meshGroupsKnown && isLoadedWithTextures()) {
|
||||
segregateMeshGroups();
|
||||
|
||||
render::PendingChanges pendingChanges;
|
||||
|
||||
foreach (auto renderItem, _transparentRenderItems) {
|
||||
auto item = scene->allocateID();
|
||||
auto renderData = MeshPartPayload::Pointer(renderItem);
|
||||
auto renderPayload = render::PayloadPointer(new MeshPartPayload::Payload(renderData));
|
||||
_renderItems.insert(item, renderPayload);
|
||||
pendingChanges.resetItem(item, renderPayload);
|
||||
}
|
||||
|
||||
foreach (auto renderItem, _opaqueRenderItems) {
|
||||
auto item = scene->allocateID();
|
||||
auto renderData = MeshPartPayload::Pointer(renderItem);
|
||||
auto renderPayload = render::PayloadPointer(new MeshPartPayload::Payload(renderData));
|
||||
_renderItems.insert(item, renderPayload);
|
||||
pendingChanges.resetItem(item, renderPayload);
|
||||
}
|
||||
scene->enqueuePendingChanges(pendingChanges);
|
||||
|
||||
_readyWhenAdded = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ModelBlender::ModelBlender() :
|
||||
_pendingBlenders(0) {
|
||||
|
|
|
@ -240,6 +240,8 @@ public:
|
|||
AABox getPartBounds(int meshIndex, int partIndex);
|
||||
void renderPart(RenderArgs* args, int meshIndex, int partIndex, bool translucent);
|
||||
|
||||
bool initWhenReady(render::ScenePointer scene);
|
||||
|
||||
protected:
|
||||
QSharedPointer<NetworkGeometry> _geometry;
|
||||
|
||||
|
@ -312,6 +314,12 @@ protected:
|
|||
_calculatedMeshTrianglesValid = false;
|
||||
}
|
||||
|
||||
// rebuild the clusterMatrices from the current jointStates
|
||||
void updateClusterMatrices();
|
||||
|
||||
// hook for derived classes to be notified when setUrl invalidates the current model.
|
||||
virtual void onInvalidate() {};
|
||||
|
||||
private:
|
||||
|
||||
friend class AnimationHandle;
|
||||
|
|
|
@ -10,12 +10,14 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Extents.h"
|
||||
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <glm/gtx/transform.hpp>
|
||||
|
||||
#include "AABox.h"
|
||||
#include "Extents.h"
|
||||
#include "Transform.h"
|
||||
|
||||
void Extents::reset() {
|
||||
minimum = glm::vec3(FLT_MAX);
|
||||
|
@ -78,3 +80,10 @@ void Extents::rotate(const glm::quat& rotation) {
|
|||
glm::max(topRightNearRotated,
|
||||
glm::max(topLeftFarRotated,topRightFarRotated)))))));
|
||||
}
|
||||
|
||||
|
||||
void Extents::transform(const Transform& transform) {
|
||||
scale(transform.getScale());
|
||||
rotate(transform.getRotation());
|
||||
shiftBy(transform.getTranslation());
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "StreamUtils.h"
|
||||
|
||||
class AABox;
|
||||
class Transform;
|
||||
|
||||
class Extents {
|
||||
public:
|
||||
|
@ -56,6 +57,13 @@ public:
|
|||
|
||||
/// rotate the extents around orign by rotation
|
||||
void rotate(const glm::quat& rotation);
|
||||
|
||||
/// scale the extents around orign by scale
|
||||
void scale(float scale) { minimum *= scale; maximum *= scale; }
|
||||
void scale(const glm::vec3& scale) { minimum *= scale; maximum *= scale; }
|
||||
|
||||
// Transform the extents with transform
|
||||
void transform(const Transform& transform);
|
||||
|
||||
glm::vec3 size() const { return maximum - minimum; }
|
||||
float largestDimension() const {glm::vec3 s = size(); return glm::max(s[0], s[1], s[2]); }
|
||||
|
|
Loading…
Reference in a new issue