Merge remote-tracking branch 'upstream/master' into homer

This commit is contained in:
Brad Davis 2015-07-12 18:52:27 -07:00
commit d3cdfb5084
26 changed files with 349 additions and 344 deletions

View file

@ -11,24 +11,26 @@
// //
"use strict"; "use strict";
/*jslint vars: true*/ /*jslint vars: true*/
var Script, Entities, MyAvatar, Window, Overlays, Controller, Vec3, Quat, print, ToolBar; // Referenced globals provided by High Fidelity. var Script, Entities, MyAvatar, Window, Overlays, Controller, Vec3, Quat, print, ToolBar, Settings; // Referenced globals provided by High Fidelity.
Script.include(["../../libraries/toolBars.js"]); Script.include("http://s3.amazonaws.com/hifi-public/scripts/libraries/toolBars.js");
var hand = "right"; var hand = Settings.getValue("highfidelity.sword.hand", "right");
var nullActionID = "00000000-0000-0000-0000-000000000000"; var nullActionID = "00000000-0000-0000-0000-000000000000";
var controllerID; var controllerID;
var controllerActive; var controllerActive;
var stickID = null; var stickID = null;
var actionID = nullActionID; var actionID = nullActionID;
var targetIDs = []; var targetIDs = [];
var dimensions = { x: 0.3, y: 0.1, z: 2.0 }; var dimensions = { x: 0.3, y: 0.15, z: 2.0 };
var AWAY_ORIENTATION = Quat.fromPitchYawRollDegrees(-90, 0, 0);
var BUTTON_SIZE = 32; var BUTTON_SIZE = 32;
var stickModel = "https://hifi-public.s3.amazonaws.com/eric/models/stick.fbx"; var stickModel = "https://hifi-public.s3.amazonaws.com/eric/models/stick.fbx";
var swordModel = "https://hifi-public.s3.amazonaws.com/ozan/props/sword/sword.fbx"; var swordModel = "https://hifi-public.s3.amazonaws.com/ozan/props/sword/sword.fbx";
var swordCollisionShape = "https://hifi-public.s3.amazonaws.com/ozan/props/sword/sword.obj";
var swordCollisionSoundURL = "http://public.highfidelity.io/sounds/Collisions-hitsandslaps/swordStrike1.wav";
var avatarCollisionSoundURL = "https://s3.amazonaws.com/hifi-public/sounds/Collisions-hitsandslaps/airhockey_hit1.wav";
var whichModel = "sword"; var whichModel = "sword";
var attachmentOffset, MOUSE_CONTROLLER_OFFSET = {x: 0.5, y: 0.4, z: 0.0}; // A fudge when using mouse rather than hand-controller, to hit yourself less often. var originalAvatarCollisionSound;
var toolBar = new ToolBar(0, 0, ToolBar.vertical, "highfidelity.sword.toolbar", function () { var toolBar = new ToolBar(0, 0, ToolBar.vertical, "highfidelity.sword.toolbar", function () {
return {x: 100, y: 380}; return {x: 100, y: 380};
@ -37,6 +39,7 @@ var toolBar = new ToolBar(0, 0, ToolBar.vertical, "highfidelity.sword.toolbar",
var SWORD_IMAGE = "http://s3.amazonaws.com/hifi-public/images/billiardsReticle.png"; // Toggle between brandishing/sheathing sword (creating if necessary) var SWORD_IMAGE = "http://s3.amazonaws.com/hifi-public/images/billiardsReticle.png"; // Toggle between brandishing/sheathing sword (creating if necessary)
var TARGET_IMAGE = "http://s3.amazonaws.com/hifi-public/images/puck.png"; // Create a target dummy var TARGET_IMAGE = "http://s3.amazonaws.com/hifi-public/images/puck.png"; // Create a target dummy
var CLEANUP_IMAGE = "http://s3.amazonaws.com/hifi-public/images/delete.png"; // Remove sword and all target dummies.f var CLEANUP_IMAGE = "http://s3.amazonaws.com/hifi-public/images/delete.png"; // Remove sword and all target dummies.f
var SWITCH_HANDS_IMAGE = "http://s3.amazonaws.com/hifi-public/images/up-arrow.svg"; // Toggle left vs right hand. Persists in settings.
var swordButton = toolBar.addOverlay("image", { var swordButton = toolBar.addOverlay("image", {
width: BUTTON_SIZE, width: BUTTON_SIZE,
height: BUTTON_SIZE, height: BUTTON_SIZE,
@ -49,6 +52,12 @@ var targetButton = toolBar.addOverlay("image", {
imageURL: TARGET_IMAGE, imageURL: TARGET_IMAGE,
alpha: 1 alpha: 1
}); });
var switchHandsButton = toolBar.addOverlay("image", {
width: BUTTON_SIZE,
height: BUTTON_SIZE,
imageURL: SWITCH_HANDS_IMAGE,
alpha: 1
});
var cleanupButton = toolBar.addOverlay("image", { var cleanupButton = toolBar.addOverlay("image", {
width: BUTTON_SIZE, width: BUTTON_SIZE,
height: BUTTON_SIZE, height: BUTTON_SIZE,
@ -77,53 +86,51 @@ function flash(color) {
flasher.timer = Script.setTimeout(clearFlash, 500); flasher.timer = Script.setTimeout(clearFlash, 500);
} }
var health = 100; var health = 100;
var display; var display2d, display3d;
var isAway = false; function trackAvatarWithText() {
Entities.editEntity(display3d, {
position: Vec3.sum(MyAvatar.position, {x: 0, y: 1.5, z: 0}),
rotation: Quat.multiply(MyAvatar.orientation, Quat.fromPitchYawRollDegrees(0, 180, 0))
});
}
function updateDisplay() { function updateDisplay() {
var text = health.toString(); var text = health.toString();
if (!display) { if (!display2d) {
health = 100; health = 100;
display = Overlays.addOverlay("text", { display2d = Overlays.addOverlay("text", {
text: text, text: text,
font: { size: 20 }, font: { size: 20 },
color: {red: 0, green: 255, blue: 0}, color: {red: 0, green: 255, blue: 0},
backgroundColor: {red: 100, green: 100, blue: 100}, // Why doesn't this and the next work? backgroundColor: {red: 100, green: 100, blue: 100}, // Why doesn't this and the next work?
backgroundAlpha: 0.9, backgroundAlpha: 0.9,
x: Window.innerWidth - 50, x: toolBar.x - 5, // I'd like to add the score to the toolBar and have it drag with it, but toolBar doesn't support text (just buttons).
y: 50 y: toolBar.y - 30 // So next best thing is to position it each time as if it were on top.
}); });
display3d = Entities.addEntity({
name: MyAvatar.displayName + " score",
textColor: {red: 255, green: 255, blue: 255},
type: "Text",
text: text,
lineHeight: 0.14,
backgroundColor: {red: 64, green: 64, blue: 64},
dimensions: {x: 0.3, y: 0.2, z: 0.01},
});
Script.update.connect(trackAvatarWithText);
} else { } else {
Overlays.editOverlay(display, {text: text}); Overlays.editOverlay(display2d, {text: text});
Entities.editEntity(display3d, {text: text});
} }
} }
function removeDisplay() { function removeDisplay() {
if (display) { if (display2d) {
Overlays.deleteOverlay(display); Overlays.deleteOverlay(display2d);
display = null; display2d = null;
Script.update.disconnect(trackAvatarWithText);
Entities.deleteEntity(display3d);
display3d = null;
} }
} }
function cleanUp(leaveButtons) {
attachmentOffset = {x: 0, y: 0, z: 0};
if (stickID) {
Entities.deleteAction(stickID, actionID);
Entities.deleteEntity(stickID);
stickID = null;
actionID = null;
}
targetIDs.forEach(function (id) {
Entities.deleteAction(id.entity, id.action);
Entities.deleteEntity(id.entity);
});
targetIDs = [];
removeDisplay();
if (!leaveButtons) {
toolBar.cleanup();
}
}
function computeEnergy(collision, entityID) { function computeEnergy(collision, entityID) {
var id = entityID || collision.idA || collision.idB; var id = entityID || collision.idA || collision.idB;
var entity = id && Entities.getEntityProperties(id); var entity = id && Entities.getEntityProperties(id);
@ -133,31 +140,67 @@ function computeEnergy(collision, entityID) {
return Math.min(Math.max(1.0, Math.round(energy)), 20); return Math.min(Math.max(1.0, Math.round(energy)), 20);
} }
function gotHit(collision) { function gotHit(collision) {
if (isAway) { return; }
var energy = computeEnergy(collision); var energy = computeEnergy(collision);
print("Got hit - " + energy + " from " + collision.idA + " " + collision.idB);
health -= energy; health -= energy;
flash({red: 255, green: 0, blue: 0}); flash({red: 255, green: 0, blue: 0});
updateDisplay(); updateDisplay();
} }
function scoreHit(idA, idB, collision) { function scoreHit(idA, idB, collision) {
if (isAway) { return; }
var energy = computeEnergy(collision, idA); var energy = computeEnergy(collision, idA);
print("Score + " + energy + " from " + JSON.stringify(idA) + " " + JSON.stringify(idB));
health += energy; health += energy;
flash({red: 0, green: 255, blue: 0}); flash({red: 0, green: 255, blue: 0});
updateDisplay(); updateDisplay();
} }
function positionStick(stickOrientation) { function isFighting() {
var baseOffset = Vec3.sum(attachmentOffset, {x: 0.0, y: 0.0, z: -dimensions.z / 2}); return stickID && (actionID !== nullActionID);
var offset = Vec3.multiplyQbyV(stickOrientation, baseOffset);
Entities.updateAction(stickID, actionID, {relativePosition: offset,
relativeRotation: stickOrientation});
} }
function initControls() {
print("Sword hand is " + hand);
if (hand === "right") {
controllerID = 3; // right handed
} else {
controllerID = 4; // left handed
}
}
var inHand = false;
function positionStick(stickOrientation) {
var reorient = Quat.fromPitchYawRollDegrees(0, -90, 0);
var baseOffset = {x: -dimensions.z * 0.8, y: 0, z: 0};
var offset = Vec3.multiplyQbyV(reorient, baseOffset);
stickOrientation = Quat.multiply(reorient, stickOrientation);
inHand = false;
Entities.updateAction(stickID, actionID, {
relativePosition: offset,
relativeRotation: stickOrientation
});
}
function resetToHand() { // Maybe coordinate with positionStick?
if (inHand) { // Optimization: bail if we're already inHand.
return;
}
print('Reset to hand');
Entities.updateAction(stickID, actionID, {
relativePosition: {x: 0.0, y: 0.0, z: -dimensions.z * 0.5},
relativeRotation: Quat.fromVec3Degrees({x: 45.0, y: 0.0, z: 0.0}),
hand: hand, // It should not be necessary to repeat these two, but there seems to be a bug in that that
timeScale: 0.05 // they do not retain their earlier values if you don't repeat them.
});
inHand = true;
}
function mouseMoveEvent(event) { function mouseMoveEvent(event) {
attachmentOffset = MOUSE_CONTROLLER_OFFSET; if (event.deviceID) { // Not a MOUSE mouse event, but a (e.g., hydra) mouse event, with x/y that is not meaningful for us.
if (!stickID || actionID === nullActionID || isAway) { resetToHand(); // Can only happen when controller is uncradled, so let's drive with that, resetting our attachement.
return;
}
controllerActive = (Vec3.length(Controller.getSpatialControlPosition(controllerID)) > 0);
//print("Mouse move with hand controller " + (controllerActive ? "active" : "inactive") + JSON.stringify(event));
if (controllerActive || !isFighting()) {
print('Attempting attachment reset');
resetToHand();
return; return;
} }
var windowCenterX = Window.innerWidth / 2; var windowCenterX = Window.innerWidth / 2;
@ -167,73 +210,80 @@ function mouseMoveEvent(event) {
var mouseXRatio = mouseXCenterOffset / windowCenterX; var mouseXRatio = mouseXCenterOffset / windowCenterX;
var mouseYRatio = mouseYCenterOffset / windowCenterY; var mouseYRatio = mouseYCenterOffset / windowCenterY;
var stickOrientation = Quat.fromPitchYawRollDegrees(mouseYRatio * -90, mouseXRatio * -90, 0); var stickOrientation = Quat.fromPitchYawRollDegrees(mouseYRatio * 90, mouseXRatio * 90, 0);
positionStick(stickOrientation); positionStick(stickOrientation);
} }
function removeSword() {
function initControls() { if (stickID) {
if (hand === "right") { print('deleting action ' + actionID + ' and entity ' + stickID);
controllerID = 3; // right handed Entities.deleteAction(stickID, actionID);
} else { Entities.deleteEntity(stickID);
controllerID = 4; // left handed stickID = null;
actionID = nullActionID;
Controller.mouseMoveEvent.disconnect(mouseMoveEvent);
MyAvatar.collisionWithEntity.disconnect(gotHit);
// removeEventhHandler happens automatically when the entity is deleted.
} }
inHand = false;
if (originalAvatarCollisionSound !== undefined) {
MyAvatar.collisionSoundURL = originalAvatarCollisionSound;
} }
function update() {
var palmPosition = Controller.getSpatialControlPosition(controllerID);
controllerActive = (Vec3.length(palmPosition) > 0);
if (!controllerActive) {
return;
}
var stickOrientation = Controller.getSpatialControlRawRotation(controllerID);
var adjustment = Quat.fromPitchYawRollDegrees(180, 0, 0);
stickOrientation = Quat.multiply(stickOrientation, adjustment);
positionStick(stickOrientation);
}
function toggleAway() {
isAway = !isAway;
if (isAway) {
positionStick(AWAY_ORIENTATION);
removeDisplay(); removeDisplay();
} else {
updateDisplay();
} }
function cleanUp(leaveButtons) {
removeSword();
targetIDs.forEach(function (id) {
Entities.deleteAction(id.entity, id.action);
Entities.deleteEntity(id.entity);
});
targetIDs = [];
if (!leaveButtons) {
toolBar.cleanup();
}
}
function makeSword() {
initControls();
stickID = Entities.addEntity({
type: "Model",
modelURL: swordModel,
compoundShapeURL: swordCollisionShape,
dimensions: dimensions,
position: (hand === 'right') ? MyAvatar.getRightPalmPosition() : MyAvatar.getLeftPalmPosition(), // initial position doesn't matter, as long as it's close
rotation: MyAvatar.orientation,
damping: 0.1,
collisionSoundURL: swordCollisionSoundURL,
restitution: 0.01,
collisionsWillMove: true
});
actionID = Entities.addAction("hold", stickID, {
relativePosition: {x: 0.0, y: 0.0, z: -dimensions.z * 0.5},
relativeRotation: Quat.fromVec3Degrees({x: 45.0, y: 0.0, z: 0.0}),
hand: hand,
timeScale: 0.05
});
if (actionID === nullActionID) {
print('*** FAILED TO MAKE SWORD ACTION ***');
cleanUp();
}
if (originalAvatarCollisionSound === undefined) {
originalAvatarCollisionSound = MyAvatar.collisionSoundURL; // We won't get MyAvatar.collisionWithEntity unless there's a sound URL. (Bug.)
SoundCache.getSound(avatarCollisionSoundURL); // Interface does not currently "preload" this? (Bug?)
}
MyAvatar.collisionSoundURL = avatarCollisionSoundURL;
Controller.mouseMoveEvent.connect(mouseMoveEvent);
MyAvatar.collisionWithEntity.connect(gotHit);
Script.addEventHandler(stickID, 'collisionWithEntity', scoreHit);
updateDisplay();
} }
function onClick(event) { function onClick(event) {
switch (Overlays.getOverlayAtPoint(event)) { switch (Overlays.getOverlayAtPoint(event)) {
case swordButton: case swordButton:
if (!stickID) { if (!stickID) {
initControls(); makeSword();
stickID = Entities.addEntity({
type: "Model",
modelURL: (whichModel === "sword") ? swordModel : stickModel,
//compoundShapeURL: "https://hifi-public.s3.amazonaws.com/eric/models/stick.obj",
shapeType: "box",
dimensions: dimensions,
position: MyAvatar.getRightPalmPosition(), // initial position doesn't matter, as long as it's close
rotation: MyAvatar.orientation,
damping: 0.1,
collisionSoundURL: "http://public.highfidelity.io/sounds/Collisions-hitsandslaps/swordStrike1.wav",
restitution: 0.01,
collisionsWillMove: true
});
actionID = Entities.addAction("hold", stickID, {relativePosition: {x: 0.0, y: 0.0, z: -dimensions.z / 2},
hand: hand,
timeScale: 0.15});
if (actionID === nullActionID) {
print('*** FAILED TO MAKE SWORD ACTION ***');
cleanUp();
}
Script.addEventHandler(stickID, 'collisionWithEntity', scoreHit);
updateDisplay();
} else { } else {
toggleAway(); removeSword();
} }
break; break;
case targetButton: case targetButton:
@ -256,6 +306,12 @@ function onClick(event) {
}); });
targetIDs.push({entity: boxId, action: action}); targetIDs.push({entity: boxId, action: action});
break; break;
case switchHandsButton:
cleanUp('leaveButtons');
hand = hand === "right" ? "left" : "right";
Settings.setValue("highfidelity.sword.hand", hand);
makeSword();
break;
case cleanupButton: case cleanupButton:
cleanUp('leaveButtons'); cleanUp('leaveButtons');
break; break;
@ -263,7 +319,4 @@ function onClick(event) {
} }
Script.scriptEnding.connect(cleanUp); Script.scriptEnding.connect(cleanUp);
Controller.mouseMoveEvent.connect(mouseMoveEvent);
Controller.mousePressEvent.connect(onClick); Controller.mousePressEvent.connect(onClick);
Script.update.connect(update);
MyAvatar.collisionWithEntity.connect(gotHit);

View file

@ -130,7 +130,7 @@ void AudioScope::render(RenderArgs* renderArgs, int width, int height) {
auto geometryCache = DependencyManager::get<GeometryCache>(); auto geometryCache = DependencyManager::get<GeometryCache>();
geometryCache->useSimpleDrawPipeline(batch); geometryCache->useSimpleDrawPipeline(batch);
auto textureCache = DependencyManager::get<TextureCache>(); auto textureCache = DependencyManager::get<TextureCache>();
batch.setUniformTexture(0, textureCache->getWhiteTexture()); batch.setResourceTexture(0, textureCache->getWhiteTexture());
mat4 legacyProjection = glm::ortho<float>(0, width, height, 0, -1000, 1000); mat4 legacyProjection = glm::ortho<float>(0, width, height, 0, -1000, 1000);
batch.setProjectionTransform(legacyProjection); batch.setProjectionTransform(legacyProjection);
batch.setModelTransform(Transform()); batch.setModelTransform(Transform());

View file

@ -644,7 +644,7 @@ void Avatar::renderBillboard(RenderArgs* renderArgs) {
glm::vec2 texCoordBottomRight(1.0f, 1.0f); glm::vec2 texCoordBottomRight(1.0f, 1.0f);
gpu::Batch& batch = *renderArgs->_batch; gpu::Batch& batch = *renderArgs->_batch;
batch.setUniformTexture(0, _billboardTexture->getGPUTexture()); batch.setResourceTexture(0, _billboardTexture->getGPUTexture());
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, true); DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, true);
DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));

View file

@ -70,30 +70,14 @@ void AvatarActionHold::updateActionWorker(float deltaTimeStep) {
return; return;
} }
// check for NaNs
if (position.x != position.x ||
position.y != position.y ||
position.z != position.z) {
qDebug() << "AvatarActionHold::updateActionWorker -- target position includes NaN";
return;
}
if (rotation.x != rotation.x ||
rotation.y != rotation.y ||
rotation.z != rotation.z ||
rotation.w != rotation.w) {
qDebug() << "AvatarActionHold::updateActionWorker -- target rotation includes NaN";
return;
}
if (_positionalTarget != position || _rotationalTarget != rotation) { if (_positionalTarget != position || _rotationalTarget != rotation) {
auto ownerEntity = _ownerEntity.lock(); auto ownerEntity = _ownerEntity.lock();
if (ownerEntity) { if (ownerEntity) {
ownerEntity->setActionDataDirty(true); ownerEntity->setActionDataDirty(true);
} }
}
_positionalTarget = position; _positionalTarget = position;
_rotationalTarget = rotation; _rotationalTarget = rotation;
}
unlock(); unlock();
ObjectActionSpring::updateActionWorker(deltaTimeStep); ObjectActionSpring::updateActionWorker(deltaTimeStep);
@ -101,59 +85,51 @@ void AvatarActionHold::updateActionWorker(float deltaTimeStep) {
bool AvatarActionHold::updateArguments(QVariantMap arguments) { bool AvatarActionHold::updateArguments(QVariantMap arguments) {
bool rPOk = true; bool ok = true;
glm::vec3 relativePosition = glm::vec3 relativePosition =
EntityActionInterface::extractVec3Argument("hold", arguments, "relativePosition", rPOk, false); EntityActionInterface::extractVec3Argument("hold", arguments, "relativePosition", ok, false);
bool rROk = true; if (!ok) {
relativePosition = _relativePosition;
}
ok = true;
glm::quat relativeRotation = glm::quat relativeRotation =
EntityActionInterface::extractQuatArgument("hold", arguments, "relativeRotation", rROk, false); EntityActionInterface::extractQuatArgument("hold", arguments, "relativeRotation", ok, false);
bool tSOk = true; if (!ok) {
relativeRotation = _relativeRotation;
}
ok = true;
float timeScale = float timeScale =
EntityActionInterface::extractFloatArgument("hold", arguments, "timeScale", tSOk, false); EntityActionInterface::extractFloatArgument("hold", arguments, "timeScale", ok, false);
bool hOk = true; if (!ok) {
timeScale = _linearTimeScale;
}
ok = true;
QString hand = QString hand =
EntityActionInterface::extractStringArgument("hold", arguments, "hand", hOk, false); EntityActionInterface::extractStringArgument("hold", arguments, "hand", ok, false);
if (!ok || !(hand == "left" || hand == "right")) {
hand = _hand;
}
if (relativePosition != _relativePosition
|| relativeRotation != _relativeRotation
|| timeScale != _linearTimeScale
|| hand != _hand) {
lockForWrite(); lockForWrite();
if (rPOk) {
_relativePosition = relativePosition; _relativePosition = relativePosition;
} else {
_relativePosition = glm::vec3(0.0f, 0.0f, 1.0f);
}
if (rROk) {
_relativeRotation = relativeRotation; _relativeRotation = relativeRotation;
} else { const float MIN_TIMESCALE = 0.1f;
_relativeRotation = glm::quat(0.0f, 0.0f, 0.0f, 1.0f); _linearTimeScale = glm::min(MIN_TIMESCALE, timeScale);
} _angularTimeScale = _linearTimeScale;
_hand = hand;
if (tSOk) {
_linearTimeScale = timeScale;
_angularTimeScale = timeScale;
} else {
_linearTimeScale = 0.2f;
_angularTimeScale = 0.2f;
}
if (hOk) {
hand = hand.toLower();
if (hand == "left") {
_hand = "left";
} else if (hand == "right") {
_hand = "right";
} else {
qDebug() << "hold action -- invalid hand argument:" << hand;
_hand = "right";
}
} else {
_hand = "right";
}
_mine = true; _mine = true;
_positionalTargetSet = true;
_rotationalTargetSet = true;
_active = true; _active = true;
activateBody();
unlock(); unlock();
}
return true; return true;
} }

View file

@ -179,7 +179,7 @@ void ApplicationCompositor::bindCursorTexture(gpu::Batch& batch, uint8_t cursorI
_cursors[iconId] = DependencyManager::get<TextureCache>()-> _cursors[iconId] = DependencyManager::get<TextureCache>()->
getImageTexture(iconPath); getImageTexture(iconPath);
} }
batch.setUniformTexture(0, _cursors[iconId]); batch.setResourceTexture(0, _cursors[iconId]);
} }
// Draws the FBO texture for the screen // Draws the FBO texture for the screen

View file

@ -200,7 +200,7 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder(RenderArgs* renderAr
geometryCache->useSimpleDrawPipeline(batch); geometryCache->useSimpleDrawPipeline(batch);
batch.setProjectionTransform(mat4()); batch.setProjectionTransform(mat4());
batch.setModelTransform(mat4()); batch.setModelTransform(mat4());
batch.setUniformTexture(0, DependencyManager::get<TextureCache>()->getWhiteTexture()); batch.setResourceTexture(0, DependencyManager::get<TextureCache>()->getWhiteTexture());
batch._glLineWidth(CONNECTION_STATUS_BORDER_LINE_WIDTH); batch._glLineWidth(CONNECTION_STATUS_BORDER_LINE_WIDTH);
// TODO animate the disconnect border for some excitement while not connected? // TODO animate the disconnect border for some excitement while not connected?

View file

@ -87,12 +87,12 @@ void BillboardOverlay::render(RenderArgs* args) {
transform.postScale(glm::vec3(getDimensions(), 1.0f)); transform.postScale(glm::vec3(getDimensions(), 1.0f));
batch->setModelTransform(transform); batch->setModelTransform(transform);
batch->setUniformTexture(0, _texture->getGPUTexture()); batch->setResourceTexture(0, _texture->getGPUTexture());
DependencyManager::get<GeometryCache>()->renderQuad(*batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, DependencyManager::get<GeometryCache>()->renderQuad(*batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha)); glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha));
batch->setUniformTexture(0, args->_whiteTexture); // restore default white color after me batch->setResourceTexture(0, args->_whiteTexture); // restore default white color after me
} }
} }

View file

@ -50,7 +50,7 @@ void RenderableParticleEffectEntityItem::render(RenderArgs* args) {
Q_ASSERT(args->_batch); Q_ASSERT(args->_batch);
gpu::Batch& batch = *args->_batch; gpu::Batch& batch = *args->_batch;
if (textured) { if (textured) {
batch.setUniformTexture(0, _texture->getGPUTexture()); batch.setResourceTexture(0, _texture->getGPUTexture());
} }
batch.setModelTransform(getTransformToCenter()); batch.setModelTransform(getTransformToCenter());
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, textured); DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, textured);

View file

@ -127,21 +127,21 @@ glm::vec3 EntityActionInterface::extractVec3Argument(QString objectName, QVarian
qDebug() << objectName << "requires argument:" << argumentName; qDebug() << objectName << "requires argument:" << argumentName;
} }
ok = false; ok = false;
return glm::vec3(); return glm::vec3(0.0f);
} }
QVariant resultV = arguments[argumentName]; QVariant resultV = arguments[argumentName];
if (resultV.type() != (QVariant::Type) QMetaType::QVariantMap) { if (resultV.type() != (QVariant::Type) QMetaType::QVariantMap) {
qDebug() << objectName << "argument" << argumentName << "must be a map"; qDebug() << objectName << "argument" << argumentName << "must be a map";
ok = false; ok = false;
return glm::vec3(); return glm::vec3(0.0f);
} }
QVariantMap resultVM = resultV.toMap(); QVariantMap resultVM = resultV.toMap();
if (!resultVM.contains("x") || !resultVM.contains("y") || !resultVM.contains("z")) { if (!resultVM.contains("x") || !resultVM.contains("y") || !resultVM.contains("z")) {
qDebug() << objectName << "argument" << argumentName << "must be a map with keys of x, y, z"; qDebug() << objectName << "argument" << argumentName << "must be a map with keys: x, y, z";
ok = false; ok = false;
return glm::vec3(); return glm::vec3(0.0f);
} }
QVariant xV = resultVM["x"]; QVariant xV = resultVM["x"];
@ -155,9 +155,15 @@ glm::vec3 EntityActionInterface::extractVec3Argument(QString objectName, QVarian
float y = yV.toFloat(&yOk); float y = yV.toFloat(&yOk);
float z = zV.toFloat(&zOk); float z = zV.toFloat(&zOk);
if (!xOk || !yOk || !zOk) { if (!xOk || !yOk || !zOk) {
qDebug() << objectName << "argument" << argumentName << "must be a map with keys of x, y, z and values of type float."; qDebug() << objectName << "argument" << argumentName << "must be a map with keys: x, y, and z of type float.";
ok = false; ok = false;
return glm::vec3(); return glm::vec3(0.0f);
}
if (x != x || y != y || z != z) {
// at least one of the values is NaN
ok = false;
return glm::vec3(0.0f);
} }
return glm::vec3(x, y, z); return glm::vec3(x, y, z);
@ -181,8 +187,8 @@ glm::quat EntityActionInterface::extractQuatArgument(QString objectName, QVarian
} }
QVariantMap resultVM = resultV.toMap(); QVariantMap resultVM = resultV.toMap();
if (!resultVM.contains("x") || !resultVM.contains("y") || !resultVM.contains("z")) { if (!resultVM.contains("x") || !resultVM.contains("y") || !resultVM.contains("z") || !resultVM.contains("w")) {
qDebug() << objectName << "argument" << argumentName << "must be a map with keys of x, y, z"; qDebug() << objectName << "argument" << argumentName << "must be a map with keys: x, y, z, and w";
ok = false; ok = false;
return glm::quat(); return glm::quat();
} }
@ -202,12 +208,18 @@ glm::quat EntityActionInterface::extractQuatArgument(QString objectName, QVarian
float w = wV.toFloat(&wOk); float w = wV.toFloat(&wOk);
if (!xOk || !yOk || !zOk || !wOk) { if (!xOk || !yOk || !zOk || !wOk) {
qDebug() << objectName << "argument" << argumentName qDebug() << objectName << "argument" << argumentName
<< "must be a map with keys of x, y, z, w and values of type float."; << "must be a map with keys: x, y, z, and w of type float.";
ok = false; ok = false;
return glm::quat(); return glm::quat();
} }
return glm::quat(w, x, y, z); if (x != x || y != y || z != z || w != w) {
// at least one of the components is NaN!
ok = false;
return glm::quat();
}
return glm::normalize(glm::quat(w, x, y, z));
} }
float EntityActionInterface::extractFloatArgument(QString objectName, QVariantMap arguments, float EntityActionInterface::extractFloatArgument(QString objectName, QVariantMap arguments,
@ -224,7 +236,7 @@ float EntityActionInterface::extractFloatArgument(QString objectName, QVariantMa
bool vOk = true; bool vOk = true;
float v = vV.toFloat(&vOk); float v = vV.toFloat(&vOk);
if (!vOk) { if (!vOk || v != v) {
ok = false; ok = false;
return 0.0f; return 0.0f;
} }

View file

@ -1496,7 +1496,7 @@ bool EntityItem::addAction(EntitySimulation* simulation, EntityActionPointer act
bool result = addActionInternal(simulation, action); bool result = addActionInternal(simulation, action);
if (!result) { if (!result) {
removeAction(simulation, action->getID()); removeActionInternal(action->getID());
} }
unlock(); unlock();
@ -1520,6 +1520,7 @@ bool EntityItem::addActionInternal(EntitySimulation* simulation, EntityActionPoi
QByteArray newDataCache = serializeActions(success); QByteArray newDataCache = serializeActions(success);
if (success) { if (success) {
_allActionsDataCache = newDataCache; _allActionsDataCache = newDataCache;
_dirtyFlags |= EntityItem::DIRTY_PHYSICS_ACTIVATION;
} }
return success; return success;
} }
@ -1537,6 +1538,7 @@ bool EntityItem::updateAction(EntitySimulation* simulation, const QUuid& actionI
bool success = action->updateArguments(arguments); bool success = action->updateArguments(arguments);
if (success) { if (success) {
_allActionsDataCache = serializeActions(success); _allActionsDataCache = serializeActions(success);
_dirtyFlags |= EntityItem::DIRTY_PHYSICS_ACTIVATION;
} else { } else {
qDebug() << "EntityItem::updateAction failed"; qDebug() << "EntityItem::updateAction failed";
} }
@ -1572,6 +1574,7 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulation* s
bool success = true; bool success = true;
_allActionsDataCache = serializeActions(success); _allActionsDataCache = serializeActions(success);
_dirtyFlags |= EntityItem::DIRTY_PHYSICS_ACTIVATION;
return success; return success;
} }
return false; return false;
@ -1590,6 +1593,7 @@ bool EntityItem::clearActions(EntitySimulation* simulation) {
// empty _serializedActions means no actions for the EntityItem // empty _serializedActions means no actions for the EntityItem
_actionsToRemove.clear(); _actionsToRemove.clear();
_allActionsDataCache.clear(); _allActionsDataCache.clear();
_dirtyFlags |= EntityItem::DIRTY_PHYSICS_ACTIVATION;
unlock(); unlock();
return true; return true;
} }

View file

@ -543,6 +543,9 @@ bool EntityScriptingInterface::actionWorker(const QUuid& entityID,
} }
bool success = actor(simulation, entity); bool success = actor(simulation, entity);
if (success) {
_entityTree->entityChanged(entity);
}
_entityTree->unlock(); _entityTree->unlock();
// transmit the change // transmit the change

View file

@ -227,15 +227,15 @@ void Batch::setUniformBuffer(uint32 slot, const BufferView& view) {
} }
void Batch::setUniformTexture(uint32 slot, const TexturePointer& texture) { void Batch::setResourceTexture(uint32 slot, const TexturePointer& texture) {
ADD_COMMAND(setUniformTexture); ADD_COMMAND(setResourceTexture);
_params.push_back(_textures.cache(texture)); _params.push_back(_textures.cache(texture));
_params.push_back(slot); _params.push_back(slot);
} }
void Batch::setUniformTexture(uint32 slot, const TextureView& view) { void Batch::setResourceTexture(uint32 slot, const TextureView& view) {
setUniformTexture(slot, view._texture); setResourceTexture(slot, view._texture);
} }
void Batch::setFramebuffer(const FramebufferPointer& framebuffer) { void Batch::setFramebuffer(const FramebufferPointer& framebuffer) {

View file

@ -103,8 +103,8 @@ public:
void setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size); void setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size);
void setUniformBuffer(uint32 slot, const BufferView& view); // not a command, just a shortcut from a BufferView void setUniformBuffer(uint32 slot, const BufferView& view); // not a command, just a shortcut from a BufferView
void setUniformTexture(uint32 slot, const TexturePointer& view); void setResourceTexture(uint32 slot, const TexturePointer& view);
void setUniformTexture(uint32 slot, const TextureView& view); // not a command, just a shortcut from a TextureView void setResourceTexture(uint32 slot, const TextureView& view); // not a command, just a shortcut from a TextureView
// Framebuffer Stage // Framebuffer Stage
void setFramebuffer(const FramebufferPointer& framebuffer); void setFramebuffer(const FramebufferPointer& framebuffer);
@ -178,7 +178,7 @@ public:
COMMAND_setStateBlendFactor, COMMAND_setStateBlendFactor,
COMMAND_setUniformBuffer, COMMAND_setUniformBuffer,
COMMAND_setUniformTexture, COMMAND_setResourceTexture,
COMMAND_setFramebuffer, COMMAND_setFramebuffer,

View file

@ -35,7 +35,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
(&::gpu::GLBackend::do_setStateBlendFactor), (&::gpu::GLBackend::do_setStateBlendFactor),
(&::gpu::GLBackend::do_setUniformBuffer), (&::gpu::GLBackend::do_setUniformBuffer),
(&::gpu::GLBackend::do_setUniformTexture), (&::gpu::GLBackend::do_setResourceTexture),
(&::gpu::GLBackend::do_setFramebuffer), (&::gpu::GLBackend::do_setFramebuffer),

View file

@ -321,7 +321,7 @@ protected:
// Uniform Stage // Uniform Stage
void do_setUniformBuffer(Batch& batch, uint32 paramOffset); void do_setUniformBuffer(Batch& batch, uint32 paramOffset);
void do_setUniformTexture(Batch& batch, uint32 paramOffset); void do_setResourceTexture(Batch& batch, uint32 paramOffset);
struct UniformStageState { struct UniformStageState {

View file

@ -188,7 +188,7 @@ void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) {
(void) CHECK_GL_ERROR(); (void) CHECK_GL_ERROR();
} }
void GLBackend::do_setUniformTexture(Batch& batch, uint32 paramOffset) { void GLBackend::do_setResourceTexture(Batch& batch, uint32 paramOffset) {
GLuint slot = batch._params[paramOffset + 1]._uint; GLuint slot = batch._params[paramOffset + 1]._uint;
TexturePointer uniformTexture = batch._textures.get(batch._params[paramOffset + 0]._uint); TexturePointer uniformTexture = batch._textures.get(batch._params[paramOffset + 0]._uint);

View file

@ -103,7 +103,7 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky
batch.setInputBuffer(gpu::Stream::POSITION, theBuffer, 0, 8); batch.setInputBuffer(gpu::Stream::POSITION, theBuffer, 0, 8);
batch.setUniformBuffer(SKYBOX_CONSTANTS_SLOT, theConstants, 0, theConstants->getSize()); batch.setUniformBuffer(SKYBOX_CONSTANTS_SLOT, theConstants, 0, theConstants->getSize());
batch.setInputFormat(theFormat); batch.setInputFormat(theFormat);
batch.setUniformTexture(0, skybox.getCubemap()); batch.setResourceTexture(0, skybox.getCubemap());
batch.draw(gpu::TRIANGLE_STRIP, 4); batch.draw(gpu::TRIANGLE_STRIP, 4);
} }

View file

@ -129,3 +129,10 @@ void ObjectAction::setAngularVelocity(glm::vec3 angularVelocity) {
rigidBody->activate(); rigidBody->activate();
} }
void ObjectAction::activateBody() {
auto rigidBody = getRigidBody();
if (rigidBody) {
rigidBody->activate();
}
}

View file

@ -55,6 +55,7 @@ protected:
virtual void setLinearVelocity(glm::vec3 linearVelocity); virtual void setLinearVelocity(glm::vec3 linearVelocity);
virtual glm::vec3 getAngularVelocity(); virtual glm::vec3 getAngularVelocity();
virtual void setAngularVelocity(glm::vec3 angularVelocity); virtual void setAngularVelocity(glm::vec3 angularVelocity);
virtual void activateBody();
void lockForRead() { _lock.lockForRead(); } void lockForRead() { _lock.lockForRead(); }
bool tryLockForRead() { return _lock.tryLockForRead(); } bool tryLockForRead() { return _lock.tryLockForRead(); }

View file

@ -59,10 +59,6 @@ void ObjectActionOffset::updateActionWorker(btScalar deltaTimeStep) {
const float MAX_LINEAR_TIMESCALE = 600.0f; // 10 minutes is a long time const float MAX_LINEAR_TIMESCALE = 600.0f; // 10 minutes is a long time
if (_positionalTargetSet && _linearTimeScale < MAX_LINEAR_TIMESCALE) { if (_positionalTargetSet && _linearTimeScale < MAX_LINEAR_TIMESCALE) {
if (_needsActivation) {
rigidBody->activate();
_needsActivation = false;
}
glm::vec3 objectPosition = bulletToGLM(rigidBody->getCenterOfMassPosition()); glm::vec3 objectPosition = bulletToGLM(rigidBody->getCenterOfMassPosition());
glm::vec3 springAxis = objectPosition - _pointToOffsetFrom; // from anchor to object glm::vec3 springAxis = objectPosition - _pointToOffsetFrom; // from anchor to object
float distance = glm::length(springAxis); float distance = glm::length(springAxis);
@ -95,26 +91,21 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) {
glm::vec3 pointToOffsetFrom = glm::vec3 pointToOffsetFrom =
EntityActionInterface::extractVec3Argument("offset action", arguments, "pointToOffsetFrom", ok, true); EntityActionInterface::extractVec3Argument("offset action", arguments, "pointToOffsetFrom", ok, true);
if (!ok) { if (!ok) {
return false; pointToOffsetFrom = _pointToOffsetFrom;
} }
ok = true; ok = true;
float linearTimeScale = float linearTimeScale =
EntityActionInterface::extractFloatArgument("offset action", arguments, "linearTimeScale", ok, false); EntityActionInterface::extractFloatArgument("offset action", arguments, "linearTimeScale", ok, false);
if (ok) { if (!ok) {
if (linearTimeScale <= 0.0f) { linearTimeScale = _linearTimeScale;
qDebug() << "offset action -- linearTimeScale must be greater than zero.";
return false;
}
} else {
linearTimeScale = 0.1f;
} }
ok = true; ok = true;
float linearDistance = float linearDistance =
EntityActionInterface::extractFloatArgument("offset action", arguments, "linearDistance", ok, false); EntityActionInterface::extractFloatArgument("offset action", arguments, "linearDistance", ok, false);
if (!ok) { if (!ok) {
linearDistance = 0.0f; linearDistance = _linearDistance;
} }
// only change stuff if something actually changed // only change stuff if something actually changed
@ -127,7 +118,7 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) {
_linearDistance = linearDistance; _linearDistance = linearDistance;
_positionalTargetSet = true; _positionalTargetSet = true;
_active = true; _active = true;
_needsActivation = true; activateBody();
unlock(); unlock();
} }
return true; return true;

View file

@ -36,7 +36,6 @@ public:
float _linearDistance; float _linearDistance;
float _linearTimeScale; float _linearTimeScale;
bool _positionalTargetSet; bool _positionalTargetSet;
bool _needsActivation = true;
}; };
#endif // hifi_ObjectActionOffset_h #endif // hifi_ObjectActionOffset_h

