mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Merge branch 'master' of https://github.com/highfidelity/hifi
This commit is contained in:
commit
2ac42d9a2b
20 changed files with 345 additions and 249 deletions
54
examples/controllers/getHUDLookAtPositionTest.js
Normal file
54
examples/controllers/getHUDLookAtPositionTest.js
Normal file
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
// getHUDLookAtPositionTest.js
|
||||
// examples/controllers
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 2015/12/15
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
|
||||
// This script demonstrates the testing of the HMD.getHUDLookAtPosition--() functions.
|
||||
// If these functions are working correctly, we'd expect to see a 3D cube and a 2D square
|
||||
// follow around the center of the HMD view.
|
||||
|
||||
var cubePosition = { x: 0, y: 0, z: 0 };
|
||||
var cubeSize = 0.03;
|
||||
var cube = Overlays.addOverlay("cube", {
|
||||
position: cubePosition,
|
||||
size: cubeSize,
|
||||
color: { red: 255, green: 0, blue: 0},
|
||||
alpha: 1,
|
||||
solid: false
|
||||
});
|
||||
|
||||
var square = Overlays.addOverlay("text", {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 20,
|
||||
height: 20,
|
||||
color: { red: 255, green: 255, blue: 0},
|
||||
backgroundColor: { red: 255, green: 255, blue: 0},
|
||||
alpha: 1
|
||||
});
|
||||
|
||||
|
||||
Script.update.connect(function(deltaTime) {
|
||||
if (!HMD.active) {
|
||||
return;
|
||||
}
|
||||
var lookAt3D = HMD.getHUDLookAtPosition3D();
|
||||
Overlays.editOverlay(cube, { position: lookAt3D });
|
||||
|
||||
var lookAt2D = HMD.getHUDLookAtPosition2D();
|
||||
Overlays.editOverlay(square, { x: lookAt2D.x, y: lookAt2D.y });
|
||||
});
|
||||
|
||||
Script.scriptEnding.connect(function(){
|
||||
Overlays.deleteOverlay(cube);
|
||||
Overlays.deleteOverlay(square);
|
||||
});
|
||||
|
||||
|
|
@ -116,6 +116,11 @@ var DEFAULT_GRABBABLE_DATA = {
|
|||
invertSolidWhileHeld: false
|
||||
};
|
||||
|
||||
|
||||
// sometimes we want to exclude objects from being picked
|
||||
var USE_BLACKLIST = true;
|
||||
var blacklist = [];
|
||||
|
||||
//we've created various ways of visualizing looking for and moving distant objects
|
||||
var USE_ENTITY_LINES_FOR_SEARCHING = false;
|
||||
var USE_OVERLAY_LINES_FOR_SEARCHING = false;
|
||||
|
@ -226,6 +231,9 @@ function getSpatialOffsetPosition(hand, spatialKey) {
|
|||
position = spatialKey.relativePosition;
|
||||
}
|
||||
|
||||
// add the relative hand center offset
|
||||
var handSizeRatio = calculateHandSizeRatio();
|
||||
position = Vec3.multiply(position, handSizeRatio);
|
||||
return position;
|
||||
}
|
||||
|
||||
|
@ -771,8 +779,14 @@ function MyController(hand) {
|
|||
})
|
||||
}
|
||||
|
||||
var intersection = Entities.findRayIntersection(pickRayBacked, true);
|
||||
var intersection;
|
||||
|
||||
if (USE_BLACKLIST === true && blacklist.length !== 0) {
|
||||
intersection = Entities.findRayIntersection(pickRay, true, [], blacklist);
|
||||
} else {
|
||||
intersection = Entities.findRayIntersection(pickRayBacked, true);
|
||||
}
|
||||
|
||||
if (intersection.intersects) {
|
||||
// the ray is intersecting something we can move.
|
||||
var intersectionDistance = Vec3.distance(pickRay.origin, intersection.intersection);
|
||||
|
@ -1159,14 +1173,16 @@ function MyController(hand) {
|
|||
if (this.state != STATE_NEAR_GRABBING && grabbableData.spatialKey) {
|
||||
// if an object is "equipped" and has a spatialKey, use it.
|
||||
this.ignoreIK = grabbableData.spatialKey.ignoreIK ? grabbableData.spatialKey.ignoreIK : false;
|
||||
if (grabbableData.spatialKey.relativePosition) {
|
||||
this.offsetPosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey);
|
||||
if (grabbableData.spatialKey.relativePosition || grabbableData.spatialKey.rightRelativePosition
|
||||
|| grabbableData.spatialKey.leftRelativePosition) {
|
||||
this.offsetPosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey);
|
||||
} else {
|
||||
this.offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, this.offsetRotation)), offset);
|
||||
}
|
||||
if (grabbableData.spatialKey.relativeRotation) {
|
||||
this.offsetRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey);
|
||||
} else {
|
||||
if (grabbableData.spatialKey.relativeRotation || grabbableData.spatialKey.rightRelativeRotation
|
||||
|| grabbableData.spatialKey.leftRelativeRotation) {
|
||||
this.offsetRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey);
|
||||
} else {
|
||||
this.offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation);
|
||||
}
|
||||
} else {
|
||||
|
@ -1626,6 +1642,7 @@ function update() {
|
|||
|
||||
Messages.subscribe('Hifi-Hand-Disabler');
|
||||
Messages.subscribe('Hifi-Hand-Grab');
|
||||
Messages.subscribe('Hifi-Hand-RayPick-Blacklist');
|
||||
|
||||
handleHandMessages = function(channel, message, sender) {
|
||||
if (sender === MyAvatar.sessionUUID) {
|
||||
|
@ -1649,6 +1666,24 @@ handleHandMessages = function(channel, message, sender) {
|
|||
|
||||
} catch (e) { }
|
||||
}
|
||||
else if (channel === 'Hifi-Hand-RayPick-Blacklist' && sender === MyAvatar.sessionUUID) {
|
||||
try {
|
||||
var data = JSON.parse(message);
|
||||
var action = data.action;
|
||||
var id = data.id;
|
||||
var index = blacklist.indexOf(id);
|
||||
|
||||
if (action === 'add' && index ===-1) {
|
||||
blacklist.push(id);
|
||||
}
|
||||
if (action === 'remove') {
|
||||
if (index > -1) {
|
||||
blacklist.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,13 +40,18 @@ RaveStick = function(spawnPosition) {
|
|||
userData: JSON.stringify({
|
||||
grabbableKey: {
|
||||
spatialKey: {
|
||||
relativePosition: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: -0.1
|
||||
rightRelativePosition: {
|
||||
x: 0.02,
|
||||
y: 0,
|
||||
z: 0
|
||||
},
|
||||
leftRelativePosition: {
|
||||
x: -0.02,
|
||||
y: 0,
|
||||
z: 0
|
||||
},
|
||||
relativeRotation: Quat.fromPitchYawRollDegrees(90, 90, 0)
|
||||
},
|
||||
relativeRotation: Quat.fromPitchYawRollDegrees(90, 90, 0)
|
||||
},
|
||||
invertSolidWhileHeld: true
|
||||
}
|
||||
})
|
||||
|
|
|
@ -271,3 +271,29 @@ hexToRgb = function(hex) {
|
|||
} : null;
|
||||
}
|
||||
|
||||
calculateHandSizeRatio = function() {
|
||||
// Get the ratio of the current avatar's hand to Owen's hand
|
||||
|
||||
var standardCenterHandPoint = 0.11288;
|
||||
var jointNames = MyAvatar.getJointNames();
|
||||
//get distance from handJoint up to leftHandIndex3 as a proxy for center of hand
|
||||
var wristToFingertipDistance = 0;;
|
||||
for (var i = 0; i < jointNames.length; i++) {
|
||||
var jointName = jointNames[i];
|
||||
print(jointName)
|
||||
if (jointName.indexOf("LeftHandIndex") !== -1) {
|
||||
// translations are relative to parent joint, so simply add them together
|
||||
// joints face down the y-axis
|
||||
var translation = MyAvatar.getDefaultJointTranslation(i).y;
|
||||
wristToFingertipDistance += translation;
|
||||
}
|
||||
}
|
||||
// Right now units are in cm, so convert to meters
|
||||
wristToFingertipDistance /= 100;
|
||||
|
||||
var centerHandPoint = wristToFingertipDistance/2;
|
||||
|
||||
// Compare against standard hand (Owen)
|
||||
var handSizeRatio = centerHandPoint/standardCenterHandPoint;
|
||||
return handSizeRatio;
|
||||
}
|
||||
|
|
|
@ -247,4 +247,4 @@ function cleanup() {
|
|||
|
||||
|
||||
// Uncomment this line to delete whiteboard and all associated entity on script close
|
||||
//Script.scriptEnding.connect(cleanup);
|
||||
// Script.scriptEnding.connect(cleanup);
|
||||
|
|
73
examples/rayPickingFilterExample.js
Normal file
73
examples/rayPickingFilterExample.js
Normal file
|
@ -0,0 +1,73 @@
|
|||
//
|
||||
// rayPickingFilterExample.js
|
||||
// examples
|
||||
//
|
||||
// Created by Eric Levin on 12/24/2015
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// This is an example script that demonstrates the use of filtering entities for ray picking
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
|
||||
var center = Vec3.sum(MyAvatar.position, Vec3.multiply(3, Quat.getFront(Camera.getOrientation())));
|
||||
|
||||
var whiteListBox = Entities.addEntity({
|
||||
type: "Box",
|
||||
color: {
|
||||
red: 10,
|
||||
green: 200,
|
||||
blue: 10
|
||||
},
|
||||
dimensions: {
|
||||
x: 0.2,
|
||||
y: 0.2,
|
||||
z: 0.2
|
||||
},
|
||||
position: center
|
||||
});
|
||||
|
||||
var blackListBox = Entities.addEntity({
|
||||
type: "Box",
|
||||
color: {
|
||||
red: 100,
|
||||
green: 10,
|
||||
blue: 10
|
||||
},
|
||||
dimensions: {
|
||||
x: 0.2,
|
||||
y: 0.2,
|
||||
z: 0.2
|
||||
},
|
||||
position: Vec3.sum(center, {
|
||||
x: 0,
|
||||
y: 0.3,
|
||||
z: 0
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
function castRay(event) {
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
// In this example every entity will be pickable except the entities in the blacklist array
|
||||
// the third argument is the whitelist array,and the fourth and final is the blacklist array
|
||||
var pickResults = Entities.findRayIntersection(pickRay, true, [], [blackListBox]);
|
||||
|
||||
// With below example, only entities added to whitelist will be pickable
|
||||
// var pickResults = Entities.findRayIntersection(pickRay, true, [whiteListBox], []);
|
||||
|
||||
if (pickResults.intersects) {
|
||||
print("INTERSECTION!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
Entities.deleteEntity(whiteListBox);
|
||||
Entities.deleteEntity(blackListBox);
|
||||
}
|
||||
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
Controller.mousePressEvent.connect(castRay);
|
|
@ -1207,23 +1207,12 @@ void Application::paintGL() {
|
|||
auto primaryFbo = DependencyManager::get<FramebufferCache>()->getPrimaryFramebuffer();
|
||||
|
||||
renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE;
|
||||
renderArgs._blitFramebuffer = DependencyManager::get<FramebufferCache>()->getSelfieFramebuffer();
|
||||
|
||||
renderRearViewMirror(&renderArgs, _mirrorViewRect);
|
||||
|
||||
renderArgs._blitFramebuffer.reset();
|
||||
renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE;
|
||||
|
||||
{
|
||||
float ratio = ((float)QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale());
|
||||
// Flip the src and destination rect horizontally to do the mirror
|
||||
auto mirrorRect = glm::ivec4(0, 0, _mirrorViewRect.width() * ratio, _mirrorViewRect.height() * ratio);
|
||||
auto mirrorRectDest = glm::ivec4(mirrorRect.z, mirrorRect.y, mirrorRect.x, mirrorRect.w);
|
||||
|
||||
auto selfieFbo = DependencyManager::get<FramebufferCache>()->getSelfieFramebuffer();
|
||||
gpu::doInBatch(renderArgs._context, [=](gpu::Batch& batch) {
|
||||
batch.setFramebuffer(selfieFbo);
|
||||
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
batch.blit(primaryFbo, mirrorRect, selfieFbo, mirrorRectDest);
|
||||
batch.setFramebuffer(nullptr);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -1394,65 +1383,11 @@ void Application::paintGL() {
|
|||
renderArgs._context->setStereoProjections(eyeProjections);
|
||||
renderArgs._context->setStereoViews(eyeOffsets);
|
||||
}
|
||||
renderArgs._blitFramebuffer = finalFramebuffer;
|
||||
displaySide(&renderArgs, _myCamera);
|
||||
|
||||
renderArgs._blitFramebuffer.reset();
|
||||
renderArgs._context->enableStereo(false);
|
||||
|
||||
// Blit primary to final FBO
|
||||
auto primaryFbo = framebufferCache->getPrimaryFramebuffer();
|
||||
|
||||
if (renderArgs._renderMode == RenderArgs::MIRROR_RENDER_MODE) {
|
||||
if (displayPlugin->isStereo()) {
|
||||
gpu::doInBatch(renderArgs._context, [=](gpu::Batch& batch) {
|
||||
gpu::Vec4i srcRectLeft;
|
||||
srcRectLeft.z = size.width() / 2;
|
||||
srcRectLeft.w = size.height();
|
||||
|
||||
gpu::Vec4i srcRectRight;
|
||||
srcRectRight.x = size.width() / 2;
|
||||
srcRectRight.z = size.width();
|
||||
srcRectRight.w = size.height();
|
||||
|
||||
gpu::Vec4i destRectLeft;
|
||||
destRectLeft.x = srcRectLeft.z;
|
||||
destRectLeft.z = srcRectLeft.x;
|
||||
destRectLeft.y = srcRectLeft.y;
|
||||
destRectLeft.w = srcRectLeft.w;
|
||||
|
||||
gpu::Vec4i destRectRight;
|
||||
destRectRight.x = srcRectRight.z;
|
||||
destRectRight.z = srcRectRight.x;
|
||||
destRectRight.y = srcRectRight.y;
|
||||
destRectRight.w = srcRectRight.w;
|
||||
|
||||
batch.setFramebuffer(finalFramebuffer);
|
||||
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(0.0f, 0.0f, 1.0f, 0.0f));
|
||||
// BLit left to right and right to left in stereo
|
||||
batch.blit(primaryFbo, srcRectRight, finalFramebuffer, destRectLeft);
|
||||
batch.blit(primaryFbo, srcRectLeft, finalFramebuffer, destRectRight);
|
||||
});
|
||||
} else {
|
||||
gpu::doInBatch(renderArgs._context, [=](gpu::Batch& batch) {
|
||||
gpu::Vec4i srcRect;
|
||||
srcRect.z = size.width();
|
||||
srcRect.w = size.height();
|
||||
gpu::Vec4i destRect;
|
||||
destRect.x = size.width();
|
||||
destRect.y = 0;
|
||||
destRect.z = 0;
|
||||
destRect.w = size.height();
|
||||
batch.setFramebuffer(finalFramebuffer);
|
||||
batch.blit(primaryFbo, srcRect, finalFramebuffer, destRect);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
gpu::doInBatch(renderArgs._context, [=](gpu::Batch& batch) {
|
||||
gpu::Vec4i rect;
|
||||
rect.z = size.width();
|
||||
rect.w = size.height();
|
||||
batch.setFramebuffer(finalFramebuffer);
|
||||
batch.blit(primaryFbo, rect, finalFramebuffer, rect);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Overlay Composition, needs to occur after screen space effects have completed
|
||||
|
|
|
@ -487,7 +487,8 @@ void EntityTreeRenderer::deleteReleasedModels() {
|
|||
}
|
||||
|
||||
RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType,
|
||||
bool precisionPicking, const QVector<EntityItemID>& entityIdsToInclude) {
|
||||
bool precisionPicking, const QVector<EntityItemID>& entityIdsToInclude,
|
||||
const QVector<EntityItemID>& entityIdsToDiscard) {
|
||||
RayToEntityIntersectionResult result;
|
||||
if (_tree) {
|
||||
EntityTreePointer entityTree = std::static_pointer_cast<EntityTree>(_tree);
|
||||
|
@ -495,7 +496,7 @@ RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(cons
|
|||
OctreeElementPointer element;
|
||||
EntityItemPointer intersectedEntity = NULL;
|
||||
result.intersects = entityTree->findRayIntersection(ray.origin, ray.direction, element, result.distance,
|
||||
result.face, result.surfaceNormal, entityIdsToInclude,
|
||||
result.face, result.surfaceNormal, entityIdsToInclude, entityIdsToDiscard,
|
||||
(void**)&intersectedEntity, lockType, &result.accurate,
|
||||
precisionPicking);
|
||||
if (result.intersects && intersectedEntity) {
|
||||
|
|
|
@ -130,7 +130,8 @@ private:
|
|||
|
||||
QList<Model*> _releasedModels;
|
||||
RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType,
|
||||
bool precisionPicking, const QVector<EntityItemID>& entityIdsToInclude = QVector<EntityItemID>());
|
||||
bool precisionPicking, const QVector<EntityItemID>& entityIdsToInclude = QVector<EntityItemID>(),
|
||||
const QVector<EntityItemID>& entityIdsToDiscard = QVector<EntityItemID>());
|
||||
|
||||
EntityItemID _currentHoverOverEntityID;
|
||||
EntityItemID _currentClickingOnEntityID;
|
||||
|
|
|
@ -357,19 +357,21 @@ QVector<QUuid> EntityScriptingInterface::findEntitiesInBox(const glm::vec3& corn
|
|||
return result;
|
||||
}
|
||||
|
||||
RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersection(const PickRay& ray, bool precisionPicking, const QScriptValue& entityIdsToInclude) {
|
||||
QVector<EntityItemID> entities = qVectorEntityItemIDFromScriptValue(entityIdsToInclude);
|
||||
return findRayIntersectionWorker(ray, Octree::TryLock, precisionPicking, entities);
|
||||
RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersection(const PickRay& ray, bool precisionPicking, const QScriptValue& entityIdsToInclude, const QScriptValue& entityIdsToDiscard) {
|
||||
QVector<EntityItemID> entitiesToInclude = qVectorEntityItemIDFromScriptValue(entityIdsToInclude);
|
||||
QVector<EntityItemID> entitiesToDiscard = qVectorEntityItemIDFromScriptValue(entityIdsToDiscard);
|
||||
return findRayIntersectionWorker(ray, Octree::TryLock, precisionPicking, entitiesToInclude, entitiesToDiscard);
|
||||
}
|
||||
|
||||
RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionBlocking(const PickRay& ray, bool precisionPicking, const QScriptValue& entityIdsToInclude) {
|
||||
const QVector<EntityItemID>& entities = qVectorEntityItemIDFromScriptValue(entityIdsToInclude);
|
||||
return findRayIntersectionWorker(ray, Octree::Lock, precisionPicking, entities);
|
||||
RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionBlocking(const PickRay& ray, bool precisionPicking, const QScriptValue& entityIdsToInclude, const QScriptValue& entityIdsToDiscard) {
|
||||
const QVector<EntityItemID>& entitiesToInclude = qVectorEntityItemIDFromScriptValue(entityIdsToInclude);
|
||||
const QVector<EntityItemID> entitiesToDiscard = qVectorEntityItemIDFromScriptValue(entityIdsToDiscard);
|
||||
return findRayIntersectionWorker(ray, Octree::Lock, precisionPicking, entitiesToInclude, entitiesToDiscard);
|
||||
}
|
||||
|
||||
RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionWorker(const PickRay& ray,
|
||||
Octree::lockType lockType,
|
||||
bool precisionPicking, const QVector<EntityItemID>& entityIdsToInclude) {
|
||||
bool precisionPicking, const QVector<EntityItemID>& entityIdsToInclude, const QVector<EntityItemID>& entityIdsToDiscard) {
|
||||
|
||||
|
||||
RayToEntityIntersectionResult result;
|
||||
|
@ -377,7 +379,7 @@ RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionWorke
|
|||
OctreeElementPointer element;
|
||||
EntityItemPointer intersectedEntity = NULL;
|
||||
result.intersects = _entityTree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face,
|
||||
result.surfaceNormal, entityIdsToInclude, (void**)&intersectedEntity, lockType, &result.accurate,
|
||||
result.surfaceNormal, entityIdsToInclude, entityIdsToDiscard, (void**)&intersectedEntity, lockType, &result.accurate,
|
||||
precisionPicking);
|
||||
if (result.intersects && intersectedEntity) {
|
||||
result.entityID = intersectedEntity->getEntityItemID();
|
||||
|
|
|
@ -112,11 +112,11 @@ public slots:
|
|||
/// If the scripting context has visible entities, this will determine a ray intersection, the results
|
||||
/// may be inaccurate if the engine is unable to access the visible entities, in which case result.accurate
|
||||
/// will be false.
|
||||
Q_INVOKABLE RayToEntityIntersectionResult findRayIntersection(const PickRay& ray, bool precisionPicking = false, const QScriptValue& entityIdsToInclude = QScriptValue());
|
||||
Q_INVOKABLE RayToEntityIntersectionResult findRayIntersection(const PickRay& ray, bool precisionPicking = false, const QScriptValue& entityIdsToInclude = QScriptValue(), const QScriptValue& entityIdsToDiscard = QScriptValue());
|
||||
|
||||
/// If the scripting context has visible entities, this will determine a ray intersection, and will block in
|
||||
/// order to return an accurate result
|
||||
Q_INVOKABLE RayToEntityIntersectionResult findRayIntersectionBlocking(const PickRay& ray, bool precisionPicking = false, const QScriptValue& entityIdsToInclude = QScriptValue());
|
||||
Q_INVOKABLE RayToEntityIntersectionResult findRayIntersectionBlocking(const PickRay& ray, bool precisionPicking = false, const QScriptValue& entityIdsToInclude = QScriptValue(), const QScriptValue& entityIdsToDiscard = QScriptValue());
|
||||
|
||||
Q_INVOKABLE void setLightsArePickable(bool value);
|
||||
Q_INVOKABLE bool getLightsArePickable() const;
|
||||
|
@ -189,7 +189,7 @@ private:
|
|||
|
||||
/// actually does the work of finding the ray intersection, can be called in locking mode or tryLock mode
|
||||
RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType,
|
||||
bool precisionPicking, const QVector<EntityItemID>& entityIdsToInclude);
|
||||
bool precisionPicking, const QVector<EntityItemID>& entityIdsToInclude, const QVector<EntityItemID>& entityIdsToDiscard);
|
||||
|
||||
EntityTreePointer _entityTree;
|
||||
EntitiesScriptEngineProvider* _entitiesScriptEngine = nullptr;
|
||||
|
|
|
@ -498,6 +498,7 @@ public:
|
|||
BoxFace& face;
|
||||
glm::vec3& surfaceNormal;
|
||||
const QVector<EntityItemID>& entityIdsToInclude;
|
||||
const QVector<EntityItemID>& entityIdsToDiscard;
|
||||
void** intersectedObject;
|
||||
bool found;
|
||||
bool precisionPicking;
|
||||
|
@ -510,7 +511,7 @@ bool findRayIntersectionOp(OctreeElementPointer element, void* extraData) {
|
|||
EntityTreeElementPointer entityTreeElementPointer = std::dynamic_pointer_cast<EntityTreeElement>(element);
|
||||
if (entityTreeElementPointer ->findRayIntersection(args->origin, args->direction, keepSearching,
|
||||
args->element, args->distance, args->face, args->surfaceNormal, args->entityIdsToInclude,
|
||||
args->intersectedObject, args->precisionPicking)) {
|
||||
args->entityIdsToDiscard, args->intersectedObject, args->precisionPicking)) {
|
||||
args->found = true;
|
||||
}
|
||||
return keepSearching;
|
||||
|
@ -518,9 +519,9 @@ bool findRayIntersectionOp(OctreeElementPointer element, void* extraData) {
|
|||
|
||||
bool EntityTree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
OctreeElementPointer& element, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal, const QVector<EntityItemID>& entityIdsToInclude, void** intersectedObject,
|
||||
BoxFace& face, glm::vec3& surfaceNormal, const QVector<EntityItemID>& entityIdsToInclude, const QVector<EntityItemID>& entityIdsToDiscard, void** intersectedObject,
|
||||
Octree::lockType lockType, bool* accurateResult, bool precisionPicking) {
|
||||
RayArgs args = { origin, direction, element, distance, face, surfaceNormal, entityIdsToInclude, intersectedObject, false, precisionPicking };
|
||||
RayArgs args = { origin, direction, element, distance, face, surfaceNormal, entityIdsToInclude, entityIdsToDiscard, intersectedObject, false, precisionPicking };
|
||||
distance = FLT_MAX;
|
||||
|
||||
bool requireLock = lockType == Octree::Lock;
|
||||
|
|
|
@ -84,6 +84,7 @@ public:
|
|||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
OctreeElementPointer& node, float& distance, BoxFace& face, glm::vec3& surfaceNormal,
|
||||
const QVector<EntityItemID>& entityIdsToInclude = QVector<EntityItemID>(),
|
||||
const QVector<EntityItemID>& entityIdsToDiscard = QVector<EntityItemID>(),
|
||||
void** intersectedObject = NULL,
|
||||
Octree::lockType lockType = Octree::TryLock,
|
||||
bool* accurateResult = NULL,
|
||||
|
|
|
@ -475,8 +475,8 @@ bool EntityTreeElement::bestFitBounds(const glm::vec3& minPoint, const glm::vec3
|
|||
|
||||
bool EntityTreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal, const QVector<EntityItemID>& entityIdsToInclude,
|
||||
void** intersectedObject, bool precisionPicking) {
|
||||
BoxFace& face, glm::vec3& surfaceNormal, const QVector<EntityItemID>& entityIdsToInclude,
|
||||
const QVector<EntityItemID>& entityIdsToDiscard, void** intersectedObject, bool precisionPicking) {
|
||||
|
||||
keepSearching = true; // assume that we will continue searching after this.
|
||||
|
||||
|
@ -501,7 +501,7 @@ bool EntityTreeElement::findRayIntersection(const glm::vec3& origin, const glm::
|
|||
if (_cube.contains(origin) || distanceToElementCube < distance) {
|
||||
|
||||
if (findDetailedRayIntersection(origin, direction, keepSearching, element, distanceToElementDetails,
|
||||
face, localSurfaceNormal, entityIdsToInclude, intersectedObject, precisionPicking, distanceToElementCube)) {
|
||||
face, localSurfaceNormal, entityIdsToInclude, entityIdsToDiscard, intersectedObject, precisionPicking, distanceToElementCube)) {
|
||||
|
||||
if (distanceToElementDetails < distance) {
|
||||
distance = distanceToElementDetails;
|
||||
|
@ -516,13 +516,13 @@ bool EntityTreeElement::findRayIntersection(const glm::vec3& origin, const glm::
|
|||
|
||||
bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching,
|
||||
OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal,
|
||||
const QVector<EntityItemID>& entityIdsToInclude, void** intersectedObject, bool precisionPicking, float distanceToElementCube) {
|
||||
const QVector<EntityItemID>& entityIdsToInclude, const QVector<EntityItemID>& entityIDsToDiscard, void** intersectedObject, bool precisionPicking, float distanceToElementCube) {
|
||||
|
||||
// only called if we do intersect our bounding cube, but find if we actually intersect with entities...
|
||||
int entityNumber = 0;
|
||||
bool somethingIntersected = false;
|
||||
forEachEntity([&](EntityItemPointer entity) {
|
||||
if (entityIdsToInclude.size() > 0 && !entityIdsToInclude.contains(entity->getID())) {
|
||||
if ( (entityIdsToInclude.size() > 0 && !entityIdsToInclude.contains(entity->getID())) || (entityIDsToDiscard.size() > 0 && entityIDsToDiscard.contains(entity->getID())) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -144,11 +144,13 @@ public:
|
|||
virtual bool canRayIntersect() const { return hasEntities(); }
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
bool& keepSearching, OctreeElementPointer& node, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal, const QVector<EntityItemID>& entityIdsToInclude,
|
||||
BoxFace& face, glm::vec3& surfaceNormal, const QVector<EntityItemID>& entityIdsToInclude,
|
||||
const QVector<EntityItemID>& entityIdsToDiscard,
|
||||
void** intersectedObject = NULL, bool precisionPicking = false);
|
||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal, const QVector<EntityItemID>& entityIdsToInclude,
|
||||
const QVector<EntityItemID>& entityIdsToDiscard,
|
||||
void** intersectedObject, bool precisionPicking, float distanceToElementCube);
|
||||
virtual bool findSpherePenetration(const glm::vec3& center, float radius,
|
||||
glm::vec3& penetration, void** penetratedObject) const;
|
||||
|
|
|
@ -126,6 +126,8 @@ RenderDeferredTask::RenderDeferredTask() : Task() {
|
|||
_jobs.push_back(Job(new HitEffect::JobModel("HitEffect")));
|
||||
_jobs.back().setEnabled(false);
|
||||
_drawHitEffectJobIndex = (int)_jobs.size() -1;
|
||||
|
||||
_jobs.push_back(Job(new Blit::JobModel("Blit")));
|
||||
}
|
||||
|
||||
RenderDeferredTask::~RenderDeferredTask() {
|
||||
|
@ -385,6 +387,76 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const
|
|||
args->_batch = nullptr;
|
||||
}
|
||||
|
||||
void Blit::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
assert(renderContext->getArgs());
|
||||
assert(renderContext->getArgs()->_context);
|
||||
|
||||
RenderArgs* renderArgs = renderContext->getArgs();
|
||||
auto blitFbo = renderArgs->_blitFramebuffer;
|
||||
|
||||
if (!blitFbo) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine size from viewport
|
||||
int width = renderArgs->_viewport.z;
|
||||
int height = renderArgs->_viewport.w;
|
||||
|
||||
// Blit primary to blit FBO
|
||||
auto framebufferCache = DependencyManager::get<FramebufferCache>();
|
||||
auto primaryFbo = framebufferCache->getPrimaryFramebuffer();
|
||||
|
||||
gpu::doInBatch(renderArgs->_context, [=](gpu::Batch& batch) {
|
||||
batch.setFramebuffer(blitFbo);
|
||||
|
||||
if (renderArgs->_renderMode == RenderArgs::MIRROR_RENDER_MODE) {
|
||||
if (renderArgs->_context->isStereo()) {
|
||||
gpu::Vec4i srcRectLeft;
|
||||
srcRectLeft.z = width / 2;
|
||||
srcRectLeft.w = height;
|
||||
|
||||
gpu::Vec4i srcRectRight;
|
||||
srcRectRight.x = width / 2;
|
||||
srcRectRight.z = width;
|
||||
srcRectRight.w = height;
|
||||
|
||||
gpu::Vec4i destRectLeft;
|
||||
destRectLeft.x = srcRectLeft.z;
|
||||
destRectLeft.z = srcRectLeft.x;
|
||||
destRectLeft.y = srcRectLeft.y;
|
||||
destRectLeft.w = srcRectLeft.w;
|
||||
|
||||
gpu::Vec4i destRectRight;
|
||||
destRectRight.x = srcRectRight.z;
|
||||
destRectRight.z = srcRectRight.x;
|
||||
destRectRight.y = srcRectRight.y;
|
||||
destRectRight.w = srcRectRight.w;
|
||||
|
||||
// Blit left to right and right to left in stereo
|
||||
batch.blit(primaryFbo, srcRectRight, blitFbo, destRectLeft);
|
||||
batch.blit(primaryFbo, srcRectLeft, blitFbo, destRectRight);
|
||||
} else {
|
||||
gpu::Vec4i srcRect;
|
||||
srcRect.z = width;
|
||||
srcRect.w = height;
|
||||
|
||||
gpu::Vec4i destRect;
|
||||
destRect.x = width;
|
||||
destRect.y = 0;
|
||||
destRect.z = 0;
|
||||
destRect.w = height;
|
||||
|
||||
batch.blit(primaryFbo, srcRect, blitFbo, destRect);
|
||||
}
|
||||
} else {
|
||||
gpu::Vec4i rect;
|
||||
rect.z = width;
|
||||
rect.w = height;
|
||||
|
||||
batch.blit(primaryFbo, rect, blitFbo, rect);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void RenderDeferredTask::setToneMappingExposure(float exposure) {
|
||||
if (_toneMappingJobIndex >= 0) {
|
||||
|
|
|
@ -90,6 +90,13 @@ public:
|
|||
typedef render::Job::Model<DrawOverlay3D> JobModel;
|
||||
};
|
||||
|
||||
class Blit {
|
||||
public:
|
||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||
|
||||
typedef render::Job::Model<Blit> JobModel;
|
||||
};
|
||||
|
||||
class RenderDeferredTask : public render::Task {
|
||||
public:
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace gpu {
|
|||
class Batch;
|
||||
class Context;
|
||||
class Texture;
|
||||
class Framebuffer;
|
||||
}
|
||||
|
||||
class RenderDetails {
|
||||
|
@ -101,6 +102,7 @@ public:
|
|||
}
|
||||
|
||||
std::shared_ptr<gpu::Context> _context = nullptr;
|
||||
std::shared_ptr<gpu::Framebuffer> _blitFramebuffer = nullptr;
|
||||
OctreeRenderer* _renderer = nullptr;
|
||||
ViewFrustum* _viewFrustum = nullptr;
|
||||
glm::ivec4 _viewport{ 0, 0, 1, 1 };
|
||||
|
|
|
@ -169,7 +169,7 @@
|
|||
}
|
||||
|
||||
function createRaveStick(position) {
|
||||
var modelURL = "https://s3.amazonaws.com/hifi-public/eric/models/rave/raveStick.fbx";
|
||||
var modelURL = "http://hifi-content.s3.amazonaws.com/eric/models/raveStick.fbx";
|
||||
var stick = Entities.addEntity({
|
||||
type: "Model",
|
||||
name: "raveStick",
|
||||
|
@ -205,71 +205,6 @@
|
|||
}
|
||||
})
|
||||
});
|
||||
var rotation = Quat.fromPitchYawRollDegrees(0, 0, 0)
|
||||
var forwardVec = Quat.getFront(Quat.multiply(rotation, Quat.fromPitchYawRollDegrees(-90, 0, 0)));
|
||||
forwardVec = Vec3.normalize(forwardVec);
|
||||
var forwardQuat = orientationOf(forwardVec);
|
||||
position = Vec3.sum(position, Vec3.multiply(Quat.getFront(rotation), 0.1));
|
||||
position.z += 0.1;
|
||||
position.x += -0.035;
|
||||
var color = {
|
||||
red: 0,
|
||||
green: 200,
|
||||
blue: 40
|
||||
};
|
||||
var props = {
|
||||
type: "ParticleEffect",
|
||||
position: position,
|
||||
parentID: stick,
|
||||
isEmitting: true,
|
||||
name: "raveBeam",
|
||||
colorStart: color,
|
||||
colorSpread: {
|
||||
red: 200,
|
||||
green: 10,
|
||||
blue: 10
|
||||
},
|
||||
color: {
|
||||
red: 200,
|
||||
green: 200,
|
||||
blue: 255
|
||||
},
|
||||
colorFinish: color,
|
||||
maxParticles: 100000,
|
||||
lifespan: 1,
|
||||
emitRate: 1000,
|
||||
emitOrientation: forwardQuat,
|
||||
emitSpeed: 0.2,
|
||||
speedSpread: 0.0,
|
||||
polarStart: 0,
|
||||
polarFinish: 0.0,
|
||||
azimuthStart: 0.1,
|
||||
azimuthFinish: 0.01,
|
||||
emitAcceleration: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
},
|
||||
accelerationSpread: {
|
||||
x: 0.00,
|
||||
y: 0.00,
|
||||
z: 0.00
|
||||
},
|
||||
radiusStart: 0.03,
|
||||
radiusFinish: 0.025,
|
||||
alpha: 0.7,
|
||||
alphaSpread:0.1,
|
||||
alphaStart: 0.5,
|
||||
alphaFinish: 0.5,
|
||||
textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png",
|
||||
emitterShouldTrail: false,
|
||||
userData: JSON.stringify({
|
||||
resetMe: {
|
||||
resetMe: true
|
||||
}
|
||||
})
|
||||
}
|
||||
var beam = Entities.addEntity(props);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ MasterReset = function() {
|
|||
}
|
||||
|
||||
function createRaveStick(position) {
|
||||
var modelURL = "https://s3.amazonaws.com/hifi-public/eric/models/rave/raveStick.fbx";
|
||||
var modelURL = "http://hifi-content.s3.amazonaws.com/eric/models/raveStick.fbx";
|
||||
var stick = Entities.addEntity({
|
||||
type: "Model",
|
||||
name: "raveStick",
|
||||
|
@ -173,10 +173,15 @@ MasterReset = function() {
|
|||
},
|
||||
grabbableKey: {
|
||||
spatialKey: {
|
||||
relativePosition: {
|
||||
x: 0,
|
||||
rightRelativePosition: {
|
||||
x: 0.02,
|
||||
y: 0,
|
||||
z: -0.1
|
||||
z: 0
|
||||
},
|
||||
leftRelativePosition: {
|
||||
x: -0.02,
|
||||
y: 0,
|
||||
z: 0
|
||||
},
|
||||
relativeRotation: Quat.fromPitchYawRollDegrees(90, 90, 0)
|
||||
},
|
||||
|
@ -184,72 +189,6 @@ MasterReset = function() {
|
|||
}
|
||||
})
|
||||
});
|
||||
var rotation = Quat.fromPitchYawRollDegrees(0, 0, 0)
|
||||
var forwardVec = Quat.getFront(Quat.multiply(rotation, Quat.fromPitchYawRollDegrees(-90, 0, 0)));
|
||||
forwardVec = Vec3.normalize(forwardVec);
|
||||
var forwardQuat = orientationOf(forwardVec);
|
||||
position = Vec3.sum(position, Vec3.multiply(Quat.getFront(rotation), 0.1));
|
||||
position.z += 0.1;
|
||||
position.x += -0.035;
|
||||
var color = {
|
||||
red: 0,
|
||||
green: 200,
|
||||
blue: 40
|
||||
};
|
||||
var props = {
|
||||
type: "ParticleEffect",
|
||||
position: position,
|
||||
parentID: stick,
|
||||
isEmitting: true,
|
||||
name: "raveBeam",
|
||||
colorStart: color,
|
||||
colorSpread: {
|
||||
red: 200,
|
||||
green: 10,
|
||||
blue: 10
|
||||
},
|
||||
color: {
|
||||
red: 200,
|
||||
green: 200,
|
||||
blue: 255
|
||||
},
|
||||
colorFinish: color,
|
||||
maxParticles: 100000,
|
||||
lifespan: 1,
|
||||
emitRate: 1000,
|
||||
emitOrientation: forwardQuat,
|
||||
emitSpeed: 0.2,
|
||||
speedSpread: 0.0,
|
||||
polarStart: 0,
|
||||
polarFinish: 0.0,
|
||||
azimuthStart: 0.1,
|
||||
azimuthFinish: 0.01,
|
||||
emitAcceleration: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
},
|
||||
accelerationSpread: {
|
||||
x: 0.00,
|
||||
y: 0.00,
|
||||
z: 0.00
|
||||
},
|
||||
radiusStart: 0.03,
|
||||
radiusFinish: 0.025,
|
||||
alpha: 0.7,
|
||||
alphaSpread: 0.1,
|
||||
alphaStart: 0.5,
|
||||
alphaFinish: 0.5,
|
||||
textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png",
|
||||
emitterShouldTrail: false,
|
||||
userData: JSON.stringify({
|
||||
resetMe: {
|
||||
resetMe: true
|
||||
}
|
||||
})
|
||||
}
|
||||
var beam = Entities.addEntity(props);
|
||||
|
||||
}
|
||||
|
||||
function createGun(position) {
|
||||
|
@ -283,10 +222,15 @@ MasterReset = function() {
|
|||
userData: JSON.stringify({
|
||||
grabbableKey: {
|
||||
spatialKey: {
|
||||
relativePosition: {
|
||||
x: 0,
|
||||
rightRelativePosition: {
|
||||
x: 0.02,
|
||||
y: 0,
|
||||
z: -0.1
|
||||
z: -0.03
|
||||
},
|
||||
leftRelativePosition: {
|
||||
x: -0.02,
|
||||
y: 0,
|
||||
z: -0.03
|
||||
},
|
||||
relativeRotation: Quat.fromPitchYawRollDegrees(100, 90, 0)
|
||||
},
|
||||
|
@ -1136,9 +1080,9 @@ MasterReset = function() {
|
|||
grabbableKey: {
|
||||
spatialKey: {
|
||||
relativePosition: {
|
||||
x: -0.05,
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0.0
|
||||
z: 0.06
|
||||
},
|
||||
relativeRotation: Quat.fromPitchYawRollDegrees(0,-90, -90)
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue