This commit is contained in:
Leonardo Murillo 2015-12-28 18:37:19 -06:00
commit 2ac42d9a2b
20 changed files with 345 additions and 249 deletions

View 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);
});

View file

@ -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) {}
}
}
}

View file

@ -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
}
})

View file

@ -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;
}

View file

@ -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);

View 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);

View file

@ -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

View file

@ -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) {

View file

@ -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;

View file

@ -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();

View file

@ -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;

View file

@ -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;

View file

@ -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,

View file

@ -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;
}

View file

@ -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;

View file

@ -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) {

View file

@ -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:

View file

@ -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 };

View file

@ -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);
}

View file

@ -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)
},