View file

@ -17,14 +17,15 @@ const float SPRING_MAX_SPEED = 10.0f;
const uint16_t ObjectActionSpring::springVersion = 1; const uint16_t ObjectActionSpring::springVersion = 1;
ObjectActionSpring::ObjectActionSpring(const QUuid& id, EntityItemPointer ownerEntity) : ObjectActionSpring::ObjectActionSpring(const QUuid& id, EntityItemPointer ownerEntity) :
ObjectAction(ACTION_TYPE_SPRING, id, ownerEntity), ObjectAction(ACTION_TYPE_SPRING, id, ownerEntity),
_positionalTarget(glm::vec3(0.0f)), _positionalTarget(glm::vec3(0.0f)),
_linearTimeScale(0.2f), _linearTimeScale(FLT_MAX),
_positionalTargetSet(false), _positionalTargetSet(true),
_rotationalTarget(glm::quat()), _rotationalTarget(glm::quat()),
_angularTimeScale(0.2f), _angularTimeScale(FLT_MAX),
_rotationalTargetSet(false) { _rotationalTargetSet(true) {
#if WANT_DEBUG #if WANT_DEBUG
qDebug() << "ObjectActionSpring::ObjectActionSpring"; qDebug() << "ObjectActionSpring::ObjectActionSpring";
#endif #endif
@ -61,130 +62,92 @@ void ObjectActionSpring::updateActionWorker(btScalar deltaTimeStep) {
return; return;
} }
// handle the linear part const float MAX_TIMESCALE = 600.0f; // 10 min is a long time
if (_positionalTargetSet) { if (_linearTimeScale < MAX_TIMESCALE) {
// check for NaN btVector3 offset = rigidBody->getCenterOfMassPosition() - glmToBullet(_positionalTarget);
if (_positionalTarget.x != _positionalTarget.x || float offsetLength = offset.length();
_positionalTarget.y != _positionalTarget.y || float speed = (offsetLength > FLT_EPSILON) ? glm::min(offsetLength / _linearTimeScale, SPRING_MAX_SPEED) : 0.0f;
_positionalTarget.z != _positionalTarget.z) {
qDebug() << "ObjectActionSpring::updateActionWorker -- target position includes NaN";
unlock();
lockForWrite();
_active = false;
unlock();
return;
}
glm::vec3 offset = _positionalTarget - bulletToGLM(rigidBody->getCenterOfMassPosition());
float offsetLength = glm::length(offset);
float speed = offsetLength / _linearTimeScale;
// cap speed // this action is aggresively critically damped and defeats the current velocity
if (speed > SPRING_MAX_SPEED) { rigidBody->setLinearVelocity((- speed / offsetLength) * offset);
speed = SPRING_MAX_SPEED;
} }
if (offsetLength > IGNORE_POSITION_DELTA) { if (_angularTimeScale < MAX_TIMESCALE) {
glm::vec3 newVelocity = glm::normalize(offset) * speed; btVector3 targetVelocity(0.0f, 0.0f, 0.0f);
rigidBody->setLinearVelocity(glmToBullet(newVelocity));
rigidBody->activate();
} else {
rigidBody->setLinearVelocity(glmToBullet(glm::vec3(0.0f)));
}
}
// handle rotation btQuaternion bodyRotation = rigidBody->getOrientation();
if (_rotationalTargetSet) { auto alignmentDot = bodyRotation.dot(glmToBullet(_rotationalTarget));
if (_rotationalTarget.x != _rotationalTarget.x || const float ALMOST_ONE = 0.99999f;
_rotationalTarget.y != _rotationalTarget.y || if (glm::abs(alignmentDot) < ALMOST_ONE) {
_rotationalTarget.z != _rotationalTarget.z || btQuaternion target = glmToBullet(_rotationalTarget);
_rotationalTarget.w != _rotationalTarget.w) { if (alignmentDot < 0.0f) {
qDebug() << "AvatarActionHold::updateActionWorker -- target rotation includes NaN";
unlock();
lockForWrite();
_active = false;
unlock();
return;
}
glm::quat bodyRotation = bulletToGLM(rigidBody->getOrientation());
// if qZero and qOne are too close to each other, we can get NaN for angle.
auto alignmentDot = glm::dot(bodyRotation, _rotationalTarget);
const float almostOne = 0.99999f;
if (glm::abs(alignmentDot) < almostOne) {
glm::quat target = _rotationalTarget;
if (alignmentDot < 0) {
target = -target; target = -target;
} }
glm::quat qZeroInverse = glm::inverse(bodyRotation); // if dQ is the incremental rotation that gets an object from Q0 to Q1 then:
glm::quat deltaQ = target * qZeroInverse; //
glm::vec3 axis = glm::axis(deltaQ); // Q1 = dQ * Q0
float angle = glm::angle(deltaQ); //
assert(!isNaN(angle)); // solving for dQ gives:
glm::vec3 newAngularVelocity = (angle / _angularTimeScale) * glm::normalize(axis); //
rigidBody->setAngularVelocity(glmToBullet(newAngularVelocity)); // dQ = Q1 * Q0^
rigidBody->activate(); btQuaternion deltaQ = target * bodyRotation.inverse();
} else { float angle = deltaQ.getAngle();
rigidBody->setAngularVelocity(glmToBullet(glm::vec3(0.0f))); const float MIN_ANGLE = 1.0e-4;
if (angle > MIN_ANGLE) {
targetVelocity = (angle / _angularTimeScale) * deltaQ.getAxis();
} }
} }
// this action is aggresively critically damped and defeats the current velocity
rigidBody->setAngularVelocity(targetVelocity);
}
unlock(); unlock();
} }
const float MIN_TIMESCALE = 0.1f;
bool ObjectActionSpring::updateArguments(QVariantMap arguments) { bool ObjectActionSpring::updateArguments(QVariantMap arguments) {
// targets are required, spring-constants are optional // targets are required, spring-constants are optional
bool ptOk = true; bool ok = true;
glm::vec3 positionalTarget = glm::vec3 positionalTarget =
EntityActionInterface::extractVec3Argument("spring action", arguments, "targetPosition", ptOk, false); EntityActionInterface::extractVec3Argument("spring action", arguments, "targetPosition", ok, false);
bool pscOk = true; if (!ok) {
positionalTarget = _positionalTarget;
}
ok = true;
float linearTimeScale = float linearTimeScale =
EntityActionInterface::extractFloatArgument("spring action", arguments, "linearTimeScale", pscOk, false); EntityActionInterface::extractFloatArgument("spring action", arguments, "linearTimeScale", ok, false);
if (ptOk && pscOk && linearTimeScale <= 0.0f) { if (!ok || linearTimeScale <= 0.0f) {
qDebug() << "spring action -- linearTimeScale must be greater than zero."; linearTimeScale = _linearTimeScale;
return false;
} }
bool rtOk = true; ok = true;
glm::quat rotationalTarget = glm::quat rotationalTarget =
EntityActionInterface::extractQuatArgument("spring action", arguments, "targetRotation", rtOk, false); EntityActionInterface::extractQuatArgument("spring action", arguments, "targetRotation", ok, false);
bool rscOk = true; if (!ok) {
rotationalTarget = _rotationalTarget;
}
ok = true;
float angularTimeScale = float angularTimeScale =
EntityActionInterface::extractFloatArgument("spring action", arguments, "angularTimeScale", rscOk, false); EntityActionInterface::extractFloatArgument("spring action", arguments, "angularTimeScale", ok, false);
if (!ok) {
if (!ptOk && !rtOk) { angularTimeScale = _angularTimeScale;
qDebug() << "spring action requires at least one of targetPosition or targetRotation argument";
return false;
} }
if (positionalTarget != _positionalTarget
|| linearTimeScale != _linearTimeScale
|| rotationalTarget != _rotationalTarget
|| angularTimeScale != _angularTimeScale) {
// something changed
lockForWrite(); lockForWrite();
_positionalTargetSet = _rotationalTargetSet = false;
if (ptOk) {
_positionalTarget = positionalTarget; _positionalTarget = positionalTarget;
_positionalTargetSet = true; _linearTimeScale = glm::max(MIN_TIMESCALE, glm::abs(linearTimeScale));
if (pscOk) {
_linearTimeScale = linearTimeScale;
} else {
_linearTimeScale = 0.1f;
}
}
if (rtOk) {
_rotationalTarget = rotationalTarget; _rotationalTarget = rotationalTarget;
_rotationalTargetSet = true; _angularTimeScale = glm::max(MIN_TIMESCALE, glm::abs(angularTimeScale));
if (rscOk) {
_angularTimeScale = angularTimeScale;
} else {
_angularTimeScale = 0.1f;
}
}
_active = true; _active = true;
activateBody();
unlock(); unlock();
}
return true; return true;
} }
@ -192,15 +155,11 @@ QVariantMap ObjectActionSpring::getArguments() {
QVariantMap arguments; QVariantMap arguments;
lockForRead(); lockForRead();
if (_positionalTargetSet) {
arguments["linearTimeScale"] = _linearTimeScale; arguments["linearTimeScale"] = _linearTimeScale;
arguments["targetPosition"] = glmToQMap(_positionalTarget); arguments["targetPosition"] = glmToQMap(_positionalTarget);
}
if (_rotationalTargetSet) {
arguments["targetRotation"] = glmToQMap(_rotationalTarget); arguments["targetRotation"] = glmToQMap(_rotationalTarget);
arguments["angularTimeScale"] = _angularTimeScale; arguments["angularTimeScale"] = _angularTimeScale;
}
unlock(); unlock();
return arguments; return arguments;
@ -210,7 +169,7 @@ QByteArray ObjectActionSpring::serialize() const {
QByteArray serializedActionArguments; QByteArray serializedActionArguments;
QDataStream dataStream(&serializedActionArguments, QIODevice::WriteOnly); QDataStream dataStream(&serializedActionArguments, QIODevice::WriteOnly);
dataStream << getType(); dataStream << ACTION_TYPE_SPRING;
dataStream << getID(); dataStream << getID();
dataStream << ObjectActionSpring::springVersion; dataStream << ObjectActionSpring::springVersion;
@ -230,7 +189,7 @@ void ObjectActionSpring::deserialize(QByteArray serializedArguments) {
EntityActionType type; EntityActionType type;
dataStream >> type; dataStream >> type;
assert(type == getType()); assert(type == ACTION_TYPE_SPRING);
QUuid id; QUuid id;
dataStream >> id; dataStream >> id;

View file

@ -146,7 +146,7 @@ void DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured,
if (!config.isTextured()) { if (!config.isTextured()) {
// If it is not textured, bind white texture and keep using textured pipeline // If it is not textured, bind white texture and keep using textured pipeline
batch.setUniformTexture(0, DependencyManager::get<TextureCache>()->getWhiteTexture()); batch.setResourceTexture(0, DependencyManager::get<TextureCache>()->getWhiteTexture());
} }
} }
@ -243,13 +243,13 @@ void DeferredLightingEffect::render(RenderArgs* args) {
batch.clearColorFramebuffer(freeFBO->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f)); batch.clearColorFramebuffer(freeFBO->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f));
batch.setUniformTexture(0, textureCache->getPrimaryColorTexture()); batch.setResourceTexture(0, textureCache->getPrimaryColorTexture());
batch.setUniformTexture(1, textureCache->getPrimaryNormalTexture()); batch.setResourceTexture(1, textureCache->getPrimaryNormalTexture());
batch.setUniformTexture(2, textureCache->getPrimarySpecularTexture()); batch.setResourceTexture(2, textureCache->getPrimarySpecularTexture());
batch.setUniformTexture(3, textureCache->getPrimaryDepthTexture()); batch.setResourceTexture(3, textureCache->getPrimaryDepthTexture());
// get the viewport side (left, right, both) // get the viewport side (left, right, both)
int viewport[4]; int viewport[4];
@ -274,7 +274,7 @@ void DeferredLightingEffect::render(RenderArgs* args) {
const LightLocations* locations = &_directionalLightLocations; const LightLocations* locations = &_directionalLightLocations;
bool shadowsEnabled = _viewState->getShadowsEnabled(); bool shadowsEnabled = _viewState->getShadowsEnabled();
if (shadowsEnabled) { if (shadowsEnabled) {
batch.setUniformTexture(4, textureCache->getShadowFramebuffer()->getDepthStencilBuffer()); batch.setResourceTexture(4, textureCache->getShadowFramebuffer()->getDepthStencilBuffer());
program = _directionalLightShadowMap; program = _directionalLightShadowMap;
locations = &_directionalLightShadowMapLocations; locations = &_directionalLightShadowMapLocations;
@ -328,7 +328,7 @@ void DeferredLightingEffect::render(RenderArgs* args) {
} }
if (useSkyboxCubemap) { if (useSkyboxCubemap) {
batch.setUniformTexture(5, _skybox->getCubemap()); batch.setResourceTexture(5, _skybox->getCubemap());
} }
if (locations->lightBufferUnit >= 0) { if (locations->lightBufferUnit >= 0) {
@ -377,11 +377,11 @@ void DeferredLightingEffect::render(RenderArgs* args) {
} }
if (useSkyboxCubemap) { if (useSkyboxCubemap) {
batch.setUniformTexture(5, nullptr); batch.setResourceTexture(5, nullptr);
} }
if (shadowsEnabled) { if (shadowsEnabled) {
batch.setUniformTexture(4, nullptr); batch.setResourceTexture(4, nullptr);
} }
glm::vec4 sCoefficients(sWidth / 2.0f, 0.0f, 0.0f, sMin + sWidth / 2.0f); glm::vec4 sCoefficients(sWidth / 2.0f, 0.0f, 0.0f, sMin + sWidth / 2.0f);
@ -530,10 +530,10 @@ void DeferredLightingEffect::render(RenderArgs* args) {
} }
// Probably not necessary in the long run because the gpu layer would unbound this texture if used as render target // Probably not necessary in the long run because the gpu layer would unbound this texture if used as render target
batch.setUniformTexture(0, nullptr); batch.setResourceTexture(0, nullptr);
batch.setUniformTexture(1, nullptr); batch.setResourceTexture(1, nullptr);
batch.setUniformTexture(2, nullptr); batch.setResourceTexture(2, nullptr);
batch.setUniformTexture(3, nullptr); batch.setResourceTexture(3, nullptr);
args->_context->syncCache(); args->_context->syncCache();
args->_context->render(batch); args->_context->render(batch);
@ -551,7 +551,7 @@ void DeferredLightingEffect::copyBack(RenderArgs* args) {
batch.setFramebuffer(textureCache->getPrimaryFramebuffer()); batch.setFramebuffer(textureCache->getPrimaryFramebuffer());
batch.setPipeline(_blitLightBuffer); batch.setPipeline(_blitLightBuffer);
batch.setUniformTexture(0, freeFBO->getRenderBuffer(0)); batch.setResourceTexture(0, freeFBO->getRenderBuffer(0));
batch.setProjectionTransform(glm::mat4()); batch.setProjectionTransform(glm::mat4());
batch.setViewTransform(Transform()); batch.setViewTransform(Transform());

View file

@ -2031,10 +2031,10 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran
} }
static bool showDiffuse = true; static bool showDiffuse = true;
if (showDiffuse && diffuseMap) { if (showDiffuse && diffuseMap) {
batch.setUniformTexture(0, diffuseMap->getGPUTexture()); batch.setResourceTexture(0, diffuseMap->getGPUTexture());
} else { } else {
batch.setUniformTexture(0, textureCache->getWhiteTexture()); batch.setResourceTexture(0, textureCache->getWhiteTexture());
} }
if (locations->texcoordMatrices >= 0) { if (locations->texcoordMatrices >= 0) {
@ -2050,14 +2050,14 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran
if (!mesh.tangents.isEmpty()) { if (!mesh.tangents.isEmpty()) {
Texture* normalMap = networkPart.normalTexture.data(); Texture* normalMap = networkPart.normalTexture.data();
batch.setUniformTexture(1, !normalMap ? batch.setResourceTexture(1, !normalMap ?
textureCache->getBlueTexture() : normalMap->getGPUTexture()); textureCache->getBlueTexture() : normalMap->getGPUTexture());
} }
if (locations->specularTextureUnit >= 0) { if (locations->specularTextureUnit >= 0) {
Texture* specularMap = networkPart.specularTexture.data(); Texture* specularMap = networkPart.specularTexture.data();
batch.setUniformTexture(locations->specularTextureUnit, !specularMap ? batch.setResourceTexture(locations->specularTextureUnit, !specularMap ?
textureCache->getWhiteTexture() : specularMap->getGPUTexture()); textureCache->getWhiteTexture() : specularMap->getGPUTexture());
} }
@ -2074,7 +2074,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran
GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale); GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale);
Texture* emissiveMap = networkPart.emissiveTexture.data(); Texture* emissiveMap = networkPart.emissiveTexture.data();
batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ? batch.setResourceTexture(locations->emissiveTextureUnit, !emissiveMap ?
textureCache->getWhiteTexture() : emissiveMap->getGPUTexture()); textureCache->getWhiteTexture() : emissiveMap->getGPUTexture());
} }

View file

@ -243,7 +243,7 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon
batch.setViewTransform(viewMat); batch.setViewTransform(viewMat);
batch.setPipeline(getOpaquePipeline()); batch.setPipeline(getOpaquePipeline());
batch.setUniformTexture(0, args->_whiteTexture); batch.setResourceTexture(0, args->_whiteTexture);
if (!inItems.empty()) { if (!inItems.empty()) {
batch.clearFramebuffer(gpu::Framebuffer::BUFFER_DEPTH, glm::vec4(), 1.f, 0); batch.clearFramebuffer(gpu::Framebuffer::BUFFER_DEPTH, glm::vec4(), 1.f, 0);

View file

@ -423,7 +423,7 @@ void Font3D::drawString(gpu::Batch& batch, float x, float y, const QString& str,
setupGPU(); setupGPU();
batch.setPipeline(_pipeline); batch.setPipeline(_pipeline);
batch.setUniformTexture(_fontLoc, _texture); batch.setResourceTexture(_fontLoc, _texture);
batch._glUniform1i(_outlineLoc, (effectType == TextRenderer3D::OUTLINE_EFFECT)); batch._glUniform1i(_outlineLoc, (effectType == TextRenderer3D::OUTLINE_EFFECT));
batch._glUniform4fv(_colorLoc, 1, (const GLfloat*)color); batch._glUniform4fv(_colorLoc, 1, (const GLfloat*)color);