mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 21:29:33 +02:00
fix FPS while still maintaining ray picking
This commit is contained in:
parent
7721f6de96
commit
1beb95cfe7
3 changed files with 42 additions and 29 deletions
|
@ -41,7 +41,11 @@ public:
|
||||||
ReadBitstreamToTreeParams& args,
|
ReadBitstreamToTreeParams& args,
|
||||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
|
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
|
||||||
|
|
||||||
virtual void somethingChangedNotification() { _needsInitialSimulation = true; }
|
virtual void somethingChangedNotification() {
|
||||||
|
// FIX ME: this is overly aggressive. We only really need to simulate() if something about
|
||||||
|
// the world space transform has changed and/or if some animation is occurring.
|
||||||
|
_needsInitialSimulation = true;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool readyToAddToScene(RenderArgs* renderArgs = nullptr);
|
virtual bool readyToAddToScene(RenderArgs* renderArgs = nullptr);
|
||||||
virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
|
virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
|
||||||
|
|
|
@ -83,6 +83,7 @@ Model::Model(QObject* parent) :
|
||||||
_blendNumber(0),
|
_blendNumber(0),
|
||||||
_appliedBlendNumber(0),
|
_appliedBlendNumber(0),
|
||||||
_calculatedMeshPartBoxesValid(false),
|
_calculatedMeshPartBoxesValid(false),
|
||||||
|
_calculatedMeshPartOffetValid(false),
|
||||||
_calculatedMeshBoxesValid(false),
|
_calculatedMeshBoxesValid(false),
|
||||||
_calculatedMeshTrianglesValid(false),
|
_calculatedMeshTrianglesValid(false),
|
||||||
_meshGroupsKnown(false),
|
_meshGroupsKnown(false),
|
||||||
|
@ -544,6 +545,10 @@ 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)) {
|
||||||
|
|
||||||
|
if (!_calculatedMeshBoxesValid) {
|
||||||
|
recalculateMeshBoxes(pickAgainstTriangles);
|
||||||
|
}
|
||||||
|
|
||||||
float bestDistance = std::numeric_limits<float>::max();
|
float bestDistance = std::numeric_limits<float>::max();
|
||||||
|
|
||||||
|
@ -660,6 +665,25 @@ bool Model::convexHullContains(glm::vec3 point) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Model::recalculateMeshPartOffsets() {
|
||||||
|
if (!_calculatedMeshPartOffetValid) {
|
||||||
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
|
int numberOfMeshes = geometry.meshes.size();
|
||||||
|
_calculatedMeshPartOffet.clear();
|
||||||
|
for (int i = 0; i < numberOfMeshes; i++) {
|
||||||
|
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||||
|
qint64 partOffset = 0;
|
||||||
|
for (int j = 0; j < mesh.parts.size(); j++) {
|
||||||
|
const FBXMeshPart& part = mesh.parts.at(j);
|
||||||
|
_calculatedMeshPartOffet[QPair<int,int>(i, j)] = partOffset;
|
||||||
|
partOffset += part.quadIndices.size() * sizeof(int);
|
||||||
|
partOffset += part.triangleIndices.size() * sizeof(int);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_calculatedMeshPartOffetValid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
// TODO: we seem to call this too often when things haven't actually changed... look into optimizing this
|
// TODO: we seem to call this too often when things haven't actually changed... look into optimizing this
|
||||||
// Any script might trigger findRayIntersectionAgainstSubMeshes (and maybe convexHullContains), so these
|
// Any script might trigger findRayIntersectionAgainstSubMeshes (and maybe convexHullContains), so these
|
||||||
// can occur multiple times. In addition, rendering does it's own ray picking in order to decide which
|
// can occur multiple times. In addition, rendering does it's own ray picking in order to decide which
|
||||||
|
@ -676,6 +700,7 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
|
||||||
_calculatedMeshTriangles.resize(numberOfMeshes);
|
_calculatedMeshTriangles.resize(numberOfMeshes);
|
||||||
_calculatedMeshPartBoxes.clear();
|
_calculatedMeshPartBoxes.clear();
|
||||||
_calculatedMeshPartOffet.clear();
|
_calculatedMeshPartOffet.clear();
|
||||||
|
_calculatedMeshPartOffetValid = false;
|
||||||
for (int i = 0; i < numberOfMeshes; i++) {
|
for (int i = 0; i < numberOfMeshes; i++) {
|
||||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||||
Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents);
|
Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents);
|
||||||
|
@ -778,6 +803,7 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
|
||||||
}
|
}
|
||||||
_calculatedMeshTriangles[i] = thisMeshTriangles;
|
_calculatedMeshTriangles[i] = thisMeshTriangles;
|
||||||
_calculatedMeshPartBoxesValid = true;
|
_calculatedMeshPartBoxesValid = true;
|
||||||
|
_calculatedMeshPartOffetValid = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_calculatedMeshBoxesValid = true;
|
_calculatedMeshBoxesValid = true;
|
||||||
|
@ -786,16 +812,6 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::renderSetup(RenderArgs* args) {
|
void Model::renderSetup(RenderArgs* args) {
|
||||||
// if we don't have valid mesh boxes, calculate them now, this only matters in cases
|
|
||||||
// where our caller has passed RenderArgs which will include a view frustum we can cull
|
|
||||||
// against. We cache the results of these calculations so long as the model hasn't been
|
|
||||||
// simulated and the mesh hasn't changed.
|
|
||||||
if (args && !_calculatedMeshBoxesValid) {
|
|
||||||
_mutex.lock();
|
|
||||||
recalculateMeshBoxes();
|
|
||||||
_mutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
// set up dilated textures on first render after load/simulate
|
// set up dilated textures on first render after load/simulate
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
if (_dilatedTextures.isEmpty()) {
|
if (_dilatedTextures.isEmpty()) {
|
||||||
|
@ -1342,18 +1358,15 @@ void Model::snapToRegistrationPoint() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::simulate(float deltaTime, bool fullUpdate) {
|
void Model::simulate(float deltaTime, bool fullUpdate) {
|
||||||
/*
|
|
||||||
qDebug() << "Model::simulate()";
|
|
||||||
qDebug() << " _translation:" << _translation;
|
|
||||||
qDebug() << " _rotation:" << _rotation;
|
|
||||||
*/
|
|
||||||
|
|
||||||
fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit)
|
fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit)
|
||||||
|| (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint);
|
|| (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint);
|
||||||
|
|
||||||
if (isActive() && fullUpdate) {
|
if (isActive() && fullUpdate) {
|
||||||
// NOTE: this seems problematic... need to review
|
// NOTE: This is overly aggressive and we are invalidating the MeshBoxes when in fact they may not be invalid
|
||||||
_calculatedMeshBoxesValid = false; // if we have to simulate, we need to assume our mesh boxes are all invalid
|
// they really only become invalid if something about the transform to world space has changed. This is
|
||||||
|
// not too bad at this point, because it doesn't impact rendering. However it does slow down ray picking
|
||||||
|
// because ray picking needs valid boxes to work
|
||||||
|
_calculatedMeshBoxesValid = false;
|
||||||
_calculatedMeshTrianglesValid = false;
|
_calculatedMeshTrianglesValid = false;
|
||||||
|
|
||||||
// check for scale to fit
|
// check for scale to fit
|
||||||
|
@ -1761,10 +1774,6 @@ void Model::setupBatchTransform(gpu::Batch& batch, RenderArgs* args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
AABox Model::getPartBounds(int meshIndex, int partIndex) {
|
AABox Model::getPartBounds(int meshIndex, int partIndex) {
|
||||||
if (!_calculatedMeshPartBoxesValid || !_calculatedMeshBoxesValid) {
|
|
||||||
recalculateMeshBoxes(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (meshIndex < _meshStates.size()) {
|
if (meshIndex < _meshStates.size()) {
|
||||||
const MeshState& state = _meshStates.at(meshIndex);
|
const MeshState& state = _meshStates.at(meshIndex);
|
||||||
bool isSkinned = state.clusterMatrices.size() > 1;
|
bool isSkinned = state.clusterMatrices.size() > 1;
|
||||||
|
@ -1774,7 +1783,7 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_calculatedMeshPartBoxesValid && _calculatedMeshPartBoxes.contains(QPair<int,int>(meshIndex, partIndex))) {
|
if (_geometry->getFBXGeometry().meshes.size() > meshIndex) {
|
||||||
|
|
||||||
// FIX ME! - This is currently a hack because for some mesh parts our efforts to calculate the bounding
|
// FIX ME! - This is currently a hack because for some mesh parts our efforts to calculate the bounding
|
||||||
// box of the mesh part fails. It seems to create boxes that are not consistent with where the
|
// box of the mesh part fails. It seems to create boxes that are not consistent with where the
|
||||||
|
@ -1795,15 +1804,13 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool translucent) {
|
void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool translucent) {
|
||||||
|
|
||||||
if (!_readyWhenAdded) {
|
if (!_readyWhenAdded) {
|
||||||
return; // bail asap
|
return; // bail asap
|
||||||
}
|
}
|
||||||
|
|
||||||
// we always need these properly calculated before we can render, this will likely already have been done
|
// We need to make sure we have valid offsets calculated before we can render
|
||||||
// since the engine will call our getPartBounds() before rendering us.
|
if (!_calculatedMeshPartOffetValid) {
|
||||||
if (!_calculatedMeshPartBoxesValid || !_calculatedMeshBoxesValid) {
|
recalculateMeshPartOffsets();
|
||||||
recalculateMeshBoxes(true);
|
|
||||||
}
|
}
|
||||||
auto textureCache = DependencyManager::get<TextureCache>();
|
auto textureCache = DependencyManager::get<TextureCache>();
|
||||||
|
|
||||||
|
|
|
@ -370,6 +370,7 @@ private:
|
||||||
|
|
||||||
QHash<QPair<int,int>, AABox> _calculatedMeshPartBoxes; // world coordinate AABoxes for all sub mesh part boxes
|
QHash<QPair<int,int>, AABox> _calculatedMeshPartBoxes; // world coordinate AABoxes for all sub mesh part boxes
|
||||||
QHash<QPair<int,int>, qint64> _calculatedMeshPartOffet;
|
QHash<QPair<int,int>, qint64> _calculatedMeshPartOffet;
|
||||||
|
bool _calculatedMeshPartOffetValid;
|
||||||
|
|
||||||
|
|
||||||
bool _calculatedMeshPartBoxesValid;
|
bool _calculatedMeshPartBoxesValid;
|
||||||
|
@ -381,6 +382,7 @@ private:
|
||||||
QMutex _mutex;
|
QMutex _mutex;
|
||||||
|
|
||||||
void recalculateMeshBoxes(bool pickAgainstTriangles = false);
|
void recalculateMeshBoxes(bool pickAgainstTriangles = false);
|
||||||
|
void recalculateMeshPartOffsets();
|
||||||
|
|
||||||
void segregateMeshGroups(); // used to calculate our list of translucent vs opaque meshes
|
void segregateMeshGroups(); // used to calculate our list of translucent vs opaque meshes
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue