mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 10:07:58 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into transmit-joint-translation
This commit is contained in:
commit
d0a1e206ca
77 changed files with 1252 additions and 4418 deletions
|
@ -186,7 +186,6 @@ setup_externals_binary_dir()
|
||||||
option(GET_BULLET "Get Bullet library automatically as external project" 1)
|
option(GET_BULLET "Get Bullet library automatically as external project" 1)
|
||||||
option(GET_GLM "Get GLM library automatically as external project" 1)
|
option(GET_GLM "Get GLM library automatically as external project" 1)
|
||||||
option(GET_GVERB "Get Gverb library automatically as external project" 1)
|
option(GET_GVERB "Get Gverb library automatically as external project" 1)
|
||||||
option(GET_SOXR "Get Soxr library automatically as external project" 1)
|
|
||||||
option(GET_TBB "Get Threading Building Blocks library automatically as external project" 1)
|
option(GET_TBB "Get Threading Building Blocks library automatically as external project" 1)
|
||||||
option(GET_LIBOVR "Get LibOVR library automatically as external project" 1)
|
option(GET_LIBOVR "Get LibOVR library automatically as external project" 1)
|
||||||
option(GET_VHACD "Get V-HACD library automatically as external project" 1)
|
option(GET_VHACD "Get V-HACD library automatically as external project" 1)
|
||||||
|
|
84
examples/acScripts/flickeringLight.js
Normal file
84
examples/acScripts/flickeringLight.js
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
//
|
||||||
|
// flickeringLight.js
|
||||||
|
// examples
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 2015/09/29.
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Creates an ephemeral flickering light that will randomly flicker as long as the script is running.
|
||||||
|
// After the script stops running, the light will eventually disappear (~10 seconds later). This script
|
||||||
|
// can run in the interface or in an assignment client and it will work equally well.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
function randFloat(low, high) {
|
||||||
|
return low + Math.random() * (high - low);
|
||||||
|
}
|
||||||
|
|
||||||
|
var LIGHT_NAME = "flickering fire";
|
||||||
|
|
||||||
|
var LIGHT_POSITION = {
|
||||||
|
x: 551.13,
|
||||||
|
y: 494.77,
|
||||||
|
z: 502.26
|
||||||
|
};
|
||||||
|
|
||||||
|
var LIGHT_COLOR = {
|
||||||
|
red: 255,
|
||||||
|
green: 100,
|
||||||
|
blue: 28
|
||||||
|
};
|
||||||
|
|
||||||
|
var ZERO_VEC = {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
var totalTime = 0;
|
||||||
|
|
||||||
|
var MINIMUM_LIGHT_INTENSITY = 0.75;
|
||||||
|
var MAXIMUM_LIGHT_INTENSITY = 2.75;
|
||||||
|
var LIGHT_INTENSITY_RANDOMNESS = 0.3;
|
||||||
|
var EPHEMERAL_LIFETIME = 10; // ephemeral entities will live for 10 seconds after script stops running
|
||||||
|
|
||||||
|
var LightMaker = {
|
||||||
|
light: null,
|
||||||
|
spawnLight: function() {
|
||||||
|
print('CREATING LIGHT')
|
||||||
|
var _this = this;
|
||||||
|
_this.light = Entities.addEntity({
|
||||||
|
type: "Light",
|
||||||
|
name: LIGHT_NAME,
|
||||||
|
position: LIGHT_POSITION,
|
||||||
|
lifetime: EPHEMERAL_LIFETIME,
|
||||||
|
color: LIGHT_COLOR,
|
||||||
|
dimensions: { x: 10, y: 10, z: 10 }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var hasSpawned = false;
|
||||||
|
|
||||||
|
function update(deltaTime) {
|
||||||
|
|
||||||
|
if (!Entities.serversExist() || !Entities.canRez()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasSpawned === false) {
|
||||||
|
hasSpawned = true;
|
||||||
|
LightMaker.spawnLight();
|
||||||
|
} else {
|
||||||
|
totalTime += deltaTime;
|
||||||
|
var intensity = (MINIMUM_LIGHT_INTENSITY + (MAXIMUM_LIGHT_INTENSITY + (Math.sin(totalTime) * MAXIMUM_LIGHT_INTENSITY)));
|
||||||
|
intensity += randFloat(-LIGHT_INTENSITY_RANDOMNESS, LIGHT_INTENSITY_RANDOMNESS);
|
||||||
|
var properties = Entities.getEntityProperties(LightMaker.light, "age");
|
||||||
|
Entities.editEntity(LightMaker.light, { intensity: intensity, lifetime: properties.age + EPHEMERAL_LIFETIME });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Script.update.connect(update);
|
|
@ -29,7 +29,7 @@ var TRIGGER_ON_VALUE = 0.2;
|
||||||
var DISTANCE_HOLDING_RADIUS_FACTOR = 5; // multiplied by distance between hand and object
|
var DISTANCE_HOLDING_RADIUS_FACTOR = 5; // multiplied by distance between hand and object
|
||||||
var DISTANCE_HOLDING_ACTION_TIMEFRAME = 0.1; // how quickly objects move to their new position
|
var DISTANCE_HOLDING_ACTION_TIMEFRAME = 0.1; // how quickly objects move to their new position
|
||||||
var DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR = 2.0; // object rotates this much more than hand did
|
var DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR = 2.0; // object rotates this much more than hand did
|
||||||
var NO_INTERSECT_COLOR = { red: 10, green: 10, blue: 255}; // line color when pick misses
|
var NO_INTERSECT_COLOR = { red: 10, green: 10, blue: 255 }; // line color when pick misses
|
||||||
var INTERSECT_COLOR = { red: 250, green: 10, blue: 10}; // line color when pick hits
|
var INTERSECT_COLOR = { red: 250, green: 10, blue: 10}; // line color when pick hits
|
||||||
var LINE_ENTITY_DIMENSIONS = { x: 1000, y: 1000, z: 1000};
|
var LINE_ENTITY_DIMENSIONS = { x: 1000, y: 1000, z: 1000};
|
||||||
var LINE_LENGTH = 500;
|
var LINE_LENGTH = 500;
|
||||||
|
@ -54,7 +54,11 @@ var RELEASE_VELOCITY_MULTIPLIER = 1.5; // affects throwing things
|
||||||
var RIGHT_HAND = 1;
|
var RIGHT_HAND = 1;
|
||||||
var LEFT_HAND = 0;
|
var LEFT_HAND = 0;
|
||||||
|
|
||||||
var ZERO_VEC = { x: 0, y: 0, z: 0};
|
var ZERO_VEC = {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
};
|
||||||
var NULL_ACTION_ID = "{00000000-0000-0000-000000000000}";
|
var NULL_ACTION_ID = "{00000000-0000-0000-000000000000}";
|
||||||
var MSEC_PER_SEC = 1000.0;
|
var MSEC_PER_SEC = 1000.0;
|
||||||
|
|
||||||
|
@ -391,6 +395,11 @@ function MyController(hand, triggerAction) {
|
||||||
this.state = STATE_RELEASE;
|
this.state = STATE_RELEASE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (this.hand === RIGHT_HAND) {
|
||||||
|
Entities.callEntityMethod(this.grabbedEntity, "setRightHand");
|
||||||
|
} else {
|
||||||
|
Entities.callEntityMethod(this.grabbedEntity, "setLeftHand");
|
||||||
|
}
|
||||||
Entities.callEntityMethod(this.grabbedEntity, "startNearGrabNonColliding");
|
Entities.callEntityMethod(this.grabbedEntity, "startNearGrabNonColliding");
|
||||||
this.state = STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING;
|
this.state = STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING;
|
||||||
};
|
};
|
||||||
|
@ -546,4 +555,4 @@ function cleanup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Script.scriptEnding.connect(cleanup);
|
Script.scriptEnding.connect(cleanup);
|
||||||
Script.update.connect(update);
|
Script.update.connect(update);
|
|
@ -1035,7 +1035,7 @@ function handeMenuEvent(menuItem) {
|
||||||
|
|
||||||
var importURL;
|
var importURL;
|
||||||
if (menuItem == "Import Entities") {
|
if (menuItem == "Import Entities") {
|
||||||
importURL = Window.browse("Select models to import", "", "*.json");
|
importURL = "file:///" + Window.browse("Select models to import", "", "*.json");
|
||||||
} else {
|
} else {
|
||||||
importURL = Window.prompt("URL of SVO to import", "");
|
importURL = Window.prompt("URL of SVO to import", "");
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,17 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
|
var normalDisplay = Entities.addEntity({
|
||||||
|
type: "Line",
|
||||||
|
name: "normalDisplay",
|
||||||
|
visible: false,
|
||||||
|
color: { red: 255, green: 0, blue: 0 },
|
||||||
|
dimensions: { x: 100, y: 100, z: 100 }
|
||||||
|
});
|
||||||
|
|
||||||
|
var wasVisible = false;
|
||||||
|
|
||||||
function mouseMoveEvent(event) {
|
function mouseMoveEvent(event) {
|
||||||
print("mouseMoveEvent event.x,y=" + event.x + ", " + event.y);
|
print("mouseMoveEvent event.x,y=" + event.x + ", " + event.y);
|
||||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||||
|
@ -18,26 +29,45 @@ function mouseMoveEvent(event) {
|
||||||
print("computePickRay origin=" + pickRay.origin.x + ", " + pickRay.origin.y + ", " + pickRay.origin.z);
|
print("computePickRay origin=" + pickRay.origin.x + ", " + pickRay.origin.y + ", " + pickRay.origin.z);
|
||||||
print("computePickRay direction=" + pickRay.direction.x + ", " + pickRay.direction.y + ", " + pickRay.direction.z);
|
print("computePickRay direction=" + pickRay.direction.x + ", " + pickRay.direction.y + ", " + pickRay.direction.z);
|
||||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||||
intersection = Entities.findRayIntersection(pickRay);
|
intersection = Entities.findRayIntersection(pickRay, true); // to get precise picking
|
||||||
if (!intersection.accurate) {
|
if (!intersection.accurate) {
|
||||||
print(">>> NOTE: intersection not accurate. will try calling Entities.findRayIntersectionBlocking()");
|
print(">>> NOTE: intersection not accurate. will try calling Entities.findRayIntersectionBlocking()");
|
||||||
intersection = Entities.findRayIntersectionBlocking(pickRay);
|
intersection = Entities.findRayIntersectionBlocking(pickRay, true); // to get precise picking
|
||||||
print(">>> AFTER BLOCKING CALL intersection.accurate=" + intersection.accurate);
|
print(">>> AFTER BLOCKING CALL intersection.accurate=" + intersection.accurate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (intersection.intersects) {
|
if (intersection.intersects) {
|
||||||
print("intersection entityID.id=" + intersection.entityID.id);
|
print("intersection entityID=" + intersection.entityID);
|
||||||
print("intersection properties.modelURL=" + intersection.properties.modelURL);
|
print("intersection properties.modelURL=" + intersection.properties.modelURL);
|
||||||
print("intersection face=" + intersection.face);
|
print("intersection face=" + intersection.face);
|
||||||
print("intersection distance=" + intersection.distance);
|
print("intersection distance=" + intersection.distance);
|
||||||
print("intersection intersection.x/y/z=" + intersection.intersection.x + ", "
|
print("intersection intersection.x/y/z=" + intersection.intersection.x + ", "
|
||||||
+ intersection.intersection.y + ", " + intersection.intersection.z);
|
+ intersection.intersection.y + ", " + intersection.intersection.z);
|
||||||
|
print("intersection surfaceNormal.x/y/z=" + intersection.surfaceNormal.x + ", "
|
||||||
|
+ intersection.surfaceNormal.y + ", " + intersection.surfaceNormal.z);
|
||||||
|
|
||||||
|
|
||||||
|
// Note: line entity takes points in "entity relative frame"
|
||||||
|
var lineStart = { x: 0, y: 0, z: 0 };
|
||||||
|
var lineEnd = intersection.surfaceNormal;
|
||||||
|
|
||||||
|
Entities.editEntity(normalDisplay, {
|
||||||
|
visible: true,
|
||||||
|
position: intersection.intersection,
|
||||||
|
linePoints: [lineStart, lineEnd],
|
||||||
|
});
|
||||||
|
wasVisible = true;
|
||||||
|
} else {
|
||||||
|
if (wasVisible) {
|
||||||
|
Entities.editEntity(normalDisplay, { visible: false });
|
||||||
|
wasVisible = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
||||||
|
|
||||||
function scriptEnding() {
|
Script.scriptEnding.connect(function() {
|
||||||
}
|
Entities.deleteEntity(normalDisplay);
|
||||||
Script.scriptEnding.connect(scriptEnding);
|
});
|
||||||
|
|
||||||
|
|
|
@ -1055,6 +1055,9 @@ void Application::paintGL() {
|
||||||
displayPlugin->preRender();
|
displayPlugin->preRender();
|
||||||
_offscreenContext->makeCurrent();
|
_offscreenContext->makeCurrent();
|
||||||
|
|
||||||
|
// update the avatar with a fresh HMD pose
|
||||||
|
_myAvatar->updateFromHMDSensorMatrix(getHMDSensorPose());
|
||||||
|
|
||||||
auto lodManager = DependencyManager::get<LODManager>();
|
auto lodManager = DependencyManager::get<LODManager>();
|
||||||
|
|
||||||
|
|
||||||
|
@ -2337,7 +2340,8 @@ bool Application::exportEntities(const QString& filename, const QVector<EntityIt
|
||||||
QVector<EntityItemPointer> entities;
|
QVector<EntityItemPointer> entities;
|
||||||
|
|
||||||
auto entityTree = _entities.getTree();
|
auto entityTree = _entities.getTree();
|
||||||
EntityTree exportTree;
|
auto exportTree = std::make_shared<EntityTree>();
|
||||||
|
exportTree->createRootElement();
|
||||||
|
|
||||||
glm::vec3 root(TREE_SCALE, TREE_SCALE, TREE_SCALE);
|
glm::vec3 root(TREE_SCALE, TREE_SCALE, TREE_SCALE);
|
||||||
for (auto entityID : entityIDs) {
|
for (auto entityID : entityIDs) {
|
||||||
|
@ -2364,10 +2368,10 @@ bool Application::exportEntities(const QString& filename, const QVector<EntityIt
|
||||||
auto properties = entityItem->getProperties();
|
auto properties = entityItem->getProperties();
|
||||||
|
|
||||||
properties.setPosition(properties.getPosition() - root);
|
properties.setPosition(properties.getPosition() - root);
|
||||||
exportTree.addEntity(entityItem->getEntityItemID(), properties);
|
exportTree->addEntity(entityItem->getEntityItemID(), properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
exportTree.writeToJSONFile(filename.toLocal8Bit().constData());
|
exportTree->writeToJSONFile(filename.toLocal8Bit().constData());
|
||||||
|
|
||||||
// restore the main window's active state
|
// restore the main window's active state
|
||||||
_window->activateWindow();
|
_window->activateWindow();
|
||||||
|
@ -2380,15 +2384,16 @@ bool Application::exportEntities(const QString& filename, float x, float y, floa
|
||||||
|
|
||||||
if (entities.size() > 0) {
|
if (entities.size() > 0) {
|
||||||
glm::vec3 root(x, y, z);
|
glm::vec3 root(x, y, z);
|
||||||
EntityTree exportTree;
|
auto exportTree = std::make_shared<EntityTree>();
|
||||||
|
exportTree->createRootElement();
|
||||||
|
|
||||||
for (int i = 0; i < entities.size(); i++) {
|
for (int i = 0; i < entities.size(); i++) {
|
||||||
EntityItemProperties properties = entities.at(i)->getProperties();
|
EntityItemProperties properties = entities.at(i)->getProperties();
|
||||||
EntityItemID id = entities.at(i)->getEntityItemID();
|
EntityItemID id = entities.at(i)->getEntityItemID();
|
||||||
properties.setPosition(properties.getPosition() - root);
|
properties.setPosition(properties.getPosition() - root);
|
||||||
exportTree.addEntity(id, properties);
|
exportTree->addEntity(id, properties);
|
||||||
}
|
}
|
||||||
exportTree.writeToSVOFile(filename.toLocal8Bit().constData());
|
exportTree->writeToSVOFile(filename.toLocal8Bit().constData());
|
||||||
} else {
|
} else {
|
||||||
qCDebug(interfaceapp) << "No models were selected";
|
qCDebug(interfaceapp) << "No models were selected";
|
||||||
return false;
|
return false;
|
||||||
|
@ -2895,9 +2900,6 @@ void Application::update(float deltaTime) {
|
||||||
userInputMapper->getActionState(UserInputMapper::SHIFT), RIGHT_HAND_INDEX);
|
userInputMapper->getActionState(UserInputMapper::SHIFT), RIGHT_HAND_INDEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the avatar with a fresh HMD pose
|
|
||||||
_myAvatar->updateFromHMDSensorMatrix(getHMDSensorPose(), deltaTime);
|
|
||||||
|
|
||||||
updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
|
updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
|
||||||
|
|
||||||
updateCamera(deltaTime); // handle various camera tweaks like off axis projection
|
updateCamera(deltaTime); // handle various camera tweaks like off axis projection
|
||||||
|
|
|
@ -272,9 +272,18 @@ glm::mat4 MyAvatar::getSensorToWorldMatrix() const {
|
||||||
return _sensorToWorldMatrix;
|
return _sensorToWorldMatrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
// best called at start of main loop just after we have a fresh hmd pose.
|
// Pass a recent sample of the HMD to the avatar.
|
||||||
// update internal body position from new hmd pose.
|
// This can also update the avatar's position to follow the HMD
|
||||||
void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix, float deltaTime) {
|
// as it moves through the world.
|
||||||
|
void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) {
|
||||||
|
|
||||||
|
auto now = usecTimestampNow();
|
||||||
|
auto deltaUsecs = now - _lastUpdateFromHMDTime;
|
||||||
|
_lastUpdateFromHMDTime = now;
|
||||||
|
double actualDeltaTime = (double)deltaUsecs / (double)USECS_PER_SECOND;
|
||||||
|
const float BIGGEST_DELTA_TIME_SECS = 0.25f;
|
||||||
|
float deltaTime = glm::clamp((float)actualDeltaTime, 0.0f, BIGGEST_DELTA_TIME_SECS);
|
||||||
|
|
||||||
// update the sensorMatrices based on the new hmd pose
|
// update the sensorMatrices based on the new hmd pose
|
||||||
_hmdSensorMatrix = hmdSensorMatrix;
|
_hmdSensorMatrix = hmdSensorMatrix;
|
||||||
_hmdSensorPosition = extractTranslation(hmdSensorMatrix);
|
_hmdSensorPosition = extractTranslation(hmdSensorMatrix);
|
||||||
|
|
|
@ -66,9 +66,10 @@ public:
|
||||||
const glm::quat& getHMDSensorOrientation() const { return _hmdSensorOrientation; }
|
const glm::quat& getHMDSensorOrientation() const { return _hmdSensorOrientation; }
|
||||||
glm::mat4 getSensorToWorldMatrix() const;
|
glm::mat4 getSensorToWorldMatrix() const;
|
||||||
|
|
||||||
// best called at start of main loop just after we have a fresh hmd pose.
|
// Pass a recent sample of the HMD to the avatar.
|
||||||
// update internal body position from new hmd pose.
|
// This can also update the avatar's position to follow the HMD
|
||||||
void updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix, float deltaTime);
|
// as it moves through the world.
|
||||||
|
void updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix);
|
||||||
|
|
||||||
// best called at end of main loop, just before rendering.
|
// best called at end of main loop, just before rendering.
|
||||||
// update sensor to world matrix from current body position and hmd sensor.
|
// update sensor to world matrix from current body position and hmd sensor.
|
||||||
|
@ -364,6 +365,8 @@ private:
|
||||||
|
|
||||||
bool _straightingLean = false;
|
bool _straightingLean = false;
|
||||||
float _straightingLeanAlpha = 0.0f;
|
float _straightingLeanAlpha = 0.0f;
|
||||||
|
|
||||||
|
quint64 _lastUpdateFromHMDTime = usecTimestampNow();
|
||||||
};
|
};
|
||||||
|
|
||||||
QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode);
|
QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode);
|
||||||
|
|
|
@ -19,17 +19,40 @@ float ClipboardScriptingInterface::getClipboardContentsLargestDimension() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClipboardScriptingInterface::exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs) {
|
bool ClipboardScriptingInterface::exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs) {
|
||||||
return Application::getInstance()->exportEntities(filename, entityIDs);
|
bool retVal;
|
||||||
|
QMetaObject::invokeMethod(Application::getInstance(), "exportEntities", Qt::BlockingQueuedConnection,
|
||||||
|
Q_RETURN_ARG(bool, retVal),
|
||||||
|
Q_ARG(const QString&, filename),
|
||||||
|
Q_ARG(const QVector<EntityItemID>&, entityIDs));
|
||||||
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClipboardScriptingInterface::exportEntities(const QString& filename, float x, float y, float z, float s) {
|
bool ClipboardScriptingInterface::exportEntities(const QString& filename, float x, float y, float z, float s) {
|
||||||
return Application::getInstance()->exportEntities(filename, x, y, z, s);
|
bool retVal;
|
||||||
|
QMetaObject::invokeMethod(Application::getInstance(), "exportEntities", Qt::BlockingQueuedConnection,
|
||||||
|
Q_RETURN_ARG(bool, retVal),
|
||||||
|
Q_ARG(const QString&, filename),
|
||||||
|
Q_ARG(float, x),
|
||||||
|
Q_ARG(float, y),
|
||||||
|
Q_ARG(float, z),
|
||||||
|
Q_ARG(float, s));
|
||||||
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClipboardScriptingInterface::importEntities(const QString& filename) {
|
bool ClipboardScriptingInterface::importEntities(const QString& filename) {
|
||||||
return Application::getInstance()->importEntities(filename);
|
bool retVal;
|
||||||
|
QMetaObject::invokeMethod(Application::getInstance(), "importEntities", Qt::BlockingQueuedConnection,
|
||||||
|
Q_RETURN_ARG(bool, retVal),
|
||||||
|
Q_ARG(const QString&, filename));
|
||||||
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<EntityItemID> ClipboardScriptingInterface::pasteEntities(glm::vec3 position) {
|
QVector<EntityItemID> ClipboardScriptingInterface::pasteEntities(glm::vec3 position) {
|
||||||
return Application::getInstance()->pasteEntities(position.x, position.y, position.z);
|
QVector<EntityItemID> retVal;
|
||||||
|
QMetaObject::invokeMethod(Application::getInstance(), "pasteEntities", Qt::BlockingQueuedConnection,
|
||||||
|
Q_RETURN_ARG(QVector<EntityItemID>, retVal),
|
||||||
|
Q_ARG(float, position.x),
|
||||||
|
Q_ARG(float, position.y),
|
||||||
|
Q_ARG(float, position.z));
|
||||||
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,6 +171,6 @@ QScriptValue Base3DOverlay::getProperty(const QString& property) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Base3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
bool Base3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
float& distance, BoxFace& face) {
|
float& distance, BoxFace& face, glm::vec3& surfaceNormal) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,11 +57,12 @@ public:
|
||||||
virtual void setProperties(const QScriptValue& properties);
|
virtual void setProperties(const QScriptValue& properties);
|
||||||
virtual QScriptValue getProperty(const QString& property);
|
virtual QScriptValue getProperty(const QString& property);
|
||||||
|
|
||||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face);
|
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal);
|
||||||
|
|
||||||
virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction,
|
virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
float& distance, BoxFace& face, QString& extraInfo) {
|
float& distance, BoxFace& face, glm::vec3& surfaceNormal, QString& extraInfo) {
|
||||||
return findRayIntersection(origin, direction, distance, face);
|
return findRayIntersection(origin, direction, distance, face, surfaceNormal);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -391,10 +391,10 @@ QScriptValue Circle3DOverlay::getProperty(const QString& property) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Circle3DOverlay::findRayIntersection(const glm::vec3& origin,
|
bool Circle3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||||
const glm::vec3& direction, float& distance, BoxFace& face) {
|
BoxFace& face, glm::vec3& surfaceNormal) {
|
||||||
|
|
||||||
bool intersects = Planar3DOverlay::findRayIntersection(origin, direction, distance, face);
|
bool intersects = Planar3DOverlay::findRayIntersection(origin, direction, distance, face, surfaceNormal);
|
||||||
|
|
||||||
if (intersects) {
|
if (intersects) {
|
||||||
glm::vec3 hitPosition = origin + (distance * direction);
|
glm::vec3 hitPosition = origin + (distance * direction);
|
||||||
|
|
|
@ -52,7 +52,8 @@ public:
|
||||||
void setMajorTickMarksColor(const xColor& value) { _majorTickMarksColor = value; }
|
void setMajorTickMarksColor(const xColor& value) { _majorTickMarksColor = value; }
|
||||||
void setMinorTickMarksColor(const xColor& value) { _minorTickMarksColor = value; }
|
void setMinorTickMarksColor(const xColor& value) { _minorTickMarksColor = value; }
|
||||||
|
|
||||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face);
|
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal);
|
||||||
|
|
||||||
virtual Circle3DOverlay* createClone() const;
|
virtual Circle3DOverlay* createClone() const;
|
||||||
|
|
||||||
|
|
|
@ -166,7 +166,7 @@ void Image3DOverlay::setURL(const QString& url) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Image3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
bool Image3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
float& distance, BoxFace& face) {
|
float& distance, BoxFace& face, glm::vec3& surfaceNormal) {
|
||||||
if (_texture && _texture->isLoaded()) {
|
if (_texture && _texture->isLoaded()) {
|
||||||
// Make sure position and rotation is updated.
|
// Make sure position and rotation is updated.
|
||||||
applyTransformTo(_transform, true);
|
applyTransformTo(_transform, true);
|
||||||
|
@ -178,6 +178,7 @@ bool Image3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec
|
||||||
float maxSize = glm::max(width, height);
|
float maxSize = glm::max(width, height);
|
||||||
glm::vec2 dimensions = _dimensions * glm::vec2(width / maxSize, height / maxSize);
|
glm::vec2 dimensions = _dimensions * glm::vec2(width / maxSize, height / maxSize);
|
||||||
|
|
||||||
|
// FIXME - face and surfaceNormal not being set
|
||||||
return findRayRectangleIntersection(origin, direction, getRotation(), getPosition(), dimensions, distance);
|
return findRayRectangleIntersection(origin, direction, getRotation(), getPosition(), dimensions, distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,8 @@ public:
|
||||||
virtual void setProperties(const QScriptValue& properties);
|
virtual void setProperties(const QScriptValue& properties);
|
||||||
virtual QScriptValue getProperty(const QString& property);
|
virtual QScriptValue getProperty(const QString& property);
|
||||||
|
|
||||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face);
|
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal);
|
||||||
|
|
||||||
virtual Image3DOverlay* createClone() const;
|
virtual Image3DOverlay* createClone() const;
|
||||||
|
|
||||||
|
|
|
@ -159,16 +159,16 @@ QScriptValue ModelOverlay::getProperty(const QString& property) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModelOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
bool ModelOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
float& distance, BoxFace& face) {
|
float& distance, BoxFace& face, glm::vec3& surfaceNormal) {
|
||||||
|
|
||||||
QString subMeshNameTemp;
|
QString subMeshNameTemp;
|
||||||
return _model.findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, subMeshNameTemp);
|
return _model.findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, surfaceNormal, subMeshNameTemp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModelOverlay::findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction,
|
bool ModelOverlay::findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
float& distance, BoxFace& face, QString& extraInfo) {
|
float& distance, BoxFace& face, glm::vec3& surfaceNormal, QString& extraInfo) {
|
||||||
|
|
||||||
return _model.findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, extraInfo);
|
return _model.findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, surfaceNormal, extraInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelOverlay* ModelOverlay::createClone() const {
|
ModelOverlay* ModelOverlay::createClone() const {
|
||||||
|
|
|
@ -29,9 +29,10 @@ public:
|
||||||
virtual void render(RenderArgs* args);
|
virtual void render(RenderArgs* args);
|
||||||
virtual void setProperties(const QScriptValue& properties);
|
virtual void setProperties(const QScriptValue& properties);
|
||||||
virtual QScriptValue getProperty(const QString& property);
|
virtual QScriptValue getProperty(const QString& property);
|
||||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face);
|
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal);
|
||||||
virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction,
|
virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
float& distance, BoxFace& face, QString& extraInfo);
|
float& distance, BoxFace& face, glm::vec3& surfaceNormal, QString& extraInfo);
|
||||||
|
|
||||||
virtual ModelOverlay* createClone() const;
|
virtual ModelOverlay* createClone() const;
|
||||||
|
|
||||||
|
|
|
@ -346,6 +346,7 @@ unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) {
|
||||||
glm::vec3 origin(pointCopy.x, pointCopy.y, LARGE_NEGATIVE_FLOAT);
|
glm::vec3 origin(pointCopy.x, pointCopy.y, LARGE_NEGATIVE_FLOAT);
|
||||||
glm::vec3 direction(0, 0, 1);
|
glm::vec3 direction(0, 0, 1);
|
||||||
BoxFace thisFace;
|
BoxFace thisFace;
|
||||||
|
glm::vec3 thisSurfaceNormal;
|
||||||
float distance;
|
float distance;
|
||||||
|
|
||||||
while (i.hasPrevious()) {
|
while (i.hasPrevious()) {
|
||||||
|
@ -354,7 +355,7 @@ unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) {
|
||||||
if (i.value()->is3D()) {
|
if (i.value()->is3D()) {
|
||||||
auto thisOverlay = std::dynamic_pointer_cast<Base3DOverlay>(i.value());
|
auto thisOverlay = std::dynamic_pointer_cast<Base3DOverlay>(i.value());
|
||||||
if (thisOverlay && !thisOverlay->getIgnoreRayIntersection()) {
|
if (thisOverlay && !thisOverlay->getIgnoreRayIntersection()) {
|
||||||
if (thisOverlay->findRayIntersection(origin, direction, distance, thisFace)) {
|
if (thisOverlay->findRayIntersection(origin, direction, distance, thisFace, thisSurfaceNormal)) {
|
||||||
return thisID;
|
return thisID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -423,8 +424,10 @@ RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray)
|
||||||
if (thisOverlay && thisOverlay->getVisible() && !thisOverlay->getIgnoreRayIntersection() && thisOverlay->isLoaded()) {
|
if (thisOverlay && thisOverlay->getVisible() && !thisOverlay->getIgnoreRayIntersection() && thisOverlay->isLoaded()) {
|
||||||
float thisDistance;
|
float thisDistance;
|
||||||
BoxFace thisFace;
|
BoxFace thisFace;
|
||||||
|
glm::vec3 thisSurfaceNormal;
|
||||||
QString thisExtraInfo;
|
QString thisExtraInfo;
|
||||||
if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance, thisFace, thisExtraInfo)) {
|
if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance,
|
||||||
|
thisFace, thisSurfaceNormal, thisExtraInfo)) {
|
||||||
bool isDrawInFront = thisOverlay->getDrawInFront();
|
bool isDrawInFront = thisOverlay->getDrawInFront();
|
||||||
if (thisDistance < bestDistance && (!bestIsFront || isDrawInFront)) {
|
if (thisDistance < bestDistance && (!bestIsFront || isDrawInFront)) {
|
||||||
bestIsFront = isDrawInFront;
|
bestIsFront = isDrawInFront;
|
||||||
|
@ -432,6 +435,7 @@ RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray)
|
||||||
result.intersects = true;
|
result.intersects = true;
|
||||||
result.distance = thisDistance;
|
result.distance = thisDistance;
|
||||||
result.face = thisFace;
|
result.face = thisFace;
|
||||||
|
result.surfaceNormal = thisSurfaceNormal;
|
||||||
result.overlayID = thisID;
|
result.overlayID = thisID;
|
||||||
result.intersection = ray.origin + (ray.direction * thisDistance);
|
result.intersection = ray.origin + (ray.direction * thisDistance);
|
||||||
result.extraInfo = thisExtraInfo;
|
result.extraInfo = thisExtraInfo;
|
||||||
|
|
|
@ -46,6 +46,7 @@ public:
|
||||||
int overlayID;
|
int overlayID;
|
||||||
float distance;
|
float distance;
|
||||||
BoxFace face;
|
BoxFace face;
|
||||||
|
glm::vec3 surfaceNormal;
|
||||||
glm::vec3 intersection;
|
glm::vec3 intersection;
|
||||||
QString extraInfo;
|
QString extraInfo;
|
||||||
};
|
};
|
||||||
|
|
|
@ -92,6 +92,7 @@ QScriptValue Planar3DOverlay::getProperty(const QString& property) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
float& distance, BoxFace& face) {
|
float& distance, BoxFace& face, glm::vec3& surfaceNormal) {
|
||||||
|
// FIXME - face and surfaceNormal not being returned
|
||||||
return findRayRectangleIntersection(origin, direction, getRotation(), getPosition(), getDimensions(), distance);
|
return findRayRectangleIntersection(origin, direction, getRotation(), getPosition(), getDimensions(), distance);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,8 @@ public:
|
||||||
virtual void setProperties(const QScriptValue& properties);
|
virtual void setProperties(const QScriptValue& properties);
|
||||||
virtual QScriptValue getProperty(const QString& property);
|
virtual QScriptValue getProperty(const QString& property);
|
||||||
|
|
||||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face);
|
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
glm::vec2 _dimensions;
|
glm::vec2 _dimensions;
|
||||||
|
|
|
@ -211,7 +211,8 @@ QSizeF Text3DOverlay::textSize(const QString& text) const {
|
||||||
return QSizeF(extents.x, extents.y) * pointToWorldScale;
|
return QSizeF(extents.x, extents.y) * pointToWorldScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Text3DOverlay::findRayIntersection(const glm::vec3 &origin, const glm::vec3 &direction, float &distance, BoxFace &face) {
|
bool Text3DOverlay::findRayIntersection(const glm::vec3 &origin, const glm::vec3 &direction, float &distance,
|
||||||
|
BoxFace &face, glm::vec3& surfaceNormal) {
|
||||||
applyTransformTo(_transform, true);
|
applyTransformTo(_transform, true);
|
||||||
return Billboard3DOverlay::findRayIntersection(origin, direction, distance, face);
|
return Billboard3DOverlay::findRayIntersection(origin, direction, distance, face, surfaceNormal);
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,8 @@ public:
|
||||||
|
|
||||||
QSizeF textSize(const QString& test) const; // Meters
|
QSizeF textSize(const QString& test) const; // Meters
|
||||||
|
|
||||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face);
|
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal);
|
||||||
|
|
||||||
virtual Text3DOverlay* createClone() const;
|
virtual Text3DOverlay* createClone() const;
|
||||||
|
|
||||||
|
|
|
@ -93,7 +93,7 @@ QScriptValue Volume3DOverlay::getProperty(const QString& property) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Volume3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
bool Volume3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
float& distance, BoxFace& face) {
|
float& distance, BoxFace& face, glm::vec3& surfaceNormal) {
|
||||||
// extents is the entity relative, scaled, centered extents of the entity
|
// extents is the entity relative, scaled, centered extents of the entity
|
||||||
glm::mat4 worldToEntityMatrix;
|
glm::mat4 worldToEntityMatrix;
|
||||||
_transform.getInverseMatrix(worldToEntityMatrix);
|
_transform.getInverseMatrix(worldToEntityMatrix);
|
||||||
|
@ -103,5 +103,5 @@ bool Volume3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::ve
|
||||||
|
|
||||||
// we can use the AABox's ray intersection by mapping our origin and direction into the overlays frame
|
// we can use the AABox's ray intersection by mapping our origin and direction into the overlays frame
|
||||||
// and testing intersection there.
|
// and testing intersection there.
|
||||||
return _localBoundingBox.findRayIntersection(overlayFrameOrigin, overlayFrameDirection, distance, face);
|
return _localBoundingBox.findRayIntersection(overlayFrameOrigin, overlayFrameDirection, distance, face, surfaceNormal);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,8 @@ public:
|
||||||
virtual void setProperties(const QScriptValue& properties);
|
virtual void setProperties(const QScriptValue& properties);
|
||||||
virtual QScriptValue getProperty(const QString& property);
|
virtual QScriptValue getProperty(const QString& property);
|
||||||
|
|
||||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face);
|
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Centered local bounding box
|
// Centered local bounding box
|
||||||
|
|
|
@ -151,8 +151,10 @@ void Web3DOverlay::setURL(const QString& url) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Web3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) {
|
bool Web3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face, glm::vec3& surfaceNormal) {
|
||||||
//// Make sure position and rotation is updated.
|
// FIXME - face and surfaceNormal not being returned
|
||||||
|
|
||||||
|
// Make sure position and rotation is updated.
|
||||||
applyTransformTo(_transform, true);
|
applyTransformTo(_transform, true);
|
||||||
vec2 size = _resolution / _dpi * INCHES_TO_METERS * vec2(getDimensions());
|
vec2 size = _resolution / _dpi * INCHES_TO_METERS * vec2(getDimensions());
|
||||||
// Produce the dimensions of the overlay based on the image's aspect ratio and the overlay's scale.
|
// Produce the dimensions of the overlay based on the image's aspect ratio and the overlay's scale.
|
||||||
|
|
|
@ -34,7 +34,8 @@ public:
|
||||||
virtual void setProperties(const QScriptValue& properties);
|
virtual void setProperties(const QScriptValue& properties);
|
||||||
virtual QScriptValue getProperty(const QString& property);
|
virtual QScriptValue getProperty(const QString& property);
|
||||||
|
|
||||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face);
|
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal);
|
||||||
|
|
||||||
virtual Web3DOverlay* createClone() const;
|
virtual Web3DOverlay* createClone() const;
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -31,6 +31,8 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float* _polyphaseFilter;
|
float* _polyphaseFilter;
|
||||||
|
int* _stepTable;
|
||||||
|
|
||||||
float* _history[MAX_CHANNELS];
|
float* _history[MAX_CHANNELS];
|
||||||
float* _inputs[MAX_CHANNELS];
|
float* _inputs[MAX_CHANNELS];
|
||||||
float* _outputs[MAX_CHANNELS];
|
float* _outputs[MAX_CHANNELS];
|
||||||
|
@ -45,10 +47,13 @@ private:
|
||||||
int _numTaps;
|
int _numTaps;
|
||||||
int _numHistory;
|
int _numHistory;
|
||||||
|
|
||||||
|
int _phase;
|
||||||
int64_t _offset;
|
int64_t _offset;
|
||||||
int64_t _step;
|
int64_t _step;
|
||||||
|
|
||||||
int createPolyphaseFilter(int upFactor, int downFactor, float gain);
|
int createRationalFilter(int upFactor, int downFactor, float gain);
|
||||||
|
int createIrrationalFilter(int upFactor, int downFactor, float gain);
|
||||||
|
|
||||||
int multirateFilter1(const float* input0, float* output0, int inputFrames);
|
int multirateFilter1(const float* input0, float* output0, int inputFrames);
|
||||||
int multirateFilter2(const float* input0, const float* input1, float* output0, float* output1, int inputFrames);
|
int multirateFilter2(const float* input0, const float* input1, float* output0, float* output1, int inputFrames);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
set(TARGET_NAME entities-renderer)
|
set(TARGET_NAME entities-renderer)
|
||||||
|
|
||||||
AUTOSCRIBE_SHADER_LIB(gpu model render)
|
AUTOSCRIBE_SHADER_LIB(gpu model render render-utils)
|
||||||
|
|
||||||
# use setup_hifi_library macro to setup our project and link appropriate Qt modules
|
# use setup_hifi_library macro to setup our project and link appropriate Qt modules
|
||||||
setup_hifi_library(Widgets Network Script)
|
setup_hifi_library(Widgets Network Script)
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
<!
|
|
||||||
// DeferredBufferWrite.slh
|
|
||||||
// libraries/render-utils/src
|
|
||||||
//
|
|
||||||
// Created by Sam Gateau on 1/12/15.
|
|
||||||
// Copyright 2013 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
!>
|
|
||||||
<@if not DEFERRED_BUFFER_WRITE_SLH@>
|
|
||||||
<@def DEFERRED_BUFFER_WRITE_SLH@>
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 _fragColor0;
|
|
||||||
layout(location = 1) out vec4 _fragColor1;
|
|
||||||
layout(location = 2) out vec4 _fragColor2;
|
|
||||||
|
|
||||||
// the glow intensity
|
|
||||||
uniform float glowIntensity;
|
|
||||||
|
|
||||||
// the alpha threshold
|
|
||||||
uniform float alphaThreshold;
|
|
||||||
|
|
||||||
uniform sampler2D normalFittingMap;
|
|
||||||
|
|
||||||
vec3 bestFitNormal(vec3 normal) {
|
|
||||||
vec3 absNorm = abs(normal);
|
|
||||||
float maxNAbs = max(absNorm.z, max(absNorm.x, absNorm.y));
|
|
||||||
|
|
||||||
vec2 texcoord = (absNorm.z < maxNAbs ?
|
|
||||||
(absNorm.y < maxNAbs ? absNorm.yz : absNorm.xz) :
|
|
||||||
absNorm.xy);
|
|
||||||
texcoord = (texcoord.x < texcoord.y ? texcoord.yx : texcoord.xy);
|
|
||||||
texcoord.y /= texcoord.x;
|
|
||||||
vec3 cN = normal / maxNAbs;
|
|
||||||
float fittingScale = texture(normalFittingMap, texcoord).a;
|
|
||||||
cN *= fittingScale;
|
|
||||||
return (cN * 0.5 + 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
float evalOpaqueFinalAlpha(float alpha, float mapAlpha) {
|
|
||||||
return mix(alpha * glowIntensity, 1.0 - alpha * glowIntensity, step(mapAlpha, alphaThreshold));
|
|
||||||
}
|
|
||||||
|
|
||||||
const vec3 DEFAULT_SPECULAR = vec3(0.1);
|
|
||||||
const float DEFAULT_SHININESS = 10;
|
|
||||||
|
|
||||||
void packDeferredFragment(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) {
|
|
||||||
if (alpha != glowIntensity) {
|
|
||||||
discard;
|
|
||||||
}
|
|
||||||
_fragColor0 = vec4(diffuse.rgb, alpha);
|
|
||||||
_fragColor1 = vec4(bestFitNormal(normal), 1.0);
|
|
||||||
_fragColor2 = vec4(specular, shininess / 128.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess, vec3 emissive) {
|
|
||||||
if (alpha != glowIntensity) {
|
|
||||||
discard;
|
|
||||||
}
|
|
||||||
|
|
||||||
_fragColor0 = vec4(diffuse.rgb, alpha);
|
|
||||||
//_fragColor1 = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
|
|
||||||
_fragColor1 = vec4(bestFitNormal(normal), 0.5);
|
|
||||||
_fragColor2 = vec4(emissive, shininess / 128.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) {
|
|
||||||
if (alpha <= alphaThreshold) {
|
|
||||||
discard;
|
|
||||||
}
|
|
||||||
|
|
||||||
_fragColor0 = vec4(diffuse.rgb, alpha);
|
|
||||||
// _fragColor1 = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
|
|
||||||
// _fragColor2 = vec4(specular, shininess / 128.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
<@endif@>
|
|
|
@ -113,9 +113,7 @@ void EntityTreeRenderer::init() {
|
||||||
DependencyManager::get<EntityScriptingInterface>()->setEntitiesScriptEngine(_entitiesScriptEngine);
|
DependencyManager::get<EntityScriptingInterface>()->setEntitiesScriptEngine(_entitiesScriptEngine);
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure our "last avatar position" is something other than our current position, so that on our
|
forceRecheckEntities(); // setup our state to force checking our inside/outsideness of entities
|
||||||
// first chance, we'll check for enter/leave entity events.
|
|
||||||
_lastAvatarPosition = _viewState->getAvatarPosition() + glm::vec3((float)TREE_SCALE);
|
|
||||||
|
|
||||||
connect(entityTree.get(), &EntityTree::deletingEntity, this, &EntityTreeRenderer::deletingEntity, Qt::QueuedConnection);
|
connect(entityTree.get(), &EntityTree::deletingEntity, this, &EntityTreeRenderer::deletingEntity, Qt::QueuedConnection);
|
||||||
connect(entityTree.get(), &EntityTree::addingEntity, this, &EntityTreeRenderer::addingEntity, Qt::QueuedConnection);
|
connect(entityTree.get(), &EntityTree::addingEntity, this, &EntityTreeRenderer::addingEntity, Qt::QueuedConnection);
|
||||||
|
@ -141,6 +139,13 @@ void EntityTreeRenderer::update() {
|
||||||
// check to see if the avatar has moved and if we need to handle enter/leave entity logic
|
// check to see if the avatar has moved and if we need to handle enter/leave entity logic
|
||||||
checkEnterLeaveEntities();
|
checkEnterLeaveEntities();
|
||||||
|
|
||||||
|
// even if we haven't changed positions, if we previously attempted to set the skybox, but
|
||||||
|
// have a pending download of the skybox texture, then we should attempt to reapply to
|
||||||
|
// get the correct texture.
|
||||||
|
if (_pendingSkyboxTextureDownload) {
|
||||||
|
applyZonePropertiesToScene(_bestZone);
|
||||||
|
}
|
||||||
|
|
||||||
// Even if we're not moving the mouse, if we started clicking on an entity and we have
|
// Even if we're not moving the mouse, if we started clicking on an entity and we have
|
||||||
// not yet released the hold then this is still considered a holdingClickOnEntity event
|
// not yet released the hold then this is still considered a holdingClickOnEntity event
|
||||||
// and we want to simulate this message here as well as in mouse move
|
// and we want to simulate this message here as well as in mouse move
|
||||||
|
@ -156,7 +161,7 @@ void EntityTreeRenderer::update() {
|
||||||
void EntityTreeRenderer::checkEnterLeaveEntities() {
|
void EntityTreeRenderer::checkEnterLeaveEntities() {
|
||||||
if (_tree && !_shuttingDown) {
|
if (_tree && !_shuttingDown) {
|
||||||
glm::vec3 avatarPosition = _viewState->getAvatarPosition();
|
glm::vec3 avatarPosition = _viewState->getAvatarPosition();
|
||||||
|
|
||||||
if (avatarPosition != _lastAvatarPosition) {
|
if (avatarPosition != _lastAvatarPosition) {
|
||||||
float radius = 1.0f; // for now, assume 1 meter radius
|
float radius = 1.0f; // for now, assume 1 meter radius
|
||||||
QVector<EntityItemPointer> foundEntities;
|
QVector<EntityItemPointer> foundEntities;
|
||||||
|
@ -238,13 +243,17 @@ void EntityTreeRenderer::leaveAllEntities() {
|
||||||
_entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity");
|
_entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity");
|
||||||
}
|
}
|
||||||
_currentEntitiesInside.clear();
|
_currentEntitiesInside.clear();
|
||||||
|
forceRecheckEntities();
|
||||||
// make sure our "last avatar position" is something other than our current position, so that on our
|
|
||||||
// first chance, we'll check for enter/leave entity events.
|
|
||||||
_lastAvatarPosition = _viewState->getAvatarPosition() + glm::vec3((float)TREE_SCALE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EntityTreeRenderer::forceRecheckEntities() {
|
||||||
|
// make sure our "last avatar position" is something other than our current position,
|
||||||
|
// so that on our next chance, we'll check for enter/leave entity events.
|
||||||
|
_lastAvatarPosition = _viewState->getAvatarPosition() + glm::vec3((float)TREE_SCALE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr<ZoneEntityItem> zone) {
|
void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr<ZoneEntityItem> zone) {
|
||||||
QSharedPointer<SceneScriptingInterface> scene = DependencyManager::get<SceneScriptingInterface>();
|
QSharedPointer<SceneScriptingInterface> scene = DependencyManager::get<SceneScriptingInterface>();
|
||||||
if (zone) {
|
if (zone) {
|
||||||
|
@ -289,7 +298,8 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr<ZoneEntityIt
|
||||||
|
|
||||||
_viewState->overrideEnvironmentData(data);
|
_viewState->overrideEnvironmentData(data);
|
||||||
scene->getSkyStage()->setBackgroundMode(model::SunSkyStage::SKY_DOME);
|
scene->getSkyStage()->setBackgroundMode(model::SunSkyStage::SKY_DOME);
|
||||||
|
_pendingSkyboxTextureDownload = false;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_viewState->endOverrideEnvironmentData();
|
_viewState->endOverrideEnvironmentData();
|
||||||
auto stage = scene->getSkyStage();
|
auto stage = scene->getSkyStage();
|
||||||
|
@ -308,17 +318,26 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr<ZoneEntityIt
|
||||||
}
|
}
|
||||||
if (zone->getSkyboxProperties().getURL().isEmpty()) {
|
if (zone->getSkyboxProperties().getURL().isEmpty()) {
|
||||||
skybox->setCubemap(gpu::TexturePointer());
|
skybox->setCubemap(gpu::TexturePointer());
|
||||||
|
_pendingSkyboxTextureDownload = false;
|
||||||
} else {
|
} else {
|
||||||
// Update the Texture of the Skybox with the one pointed by this zone
|
// Update the Texture of the Skybox with the one pointed by this zone
|
||||||
auto cubeMap = DependencyManager::get<TextureCache>()->getTexture(zone->getSkyboxProperties().getURL(), CUBE_TEXTURE);
|
auto cubeMap = DependencyManager::get<TextureCache>()->getTexture(zone->getSkyboxProperties().getURL(), CUBE_TEXTURE);
|
||||||
skybox->setCubemap(cubeMap->getGPUTexture());
|
|
||||||
|
if (cubeMap->getGPUTexture()) {
|
||||||
|
skybox->setCubemap(cubeMap->getGPUTexture());
|
||||||
|
_pendingSkyboxTextureDownload = false;
|
||||||
|
} else {
|
||||||
|
_pendingSkyboxTextureDownload = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
stage->setBackgroundMode(model::SunSkyStage::SKY_BOX);
|
stage->setBackgroundMode(model::SunSkyStage::SKY_BOX);
|
||||||
} else {
|
} else {
|
||||||
stage->setBackgroundMode(model::SunSkyStage::SKY_DOME); // let the application atmosphere through
|
stage->setBackgroundMode(model::SunSkyStage::SKY_DOME); // let the application atmosphere through
|
||||||
|
_pendingSkyboxTextureDownload = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
_pendingSkyboxTextureDownload = false;
|
||||||
if (_hasPreviousZone) {
|
if (_hasPreviousZone) {
|
||||||
scene->setKeyLightColor(_previousKeyLightColor);
|
scene->setKeyLightColor(_previousKeyLightColor);
|
||||||
scene->setKeyLightIntensity(_previousKeyLightIntensity);
|
scene->setKeyLightIntensity(_previousKeyLightIntensity);
|
||||||
|
@ -470,9 +489,10 @@ RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(cons
|
||||||
|
|
||||||
OctreeElementPointer element;
|
OctreeElementPointer element;
|
||||||
EntityItemPointer intersectedEntity = NULL;
|
EntityItemPointer intersectedEntity = NULL;
|
||||||
result.intersects = entityTree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face,
|
result.intersects = entityTree->findRayIntersection(ray.origin, ray.direction, element, result.distance,
|
||||||
(void**)&intersectedEntity, lockType, &result.accurate,
|
result.face, result.surfaceNormal,
|
||||||
precisionPicking);
|
(void**)&intersectedEntity, lockType, &result.accurate,
|
||||||
|
precisionPicking);
|
||||||
if (result.intersects && intersectedEntity) {
|
if (result.intersects && intersectedEntity) {
|
||||||
result.entityID = intersectedEntity->getEntityItemID();
|
result.entityID = intersectedEntity->getEntityItemID();
|
||||||
result.properties = intersectedEntity->getProperties();
|
result.properties = intersectedEntity->getProperties();
|
||||||
|
@ -641,6 +661,8 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) {
|
||||||
_entitiesScriptEngine->unloadEntityScript(entityID);
|
_entitiesScriptEngine->unloadEntityScript(entityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
forceRecheckEntities(); // reset our state to force checking our inside/outsideness of entities
|
||||||
|
|
||||||
// here's where we remove the entity payload from the scene
|
// here's where we remove the entity payload from the scene
|
||||||
if (_entitiesInScene.contains(entityID)) {
|
if (_entitiesInScene.contains(entityID)) {
|
||||||
auto entity = _entitiesInScene.take(entityID);
|
auto entity = _entitiesInScene.take(entityID);
|
||||||
|
@ -652,6 +674,7 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTreeRenderer::addingEntity(const EntityItemID& entityID) {
|
void EntityTreeRenderer::addingEntity(const EntityItemID& entityID) {
|
||||||
|
forceRecheckEntities(); // reset our state to force checking our inside/outsideness of entities
|
||||||
checkAndCallPreload(entityID);
|
checkAndCallPreload(entityID);
|
||||||
auto entity = std::static_pointer_cast<EntityTree>(_tree)->findEntityByID(entityID);
|
auto entity = std::static_pointer_cast<EntityTree>(_tree)->findEntityByID(entityID);
|
||||||
if (entity) {
|
if (entity) {
|
||||||
|
|
|
@ -87,10 +87,10 @@ public:
|
||||||
QList<EntityItemID>& getEntitiesLastInScene() { return _entityIDsLastInScene; }
|
QList<EntityItemID>& getEntitiesLastInScene() { return _entityIDsLastInScene; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void mousePressOnEntity(const RayToEntityIntersectionResult& entityItemID, const QMouseEvent* event, unsigned int deviceId);
|
void mousePressOnEntity(const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId);
|
||||||
void mousePressOffEntity(const RayToEntityIntersectionResult& entityItemID, const QMouseEvent* event, unsigned int deviceId);
|
void mousePressOffEntity(const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId);
|
||||||
void mouseMoveOnEntity(const RayToEntityIntersectionResult& entityItemID, const QMouseEvent* event, unsigned int deviceId);
|
void mouseMoveOnEntity(const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId);
|
||||||
void mouseReleaseOnEntity(const RayToEntityIntersectionResult& entityItemID, const QMouseEvent* event, unsigned int deviceId);
|
void mouseReleaseOnEntity(const RayToEntityIntersectionResult& intersection, const QMouseEvent* event, unsigned int deviceId);
|
||||||
|
|
||||||
void clickDownOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
void clickDownOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||||
void holdingClickOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
void holdingClickOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||||
|
@ -138,7 +138,10 @@ private:
|
||||||
QScriptValueList createEntityArgs(const EntityItemID& entityID);
|
QScriptValueList createEntityArgs(const EntityItemID& entityID);
|
||||||
void checkEnterLeaveEntities();
|
void checkEnterLeaveEntities();
|
||||||
void leaveAllEntities();
|
void leaveAllEntities();
|
||||||
|
void forceRecheckEntities();
|
||||||
|
|
||||||
glm::vec3 _lastAvatarPosition;
|
glm::vec3 _lastAvatarPosition;
|
||||||
|
bool _pendingSkyboxTextureDownload = false;
|
||||||
QVector<EntityItemID> _currentEntitiesInside;
|
QVector<EntityItemID> _currentEntitiesInside;
|
||||||
|
|
||||||
bool _wantScripts;
|
bool _wantScripts;
|
||||||
|
|
|
@ -54,8 +54,9 @@ void RenderableLightEntityItem::render(RenderArgs* args) {
|
||||||
};
|
};
|
||||||
|
|
||||||
bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
void** intersectedObject, bool precisionPicking) const {
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
|
void** intersectedObject, bool precisionPicking) const {
|
||||||
|
|
||||||
// TODO: consider if this is really what we want to do. We've made it so that "lights are pickable" is a global state
|
// TODO: consider if this is really what we want to do. We've made it so that "lights are pickable" is a global state
|
||||||
// this is probably reasonable since there's typically only one tree you'd be picking on at a time. Technically we could
|
// this is probably reasonable since there's typically only one tree you'd be picking on at a time. Technically we could
|
||||||
|
|
|
@ -26,7 +26,8 @@ public:
|
||||||
virtual void render(RenderArgs* args);
|
virtual void render(RenderArgs* args);
|
||||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
void** intersectedObject, bool precisionPicking) const;
|
void** intersectedObject, bool precisionPicking) const;
|
||||||
|
|
||||||
SIMPLE_RENDERABLE();
|
SIMPLE_RENDERABLE();
|
||||||
|
|
|
@ -369,9 +369,9 @@ EntityItemProperties RenderableModelEntityItem::getProperties(EntityPropertyFlag
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
||||||
void** intersectedObject, bool precisionPicking) const {
|
glm::vec3& surfaceNormal, void** intersectedObject, bool precisionPicking) const {
|
||||||
if (!_model) {
|
if (!_model) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -379,7 +379,8 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori
|
||||||
// << precisionPicking;
|
// << precisionPicking;
|
||||||
|
|
||||||
QString extraInfo;
|
QString extraInfo;
|
||||||
return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, extraInfo, precisionPicking);
|
return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance,
|
||||||
|
face, surfaceNormal, extraInfo, precisionPicking);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderableModelEntityItem::setCompoundShapeURL(const QString& url) {
|
void RenderableModelEntityItem::setCompoundShapeURL(const QString& url) {
|
||||||
|
|
|
@ -55,8 +55,9 @@ public:
|
||||||
virtual void render(RenderArgs* args);
|
virtual void render(RenderArgs* args);
|
||||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
void** intersectedObject, bool precisionPicking) const;
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
|
void** intersectedObject, bool precisionPicking) const;
|
||||||
|
|
||||||
Model* getModel(EntityTreeRenderer* renderer);
|
Model* getModel(EntityTreeRenderer* renderer);
|
||||||
|
|
||||||
|
|
|
@ -348,13 +348,10 @@ public:
|
||||||
const PolyVox::SimpleVolume<uint8_t>* _vol = nullptr;
|
const PolyVox::SimpleVolume<uint8_t>* _vol = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& origin,
|
bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
const glm::vec3& direction,
|
bool& keepSearching, OctreeElementPointer& element,
|
||||||
bool& keepSearching,
|
float& distance, BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
OctreeElementPointer& element,
|
void** intersectedObject, bool precisionPicking) const
|
||||||
float& distance, BoxFace& face,
|
|
||||||
void** intersectedObject,
|
|
||||||
bool precisionPicking) const
|
|
||||||
{
|
{
|
||||||
// TODO -- correctly pick against marching-cube generated meshes
|
// TODO -- correctly pick against marching-cube generated meshes
|
||||||
if (!precisionPicking) {
|
if (!precisionPicking) {
|
||||||
|
@ -392,7 +389,7 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o
|
||||||
|
|
||||||
float voxelDistance;
|
float voxelDistance;
|
||||||
|
|
||||||
bool hit = voxelBox.findRayIntersection(glm::vec3(originInVoxel), glm::vec3(directionInVoxel), voxelDistance, face);
|
bool hit = voxelBox.findRayIntersection(glm::vec3(originInVoxel), glm::vec3(directionInVoxel), voxelDistance, face, surfaceNormal);
|
||||||
|
|
||||||
glm::vec4 voxelIntersectionPoint = glm::vec4(glm::vec3(originInVoxel) + glm::vec3(directionInVoxel) * voxelDistance, 1.0);
|
glm::vec4 voxelIntersectionPoint = glm::vec4(glm::vec3(originInVoxel) + glm::vec3(directionInVoxel) * voxelDistance, 1.0);
|
||||||
glm::vec4 intersectionPoint = vtwMatrix * voxelIntersectionPoint;
|
glm::vec4 intersectionPoint = vtwMatrix * voxelIntersectionPoint;
|
||||||
|
|
|
@ -64,8 +64,9 @@ public:
|
||||||
void render(RenderArgs* args);
|
void render(RenderArgs* args);
|
||||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
void** intersectedObject, bool precisionPicking) const;
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
|
void** intersectedObject, bool precisionPicking) const;
|
||||||
|
|
||||||
virtual void setVoxelData(QByteArray voxelData);
|
virtual void setVoxelData(QByteArray voxelData);
|
||||||
virtual void setVoxelVolumeSize(glm::vec3 voxelVolumeSize);
|
virtual void setVoxelVolumeSize(glm::vec3 voxelVolumeSize);
|
||||||
|
|
|
@ -206,7 +206,8 @@ public:
|
||||||
|
|
||||||
virtual bool supportsDetailedRayIntersection() const { return false; }
|
virtual bool supportsDetailedRayIntersection() const { return false; }
|
||||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
void** intersectedObject, bool precisionPicking) const { return true; }
|
void** intersectedObject, bool precisionPicking) const { return true; }
|
||||||
|
|
||||||
// attributes applicable to all entity types
|
// attributes applicable to all entity types
|
||||||
|
|
|
@ -297,7 +297,7 @@ RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionWorke
|
||||||
OctreeElementPointer element;
|
OctreeElementPointer element;
|
||||||
EntityItemPointer intersectedEntity = NULL;
|
EntityItemPointer intersectedEntity = NULL;
|
||||||
result.intersects = _entityTree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face,
|
result.intersects = _entityTree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face,
|
||||||
(void**)&intersectedEntity, lockType, &result.accurate,
|
result.surfaceNormal, (void**)&intersectedEntity, lockType, &result.accurate,
|
||||||
precisionPicking);
|
precisionPicking);
|
||||||
if (result.intersects && intersectedEntity) {
|
if (result.intersects && intersectedEntity) {
|
||||||
result.entityID = intersectedEntity->getEntityItemID();
|
result.entityID = intersectedEntity->getEntityItemID();
|
||||||
|
@ -393,6 +393,9 @@ QScriptValue RayToEntityIntersectionResultToScriptValue(QScriptEngine* engine, c
|
||||||
|
|
||||||
QScriptValue intersection = vec3toScriptValue(engine, value.intersection);
|
QScriptValue intersection = vec3toScriptValue(engine, value.intersection);
|
||||||
obj.setProperty("intersection", intersection);
|
obj.setProperty("intersection", intersection);
|
||||||
|
|
||||||
|
QScriptValue surfaceNormal = vec3toScriptValue(engine, value.surfaceNormal);
|
||||||
|
obj.setProperty("surfaceNormal", surfaceNormal);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,6 +429,10 @@ void RayToEntityIntersectionResultFromScriptValue(const QScriptValue& object, Ra
|
||||||
if (intersection.isValid()) {
|
if (intersection.isValid()) {
|
||||||
vec3FromScriptValue(intersection, value.intersection);
|
vec3FromScriptValue(intersection, value.intersection);
|
||||||
}
|
}
|
||||||
|
QScriptValue surfaceNormal = object.property("surfaceNormal");
|
||||||
|
if (surfaceNormal.isValid()) {
|
||||||
|
vec3FromScriptValue(surfaceNormal, value.surfaceNormal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityScriptingInterface::setVoxels(QUuid entityID,
|
bool EntityScriptingInterface::setVoxels(QUuid entityID,
|
||||||
|
|
|
@ -43,6 +43,7 @@ public:
|
||||||
float distance;
|
float distance;
|
||||||
BoxFace face;
|
BoxFace face;
|
||||||
glm::vec3 intersection;
|
glm::vec3 intersection;
|
||||||
|
glm::vec3 surfaceNormal;
|
||||||
EntityItemPointer entity;
|
EntityItemPointer entity;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -492,9 +492,9 @@ bool EntityTreeElement::bestFitBounds(const glm::vec3& minPoint, const glm::vec3
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
void** intersectedObject, bool precisionPicking, float distanceToElementCube) {
|
void** intersectedObject, bool precisionPicking, float distanceToElementCube) {
|
||||||
|
|
||||||
// only called if we do intersect our bounding cube, but find if we actually intersect with entities...
|
// only called if we do intersect our bounding cube, but find if we actually intersect with entities...
|
||||||
int entityNumber = 0;
|
int entityNumber = 0;
|
||||||
|
@ -503,9 +503,10 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con
|
||||||
AABox entityBox = entity->getAABox();
|
AABox entityBox = entity->getAABox();
|
||||||
float localDistance;
|
float localDistance;
|
||||||
BoxFace localFace;
|
BoxFace localFace;
|
||||||
|
glm::vec3 localSurfaceNormal;
|
||||||
|
|
||||||
// if the ray doesn't intersect with our cube, we can stop searching!
|
// if the ray doesn't intersect with our cube, we can stop searching!
|
||||||
if (!entityBox.findRayIntersection(origin, direction, localDistance, localFace)) {
|
if (!entityBox.findRayIntersection(origin, direction, localDistance, localFace, localSurfaceNormal)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,16 +527,18 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con
|
||||||
|
|
||||||
// we can use the AABox's ray intersection by mapping our origin and direction into the entity frame
|
// we can use the AABox's ray intersection by mapping our origin and direction into the entity frame
|
||||||
// and testing intersection there.
|
// and testing intersection there.
|
||||||
if (entityFrameBox.findRayIntersection(entityFrameOrigin, entityFrameDirection, localDistance, localFace)) {
|
if (entityFrameBox.findRayIntersection(entityFrameOrigin, entityFrameDirection, localDistance,
|
||||||
|
localFace, localSurfaceNormal)) {
|
||||||
if (localDistance < distance) {
|
if (localDistance < distance) {
|
||||||
// now ask the entity if we actually intersect
|
// now ask the entity if we actually intersect
|
||||||
if (entity->supportsDetailedRayIntersection()) {
|
if (entity->supportsDetailedRayIntersection()) {
|
||||||
if (entity->findDetailedRayIntersection(origin, direction, keepSearching, element, localDistance,
|
if (entity->findDetailedRayIntersection(origin, direction, keepSearching, element, localDistance,
|
||||||
localFace, intersectedObject, precisionPicking)) {
|
localFace, localSurfaceNormal, intersectedObject, precisionPicking)) {
|
||||||
|
|
||||||
if (localDistance < distance) {
|
if (localDistance < distance) {
|
||||||
distance = localDistance;
|
distance = localDistance;
|
||||||
face = localFace;
|
face = localFace;
|
||||||
|
surfaceNormal = localSurfaceNormal;
|
||||||
*intersectedObject = (void*)entity.get();
|
*intersectedObject = (void*)entity.get();
|
||||||
somethingIntersected = true;
|
somethingIntersected = true;
|
||||||
}
|
}
|
||||||
|
@ -545,6 +548,7 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con
|
||||||
if (localDistance < distance) {
|
if (localDistance < distance) {
|
||||||
distance = localDistance;
|
distance = localDistance;
|
||||||
face = localFace;
|
face = localFace;
|
||||||
|
surfaceNormal = localSurfaceNormal;
|
||||||
*intersectedObject = (void*)entity.get();
|
*intersectedObject = (void*)entity.get();
|
||||||
somethingIntersected = true;
|
somethingIntersected = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,7 +143,8 @@ public:
|
||||||
|
|
||||||
virtual bool canRayIntersect() const { return hasEntities(); }
|
virtual bool canRayIntersect() const { return hasEntities(); }
|
||||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
void** intersectedObject, bool precisionPicking, float distanceToElementCube);
|
void** intersectedObject, bool precisionPicking, float distanceToElementCube);
|
||||||
|
|
||||||
virtual bool findSpherePenetration(const glm::vec3& center, float radius,
|
virtual bool findSpherePenetration(const glm::vec3& center, float radius,
|
||||||
|
|
|
@ -64,8 +64,9 @@ class LineEntityItem : public EntityItem {
|
||||||
// never have a ray intersection pick a LineEntityItem.
|
// never have a ray intersection pick a LineEntityItem.
|
||||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
void** intersectedObject, bool precisionPicking) const { return false; }
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
|
void** intersectedObject, bool precisionPicking) const { return false; }
|
||||||
|
|
||||||
virtual void debugDump() const;
|
virtual void debugDump() const;
|
||||||
static const float DEFAULT_LINE_WIDTH;
|
static const float DEFAULT_LINE_WIDTH;
|
||||||
|
|
|
@ -73,8 +73,9 @@ class PolyLineEntityItem : public EntityItem {
|
||||||
// never have a ray intersection pick a PolyLineEntityItem.
|
// never have a ray intersection pick a PolyLineEntityItem.
|
||||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
void** intersectedObject, bool precisionPicking) const { return false; }
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
|
void** intersectedObject, bool precisionPicking) const { return false;}
|
||||||
|
|
||||||
virtual void debugDump() const;
|
virtual void debugDump() const;
|
||||||
static const float DEFAULT_LINE_WIDTH;
|
static const float DEFAULT_LINE_WIDTH;
|
||||||
|
|
|
@ -44,8 +44,9 @@ class PolyVoxEntityItem : public EntityItem {
|
||||||
// never have a ray intersection pick a PolyVoxEntityItem.
|
// never have a ray intersection pick a PolyVoxEntityItem.
|
||||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
void** intersectedObject, bool precisionPicking) const { return false; }
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
|
void** intersectedObject, bool precisionPicking) const { return false; }
|
||||||
|
|
||||||
virtual void debugDump() const;
|
virtual void debugDump() const;
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ void SphereEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBi
|
||||||
|
|
||||||
bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element,
|
bool& keepSearching, OctreeElementPointer& element,
|
||||||
float& distance, BoxFace& face,
|
float& distance, BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
void** intersectedObject, bool precisionPicking) const {
|
void** intersectedObject, bool precisionPicking) const {
|
||||||
// determine the ray in the frame of the entity transformed from a unit sphere
|
// determine the ray in the frame of the entity transformed from a unit sphere
|
||||||
glm::mat4 entityToWorldMatrix = getEntityToWorldMatrix();
|
glm::mat4 entityToWorldMatrix = getEntityToWorldMatrix();
|
||||||
|
@ -111,6 +111,7 @@ bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, cons
|
||||||
// then translate back to work coordinates
|
// then translate back to work coordinates
|
||||||
glm::vec3 hitAt = glm::vec3(entityToWorldMatrix * glm::vec4(entityFrameHitAt, 1.0f));
|
glm::vec3 hitAt = glm::vec3(entityToWorldMatrix * glm::vec4(entityFrameHitAt, 1.0f));
|
||||||
distance = glm::distance(origin, hitAt);
|
distance = glm::distance(origin, hitAt);
|
||||||
|
surfaceNormal = glm::normalize(hitAt - getCenterPosition());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -54,8 +54,9 @@ public:
|
||||||
|
|
||||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
void** intersectedObject, bool precisionPicking) const;
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
|
void** intersectedObject, bool precisionPicking) const;
|
||||||
|
|
||||||
virtual void debugDump() const;
|
virtual void debugDump() const;
|
||||||
|
|
||||||
|
|
|
@ -129,12 +129,15 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
void** intersectedObject, bool precisionPicking) const {
|
void** intersectedObject, bool precisionPicking) const {
|
||||||
glm::vec3 dimensions = getDimensions();
|
glm::vec3 dimensions = getDimensions();
|
||||||
glm::vec2 xyDimensions(dimensions.x, dimensions.y);
|
glm::vec2 xyDimensions(dimensions.x, dimensions.y);
|
||||||
glm::quat rotation = getRotation();
|
glm::quat rotation = getRotation();
|
||||||
glm::vec3 position = getPosition() + rotation *
|
glm::vec3 position = getPosition() + rotation *
|
||||||
(dimensions * (getRegistrationPoint() - ENTITY_ITEM_DEFAULT_REGISTRATION_POINT));
|
(dimensions * (getRegistrationPoint() - ENTITY_ITEM_DEFAULT_REGISTRATION_POINT));
|
||||||
|
|
||||||
|
// FIXME - should set face and surfaceNormal
|
||||||
return findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance);
|
return findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,8 @@ public:
|
||||||
|
|
||||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
void** intersectedObject, bool precisionPicking) const;
|
void** intersectedObject, bool precisionPicking) const;
|
||||||
|
|
||||||
static const QString DEFAULT_TEXT;
|
static const QString DEFAULT_TEXT;
|
||||||
|
|
|
@ -99,13 +99,15 @@ void WebEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitst
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
void** intersectedObject, bool precisionPicking) const {
|
void** intersectedObject, bool precisionPicking) const {
|
||||||
glm::vec3 dimensions = getDimensions();
|
glm::vec3 dimensions = getDimensions();
|
||||||
glm::vec2 xyDimensions(dimensions.x, dimensions.y);
|
glm::vec2 xyDimensions(dimensions.x, dimensions.y);
|
||||||
glm::quat rotation = getRotation();
|
glm::quat rotation = getRotation();
|
||||||
glm::vec3 position = getPosition() + rotation *
|
glm::vec3 position = getPosition() + rotation *
|
||||||
(dimensions * (getRegistrationPoint() - ENTITY_ITEM_DEFAULT_REGISTRATION_POINT));
|
(dimensions * (getRegistrationPoint() - ENTITY_ITEM_DEFAULT_REGISTRATION_POINT));
|
||||||
|
// FIXME - should set face and surfaceNormal
|
||||||
return findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance);
|
return findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,8 @@ public:
|
||||||
|
|
||||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
void** intersectedObject, bool precisionPicking) const;
|
void** intersectedObject, bool precisionPicking) const;
|
||||||
|
|
||||||
virtual void setSourceUrl(const QString& value);
|
virtual void setSourceUrl(const QString& value);
|
||||||
|
|
|
@ -246,7 +246,8 @@ void ZoneEntityItem::setCompoundShapeURL(const QString& url) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
void** intersectedObject, bool precisionPicking) const {
|
void** intersectedObject, bool precisionPicking) const {
|
||||||
|
|
||||||
return _zonesArePickable;
|
return _zonesArePickable;
|
||||||
|
|
|
@ -100,7 +100,8 @@ public:
|
||||||
|
|
||||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
void** intersectedObject, bool precisionPicking) const;
|
void** intersectedObject, bool precisionPicking) const;
|
||||||
|
|
||||||
virtual void debugDump() const;
|
virtual void debugDump() const;
|
||||||
|
|
|
@ -935,7 +935,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
|
||||||
_textureContent.insert(filename, content);
|
_textureContent.insert(filename, content);
|
||||||
}
|
}
|
||||||
} else if (object.name == "Material") {
|
} else if (object.name == "Material") {
|
||||||
FBXMaterial material(glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(1.0f), glm::vec3(), glm::vec2(0.f, 1.0f), 96.0f, 1.0f);
|
FBXMaterial material;
|
||||||
foreach (const FBXNode& subobject, object.children) {
|
foreach (const FBXNode& subobject, object.children) {
|
||||||
bool properties = false;
|
bool properties = false;
|
||||||
QByteArray propertyName;
|
QByteArray propertyName;
|
||||||
|
@ -955,9 +955,17 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
|
||||||
if (property.name == propertyName) {
|
if (property.name == propertyName) {
|
||||||
if (property.properties.at(0) == "DiffuseColor") {
|
if (property.properties.at(0) == "DiffuseColor") {
|
||||||
material.diffuseColor = getVec3(property.properties, index);
|
material.diffuseColor = getVec3(property.properties, index);
|
||||||
|
} else if (property.properties.at(0) == "Diffuse") {
|
||||||
|
material.diffuseColor = getVec3(property.properties, index);
|
||||||
|
} else if (property.properties.at(0) == "DiffuseFactor") {
|
||||||
|
material.diffuseFactor = property.properties.at(index).value<double>();
|
||||||
|
|
||||||
} else if (property.properties.at(0) == "SpecularColor") {
|
} else if (property.properties.at(0) == "SpecularColor") {
|
||||||
material.specularColor = getVec3(property.properties, index);
|
material.specularColor = getVec3(property.properties, index);
|
||||||
|
} else if (property.properties.at(0) == "Specular") {
|
||||||
|
material.specularColor = getVec3(property.properties, index);
|
||||||
|
} else if (property.properties.at(0) == "SpecularFactor") {
|
||||||
|
material.specularFactor = property.properties.at(index).value<double>();
|
||||||
|
|
||||||
} else if (property.properties.at(0) == "Emissive") {
|
} else if (property.properties.at(0) == "Emissive") {
|
||||||
material.emissiveColor = getVec3(property.properties, index);
|
material.emissiveColor = getVec3(property.properties, index);
|
||||||
|
|
|
@ -137,21 +137,24 @@ public:
|
||||||
class FBXMaterial {
|
class FBXMaterial {
|
||||||
public:
|
public:
|
||||||
FBXMaterial() {};
|
FBXMaterial() {};
|
||||||
FBXMaterial(const glm::vec3& diffuseColor, const glm::vec3& specularColor, const glm::vec3& emissiveColor,
|
FBXMaterial(const glm::vec3& diffuseColor, const glm::vec3& specularColor, const glm::vec3& emissiveColor,
|
||||||
const glm::vec2& emissiveParams, float shininess, float opacity) :
|
const glm::vec2& emissiveParams, float shininess, float opacity) :
|
||||||
diffuseColor(diffuseColor),
|
diffuseColor(diffuseColor),
|
||||||
specularColor(specularColor),
|
specularColor(specularColor),
|
||||||
emissiveColor(emissiveColor),
|
emissiveColor(emissiveColor),
|
||||||
emissiveParams(emissiveParams),
|
emissiveParams(emissiveParams),
|
||||||
shininess(shininess),
|
shininess(shininess),
|
||||||
opacity(opacity) {}
|
opacity(opacity) {}
|
||||||
|
|
||||||
glm::vec3 diffuseColor;
|
glm::vec3 diffuseColor{ 1.0f };
|
||||||
glm::vec3 specularColor;
|
float diffuseFactor = 1.0f;
|
||||||
glm::vec3 emissiveColor;
|
glm::vec3 specularColor{ 0.02f };
|
||||||
glm::vec2 emissiveParams;
|
float specularFactor = 1.0f;
|
||||||
float shininess;
|
|
||||||
float opacity;
|
glm::vec3 emissiveColor{ 0.0f };
|
||||||
|
glm::vec2 emissiveParams{ 0.0f, 1.0f };
|
||||||
|
float shininess = 23.0f;
|
||||||
|
float opacity = 1.0f;
|
||||||
|
|
||||||
QString materialID;
|
QString materialID;
|
||||||
model::MaterialPointer _material;
|
model::MaterialPointer _material;
|
||||||
|
|
|
@ -134,12 +134,16 @@ void FBXReader::consolidateFBXMaterials() {
|
||||||
// Finally create the true material representation
|
// Finally create the true material representation
|
||||||
material._material = std::make_shared<model::Material>();
|
material._material = std::make_shared<model::Material>();
|
||||||
material._material->setEmissive(material.emissiveColor);
|
material._material->setEmissive(material.emissiveColor);
|
||||||
if (glm::all(glm::equal(material.diffuseColor, glm::vec3(0.0f)))) {
|
|
||||||
material._material->setDiffuse(material.diffuseColor);
|
auto diffuse = material.diffuseColor;
|
||||||
} else {
|
// FIXME: Do not use the Diffuse Factor yet as some FBX models have it set to 0
|
||||||
material._material->setDiffuse(material.diffuseColor);
|
// diffuse *= material.diffuseFactor;
|
||||||
}
|
material._material->setDiffuse(diffuse);
|
||||||
material._material->setMetallic(glm::length(material.specularColor));
|
|
||||||
|
float metallic = std::max(material.specularColor.x, std::max(material.specularColor.y, material.specularColor.z));
|
||||||
|
// FIXME: Do not use the Specular Factor yet as some FBX models have it set to 0
|
||||||
|
// metallic *= material.specularFactor;
|
||||||
|
material._material->setMetallic(metallic);
|
||||||
material._material->setGloss(material.shininess);
|
material._material->setGloss(material.shininess);
|
||||||
|
|
||||||
if (material.opacity <= 0.0f) {
|
if (material.opacity <= 0.0f) {
|
||||||
|
|
|
@ -418,10 +418,10 @@ void GLBackend::resetStages() {
|
||||||
#define DO_IT_NOW(call, offset)
|
#define DO_IT_NOW(call, offset)
|
||||||
|
|
||||||
void Batch::_glActiveBindTexture(GLenum unit, GLenum target, GLuint texture) {
|
void Batch::_glActiveBindTexture(GLenum unit, GLenum target, GLuint texture) {
|
||||||
|
// clean the cache on the texture unit we are going to use so the next call to setResourceTexture() at the same slot works fine
|
||||||
setResourceTexture(unit - GL_TEXTURE0, nullptr);
|
setResourceTexture(unit - GL_TEXTURE0, nullptr);
|
||||||
|
|
||||||
ADD_COMMAND_GL(glActiveBindTexture);
|
ADD_COMMAND_GL(glActiveBindTexture);
|
||||||
|
|
||||||
_params.push_back(texture);
|
_params.push_back(texture);
|
||||||
_params.push_back(target);
|
_params.push_back(target);
|
||||||
_params.push_back(unit);
|
_params.push_back(unit);
|
||||||
|
@ -434,6 +434,7 @@ void GLBackend::do_glActiveBindTexture(Batch& batch, uint32 paramOffset) {
|
||||||
glBindTexture(
|
glBindTexture(
|
||||||
batch._params[paramOffset + 1]._uint,
|
batch._params[paramOffset + 1]._uint,
|
||||||
batch._params[paramOffset + 0]._uint);
|
batch._params[paramOffset + 0]._uint);
|
||||||
|
|
||||||
(void) CHECK_GL_ERROR();
|
(void) CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,8 @@ void GLBackend::syncInputStateCache() {
|
||||||
|
|
||||||
// Core 41 doesn't expose the features to really separate the vertex format from the vertex buffers binding
|
// Core 41 doesn't expose the features to really separate the vertex format from the vertex buffers binding
|
||||||
// Core 43 does :)
|
// Core 43 does :)
|
||||||
#if (GPU_INPUT_PROFILE == GPU_CORE_41)
|
// FIXME crashing problem with glVertexBindingDivisor / glVertexAttribFormat
|
||||||
|
#if 1 || (GPU_INPUT_PROFILE == GPU_CORE_41)
|
||||||
#define NO_SUPPORT_VERTEX_ATTRIB_FORMAT
|
#define NO_SUPPORT_VERTEX_ATTRIB_FORMAT
|
||||||
#else
|
#else
|
||||||
#define SUPPORT_VERTEX_ATTRIB_FORMAT
|
#define SUPPORT_VERTEX_ATTRIB_FORMAT
|
||||||
|
@ -117,9 +118,9 @@ void GLBackend::updateInput() {
|
||||||
for (size_t locNum = 0; locNum < locationCount; ++locNum) {
|
for (size_t locNum = 0; locNum < locationCount; ++locNum) {
|
||||||
newActivation.set(slot + locNum);
|
newActivation.set(slot + locNum);
|
||||||
glVertexAttribFormat(slot + locNum, count, type, isNormalized, offset + locNum * perLocationSize);
|
glVertexAttribFormat(slot + locNum, count, type, isNormalized, offset + locNum * perLocationSize);
|
||||||
glVertexAttribDivisor(slot + locNum, attrib._frequency);
|
|
||||||
glVertexAttribBinding(slot + locNum, attrib._channel);
|
glVertexAttribBinding(slot + locNum, attrib._channel);
|
||||||
}
|
}
|
||||||
|
glVertexBindingDivisor(attrib._channel, attrib._frequency);
|
||||||
}
|
}
|
||||||
(void) CHECK_GL_ERROR();
|
(void) CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,12 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo
|
||||||
|
|
||||||
if (_invalidModel) {
|
if (_invalidModel) {
|
||||||
_model.getMatrix(_object._model);
|
_model.getMatrix(_object._model);
|
||||||
_model.getInverseMatrix(_object._modelInverse);
|
|
||||||
|
// FIXME - we don't want to be using glm::inverse() here but it fixes the flickering issue we are
|
||||||
|
// seeing with planky blocks in toybox. Our implementation of getInverseMatrix() is buggy in cases
|
||||||
|
// of non-uniform scale. We need to fix that. In the mean time, glm::inverse() works.
|
||||||
|
//_model.getInverseMatrix(_object._modelInverse);
|
||||||
|
_object._modelInverse = glm::inverse(_object._model);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_invalidView || _invalidProj || _invalidViewport) {
|
if (_invalidView || _invalidProj || _invalidViewport) {
|
||||||
|
|
|
@ -230,12 +230,15 @@ NetworkTexture::TextureLoaderFunc NetworkTexture::getTextureLoader() const {
|
||||||
return TextureLoaderFunc(model::TextureUsage::createNormalTextureFromBumpImage);
|
return TextureLoaderFunc(model::TextureUsage::createNormalTextureFromBumpImage);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case NORMAL_TEXTURE: {
|
||||||
|
return TextureLoaderFunc(model::TextureUsage::createNormalTextureFromNormalImage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case CUSTOM_TEXTURE: {
|
case CUSTOM_TEXTURE: {
|
||||||
return _textureLoader;
|
return _textureLoader;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DEFAULT_TEXTURE:
|
case DEFAULT_TEXTURE:
|
||||||
case NORMAL_TEXTURE:
|
|
||||||
case SPECULAR_TEXTURE:
|
case SPECULAR_TEXTURE:
|
||||||
case EMISSIVE_TEXTURE:
|
case EMISSIVE_TEXTURE:
|
||||||
default: {
|
default: {
|
||||||
|
|
|
@ -137,6 +137,40 @@ gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, con
|
||||||
return theTexture;
|
return theTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& srcImage, const std::string& srcImageName) {
|
||||||
|
QImage image = srcImage;
|
||||||
|
|
||||||
|
if (!image.hasAlphaChannel()) {
|
||||||
|
if (image.format() != QImage::Format_RGB888) {
|
||||||
|
image = image.convertToFormat(QImage::Format_RGB888);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (image.format() != QImage::Format_ARGB32) {
|
||||||
|
image = image.convertToFormat(QImage::Format_ARGB32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gpu::Texture* theTexture = nullptr;
|
||||||
|
if ((image.width() > 0) && (image.height() > 0)) {
|
||||||
|
|
||||||
|
bool isLinearRGB = true;
|
||||||
|
|
||||||
|
gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB));
|
||||||
|
gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB));
|
||||||
|
if (image.hasAlphaChannel()) {
|
||||||
|
formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA));
|
||||||
|
formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA));
|
||||||
|
}
|
||||||
|
|
||||||
|
theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
|
||||||
|
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
|
||||||
|
theTexture->autoGenerateMips(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return theTexture;
|
||||||
|
}
|
||||||
|
|
||||||
int clampPixelCoordinate(int coordinate, int maxCoordinate) {
|
int clampPixelCoordinate(int coordinate, int maxCoordinate) {
|
||||||
return coordinate - ((int)(coordinate < 0) * coordinate) + ((int)(coordinate > maxCoordinate) * (maxCoordinate - coordinate));
|
return coordinate - ((int)(coordinate < 0) * coordinate) + ((int)(coordinate > maxCoordinate) * (maxCoordinate - coordinate));
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ public:
|
||||||
int _environmentUsage = 0;
|
int _environmentUsage = 0;
|
||||||
|
|
||||||
static gpu::Texture* create2DTextureFromImage(const QImage& image, const std::string& srcImageName);
|
static gpu::Texture* create2DTextureFromImage(const QImage& image, const std::string& srcImageName);
|
||||||
|
static gpu::Texture* createNormalTextureFromNormalImage(const QImage& image, const std::string& srcImageName);
|
||||||
static gpu::Texture* createNormalTextureFromBumpImage(const QImage& image, const std::string& srcImageName);
|
static gpu::Texture* createNormalTextureFromBumpImage(const QImage& image, const std::string& srcImageName);
|
||||||
static gpu::Texture* createCubeTextureFromImage(const QImage& image, const std::string& srcImageName);
|
static gpu::Texture* createCubeTextureFromImage(const QImage& image, const std::string& srcImageName);
|
||||||
};
|
};
|
||||||
|
|
|
@ -702,6 +702,7 @@ public:
|
||||||
OctreeElementPointer& element;
|
OctreeElementPointer& element;
|
||||||
float& distance;
|
float& distance;
|
||||||
BoxFace& face;
|
BoxFace& face;
|
||||||
|
glm::vec3& surfaceNormal;
|
||||||
void** intersectedObject;
|
void** intersectedObject;
|
||||||
bool found;
|
bool found;
|
||||||
bool precisionPicking;
|
bool precisionPicking;
|
||||||
|
@ -711,17 +712,18 @@ bool findRayIntersectionOp(OctreeElementPointer element, void* extraData) {
|
||||||
RayArgs* args = static_cast<RayArgs*>(extraData);
|
RayArgs* args = static_cast<RayArgs*>(extraData);
|
||||||
bool keepSearching = true;
|
bool keepSearching = true;
|
||||||
if (element->findRayIntersection(args->origin, args->direction, keepSearching,
|
if (element->findRayIntersection(args->origin, args->direction, keepSearching,
|
||||||
args->element, args->distance, args->face, args->intersectedObject, args->precisionPicking)) {
|
args->element, args->distance, args->face, args->surfaceNormal,
|
||||||
|
args->intersectedObject, args->precisionPicking)) {
|
||||||
args->found = true;
|
args->found = true;
|
||||||
}
|
}
|
||||||
return keepSearching;
|
return keepSearching;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Octree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
bool Octree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject,
|
OctreeElementPointer& element, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal, void** intersectedObject,
|
||||||
Octree::lockType lockType, bool* accurateResult, bool precisionPicking) {
|
Octree::lockType lockType, bool* accurateResult, bool precisionPicking) {
|
||||||
RayArgs args = { origin, direction, element, distance, face,
|
RayArgs args = { origin, direction, element, distance, face, surfaceNormal, intersectedObject, false, precisionPicking};
|
||||||
intersectedObject, false, precisionPicking};
|
|
||||||
distance = FLT_MAX;
|
distance = FLT_MAX;
|
||||||
|
|
||||||
bool requireLock = lockType == Octree::Lock;
|
bool requireLock = lockType == Octree::Lock;
|
||||||
|
|
|
@ -299,7 +299,7 @@ public:
|
||||||
} lockType;
|
} lockType;
|
||||||
|
|
||||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
OctreeElementPointer& node, float& distance, BoxFace& face,
|
OctreeElementPointer& node, float& distance, BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
void** intersectedObject = NULL,
|
void** intersectedObject = NULL,
|
||||||
Octree::lockType lockType = Octree::TryLock,
|
Octree::lockType lockType = Octree::TryLock,
|
||||||
bool* accurateResult = NULL,
|
bool* accurateResult = NULL,
|
||||||
|
|
|
@ -574,7 +574,8 @@ void OctreeElement::notifyUpdateHooks() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
void** intersectedObject, bool precisionPicking) {
|
void** intersectedObject, bool precisionPicking) {
|
||||||
|
|
||||||
keepSearching = true; // assume that we will continue searching after this.
|
keepSearching = true; // assume that we will continue searching after this.
|
||||||
|
@ -582,9 +583,10 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3
|
||||||
float distanceToElementCube = std::numeric_limits<float>::max();
|
float distanceToElementCube = std::numeric_limits<float>::max();
|
||||||
float distanceToElementDetails = distance;
|
float distanceToElementDetails = distance;
|
||||||
BoxFace localFace;
|
BoxFace localFace;
|
||||||
|
glm::vec3 localSurfaceNormal;
|
||||||
|
|
||||||
// if the ray doesn't intersect with our cube, we can stop searching!
|
// if the ray doesn't intersect with our cube, we can stop searching!
|
||||||
if (!_cube.findRayIntersection(origin, direction, distanceToElementCube, localFace)) {
|
if (!_cube.findRayIntersection(origin, direction, distanceToElementCube, localFace, localSurfaceNormal)) {
|
||||||
keepSearching = false; // no point in continuing to search
|
keepSearching = false; // no point in continuing to search
|
||||||
return false; // we did not intersect
|
return false; // we did not intersect
|
||||||
}
|
}
|
||||||
|
@ -599,11 +601,12 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3
|
||||||
if (_cube.contains(origin) || distanceToElementCube < distance) {
|
if (_cube.contains(origin) || distanceToElementCube < distance) {
|
||||||
|
|
||||||
if (findDetailedRayIntersection(origin, direction, keepSearching, element, distanceToElementDetails,
|
if (findDetailedRayIntersection(origin, direction, keepSearching, element, distanceToElementDetails,
|
||||||
face, intersectedObject, precisionPicking, distanceToElementCube)) {
|
face, localSurfaceNormal, intersectedObject, precisionPicking, distanceToElementCube)) {
|
||||||
|
|
||||||
if (distanceToElementDetails < distance) {
|
if (distanceToElementDetails < distance) {
|
||||||
distance = distanceToElementDetails;
|
distance = distanceToElementDetails;
|
||||||
face = localFace;
|
face = localFace;
|
||||||
|
surfaceNormal = localSurfaceNormal;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -612,7 +615,8 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OctreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
bool OctreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
void** intersectedObject, bool precisionPicking, float distanceToElementCube) {
|
void** intersectedObject, bool precisionPicking, float distanceToElementCube) {
|
||||||
|
|
||||||
// we did hit this element, so calculate appropriate distances
|
// we did hit this element, so calculate appropriate distances
|
||||||
|
|
|
@ -119,11 +119,13 @@ public:
|
||||||
|
|
||||||
virtual bool canRayIntersect() const { return isLeaf(); }
|
virtual bool canRayIntersect() const { return isLeaf(); }
|
||||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& node, float& distance, BoxFace& face,
|
bool& keepSearching, OctreeElementPointer& node, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
void** intersectedObject = NULL, bool precisionPicking = false);
|
void** intersectedObject = NULL, bool precisionPicking = false);
|
||||||
|
|
||||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
void** intersectedObject, bool precisionPicking, float distanceToElementCube);
|
void** intersectedObject, bool precisionPicking, float distanceToElementCube);
|
||||||
|
|
||||||
/// \param center center of sphere in meters
|
/// \param center center of sphere in meters
|
||||||
|
|
|
@ -189,6 +189,7 @@ void Model::RenderPipelineLib::initLocations(gpu::ShaderPointer& program, Model:
|
||||||
locations.emissiveParams = program->getUniforms().findLocation("emissiveParams");
|
locations.emissiveParams = program->getUniforms().findLocation("emissiveParams");
|
||||||
locations.glowIntensity = program->getUniforms().findLocation("glowIntensity");
|
locations.glowIntensity = program->getUniforms().findLocation("glowIntensity");
|
||||||
locations.normalFittingMapUnit = program->getTextures().findLocation("normalFittingMap");
|
locations.normalFittingMapUnit = program->getTextures().findLocation("normalFittingMap");
|
||||||
|
locations.diffuseTextureUnit = program->getTextures().findLocation("diffuseMap");
|
||||||
locations.normalTextureUnit = program->getTextures().findLocation("normalMap");
|
locations.normalTextureUnit = program->getTextures().findLocation("normalMap");
|
||||||
locations.specularTextureUnit = program->getTextures().findLocation("specularMap");
|
locations.specularTextureUnit = program->getTextures().findLocation("specularMap");
|
||||||
locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap");
|
locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap");
|
||||||
|
@ -457,7 +458,8 @@ void Model::initJointStates(QVector<JointState> states) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||||
BoxFace& face, QString& extraInfo, bool pickAgainstTriangles) {
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
|
QString& extraInfo, bool pickAgainstTriangles) {
|
||||||
|
|
||||||
bool intersectedSomething = false;
|
bool intersectedSomething = false;
|
||||||
|
|
||||||
|
@ -484,11 +486,12 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g
|
||||||
|
|
||||||
// we can use the AABox's ray intersection by mapping our origin and direction into the model frame
|
// we can use the AABox's ray intersection by mapping our origin and direction into the model frame
|
||||||
// and testing intersection there.
|
// and testing intersection there.
|
||||||
if (modelFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face)) {
|
if (modelFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face, surfaceNormal)) {
|
||||||
float bestDistance = std::numeric_limits<float>::max();
|
float bestDistance = std::numeric_limits<float>::max();
|
||||||
|
|
||||||
float distanceToSubMesh;
|
float distanceToSubMesh;
|
||||||
BoxFace subMeshFace;
|
BoxFace subMeshFace;
|
||||||
|
glm::vec3 subMeshSurfaceNormal;
|
||||||
int subMeshIndex = 0;
|
int subMeshIndex = 0;
|
||||||
|
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
|
@ -500,9 +503,9 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g
|
||||||
recalculateMeshBoxes(pickAgainstTriangles);
|
recalculateMeshBoxes(pickAgainstTriangles);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(const AABox& subMeshBox, _calculatedMeshBoxes) {
|
foreach (const AABox& subMeshBox, _calculatedMeshBoxes) {
|
||||||
|
|
||||||
if (subMeshBox.findRayIntersection(origin, direction, distanceToSubMesh, subMeshFace)) {
|
if (subMeshBox.findRayIntersection(origin, direction, distanceToSubMesh, subMeshFace, subMeshSurfaceNormal)) {
|
||||||
if (distanceToSubMesh < bestDistance) {
|
if (distanceToSubMesh < bestDistance) {
|
||||||
if (pickAgainstTriangles) {
|
if (pickAgainstTriangles) {
|
||||||
if (!_calculatedMeshTrianglesValid) {
|
if (!_calculatedMeshTrianglesValid) {
|
||||||
|
@ -520,6 +523,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g
|
||||||
bestDistance = thisTriangleDistance;
|
bestDistance = thisTriangleDistance;
|
||||||
intersectedSomething = true;
|
intersectedSomething = true;
|
||||||
face = subMeshFace;
|
face = subMeshFace;
|
||||||
|
surfaceNormal = triangle.getNormal();
|
||||||
extraInfo = geometry.getModelNameOfMesh(subMeshIndex);
|
extraInfo = geometry.getModelNameOfMesh(subMeshIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -529,6 +533,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g
|
||||||
bestDistance = distanceToSubMesh;
|
bestDistance = distanceToSubMesh;
|
||||||
intersectedSomething = true;
|
intersectedSomething = true;
|
||||||
face = subMeshFace;
|
face = subMeshFace;
|
||||||
|
surfaceNormal = subMeshSurfaceNormal;
|
||||||
extraInfo = geometry.getModelNameOfMesh(subMeshIndex);
|
extraInfo = geometry.getModelNameOfMesh(subMeshIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1637,7 +1642,6 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, int shape
|
||||||
// Diffuse
|
// Diffuse
|
||||||
if (materialKey.isDiffuseMap()) {
|
if (materialKey.isDiffuseMap()) {
|
||||||
auto diffuseMap = textureMaps[model::MaterialKey::DIFFUSE_MAP];
|
auto diffuseMap = textureMaps[model::MaterialKey::DIFFUSE_MAP];
|
||||||
|
|
||||||
if (diffuseMap && diffuseMap->isDefined()) {
|
if (diffuseMap && diffuseMap->isDefined()) {
|
||||||
batch.setResourceTexture(DIFFUSE_MAP_SLOT, diffuseMap->getTextureView());
|
batch.setResourceTexture(DIFFUSE_MAP_SLOT, diffuseMap->getTextureView());
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,8 @@ public:
|
||||||
void setJointTranslation(int index, bool valid, const glm::vec3& translation, float priority);
|
void setJointTranslation(int index, bool valid, const glm::vec3& translation, float priority);
|
||||||
|
|
||||||
bool findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
bool findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||||
BoxFace& face, QString& extraInfo, bool pickAgainstTriangles = false);
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
|
QString& extraInfo, bool pickAgainstTriangles = false);
|
||||||
|
|
||||||
// Set the model to use for collisions
|
// Set the model to use for collisions
|
||||||
Q_INVOKABLE void setCollisionModelURL(const QUrl& url);
|
Q_INVOKABLE void setCollisionModelURL(const QUrl& url);
|
||||||
|
@ -347,6 +348,7 @@ private:
|
||||||
int tangent;
|
int tangent;
|
||||||
int alphaThreshold;
|
int alphaThreshold;
|
||||||
int texcoordMatrices;
|
int texcoordMatrices;
|
||||||
|
int diffuseTextureUnit;
|
||||||
int normalTextureUnit;
|
int normalTextureUnit;
|
||||||
int specularTextureUnit;
|
int specularTextureUnit;
|
||||||
int emissiveTextureUnit;
|
int emissiveTextureUnit;
|
||||||
|
|
|
@ -221,7 +221,8 @@ bool AABox::expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& e
|
||||||
isWithin(start.x + axisDistance*direction.x, expandedCorner.x, expandedSize.x));
|
isWithin(start.x + axisDistance*direction.x, expandedCorner.x, expandedSize.x));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const {
|
bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal) const {
|
||||||
// handle the trivial case where the box contains the origin
|
// handle the trivial case where the box contains the origin
|
||||||
if (contains(origin)) {
|
if (contains(origin)) {
|
||||||
// We still want to calculate the distance from the origin to the inside out plane
|
// We still want to calculate the distance from the origin to the inside out plane
|
||||||
|
@ -231,6 +232,7 @@ bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct
|
||||||
isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale.z))) {
|
isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale.z))) {
|
||||||
distance = axisDistance;
|
distance = axisDistance;
|
||||||
face = direction.x > 0 ? MAX_X_FACE : MIN_X_FACE;
|
face = direction.x > 0 ? MAX_X_FACE : MIN_X_FACE;
|
||||||
|
surfaceNormal = glm::vec3(direction.x > 0 ? 1.0f : -1.0f, 0.0f, 0.0f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ((findInsideOutIntersection(origin.y, direction.y, _corner.y, _scale.y, axisDistance) && axisDistance >= 0 &&
|
if ((findInsideOutIntersection(origin.y, direction.y, _corner.y, _scale.y, axisDistance) && axisDistance >= 0 &&
|
||||||
|
@ -238,6 +240,7 @@ bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct
|
||||||
isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale.z))) {
|
isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale.z))) {
|
||||||
distance = axisDistance;
|
distance = axisDistance;
|
||||||
face = direction.y > 0 ? MAX_Y_FACE : MIN_Y_FACE;
|
face = direction.y > 0 ? MAX_Y_FACE : MIN_Y_FACE;
|
||||||
|
surfaceNormal = glm::vec3(0.0f, direction.y > 0 ? 1.0f : -1.0f, 0.0f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ((findInsideOutIntersection(origin.z, direction.z, _corner.z, _scale.z, axisDistance) && axisDistance >= 0 &&
|
if ((findInsideOutIntersection(origin.z, direction.z, _corner.z, _scale.z, axisDistance) && axisDistance >= 0 &&
|
||||||
|
@ -245,6 +248,7 @@ bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct
|
||||||
isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale.x))) {
|
isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale.x))) {
|
||||||
distance = axisDistance;
|
distance = axisDistance;
|
||||||
face = direction.z > 0 ? MAX_Z_FACE : MIN_Z_FACE;
|
face = direction.z > 0 ? MAX_Z_FACE : MIN_Z_FACE;
|
||||||
|
surfaceNormal = glm::vec3(0.0f, 0.0f, direction.z > 0 ? 1.0f : -1.0f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// This case is unexpected, but mimics the previous behavior for inside out intersections
|
// This case is unexpected, but mimics the previous behavior for inside out intersections
|
||||||
|
@ -259,6 +263,7 @@ bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct
|
||||||
isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale.z))) {
|
isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale.z))) {
|
||||||
distance = axisDistance;
|
distance = axisDistance;
|
||||||
face = direction.x > 0 ? MIN_X_FACE : MAX_X_FACE;
|
face = direction.x > 0 ? MIN_X_FACE : MAX_X_FACE;
|
||||||
|
surfaceNormal = glm::vec3(direction.x > 0 ? -1.0f : 1.0f, 0.0f, 0.0f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ((findIntersection(origin.y, direction.y, _corner.y, _scale.y, axisDistance) && axisDistance >= 0 &&
|
if ((findIntersection(origin.y, direction.y, _corner.y, _scale.y, axisDistance) && axisDistance >= 0 &&
|
||||||
|
@ -266,6 +271,7 @@ bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct
|
||||||
isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale.z))) {
|
isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale.z))) {
|
||||||
distance = axisDistance;
|
distance = axisDistance;
|
||||||
face = direction.y > 0 ? MIN_Y_FACE : MAX_Y_FACE;
|
face = direction.y > 0 ? MIN_Y_FACE : MAX_Y_FACE;
|
||||||
|
surfaceNormal = glm::vec3(0.0f, direction.y > 0 ? -1.0f : 1.0f, 0.0f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ((findIntersection(origin.z, direction.z, _corner.z, _scale.z, axisDistance) && axisDistance >= 0 &&
|
if ((findIntersection(origin.z, direction.z, _corner.z, _scale.z, axisDistance) && axisDistance >= 0 &&
|
||||||
|
@ -273,6 +279,7 @@ bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct
|
||||||
isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale.x))) {
|
isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale.x))) {
|
||||||
distance = axisDistance;
|
distance = axisDistance;
|
||||||
face = direction.z > 0 ? MIN_Z_FACE : MAX_Z_FACE;
|
face = direction.z > 0 ? MIN_Z_FACE : MAX_Z_FACE;
|
||||||
|
surfaceNormal = glm::vec3(0.0f, 0.0f, direction.z > 0 ? -1.0f : 1.0f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -67,7 +67,8 @@ public:
|
||||||
|
|
||||||
bool expandedContains(const glm::vec3& point, float expansion) const;
|
bool expandedContains(const glm::vec3& point, float expansion) const;
|
||||||
bool expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& end, float expansion) const;
|
bool expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& end, float expansion) const;
|
||||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
|
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal) const;
|
||||||
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const;
|
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const;
|
||||||
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) const;
|
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) const;
|
||||||
|
|
||||||
|
|
|
@ -219,7 +219,8 @@ bool AACube::expandedIntersectsSegment(const glm::vec3& start, const glm::vec3&
|
||||||
isWithin(start.x + axisDistance*direction.x, expandedCorner.x, expandedSize.x));
|
isWithin(start.x + axisDistance*direction.x, expandedCorner.x, expandedSize.x));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AACube::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const {
|
bool AACube::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal) const {
|
||||||
// handle the trivial case where the box contains the origin
|
// handle the trivial case where the box contains the origin
|
||||||
if (contains(origin)) {
|
if (contains(origin)) {
|
||||||
|
|
||||||
|
@ -230,6 +231,7 @@ bool AACube::findRayIntersection(const glm::vec3& origin, const glm::vec3& direc
|
||||||
isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale))) {
|
isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale))) {
|
||||||
distance = axisDistance;
|
distance = axisDistance;
|
||||||
face = direction.x > 0 ? MAX_X_FACE : MIN_X_FACE;
|
face = direction.x > 0 ? MAX_X_FACE : MIN_X_FACE;
|
||||||
|
surfaceNormal = glm::vec3(direction.x > 0 ? 1.0f : -1.0f, 0.0f, 0.0f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ((findInsideOutIntersection(origin.y, direction.y, _corner.y, _scale, axisDistance) && axisDistance >= 0 &&
|
if ((findInsideOutIntersection(origin.y, direction.y, _corner.y, _scale, axisDistance) && axisDistance >= 0 &&
|
||||||
|
@ -237,6 +239,7 @@ bool AACube::findRayIntersection(const glm::vec3& origin, const glm::vec3& direc
|
||||||
isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale))) {
|
isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale))) {
|
||||||
distance = axisDistance;
|
distance = axisDistance;
|
||||||
face = direction.y > 0 ? MAX_Y_FACE : MIN_Y_FACE;
|
face = direction.y > 0 ? MAX_Y_FACE : MIN_Y_FACE;
|
||||||
|
surfaceNormal = glm::vec3(0.0f, direction.y > 0 ? 1.0f : -1.0f, 0.0f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ((findInsideOutIntersection(origin.z, direction.z, _corner.z, _scale, axisDistance) && axisDistance >= 0 &&
|
if ((findInsideOutIntersection(origin.z, direction.z, _corner.z, _scale, axisDistance) && axisDistance >= 0 &&
|
||||||
|
@ -244,6 +247,7 @@ bool AACube::findRayIntersection(const glm::vec3& origin, const glm::vec3& direc
|
||||||
isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale))) {
|
isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale))) {
|
||||||
distance = axisDistance;
|
distance = axisDistance;
|
||||||
face = direction.z > 0 ? MAX_Z_FACE : MIN_Z_FACE;
|
face = direction.z > 0 ? MAX_Z_FACE : MIN_Z_FACE;
|
||||||
|
surfaceNormal = glm::vec3(0.0f, 0.0f, direction.z > 0 ? 1.0f : -1.0f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// This case is unexpected, but mimics the previous behavior for inside out intersections
|
// This case is unexpected, but mimics the previous behavior for inside out intersections
|
||||||
|
@ -258,6 +262,7 @@ bool AACube::findRayIntersection(const glm::vec3& origin, const glm::vec3& direc
|
||||||
isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale))) {
|
isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale))) {
|
||||||
distance = axisDistance;
|
distance = axisDistance;
|
||||||
face = direction.x > 0 ? MIN_X_FACE : MAX_X_FACE;
|
face = direction.x > 0 ? MIN_X_FACE : MAX_X_FACE;
|
||||||
|
surfaceNormal = glm::vec3(direction.x > 0 ? -1.0f : 1.0f, 0.0f, 0.0f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ((findIntersection(origin.y, direction.y, _corner.y, _scale, axisDistance) && axisDistance >= 0 &&
|
if ((findIntersection(origin.y, direction.y, _corner.y, _scale, axisDistance) && axisDistance >= 0 &&
|
||||||
|
@ -265,6 +270,7 @@ bool AACube::findRayIntersection(const glm::vec3& origin, const glm::vec3& direc
|
||||||
isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale))) {
|
isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale))) {
|
||||||
distance = axisDistance;
|
distance = axisDistance;
|
||||||
face = direction.y > 0 ? MIN_Y_FACE : MAX_Y_FACE;
|
face = direction.y > 0 ? MIN_Y_FACE : MAX_Y_FACE;
|
||||||
|
surfaceNormal = glm::vec3(0.0f, direction.y > 0 ? -1.0f : 1.0f, 0.0f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ((findIntersection(origin.z, direction.z, _corner.z, _scale, axisDistance) && axisDistance >= 0 &&
|
if ((findIntersection(origin.z, direction.z, _corner.z, _scale, axisDistance) && axisDistance >= 0 &&
|
||||||
|
@ -272,6 +278,7 @@ bool AACube::findRayIntersection(const glm::vec3& origin, const glm::vec3& direc
|
||||||
isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale))) {
|
isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale))) {
|
||||||
distance = axisDistance;
|
distance = axisDistance;
|
||||||
face = direction.z > 0 ? MIN_Z_FACE : MAX_Z_FACE;
|
face = direction.z > 0 ? MIN_Z_FACE : MAX_Z_FACE;
|
||||||
|
surfaceNormal = glm::vec3(0.0f, 0.0f, direction.z > 0 ? -1.0f : 1.0f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -56,7 +56,8 @@ public:
|
||||||
bool touches(const AABox& otherBox) const;
|
bool touches(const AABox& otherBox) const;
|
||||||
bool expandedContains(const glm::vec3& point, float expansion) const;
|
bool expandedContains(const glm::vec3& point, float expansion) const;
|
||||||
bool expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& end, float expansion) const;
|
bool expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& end, float expansion) const;
|
||||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
|
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||||
|
BoxFace& face, glm::vec3& surfaceNormal) const;
|
||||||
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const;
|
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const;
|
||||||
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) const;
|
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) const;
|
||||||
|
|
||||||
|
|
|
@ -255,6 +255,13 @@ bool findRayCapsuleIntersection(const glm::vec3& origin, const glm::vec3& direct
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reference https://www.opengl.org/wiki/Calculating_a_Surface_Normal
|
||||||
|
glm::vec3 Triangle::getNormal() const {
|
||||||
|
glm::vec3 edge1 = v1 - v0;
|
||||||
|
glm::vec3 edge2 = v2 - v0;
|
||||||
|
return glm::normalize(glm::cross(edge1, edge2));
|
||||||
|
}
|
||||||
|
|
||||||
bool findRayTriangleIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
bool findRayTriangleIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& distance) {
|
const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& distance) {
|
||||||
glm::vec3 firstSide = v0 - v1;
|
glm::vec3 firstSide = v0 - v1;
|
||||||
|
|
|
@ -97,6 +97,7 @@ public:
|
||||||
glm::vec3 v0;
|
glm::vec3 v0;
|
||||||
glm::vec3 v1;
|
glm::vec3 v1;
|
||||||
glm::vec3 v2;
|
glm::vec3 v2;
|
||||||
|
glm::vec3 getNormal() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool findRayTriangleIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
inline bool findRayTriangleIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
|
|
|
@ -26,8 +26,9 @@ void AABoxCubeTests::raycastOutHitsXMinFace() {
|
||||||
glm::vec3 direction(-1.0f, 0.0f, 0.0f);
|
glm::vec3 direction(-1.0f, 0.0f, 0.0f);
|
||||||
float distance;
|
float distance;
|
||||||
BoxFace face;
|
BoxFace face;
|
||||||
|
glm::vec3 surfaceNormal;
|
||||||
|
|
||||||
bool intersects = box.findRayIntersection(origin, direction, distance, face);
|
bool intersects = box.findRayIntersection(origin, direction, distance, face, surfaceNormal);
|
||||||
|
|
||||||
QCOMPARE(intersects, true);
|
QCOMPARE(intersects, true);
|
||||||
QCOMPARE(distance, 0.5f);
|
QCOMPARE(distance, 0.5f);
|
||||||
|
@ -44,9 +45,10 @@ void AABoxCubeTests::raycastOutHitsXMaxFace () {
|
||||||
glm::vec3 direction(1.0f, 0.0f, 0.0f);
|
glm::vec3 direction(1.0f, 0.0f, 0.0f);
|
||||||
float distance;
|
float distance;
|
||||||
BoxFace face;
|
BoxFace face;
|
||||||
|
glm::vec3 surfaceNormal;
|
||||||
|
|
||||||
|
bool intersects = box.findRayIntersection(origin, direction, distance, face, surfaceNormal);
|
||||||
|
|
||||||
bool intersects = box.findRayIntersection(origin, direction, distance, face);
|
|
||||||
|
|
||||||
QCOMPARE(intersects, true);
|
QCOMPARE(intersects, true);
|
||||||
QCOMPARE(distance, 0.5f);
|
QCOMPARE(distance, 0.5f);
|
||||||
QCOMPARE(face, MAX_X_FACE);
|
QCOMPARE(face, MAX_X_FACE);
|
||||||
|
@ -61,9 +63,10 @@ void AABoxCubeTests::raycastInHitsXMinFace () {
|
||||||
glm::vec3 direction(1.0f, 0.0f, 0.0f);
|
glm::vec3 direction(1.0f, 0.0f, 0.0f);
|
||||||
float distance;
|
float distance;
|
||||||
BoxFace face;
|
BoxFace face;
|
||||||
|
glm::vec3 surfaceNormal;
|
||||||
|
|
||||||
|
bool intersects = box.findRayIntersection(origin, direction, distance, face, surfaceNormal);
|
||||||
|
|
||||||
bool intersects = box.findRayIntersection(origin, direction, distance, face);
|
|
||||||
|
|
||||||
QCOMPARE(intersects, true);
|
QCOMPARE(intersects, true);
|
||||||
QCOMPARE(distance, 0.25f);
|
QCOMPARE(distance, 0.25f);
|
||||||
QCOMPARE(face, MIN_X_FACE);
|
QCOMPARE(face, MIN_X_FACE);
|
||||||
|
|
Loading…
Reference in a new issue