From b6fd3628c8524799c60bfa8a9c2f1405c7ad3bc1 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 4 Dec 2014 12:00:38 -0800 Subject: [PATCH 01/21] first round of hacking on implementing rendering of models for detailed ray picking --- interface/resources/shaders/select.frag | 25 ++ interface/resources/shaders/select.vert | 26 ++ .../entities/RenderableModelEntityItem.cpp | 382 ++++++++++++++++++ .../src/entities/RenderableModelEntityItem.h | 11 + interface/src/renderer/Model.cpp | 20 +- interface/src/renderer/Model.h | 6 +- 6 files changed, 468 insertions(+), 2 deletions(-) create mode 100644 interface/resources/shaders/select.frag create mode 100644 interface/resources/shaders/select.vert diff --git a/interface/resources/shaders/select.frag b/interface/resources/shaders/select.frag new file mode 100644 index 0000000000..a7c5067fbc --- /dev/null +++ b/interface/resources/shaders/select.frag @@ -0,0 +1,25 @@ +#version 120 + +// +// simple.frag +// fragment shader +// +// Created by Andrzej Kapolka on 9/15/14. +// Copyright 2014 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 +// + +// the interpolated normal +varying vec4 normal; + +// the glow intensity +uniform float glowIntensity; + +void main(void) { + // set the diffuse, normal, specular data + gl_FragData[0] = vec4(1.0f, 1.0f, 0.0f, 0.0f); //vec4(gl_Color.rgb, glowIntensity); + gl_FragData[1] = vec4(1.0f, 1.0f, 0.0f, 0.0f); //normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); + gl_FragData[2] = vec4(1.0f, 1.0f, 0.0f, 0.0f); //vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); +} diff --git a/interface/resources/shaders/select.vert b/interface/resources/shaders/select.vert new file mode 100644 index 0000000000..9f76597fd6 --- /dev/null +++ b/interface/resources/shaders/select.vert @@ -0,0 +1,26 @@ +#version 120 + +// +// simple.vert +// vertex shader +// +// Created by Andrzej Kapolka on 9/15/14. +// Copyright 2014 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 +// + +// the interpolated normal +varying vec4 normal; + +void main(void) { + // transform and store the normal for interpolation + normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); + + // pass along the diffuse color + gl_FrontColor = vec4(1.0f, 0.0f, 0.0f, 0.0f); //gl_Color; + + // use standard pipeline transform + gl_Position = ftransform(); +} diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index 10b18ad9c5..11d16c39f8 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -133,6 +133,9 @@ void RenderableModelEntityItem::render(RenderArgs* args) { getModel(renderer); } + + + if (_model) { // handle animations.. if (hasAnimation()) { @@ -257,7 +260,386 @@ EntityItemProperties RenderableModelEntityItem::getProperties() const { return properties; } +bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) const { + + // extents is the entity relative, scaled, centered extents of the entity + glm::mat4 rotation = glm::mat4_cast(getRotation()); + glm::mat4 translation = glm::translate(getPosition()); + glm::mat4 entityToWorldMatrix = translation * rotation; + glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); + + glm::vec3 entityFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); + glm::vec3 entityFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f)); + + float depth = depthOfRayIntersection(entityFrameOrigin, entityFrameDirection); + + return true; // we only got here if we intersected our non-aabox +} +/* +void RenderableModelEntityItem::renderEntityAsBillboard() { + TextureCache* textureCache = Application->getInstance()->getTextureCache(); + textureCache->getPrimaryFramebufferObject()->bind(); + + const int BILLBOARD_SIZE = 64; + renderRearViewMirror(QRect(0, _glWidget->getDeviceHeight() - BILLBOARD_SIZE, BILLBOARD_SIZE, BILLBOARD_SIZE), true); + + //QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); + //glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); + + textureCache->getPrimaryFramebufferObject()->release(); + + return image; +} +*/ + +float RenderableModelEntityItem::depthOfRayIntersection(const glm::vec3& entityFrameOrigin, const glm::vec3& entityFrameDirection) const { + qDebug() << "RenderableModelEntityItem::depthOfRayIntersection()...."; + + Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->bind(); + + glEnable(GL_SCISSOR_TEST); + glEnable(GL_LIGHTING); // enable? + glEnable(GL_DEPTH_TEST); + glDisable(GL_BLEND); // we don't need blending + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + + // * we know the direction that the ray is coming into our bounding box. + // * we know the location on our bounding box that the ray intersected + // * because this API is theoretically called for things that aren't on the screen, + // or could be off in the distance, but with an original ray pick origin ALSO off + // in the distance, we don't really know the "pixel" size of the model at that + // place in space. In fact that concept really doesn't make sense at all... so + // we need to pick our own "scale" based on whatever level of precision makes + // sense... what makes sense? + // * we could say that we allow ray intersections down to some N meters (say 1cm + // or 0.01 meters) in real space. The model's bounds in meters are known. + // + // + float renderGranularity = 0.01f; // 1cm of render granularity - this could be ridiculous for large models + + qDebug() << " renderGranularity:" << renderGranularity; + + // note: these are in tree units, not meters + glm::vec3 dimensions = getDimensions(); + glm::vec3 registrationPoint = getRegistrationPoint(); + glm::vec3 corner = -(dimensions * registrationPoint); + + AABox entityFrameBox(corner, dimensions); + entityFrameBox.scale((float)TREE_SCALE); + + // rotationBetween(v1, v2) -- Helper function return the rotation from the first vector onto the second + //glm::quat viewRotation = rotationBetween(entityFrameDirection, IDENTITY_FRONT); + //glm::quat viewRotation = rotationBetween(IDENTITY_FRONT, entityFrameDirection); + glm::quat viewRotation = rotationBetween(glm::vec3(0.0f, 1.0f, 0.0f), IDENTITY_FRONT); + //glm::quat viewRotation = rotationBetween(IDENTITY_FRONT, IDENTITY_FRONT); + + // I'd like to calculate the tightest bounding box around the entity for + // the direction of the + glm::vec3 minima(FLT_MAX, FLT_MAX, FLT_MAX); + glm::vec3 maxima(-FLT_MAX, -FLT_MAX, -FLT_MAX); + const int VERTEX_COUNT = 8; + for (int j = 0; j < VERTEX_COUNT; j++) { + glm::vec3 vertex = entityFrameBox.getVertex((BoxVertex)j); + qDebug() << " vertex[" << j <<"]:" << vertex; + + glm::vec3 rotated = viewRotation * vertex; + qDebug() << " rotated[" << j <<"]:" << rotated; + + minima = glm::min(minima, rotated); + maxima = glm::max(maxima, rotated); + } + + qDebug() << " minima:" << minima; + qDebug() << " maxima:" << maxima; + + int width = glm::round((maxima.x - minima.x) / renderGranularity); + int height = glm::round((maxima.y - minima.y) / renderGranularity); + + qDebug() << " width:" << width; + qDebug() << " height:" << height; + + glViewport(0, 0, width, height); + glScissor(0, 0, width, height); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glLoadIdentity(); + glOrtho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glm::vec3 axis = glm::axis(viewRotation); + glRotatef(glm::degrees(glm::angle(viewRotation)), axis.x, axis.y, axis.z); + + glm::vec3 entityFrameOriginInMeters = entityFrameOrigin * (float)TREE_SCALE; + glm::vec3 entityFrameDirectionInMeters = entityFrameDirection * (float)TREE_SCALE; + //glTranslatef(entityFrameOriginInMerters.x, entityFrameOriginInMerters.y, entityFrameOriginInMerters.z); + + Application::getInstance()->setupWorldLight(); + Application::getInstance()->updateUntranslatedViewMatrix(); + + + bool renderAsModel = true; + + if (renderAsModel) { + const float alpha = 1.0f; + + glm::vec3 position = getPositionInMeters(); + glm::vec3 center = getCenterInMeters(); + dimensions = getDimensions() * (float)TREE_SCALE; + glm::quat rotation = getRotation(); + + const float MAX_COLOR = 255.0f; + glColor4f(1.0f, 0.0f, 0.0f, 1.0f); + + glPushMatrix(); + { + //glTranslatef(position.x, position.y, position.z); + //glm::vec3 axis = glm::axis(rotation); + //glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); + + + glPushMatrix(); + glm::vec3 positionToCenter = center - position; + //glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); + + //glScalef(dimensions.x, dimensions.y, dimensions.z); + //Application::getInstance()->getDeferredLightingEffect()->renderSolidSphere(0.5f, 15, 15); + + //_model->setRotation(rotation); + //_model->setScaleToFit(true, glm::vec3(1.0f,1.0f,1.0f)); + + //glm::vec3(0.0f,2.0f,0.0f) + _model->setSnapModelToRegistrationPoint(true, glm::vec3(0.5f,0.5f,0.5f)); + _model->setTranslation(glm::vec3(0.0f,0.0f,0.0f)); + _model->simulate(0.0f); + _model->render(alpha, Model::DEFAULT_RENDER_MODE); + + //_model->render(1.0f, Model::DEFAULT_RENDER_MODE); + + //_model->setScaleToFit(true, dimensions); + _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); + _model->setTranslation(position); + _model->simulate(0.0f); + + glPushMatrix(); + glScalef(dimensions.x, dimensions.y, dimensions.z); + Application::getInstance()->getDeferredLightingEffect()->renderWireSphere(0.5f, 15, 15); + glPopMatrix(); + + /* + glBegin(GL_LINES); + + // low-z side - blue + glColor4f(0.0f, 0.0f, 1.0f, 1.0f); + glVertex3f(-0.5f, -0.5f, -0.5f); + glVertex3f(0.5f, -0.5f, -0.5f); + glVertex3f(-0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, -0.5f, -0.5f); + glVertex3f(-0.5f, 0.5f, -0.5f); + glVertex3f(-0.5f, -0.5f, -0.5f); + + // high-z side - cyan + glColor4f(0.0f, 1.0f, 1.0f, 1.0f); + glVertex3f(-0.5f, -0.5f, 0.5f); + glVertex3f( 0.5f, -0.5f, 0.5f); + glVertex3f(-0.5f, 0.5f, 0.5f); + glVertex3f( 0.5f, 0.5f, 0.5f); + glVertex3f( 0.5f, 0.5f, 0.5f); + glVertex3f( 0.5f, -0.5f, 0.5f); + glVertex3f(-0.5f, 0.5f, 0.5f); + glVertex3f(-0.5f, -0.5f, 0.5f); + + // low-x side - yellow + glColor4f(1.0f, 1.0f, 0.0f, 1.0f); + glVertex3f(-0.5f, -0.5f, -0.5f); + glVertex3f(-0.5f, -0.5f, 0.5f); + + glVertex3f(-0.5f, -0.5f, 0.5f); + glVertex3f(-0.5f, 0.5f, 0.5f); + + glVertex3f(-0.5f, 0.5f, 0.5f); + glVertex3f(-0.5f, 0.5f, -0.5f); + + glVertex3f(-0.5f, 0.5f, -0.5f); + glVertex3f(-0.5f, -0.5f, -0.5f); + + // high-x side - red + glColor4f(1.0f, 0.0f, 0.0f, 1.0f); + glVertex3f(0.5f, -0.5f, -0.5f); + glVertex3f(0.5f, -0.5f, 0.5f); + glVertex3f(0.5f, -0.5f, 0.5f); + glVertex3f(0.5f, 0.5f, 0.5f); + glVertex3f(0.5f, 0.5f, 0.5f); + glVertex3f(0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, -0.5f, -0.5f); + // origin and direction - green + float distanceToHit; + BoxFace ignoreFace; + + entityFrameBox.findRayIntersection(entityFrameOriginInMeters, entityFrameDirectionInMeters, distanceToHit, ignoreFace); + glm::vec3 pointOfIntersection = entityFrameOriginInMeters + (entityFrameDirectionInMeters * distanceToHit); + +qDebug() << "distanceToHit: " << distanceToHit; +qDebug() << "pointOfIntersection: " << pointOfIntersection; + + glm::vec3 pointA = pointOfIntersection + (entityFrameDirectionInMeters * -1.0f); + glm::vec3 pointB = pointOfIntersection + (entityFrameDirectionInMeters * 1.0f); +qDebug() << "pointA: " << pointA; +qDebug() << "pointB: " << pointB; + + glColor4f(0.0f, 1.0f, 0.0f, 1.0f); + glVertex3f(pointA.x, pointA.y, pointA.z); + glVertex3f(pointB.x, pointB.y, pointB.z); + + glEnd(); + */ + + + glPopMatrix(); + } + glPopMatrix(); + + + } else { + glm::vec3 position = getPositionInMeters(); + glm::vec3 center = getCenterInMeters(); + dimensions = getDimensions() * (float)TREE_SCALE; + glm::quat rotation = getRotation(); + + glColor4f(1.0f, 0.0f, 1.0f, 1.0f); + glLineWidth(2.0f); + + glPushMatrix(); + { + //glTranslatef(position.x, position.y, position.z); + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); + + + glPushMatrix(); + glm::vec3 positionToCenter = center - position; + glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); + + glScalef(dimensions.x, dimensions.y, dimensions.z); + //Application::getInstance()->getDeferredLightingEffect()->renderWireCube(1.0f); + Application::getInstance()->getDeferredLightingEffect()->renderWireSphere(0.5f, 15, 15); + + glBegin(GL_LINES); + + // low-z side - blue + glColor4f(0.0f, 0.0f, 1.0f, 1.0f); + glVertex3f(-0.5f, -0.5f, -0.5f); + glVertex3f(0.5f, -0.5f, -0.5f); + glVertex3f(-0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, -0.5f, -0.5f); + glVertex3f(-0.5f, 0.5f, -0.5f); + glVertex3f(-0.5f, -0.5f, -0.5f); + + // high-z side - cyan + glColor4f(0.0f, 1.0f, 1.0f, 1.0f); + glVertex3f(-0.5f, -0.5f, 0.5f); + glVertex3f( 0.5f, -0.5f, 0.5f); + glVertex3f(-0.5f, 0.5f, 0.5f); + glVertex3f( 0.5f, 0.5f, 0.5f); + glVertex3f( 0.5f, 0.5f, 0.5f); + glVertex3f( 0.5f, -0.5f, 0.5f); + glVertex3f(-0.5f, 0.5f, 0.5f); + glVertex3f(-0.5f, -0.5f, 0.5f); + + // low-x side - yellow + glColor4f(1.0f, 1.0f, 0.0f, 1.0f); + glVertex3f(-0.5f, -0.5f, -0.5f); + glVertex3f(-0.5f, -0.5f, 0.5f); + + glVertex3f(-0.5f, -0.5f, 0.5f); + glVertex3f(-0.5f, 0.5f, 0.5f); + + glVertex3f(-0.5f, 0.5f, 0.5f); + glVertex3f(-0.5f, 0.5f, -0.5f); + + glVertex3f(-0.5f, 0.5f, -0.5f); + glVertex3f(-0.5f, -0.5f, -0.5f); + + // high-x side - red + glColor4f(1.0f, 0.0f, 0.0f, 1.0f); + glVertex3f(0.5f, -0.5f, -0.5f); + glVertex3f(0.5f, -0.5f, 0.5f); + glVertex3f(0.5f, -0.5f, 0.5f); + glVertex3f(0.5f, 0.5f, 0.5f); + glVertex3f(0.5f, 0.5f, 0.5f); + glVertex3f(0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, 0.5f, -0.5f); + glVertex3f(0.5f, -0.5f, -0.5f); + + + // origin and direction - green + float distanceToHit; + BoxFace ignoreFace; + + entityFrameBox.findRayIntersection(entityFrameOriginInMeters, entityFrameDirectionInMeters, distanceToHit, ignoreFace); + glm::vec3 pointOfIntersection = entityFrameOriginInMeters + (entityFrameDirectionInMeters * distanceToHit); + +qDebug() << "distanceToHit: " << distanceToHit; +qDebug() << "pointOfIntersection: " << pointOfIntersection; + + glm::vec3 pointA = pointOfIntersection + (entityFrameDirectionInMeters * -1.0f); + glm::vec3 pointB = pointOfIntersection + (entityFrameDirectionInMeters * 1.0f); +qDebug() << "pointA: " << pointA; +qDebug() << "pointB: " << pointB; + + glColor4f(0.0f, 1.0f, 0.0f, 1.0f); + glVertex3f(pointA.x, pointA.y, pointA.z); + glVertex3f(pointB.x, pointB.y, pointB.z); + + glEnd(); + + glPopMatrix(); + } + glPopMatrix(); + } + + QImage colorData(width, height, QImage::Format_ARGB32); + QVector depthData(width * height); + + glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, colorData.bits()); + glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, depthData.data()); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glEnable(GL_BLEND); + glDisable(GL_SCISSOR_TEST); + + Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->release(); + + glViewport(0, 0, Application::getInstance()->getGLWidget()->width(), Application::getInstance()->getGLWidget()->height()); + + QImage imageData = colorData.mirrored(false,true); + + bool saved = imageData.save("/Users/zappoman/Development/foo.bmp"); + + qDebug() << " saved:" << saved; + + + return 0.0f; +} + diff --git a/interface/src/entities/RenderableModelEntityItem.h b/interface/src/entities/RenderableModelEntityItem.h index 48c9a26051..09db54d64f 100644 --- a/interface/src/entities/RenderableModelEntityItem.h +++ b/interface/src/entities/RenderableModelEntityItem.h @@ -28,6 +28,9 @@ #include #include +#include +#include + class RenderableModelEntityItem : public ModelEntityItem { public: static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties); @@ -51,6 +54,11 @@ public: virtual void somethingChangedNotification() { _needsInitialSimulation = true; } virtual void render(RenderArgs* args); + virtual bool supportsDetailedRayIntersection() const { return true; } + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) const; + Model* getModel(EntityTreeRenderer* renderer); private: void remapTextures(); @@ -63,6 +71,9 @@ private: QString _currentTextures; QStringList _originalTextures; bool _originalTexturesRead; + + float depthOfRayIntersection(const glm::vec3& entityFrameOrigin, const glm::vec3& entityFrameDirection) const; + }; #endif // hifi_RenderableModelEntityItem_h diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index b2570b7c28..74aa190a26 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -103,6 +103,9 @@ Model::SkinLocations Model::_skinNormalSpecularMapLocations; Model::SkinLocations Model::_skinShadowLocations; Model::SkinLocations Model::_skinTranslucentLocations; +ProgramObject Model::_selectProgram; +Model::Locations Model::_selectLocations; + void Model::setScale(const glm::vec3& scale) { setScaleInternal(scale); // if anyone sets scale manually, then we are no longer scaled to fit @@ -269,7 +272,7 @@ void Model::init() { _program.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model.vert"); _program.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model.frag"); _program.link(); - + initProgram(_program, _locations); _normalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, @@ -387,6 +390,14 @@ void Model::init() { _skinTranslucentProgram.link(); initSkinProgram(_skinTranslucentProgram, _skinTranslucentLocations); + + + // select/ray picking program + _selectProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/select.vert"); + _selectProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/select.frag"); + _selectProgram.link(); + initProgram(_selectProgram, _selectLocations); + } } @@ -2148,6 +2159,13 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f ProgramObject* activeProgram = program; Locations* activeLocations = locations; + // XXXBHG - hack to render yellow + if (mode == SELECT_RENDER_MODE) { + //activeProgram = &_selectProgram; + //activeLocations = &_selectLocations; + // need skin version + } + if (isSkinned) { activeProgram = skinProgram; activeLocations = skinLocations; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index d24e4d9f2e..9fdec3f25b 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -86,7 +86,7 @@ public: void reset(); virtual void simulate(float deltaTime, bool fullUpdate = true); - enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE }; + enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE, SELECT_RENDER_MODE }; bool render(float alpha = 1.0f, RenderMode mode = DEFAULT_RENDER_MODE, RenderArgs* args = NULL); @@ -318,6 +318,8 @@ private: static ProgramObject _skinTranslucentProgram; static ProgramObject _skinShadowProgram; + + static ProgramObject _selectProgram; static int _normalMapTangentLocation; static int _normalSpecularMapTangentLocation; @@ -343,6 +345,8 @@ private: static Locations _lightmapSpecularMapLocations; static Locations _lightmapNormalSpecularMapLocations; + static Locations _selectLocations; + static void initProgram(ProgramObject& program, Locations& locations, int specularTextureUnit = 1); class SkinLocations : public Locations { From 5ec9a9b6eda41117da2002c2f56da4d89693cfcf Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 4 Dec 2014 13:08:16 -0800 Subject: [PATCH 02/21] make text entities correctly ray pick --- libraries/entities/src/TextEntityItem.cpp | 49 ++++++++++++++++++++++- libraries/entities/src/TextEntityItem.h | 5 +++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index 491240c178..17ef33ee1c 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -10,9 +10,12 @@ // +#include + #include #include +#include #include "EntityTree.h" #include "EntityTreeElement.h" @@ -110,4 +113,48 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, appendValue, getLineHeight()); APPEND_ENTITY_PROPERTY(PROP_TEXT_COLOR, appendColor, getTextColor()); APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, appendColor, getBackgroundColor()); -} \ No newline at end of file +} + + +bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) const { + + RayIntersectionInfo rayInfo; + rayInfo._rayStart = origin; + rayInfo._rayDirection = direction; + rayInfo._rayLength = std::numeric_limits::max(); + + PlaneShape plane; + + const glm::vec3 UNROTATED_NORMAL(0.0f, 0.0f, -1.0f); + glm::vec3 normal = _rotation * UNROTATED_NORMAL; + plane.setNormal(normal); + plane.setPoint(_position); // the position is definitely a point on our plane + + bool intersects = plane.findRayIntersection(rayInfo); + + if (intersects) { + glm::vec3 hitAt = origin + (direction * rayInfo._hitDistance); + // now we know the point the ray hit our plane + + glm::mat4 rotation = glm::mat4_cast(getRotation()); + glm::mat4 translation = glm::translate(getPosition()); + glm::mat4 entityToWorldMatrix = translation * rotation; + glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); + + glm::vec3 dimensions = getDimensions(); + glm::vec3 registrationPoint = getRegistrationPoint(); + glm::vec3 corner = -(dimensions * registrationPoint); + AABox entityFrameBox(corner, dimensions); + + glm::vec3 entityFrameHitAt = glm::vec3(worldToEntityMatrix * glm::vec4(hitAt, 1.0f)); + + intersects = entityFrameBox.contains(entityFrameHitAt); + } + + if (intersects) { + distance = rayInfo._hitDistance; + } + return intersects; +} diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 019d230c36..a3d323aefd 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -41,6 +41,11 @@ public: ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData); + virtual bool supportsDetailedRayIntersection() const { return true; } + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) const; + static const QString DEFAULT_TEXT; void setText(const QString& value) { _text = value; } const QString& getText() const { return _text; } From 37ffa48fa3ef45e6f1840f8327ead23e45846c05 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 4 Dec 2014 16:43:12 -0800 Subject: [PATCH 03/21] more work on improved model picking --- .../entities/RenderableModelEntityItem.cpp | 385 +----------------- .../src/entities/RenderableModelEntityItem.h | 3 - interface/src/renderer/Model.cpp | 7 + 3 files changed, 18 insertions(+), 377 deletions(-) diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index 11d16c39f8..ccd6622856 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -263,383 +263,20 @@ EntityItemProperties RenderableModelEntityItem::getProperties() const { bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject) const { - - // extents is the entity relative, scaled, centered extents of the entity - glm::mat4 rotation = glm::mat4_cast(getRotation()); - glm::mat4 translation = glm::translate(getPosition()); - glm::mat4 entityToWorldMatrix = translation * rotation; - glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); - glm::vec3 entityFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); - glm::vec3 entityFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f)); - - float depth = depthOfRayIntersection(entityFrameOrigin, entityFrameDirection); - - return true; // we only got here if we intersected our non-aabox -} - - -/* -void RenderableModelEntityItem::renderEntityAsBillboard() { - TextureCache* textureCache = Application->getInstance()->getTextureCache(); - textureCache->getPrimaryFramebufferObject()->bind(); - - const int BILLBOARD_SIZE = 64; - renderRearViewMirror(QRect(0, _glWidget->getDeviceHeight() - BILLBOARD_SIZE, BILLBOARD_SIZE, BILLBOARD_SIZE), true); - - //QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); - //glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); - - textureCache->getPrimaryFramebufferObject()->release(); - - return image; -} -*/ - -float RenderableModelEntityItem::depthOfRayIntersection(const glm::vec3& entityFrameOrigin, const glm::vec3& entityFrameDirection) const { - qDebug() << "RenderableModelEntityItem::depthOfRayIntersection()...."; + qDebug() << "RenderableModelEntityItem::findDetailedRayIntersection()...."; + qDebug() << " origin:" << origin; + glm::vec3 originInMeters = origin * (float)TREE_SCALE; + qDebug() << " originInMeters:" << originInMeters; + QString extraInfo; + float localDistance; + bool intersectsModel = _model->findRayIntersectionAgainstSubMeshes(originInMeters, direction, localDistance, face, extraInfo); - Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->bind(); - - glEnable(GL_SCISSOR_TEST); - glEnable(GL_LIGHTING); // enable? - glEnable(GL_DEPTH_TEST); - glDisable(GL_BLEND); // we don't need blending - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - - // * we know the direction that the ray is coming into our bounding box. - // * we know the location on our bounding box that the ray intersected - // * because this API is theoretically called for things that aren't on the screen, - // or could be off in the distance, but with an original ray pick origin ALSO off - // in the distance, we don't really know the "pixel" size of the model at that - // place in space. In fact that concept really doesn't make sense at all... so - // we need to pick our own "scale" based on whatever level of precision makes - // sense... what makes sense? - // * we could say that we allow ray intersections down to some N meters (say 1cm - // or 0.01 meters) in real space. The model's bounds in meters are known. - // - // - float renderGranularity = 0.01f; // 1cm of render granularity - this could be ridiculous for large models - - qDebug() << " renderGranularity:" << renderGranularity; - - // note: these are in tree units, not meters - glm::vec3 dimensions = getDimensions(); - glm::vec3 registrationPoint = getRegistrationPoint(); - glm::vec3 corner = -(dimensions * registrationPoint); - - AABox entityFrameBox(corner, dimensions); - entityFrameBox.scale((float)TREE_SCALE); - - // rotationBetween(v1, v2) -- Helper function return the rotation from the first vector onto the second - //glm::quat viewRotation = rotationBetween(entityFrameDirection, IDENTITY_FRONT); - //glm::quat viewRotation = rotationBetween(IDENTITY_FRONT, entityFrameDirection); - glm::quat viewRotation = rotationBetween(glm::vec3(0.0f, 1.0f, 0.0f), IDENTITY_FRONT); - //glm::quat viewRotation = rotationBetween(IDENTITY_FRONT, IDENTITY_FRONT); - - // I'd like to calculate the tightest bounding box around the entity for - // the direction of the - glm::vec3 minima(FLT_MAX, FLT_MAX, FLT_MAX); - glm::vec3 maxima(-FLT_MAX, -FLT_MAX, -FLT_MAX); - const int VERTEX_COUNT = 8; - for (int j = 0; j < VERTEX_COUNT; j++) { - glm::vec3 vertex = entityFrameBox.getVertex((BoxVertex)j); - qDebug() << " vertex[" << j <<"]:" << vertex; - - glm::vec3 rotated = viewRotation * vertex; - qDebug() << " rotated[" << j <<"]:" << rotated; - - minima = glm::min(minima, rotated); - maxima = glm::max(maxima, rotated); + if (intersectsModel) { + distance = localDistance / (float)TREE_SCALE; } - qDebug() << " minima:" << minima; - qDebug() << " maxima:" << maxima; - - int width = glm::round((maxima.x - minima.x) / renderGranularity); - int height = glm::round((maxima.y - minima.y) / renderGranularity); - - qDebug() << " width:" << width; - qDebug() << " height:" << height; - - glViewport(0, 0, width, height); - glScissor(0, 0, width, height); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glLoadIdentity(); - glOrtho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glm::vec3 axis = glm::axis(viewRotation); - glRotatef(glm::degrees(glm::angle(viewRotation)), axis.x, axis.y, axis.z); - - glm::vec3 entityFrameOriginInMeters = entityFrameOrigin * (float)TREE_SCALE; - glm::vec3 entityFrameDirectionInMeters = entityFrameDirection * (float)TREE_SCALE; - //glTranslatef(entityFrameOriginInMerters.x, entityFrameOriginInMerters.y, entityFrameOriginInMerters.z); - - Application::getInstance()->setupWorldLight(); - Application::getInstance()->updateUntranslatedViewMatrix(); - - - bool renderAsModel = true; - - if (renderAsModel) { - const float alpha = 1.0f; - - glm::vec3 position = getPositionInMeters(); - glm::vec3 center = getCenterInMeters(); - dimensions = getDimensions() * (float)TREE_SCALE; - glm::quat rotation = getRotation(); - - const float MAX_COLOR = 255.0f; - glColor4f(1.0f, 0.0f, 0.0f, 1.0f); - - glPushMatrix(); - { - //glTranslatef(position.x, position.y, position.z); - //glm::vec3 axis = glm::axis(rotation); - //glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - - - glPushMatrix(); - glm::vec3 positionToCenter = center - position; - //glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); - - //glScalef(dimensions.x, dimensions.y, dimensions.z); - //Application::getInstance()->getDeferredLightingEffect()->renderSolidSphere(0.5f, 15, 15); - - //_model->setRotation(rotation); - //_model->setScaleToFit(true, glm::vec3(1.0f,1.0f,1.0f)); - - //glm::vec3(0.0f,2.0f,0.0f) - _model->setSnapModelToRegistrationPoint(true, glm::vec3(0.5f,0.5f,0.5f)); - _model->setTranslation(glm::vec3(0.0f,0.0f,0.0f)); - _model->simulate(0.0f); - _model->render(alpha, Model::DEFAULT_RENDER_MODE); - - //_model->render(1.0f, Model::DEFAULT_RENDER_MODE); - - //_model->setScaleToFit(true, dimensions); - _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); - _model->setTranslation(position); - _model->simulate(0.0f); - - glPushMatrix(); - glScalef(dimensions.x, dimensions.y, dimensions.z); - Application::getInstance()->getDeferredLightingEffect()->renderWireSphere(0.5f, 15, 15); - glPopMatrix(); - - /* - glBegin(GL_LINES); - - // low-z side - blue - glColor4f(0.0f, 0.0f, 1.0f, 1.0f); - glVertex3f(-0.5f, -0.5f, -0.5f); - glVertex3f(0.5f, -0.5f, -0.5f); - glVertex3f(-0.5f, 0.5f, -0.5f); - glVertex3f(0.5f, 0.5f, -0.5f); - glVertex3f(0.5f, 0.5f, -0.5f); - glVertex3f(0.5f, -0.5f, -0.5f); - glVertex3f(-0.5f, 0.5f, -0.5f); - glVertex3f(-0.5f, -0.5f, -0.5f); - - // high-z side - cyan - glColor4f(0.0f, 1.0f, 1.0f, 1.0f); - glVertex3f(-0.5f, -0.5f, 0.5f); - glVertex3f( 0.5f, -0.5f, 0.5f); - glVertex3f(-0.5f, 0.5f, 0.5f); - glVertex3f( 0.5f, 0.5f, 0.5f); - glVertex3f( 0.5f, 0.5f, 0.5f); - glVertex3f( 0.5f, -0.5f, 0.5f); - glVertex3f(-0.5f, 0.5f, 0.5f); - glVertex3f(-0.5f, -0.5f, 0.5f); - - // low-x side - yellow - glColor4f(1.0f, 1.0f, 0.0f, 1.0f); - glVertex3f(-0.5f, -0.5f, -0.5f); - glVertex3f(-0.5f, -0.5f, 0.5f); - - glVertex3f(-0.5f, -0.5f, 0.5f); - glVertex3f(-0.5f, 0.5f, 0.5f); - - glVertex3f(-0.5f, 0.5f, 0.5f); - glVertex3f(-0.5f, 0.5f, -0.5f); - - glVertex3f(-0.5f, 0.5f, -0.5f); - glVertex3f(-0.5f, -0.5f, -0.5f); - - // high-x side - red - glColor4f(1.0f, 0.0f, 0.0f, 1.0f); - glVertex3f(0.5f, -0.5f, -0.5f); - glVertex3f(0.5f, -0.5f, 0.5f); - glVertex3f(0.5f, -0.5f, 0.5f); - glVertex3f(0.5f, 0.5f, 0.5f); - glVertex3f(0.5f, 0.5f, 0.5f); - glVertex3f(0.5f, 0.5f, -0.5f); - glVertex3f(0.5f, 0.5f, -0.5f); - glVertex3f(0.5f, -0.5f, -0.5f); - - - // origin and direction - green - float distanceToHit; - BoxFace ignoreFace; - - entityFrameBox.findRayIntersection(entityFrameOriginInMeters, entityFrameDirectionInMeters, distanceToHit, ignoreFace); - glm::vec3 pointOfIntersection = entityFrameOriginInMeters + (entityFrameDirectionInMeters * distanceToHit); - -qDebug() << "distanceToHit: " << distanceToHit; -qDebug() << "pointOfIntersection: " << pointOfIntersection; - - glm::vec3 pointA = pointOfIntersection + (entityFrameDirectionInMeters * -1.0f); - glm::vec3 pointB = pointOfIntersection + (entityFrameDirectionInMeters * 1.0f); -qDebug() << "pointA: " << pointA; -qDebug() << "pointB: " << pointB; - - glColor4f(0.0f, 1.0f, 0.0f, 1.0f); - glVertex3f(pointA.x, pointA.y, pointA.z); - glVertex3f(pointB.x, pointB.y, pointB.z); - - glEnd(); - */ - - - glPopMatrix(); - } - glPopMatrix(); - - - } else { - glm::vec3 position = getPositionInMeters(); - glm::vec3 center = getCenterInMeters(); - dimensions = getDimensions() * (float)TREE_SCALE; - glm::quat rotation = getRotation(); - - glColor4f(1.0f, 0.0f, 1.0f, 1.0f); - glLineWidth(2.0f); - - glPushMatrix(); - { - //glTranslatef(position.x, position.y, position.z); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - - - glPushMatrix(); - glm::vec3 positionToCenter = center - position; - glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); - - glScalef(dimensions.x, dimensions.y, dimensions.z); - //Application::getInstance()->getDeferredLightingEffect()->renderWireCube(1.0f); - Application::getInstance()->getDeferredLightingEffect()->renderWireSphere(0.5f, 15, 15); - - glBegin(GL_LINES); - - // low-z side - blue - glColor4f(0.0f, 0.0f, 1.0f, 1.0f); - glVertex3f(-0.5f, -0.5f, -0.5f); - glVertex3f(0.5f, -0.5f, -0.5f); - glVertex3f(-0.5f, 0.5f, -0.5f); - glVertex3f(0.5f, 0.5f, -0.5f); - glVertex3f(0.5f, 0.5f, -0.5f); - glVertex3f(0.5f, -0.5f, -0.5f); - glVertex3f(-0.5f, 0.5f, -0.5f); - glVertex3f(-0.5f, -0.5f, -0.5f); - - // high-z side - cyan - glColor4f(0.0f, 1.0f, 1.0f, 1.0f); - glVertex3f(-0.5f, -0.5f, 0.5f); - glVertex3f( 0.5f, -0.5f, 0.5f); - glVertex3f(-0.5f, 0.5f, 0.5f); - glVertex3f( 0.5f, 0.5f, 0.5f); - glVertex3f( 0.5f, 0.5f, 0.5f); - glVertex3f( 0.5f, -0.5f, 0.5f); - glVertex3f(-0.5f, 0.5f, 0.5f); - glVertex3f(-0.5f, -0.5f, 0.5f); - - // low-x side - yellow - glColor4f(1.0f, 1.0f, 0.0f, 1.0f); - glVertex3f(-0.5f, -0.5f, -0.5f); - glVertex3f(-0.5f, -0.5f, 0.5f); - - glVertex3f(-0.5f, -0.5f, 0.5f); - glVertex3f(-0.5f, 0.5f, 0.5f); - - glVertex3f(-0.5f, 0.5f, 0.5f); - glVertex3f(-0.5f, 0.5f, -0.5f); - - glVertex3f(-0.5f, 0.5f, -0.5f); - glVertex3f(-0.5f, -0.5f, -0.5f); - - // high-x side - red - glColor4f(1.0f, 0.0f, 0.0f, 1.0f); - glVertex3f(0.5f, -0.5f, -0.5f); - glVertex3f(0.5f, -0.5f, 0.5f); - glVertex3f(0.5f, -0.5f, 0.5f); - glVertex3f(0.5f, 0.5f, 0.5f); - glVertex3f(0.5f, 0.5f, 0.5f); - glVertex3f(0.5f, 0.5f, -0.5f); - glVertex3f(0.5f, 0.5f, -0.5f); - glVertex3f(0.5f, -0.5f, -0.5f); - - - // origin and direction - green - float distanceToHit; - BoxFace ignoreFace; - - entityFrameBox.findRayIntersection(entityFrameOriginInMeters, entityFrameDirectionInMeters, distanceToHit, ignoreFace); - glm::vec3 pointOfIntersection = entityFrameOriginInMeters + (entityFrameDirectionInMeters * distanceToHit); - -qDebug() << "distanceToHit: " << distanceToHit; -qDebug() << "pointOfIntersection: " << pointOfIntersection; - - glm::vec3 pointA = pointOfIntersection + (entityFrameDirectionInMeters * -1.0f); - glm::vec3 pointB = pointOfIntersection + (entityFrameDirectionInMeters * 1.0f); -qDebug() << "pointA: " << pointA; -qDebug() << "pointB: " << pointB; - - glColor4f(0.0f, 1.0f, 0.0f, 1.0f); - glVertex3f(pointA.x, pointA.y, pointA.z); - glVertex3f(pointB.x, pointB.y, pointB.z); - - glEnd(); - - glPopMatrix(); - } - glPopMatrix(); - } - - QImage colorData(width, height, QImage::Format_ARGB32); - QVector depthData(width * height); - - glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, colorData.bits()); - glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, depthData.data()); - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - glEnable(GL_BLEND); - glDisable(GL_SCISSOR_TEST); - - Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->release(); - - glViewport(0, 0, Application::getInstance()->getGLWidget()->width(), Application::getInstance()->getGLWidget()->height()); - - QImage imageData = colorData.mirrored(false,true); - - bool saved = imageData.save("/Users/zappoman/Development/foo.bmp"); - - qDebug() << " saved:" << saved; - - - return 0.0f; + return intersectsModel; // we only got here if we intersected our non-aabox } + diff --git a/interface/src/entities/RenderableModelEntityItem.h b/interface/src/entities/RenderableModelEntityItem.h index 09db54d64f..4c6bb5a046 100644 --- a/interface/src/entities/RenderableModelEntityItem.h +++ b/interface/src/entities/RenderableModelEntityItem.h @@ -71,9 +71,6 @@ private: QString _currentTextures; QStringList _originalTextures; bool _originalTexturesRead; - - float depthOfRayIntersection(const glm::vec3& entityFrameOrigin, const glm::vec3& entityFrameDirection) const; - }; #endif // hifi_RenderableModelEntityItem_h diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 74aa190a26..9941be566a 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -536,6 +536,8 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g return intersectedSomething; } + qDebug() << "Model::findRayIntersectionAgainstSubMeshes()..."; + // extents is the entity relative, scaled, centered extents of the entity glm::vec3 position = _translation; glm::mat4 rotation = glm::mat4_cast(_rotation); @@ -544,11 +546,14 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix); Extents modelExtents = getMeshExtents(); // NOTE: unrotated + qDebug() << " modelExtents:" << modelExtents; glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum; glm::vec3 corner = dimensions * -0.5f; // since we're going to do the ray picking in the model frame of reference AABox overlayFrameBox(corner, dimensions); + qDebug() << " overlayFrameBox:" << overlayFrameBox; + glm::vec3 modelFrameOrigin = glm::vec3(worldToModelMatrix * glm::vec4(origin, 1.0f)); glm::vec3 modelFrameDirection = glm::vec3(worldToModelMatrix * glm::vec4(direction, 0.0f)); @@ -560,11 +565,13 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g float distanceToSubMesh; BoxFace subMeshFace; int subMeshIndex = 0; + // If we hit the models box, then consider the submeshes... foreach(const AABox& subMeshBox, _calculatedMeshBoxes) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); + qDebug() << "subMeshBox[" << subMeshIndex <<"]:" << subMeshBox; if (subMeshBox.findRayIntersection(origin, direction, distanceToSubMesh, subMeshFace)) { if (distanceToSubMesh < bestDistance) { bestDistance = distanceToSubMesh; From f13bf65554c3c8629f5d6cb45e5f72154a48c91b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 4 Dec 2014 16:43:34 -0800 Subject: [PATCH 04/21] more work on improved model picking --- interface/resources/shaders/select.frag | 25 ------------------------ interface/resources/shaders/select.vert | 26 ------------------------- 2 files changed, 51 deletions(-) delete mode 100644 interface/resources/shaders/select.frag delete mode 100644 interface/resources/shaders/select.vert diff --git a/interface/resources/shaders/select.frag b/interface/resources/shaders/select.frag deleted file mode 100644 index a7c5067fbc..0000000000 --- a/interface/resources/shaders/select.frag +++ /dev/null @@ -1,25 +0,0 @@ -#version 120 - -// -// simple.frag -// fragment shader -// -// Created by Andrzej Kapolka on 9/15/14. -// Copyright 2014 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 -// - -// the interpolated normal -varying vec4 normal; - -// the glow intensity -uniform float glowIntensity; - -void main(void) { - // set the diffuse, normal, specular data - gl_FragData[0] = vec4(1.0f, 1.0f, 0.0f, 0.0f); //vec4(gl_Color.rgb, glowIntensity); - gl_FragData[1] = vec4(1.0f, 1.0f, 0.0f, 0.0f); //normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); - gl_FragData[2] = vec4(1.0f, 1.0f, 0.0f, 0.0f); //vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); -} diff --git a/interface/resources/shaders/select.vert b/interface/resources/shaders/select.vert deleted file mode 100644 index 9f76597fd6..0000000000 --- a/interface/resources/shaders/select.vert +++ /dev/null @@ -1,26 +0,0 @@ -#version 120 - -// -// simple.vert -// vertex shader -// -// Created by Andrzej Kapolka on 9/15/14. -// Copyright 2014 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 -// - -// the interpolated normal -varying vec4 normal; - -void main(void) { - // transform and store the normal for interpolation - normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); - - // pass along the diffuse color - gl_FrontColor = vec4(1.0f, 0.0f, 0.0f, 0.0f); //gl_Color; - - // use standard pipeline transform - gl_Position = ftransform(); -} From 6b5fdceb6e2c8dd656123d16dff49752d000e503 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 4 Dec 2014 16:48:04 -0800 Subject: [PATCH 05/21] more work on improved model picking --- .../src/entities/RenderableModelEntityItem.h | 3 --- interface/src/renderer/Model.cpp | 18 ------------------ interface/src/renderer/Model.h | 6 +----- 3 files changed, 1 insertion(+), 26 deletions(-) diff --git a/interface/src/entities/RenderableModelEntityItem.h b/interface/src/entities/RenderableModelEntityItem.h index 4c6bb5a046..9ed85beeaa 100644 --- a/interface/src/entities/RenderableModelEntityItem.h +++ b/interface/src/entities/RenderableModelEntityItem.h @@ -28,9 +28,6 @@ #include #include -#include -#include - class RenderableModelEntityItem : public ModelEntityItem { public: static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 9941be566a..19176c4833 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -103,9 +103,6 @@ Model::SkinLocations Model::_skinNormalSpecularMapLocations; Model::SkinLocations Model::_skinShadowLocations; Model::SkinLocations Model::_skinTranslucentLocations; -ProgramObject Model::_selectProgram; -Model::Locations Model::_selectLocations; - void Model::setScale(const glm::vec3& scale) { setScaleInternal(scale); // if anyone sets scale manually, then we are no longer scaled to fit @@ -390,14 +387,6 @@ void Model::init() { _skinTranslucentProgram.link(); initSkinProgram(_skinTranslucentProgram, _skinTranslucentLocations); - - - // select/ray picking program - _selectProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/select.vert"); - _selectProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/select.frag"); - _selectProgram.link(); - initProgram(_selectProgram, _selectLocations); - } } @@ -2166,13 +2155,6 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f ProgramObject* activeProgram = program; Locations* activeLocations = locations; - // XXXBHG - hack to render yellow - if (mode == SELECT_RENDER_MODE) { - //activeProgram = &_selectProgram; - //activeLocations = &_selectLocations; - // need skin version - } - if (isSkinned) { activeProgram = skinProgram; activeLocations = skinLocations; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 9fdec3f25b..b16cf11b09 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -86,7 +86,7 @@ public: void reset(); virtual void simulate(float deltaTime, bool fullUpdate = true); - enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE, SELECT_RENDER_MODE }; + enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE }; bool render(float alpha = 1.0f, RenderMode mode = DEFAULT_RENDER_MODE, RenderArgs* args = NULL); @@ -319,8 +319,6 @@ private: static ProgramObject _skinShadowProgram; - static ProgramObject _selectProgram; - static int _normalMapTangentLocation; static int _normalSpecularMapTangentLocation; @@ -345,8 +343,6 @@ private: static Locations _lightmapSpecularMapLocations; static Locations _lightmapNormalSpecularMapLocations; - static Locations _selectLocations; - static void initProgram(ProgramObject& program, Locations& locations, int specularTextureUnit = 1); class SkinLocations : public Locations { From a6b86da47af2f75ec013d6e3eaa6d08793629f7c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 5 Dec 2014 11:31:27 -0800 Subject: [PATCH 06/21] basics of triangle picking working for models --- examples/developerMenuItems.js | 1 + interface/src/Menu.h | 1 + .../entities/RenderableModelEntityItem.cpp | 9 +- interface/src/renderer/Model.cpp | 148 +++++++++++++++++- interface/src/renderer/Model.h | 12 +- interface/src/ui/overlays/Base3DOverlay.cpp | 2 +- interface/src/ui/overlays/Base3DOverlay.h | 4 +- .../src/ui/overlays/BillboardOverlay.cpp | 2 +- interface/src/ui/overlays/BillboardOverlay.h | 2 +- interface/src/ui/overlays/Circle3DOverlay.cpp | 2 +- interface/src/ui/overlays/Circle3DOverlay.h | 2 +- interface/src/ui/overlays/ModelOverlay.cpp | 4 +- interface/src/ui/overlays/ModelOverlay.h | 4 +- interface/src/ui/overlays/Planar3DOverlay.cpp | 2 +- interface/src/ui/overlays/Planar3DOverlay.h | 2 +- interface/src/ui/overlays/Volume3DOverlay.cpp | 2 +- interface/src/ui/overlays/Volume3DOverlay.h | 2 +- libraries/entities/src/EntityTreeElement.cpp | 23 ++- libraries/entities/src/EntityTreeElement.h | 2 +- libraries/fbx/src/FBXReader.cpp | 1 + libraries/fbx/src/FBXReader.h | 1 + libraries/octree/src/OctreeElement.cpp | 45 ++++-- libraries/octree/src/OctreeElement.h | 2 +- libraries/shared/src/GeometryUtil.cpp | 46 ++++++ libraries/shared/src/GeometryUtil.h | 16 ++ 25 files changed, 298 insertions(+), 39 deletions(-) diff --git a/examples/developerMenuItems.js b/examples/developerMenuItems.js index 221975c9c8..0d2c4895ea 100644 --- a/examples/developerMenuItems.js +++ b/examples/developerMenuItems.js @@ -24,6 +24,7 @@ function setupMenus() { Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Disable Light Entities", isCheckable: true, isChecked: false }); Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Attempt to Reduce Material Switches", isCheckable: true, isChecked: false }); Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Attempt Render Entities as Scene", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Pick Against Model Triangles", isCheckable: true, isChecked: false }); Menu.addMenu("Developer > Entities > Culling"); Menu.addMenuItem({ menuName: "Developer > Entities > Culling", menuItemName: "Don't Cull Out Of View Mesh Parts", isCheckable: true, isChecked: false }); Menu.addMenuItem({ menuName: "Developer > Entities > Culling", menuItemName: "Don't Cull Too Small Mesh Parts", isCheckable: true, isChecked: false }); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 0d46c4020d..520c83177e 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -432,6 +432,7 @@ namespace MenuOption { const QString OldVoxelCullingMode = "Old Voxel Culling Mode"; const QString Pair = "Pair"; const QString PasteToVoxel = "Paste to Voxel..."; + const QString PickAgainstModelTriangles = "Pick Against Model Triangles"; const QString PipelineWarnings = "Log Render Pipeline Warnings"; const QString Preferences = "Preferences..."; const QString Quit = "Quit"; diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index ccd6622856..6bc6f52782 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -133,9 +133,6 @@ void RenderableModelEntityItem::render(RenderArgs* args) { getModel(renderer); } - - - if (_model) { // handle animations.. if (hasAnimation()) { @@ -175,7 +172,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { // TODO: this is the majority of model render time. And rendering of a cube model vs the basic Box render // is significantly more expensive. Is there a way to call this that doesn't cost us as much? PerformanceTimer perfTimer("model->render"); - bool dontRenderAsScene = Menu::getInstance()->isOptionChecked(MenuOption::DontRenderEntitiesAsScene); + bool dontRenderAsScene = true; // Menu::getInstance()->isOptionChecked(MenuOption::DontRenderEntitiesAsScene); if (dontRenderAsScene) { _model->render(alpha, modelRenderMode, args); } else { @@ -270,10 +267,14 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori qDebug() << " originInMeters:" << originInMeters; QString extraInfo; float localDistance; + bool intersectsModel = _model->findRayIntersectionAgainstSubMeshes(originInMeters, direction, localDistance, face, extraInfo); if (intersectsModel) { + // NOTE: findRayIntersectionAgainstSubMeshes() does work in meters, but we're expected to return + // results in tree scale. distance = localDistance / (float)TREE_SCALE; + qDebug() << " --hit this mode -- returning distance:" << distance; } return intersectsModel; // we only got here if we intersected our non-aabox diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 19176c4833..6b398284a3 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -54,6 +54,7 @@ Model::Model(QObject* parent) : _blendNumber(0), _appliedBlendNumber(0), _calculatedMeshBoxesValid(false), + _calculatedMeshTrianglesValid(false), _meshGroupsKnown(false) { // we may have been created in the network thread, but we live in the main thread @@ -516,7 +517,7 @@ void Model::setJointStates(QVector states) { } bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, QString& extraInfo) const { + float& distance, BoxFace& face, QString& extraInfo) { bool intersectedSomething = false; @@ -524,8 +525,12 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g if (!isActive()) { return intersectedSomething; } + + bool pickAgainstTriangles = Menu::getInstance()->isOptionChecked(MenuOption::PickAgainstModelTriangles); qDebug() << "Model::findRayIntersectionAgainstSubMeshes()..."; + qDebug() << " origin:" << origin; + qDebug() << " direction:" << direction; // extents is the entity relative, scaled, centered extents of the entity glm::vec3 position = _translation; @@ -538,31 +543,58 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g qDebug() << " modelExtents:" << modelExtents; glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum; - glm::vec3 corner = dimensions * -0.5f; // since we're going to do the ray picking in the model frame of reference + glm::vec3 corner = dimensions * _registrationPoint; // since we're going to do the ray picking in the model frame of reference AABox overlayFrameBox(corner, dimensions); qDebug() << " overlayFrameBox:" << overlayFrameBox; glm::vec3 modelFrameOrigin = glm::vec3(worldToModelMatrix * glm::vec4(origin, 1.0f)); glm::vec3 modelFrameDirection = glm::vec3(worldToModelMatrix * glm::vec4(direction, 0.0f)); + qDebug() << " modelFrameOrigin:" << modelFrameOrigin; + qDebug() << " modelFrameDirection:" << modelFrameDirection; // we can use the AABox's ray intersection by mapping our origin and direction into the model frame // and testing intersection there. if (overlayFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face)) { float bestDistance = std::numeric_limits::max(); + float bestTriangleDistance = std::numeric_limits::max(); + bool someTriangleHit = false; + float distanceToSubMesh; BoxFace subMeshFace; int subMeshIndex = 0; - + + const FBXGeometry& geometry = _geometry->getFBXGeometry(); // If we hit the models box, then consider the submeshes... foreach(const AABox& subMeshBox, _calculatedMeshBoxes) { - const FBXGeometry& geometry = _geometry->getFBXGeometry(); qDebug() << "subMeshBox[" << subMeshIndex <<"]:" << subMeshBox; if (subMeshBox.findRayIntersection(origin, direction, distanceToSubMesh, subMeshFace)) { if (distanceToSubMesh < bestDistance) { + + if (pickAgainstTriangles) { + if (!_calculatedMeshTrianglesValid) { + recalcuateMeshBoxes(); + } + // check our triangles here.... + const QVector& meshTriangles = _calculatedMeshTriangles[subMeshIndex]; + int t = 0; + foreach (const Triangle& triangle, meshTriangles) { + //qDebug() << "triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2; + t++; + + float thisTriangleDistance; + if (findRayTrianlgeIntersection(origin, direction, triangle, thisTriangleDistance)) { + if (thisTriangleDistance < bestTriangleDistance) { + bestTriangleDistance = thisTriangleDistance; + someTriangleHit = true; + } + } + } + } + bestDistance = distanceToSubMesh; intersectedSomething = true; face = subMeshFace; @@ -571,6 +603,27 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g } subMeshIndex++; } + + // if we were asked to pick against triangles, and we didn't hit one, then we + // do not consider this model to be hit at all. + if (pickAgainstTriangles && !someTriangleHit) { + intersectedSomething = false; + } + qDebug() << "pickAgainstTriangles:" << pickAgainstTriangles; + qDebug() << "someTriangleHit:" << someTriangleHit; + qDebug() << "bestTriangleDistance:" << bestTriangleDistance; + qDebug() << "bestDistance:" << bestDistance; + + if (intersectedSomething) { + qDebug() << " --- we hit this model --- "; + + if (pickAgainstTriangles) { + distance = bestTriangleDistance; + } else { + distance = bestDistance; + } + qDebug() << "distance:" << distance; + } return intersectedSomething; } @@ -579,17 +632,92 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g } void Model::recalcuateMeshBoxes() { - if (!_calculatedMeshBoxesValid) { + bool pickAgainstTriangles = Menu::getInstance()->isOptionChecked(MenuOption::PickAgainstModelTriangles); + bool calculatedMeshTrianglesNeeded = pickAgainstTriangles && !_calculatedMeshTrianglesValid; + + if (!_calculatedMeshBoxesValid || calculatedMeshTrianglesNeeded) { + qDebug() << "Model::recalcuateMeshBoxes()"; PerformanceTimer perfTimer("calculatedMeshBoxes"); const FBXGeometry& geometry = _geometry->getFBXGeometry(); int numberOfMeshes = geometry.meshes.size(); _calculatedMeshBoxes.resize(numberOfMeshes); + _calculatedMeshTriangles.clear(); for (int i = 0; i < numberOfMeshes; i++) { const FBXMesh& mesh = geometry.meshes.at(i); Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents); + + qDebug() << "mesh.meshExtents["< thisMeshTriangles; + for (int j = 0; j < mesh.parts.size(); j++) { + const FBXMeshPart& part = mesh.parts.at(j); + + const int INDICES_PER_TRIANGLE = 3; + const int INDICES_PER_QUAD = 4; + + if (part.quadIndices.size() > 0) { + int numberOfQuads = part.quadIndices.size() / INDICES_PER_QUAD; + qDebug() << "numberOfQuads:" << numberOfQuads; + int vIndex = 0; + for (int q = 0; q < numberOfQuads; q++) { + int i0 = part.quadIndices[vIndex++]; + int i1 = part.quadIndices[vIndex++]; + int i2 = part.quadIndices[vIndex++]; + int i3 = part.quadIndices[vIndex++]; + + glm::vec3 v0 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i0], 1.0f))); + glm::vec3 v1 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i1], 1.0f))); + glm::vec3 v2 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i2], 1.0f))); + glm::vec3 v3 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i3], 1.0f))); + + Triangle tri1 = { v0, v1, v3 }; + Triangle tri2 = { v1, v2, v3 }; + + //qDebug() << "quad["<< q <<"].t1 :" << v0 << ", "<< v1 << ", " << v3; + //qDebug() << "quad["<< q <<"].t2 :" << v1 << ", "<< v2 << ", " << v3; + + thisMeshTriangles.push_back(tri1); + thisMeshTriangles.push_back(tri2); + } + } + + if (part.triangleIndices.size() > 0) { + int numberOfTris = part.triangleIndices.size() / INDICES_PER_TRIANGLE; + qDebug() << "numberOfTris:" << numberOfTris; + int vIndex = 0; + for (int t = 0; t < numberOfTris; t++) { + int i0 = part.triangleIndices[vIndex++]; + int i1 = part.triangleIndices[vIndex++]; + int i2 = part.triangleIndices[vIndex++]; + + glm::vec3 v0 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i0], 1.0f))); + glm::vec3 v1 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i1], 1.0f))); + glm::vec3 v2 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i2], 1.0f))); + + Triangle tri = { v0, v1, v2 }; + + //qDebug() << "triangle["<< t <<"] :" << v0 << ", " << v1 << ", " << v2; + + thisMeshTriangles.push_back(tri); + } + } + } + + _calculatedMeshTriangles.push_back(thisMeshTriangles); + qDebug() << "------------------------------------------------------------------------------"; + } + } _calculatedMeshBoxesValid = true; + _calculatedMeshTrianglesValid = pickAgainstTriangles; } } @@ -851,6 +979,15 @@ Extents Model::calculateScaledOffsetExtents(const Extents& extents) const { return translatedExtents; } +glm::vec3 Model::calculateScaledOffsetPoint(const glm::vec3& point) const { + // we need to include any fst scaling, translation, and rotation, which is captured in the offset matrix + glm::vec3 offsetPoint = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(point, 1.0f)); + glm::vec3 scaledPoint = ((offsetPoint + _offset) * _scale); + glm::vec3 rotatedPoint = _rotation * scaledPoint; + glm::vec3 translatedPoint = rotatedPoint + _translation; + return translatedPoint; +} + bool Model::getJointState(int index, glm::quat& rotation) const { if (index == -1 || index >= _jointStates.size()) { @@ -1149,6 +1286,7 @@ void Model::simulate(float deltaTime, bool fullUpdate) { if (isActive() && fullUpdate) { _calculatedMeshBoxesValid = false; // if we have to simulate, we need to assume our mesh boxes are all invalid + _calculatedMeshTrianglesValid = false; // check for scale to fit if (_scaleToFit && !_scaledToFit) { diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index b16cf11b09..406622e6a8 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -19,6 +19,7 @@ #include "Transform.h" #include #include +#include #include #include "AnimationHandle.h" @@ -34,7 +35,6 @@ class Shape; #include "RenderArgs.h" class ViewFrustum; - #include "gpu/Stream.h" #include "gpu/Batch.h" @@ -119,6 +119,9 @@ public: /// Returns the scaled equivalent of some extents in model space. Extents calculateScaledOffsetExtents(const Extents& extents) const; + /// Returns the scaled equivalent of a point in model space. + glm::vec3 calculateScaledOffsetPoint(const glm::vec3& point) const; + /// Returns a reference to the shared geometry. const QSharedPointer& getGeometry() const { return _geometry; } @@ -194,7 +197,7 @@ public: { _geometry->setTextureWithNameToURL(name, url); } bool findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, QString& extraInfo) const; + float& distance, BoxFace& face, QString& extraInfo); protected: QSharedPointer _geometry; @@ -361,8 +364,11 @@ private: static void initSkinProgram(ProgramObject& program, SkinLocations& locations, int specularTextureUnit = 1); - QVector _calculatedMeshBoxes; + QVector _calculatedMeshBoxes; // world coordinate AABoxes for all sub mesh boxes bool _calculatedMeshBoxesValid; + + QVector< QVector > _calculatedMeshTriangles; // world coordinate triangles for all sub meshes + bool _calculatedMeshTrianglesValid; void recalcuateMeshBoxes(); diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 55b4c88812..a9588cd7a3 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -167,7 +167,7 @@ QScriptValue Base3DOverlay::getProperty(const QString& property) { } bool Base3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face) const { + float& distance, BoxFace& face) { return false; } diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index d57f9731c4..b5314bd6d3 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -50,10 +50,10 @@ public: virtual void setProperties(const QScriptValue& properties); virtual QScriptValue getProperty(const QString& property); - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; + virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face); virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, QString& extraInfo) const { + float& distance, BoxFace& face, QString& extraInfo) { return findRayIntersection(origin, direction, distance, face); } diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index 5fbad7839a..f9ad7fdb38 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -213,7 +213,7 @@ void BillboardOverlay::replyFinished() { } bool BillboardOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face) const { + float& distance, BoxFace& face) { if (_billboardTexture) { float maxSize = glm::max(_fromImage.width(), _fromImage.height()); diff --git a/interface/src/ui/overlays/BillboardOverlay.h b/interface/src/ui/overlays/BillboardOverlay.h index be947acf98..03daef934d 100644 --- a/interface/src/ui/overlays/BillboardOverlay.h +++ b/interface/src/ui/overlays/BillboardOverlay.h @@ -35,7 +35,7 @@ public: void setClipFromSource(const QRect& bounds) { _fromImage = bounds; } virtual QScriptValue getProperty(const QString& property); - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; + virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face); virtual BillboardOverlay* createClone() const; diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index d19297b589..68d589d20b 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -355,7 +355,7 @@ QScriptValue Circle3DOverlay::getProperty(const QString& property) { bool Circle3DOverlay::findRayIntersection(const glm::vec3& origin, - const glm::vec3& direction, float& distance, BoxFace& face) const { + const glm::vec3& direction, float& distance, BoxFace& face) { bool intersects = Planar3DOverlay::findRayIntersection(origin, direction, distance, face); if (intersects) { diff --git a/interface/src/ui/overlays/Circle3DOverlay.h b/interface/src/ui/overlays/Circle3DOverlay.h index b428be7a43..92fdf54c82 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.h +++ b/interface/src/ui/overlays/Circle3DOverlay.h @@ -48,7 +48,7 @@ public: void setMajorTickMarksColor(const xColor& value) { _majorTickMarksColor = value; } void setMinorTickMarksColor(const xColor& value) { _minorTickMarksColor = value; } - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; + virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face); virtual Circle3DOverlay* createClone() const; diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 60049e0b3b..ecce137f4d 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -170,14 +170,14 @@ QScriptValue ModelOverlay::getProperty(const QString& property) { } bool ModelOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face) const { + float& distance, BoxFace& face) { QString subMeshNameTemp; return _model.findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, subMeshNameTemp); } bool ModelOverlay::findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, QString& extraInfo) const { + float& distance, BoxFace& face, QString& extraInfo) { return _model.findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, extraInfo); } diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h index 80b52ea27e..567498feb5 100644 --- a/interface/src/ui/overlays/ModelOverlay.h +++ b/interface/src/ui/overlays/ModelOverlay.h @@ -26,9 +26,9 @@ public: virtual void render(RenderArgs* args); virtual void setProperties(const QScriptValue& properties); virtual QScriptValue getProperty(const QString& property); - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; + virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face); virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, QString& extraInfo) const; + float& distance, BoxFace& face, QString& extraInfo); virtual ModelOverlay* createClone() const; diff --git a/interface/src/ui/overlays/Planar3DOverlay.cpp b/interface/src/ui/overlays/Planar3DOverlay.cpp index a8288b241c..628ff6a7dc 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.cpp +++ b/interface/src/ui/overlays/Planar3DOverlay.cpp @@ -92,7 +92,7 @@ QScriptValue Planar3DOverlay::getProperty(const QString& property) { } bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face) const { + float& distance, BoxFace& face) { RayIntersectionInfo rayInfo; rayInfo._rayStart = origin; diff --git a/interface/src/ui/overlays/Planar3DOverlay.h b/interface/src/ui/overlays/Planar3DOverlay.h index d34fe44ebc..9355265f80 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.h +++ b/interface/src/ui/overlays/Planar3DOverlay.h @@ -39,7 +39,7 @@ public: virtual void setProperties(const QScriptValue& properties); virtual QScriptValue getProperty(const QString& property); - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; + virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face); protected: glm::vec2 _dimensions; diff --git a/interface/src/ui/overlays/Volume3DOverlay.cpp b/interface/src/ui/overlays/Volume3DOverlay.cpp index c4192a15b2..40fea5c8c9 100644 --- a/interface/src/ui/overlays/Volume3DOverlay.cpp +++ b/interface/src/ui/overlays/Volume3DOverlay.cpp @@ -100,7 +100,7 @@ QScriptValue Volume3DOverlay::getProperty(const QString& property) { } bool Volume3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face) const { + float& distance, BoxFace& face) { // extents is the entity relative, scaled, centered extents of the entity glm::vec3 position = getPosition(); diff --git a/interface/src/ui/overlays/Volume3DOverlay.h b/interface/src/ui/overlays/Volume3DOverlay.h index 005646c036..7938641a8f 100644 --- a/interface/src/ui/overlays/Volume3DOverlay.h +++ b/interface/src/ui/overlays/Volume3DOverlay.h @@ -41,7 +41,7 @@ public: virtual void setProperties(const QScriptValue& properties); virtual QScriptValue getProperty(const QString& property); - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; + virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face); protected: glm::vec3 _dimensions; diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index e18f79276e..e0ebe47412 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -475,7 +475,7 @@ bool EntityTreeElement::bestFitBounds(const glm::vec3& minPoint, const glm::vec3 bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) { + void** intersectedObject, float distanceToElementCube) { // only called if we do intersect our bounding cube, but find if we actually intersect with entities... @@ -509,15 +509,32 @@ 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 // and testing intersection there. + qDebug() << "EntityTreeElement::findDetailedRayIntersection()...."; + qDebug() << " origin:" << origin; + qDebug() << " checking entity:" << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); + qDebug() << " distance:" << distance; + if (entityFrameBox.findRayIntersection(entityFrameOrigin, entityFrameDirection, localDistance, localFace)) { + qDebug() << " localDistance:" << localDistance; + if (localDistance < distance) { + qDebug() << " localDistance < distance... continue..."; + // now ask the entity if we actually intersect if (entity->supportsDetailedRayIntersection()) { + + qDebug() << " entity->supportsDetailedRayIntersection()...."; if (entity->findDetailedRayIntersection(origin, direction, keepSearching, element, localDistance, localFace, intersectedObject)) { + + qDebug() << " localDistance (detailed):" << localDistance; if (localDistance < distance) { + + qDebug() << " localDistance < distance..."; + qDebug() << " CHOOSING THIS ONE ---> " << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); + distance = localDistance; face = localFace; *intersectedObject = (void*)entity; @@ -527,6 +544,10 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con } else { // if the entity type doesn't support a detailed intersection, then just return the non-AABox results if (localDistance < distance) { + + qDebug() << " localDistance < distance..."; + qDebug() << " CHOOSING THIS ONE ---> " << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); + distance = localDistance; face = localFace; *intersectedObject = (void*)entity; diff --git a/libraries/entities/src/EntityTreeElement.h b/libraries/entities/src/EntityTreeElement.h index ab3754749b..e59b35189f 100644 --- a/libraries/entities/src/EntityTreeElement.h +++ b/libraries/entities/src/EntityTreeElement.h @@ -137,7 +137,7 @@ public: virtual bool canRayIntersect() const { return hasEntities(); } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject); + void** intersectedObject, float distanceToElementCube); virtual bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject) const; diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 8126463d27..d52d342d78 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -2044,6 +2044,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, extracted.mesh.meshExtents.minimum = glm::min(extracted.mesh.meshExtents.minimum, transformedVertex); extracted.mesh.meshExtents.maximum = glm::max(extracted.mesh.meshExtents.maximum, transformedVertex); + extracted.mesh.modelTransform = modelTransform; } // look for textures, material properties diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index c34a9677a6..659893c128 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -149,6 +149,7 @@ public: QVector clusters; Extents meshExtents; + glm::mat4 modelTransform; bool isEye; diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index e5db8b24f8..e085298c33 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -1339,28 +1339,54 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 keepSearching = true; // assume that we will continue searching after this. AACube cube = getAACube(); - float localDistance; + float distanceToElementCube = std::numeric_limits::max(); + float distanceToElementDetails = distance; BoxFace localFace; + qDebug() << "OctreeElement::findRayIntersection()...."; + qDebug() << " origin:" << origin; + qDebug() << " checking element:" << cube; + qDebug() << " distance:" << distance; + // if the ray doesn't intersect with our cube, we can stop searching! - if (!cube.findRayIntersection(origin, direction, localDistance, localFace)) { + if (!cube.findRayIntersection(origin, direction, distanceToElementCube, localFace)) { + qDebug() << " didn't intersect cube... done searching..."; keepSearching = false; // no point in continuing to search return false; // we did not intersect } + qDebug() << " distanceToElementCube:" << distanceToElementCube; + // by default, we only allow intersections with leaves with content if (!canRayIntersect()) { return false; // we don't intersect with non-leaves, and we keep searching } // we did hit this element, so calculate appropriate distances - localDistance *= TREE_SCALE; - if (localDistance < distance) { + //localDistance *= TREE_SCALE; + + // if the distance to the element cube is not less than the current best distance, then it's not possible + // for any details inside the cube to be closer so we don't need to consider them. + if (distanceToElementCube < distance) { + + qDebug() << " distanceToElementCube < distance:" << (distanceToElementCube < distance); + qDebug() << " continue.... call... findDetailedRayIntersection()..."; + //qDebug() << " distanceToElementCube < distance -- continue.... call... findDetailedRayIntersection()..."; + if (findDetailedRayIntersection(origin, direction, keepSearching, - element, distance, face, intersectedObject)) { - distance = localDistance; - face = localFace; - return true; + element, distanceToElementDetails, face, intersectedObject, distanceToElementCube)) { + + qDebug() << " findDetailedRayIntersection() -- intersected something"; + if (distanceToElementDetails < distance) { + qDebug() << " distanceToElementDetails < distance -- THIS ONE IS GOOD -------"; + + distance = distanceToElementDetails; + face = localFace; + + qDebug() << " distance:" << distance << " -- THIS ONE IS GOOD -------"; + + return true; + } } } return false; @@ -1368,11 +1394,12 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 bool OctreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) { + void** intersectedObject, float distanceToElementCube) { // we did hit this element, so calculate appropriate distances if (hasContent()) { element = this; + distance = distanceToElementCube; if (intersectedObject) { *intersectedObject = this; } diff --git a/libraries/octree/src/OctreeElement.h b/libraries/octree/src/OctreeElement.h index 2bd5e3ae1e..9161a9b171 100644 --- a/libraries/octree/src/OctreeElement.h +++ b/libraries/octree/src/OctreeElement.h @@ -123,7 +123,7 @@ public: virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject); + void** intersectedObject, float distanceToElementCube); virtual bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject) const; diff --git a/libraries/shared/src/GeometryUtil.cpp b/libraries/shared/src/GeometryUtil.cpp index 1b6472a18f..c064630f83 100644 --- a/libraries/shared/src/GeometryUtil.cpp +++ b/libraries/shared/src/GeometryUtil.cpp @@ -252,6 +252,52 @@ bool findRayCapsuleIntersection(const glm::vec3& origin, const glm::vec3& direct return true; } +bool findRayTrianlgeIntersection(const glm::vec3& origin, const glm::vec3& direction, + const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& distance) { + + glm::vec3 e1, e2, h, s, q; + float a, f, u, v, t; + + e1 = v1 - v0; + e2 = v2 - v0; + + h = glm::cross(direction, e2); + a = glm::dot(e1, h); + + if (a > -0.00001 && a < 0.00001) { + return false; + } + + f = 1/a; + s = origin - v0; + u = f * glm::dot(s,h); + + if (u < 0.0 || u > 1.0) { + return false; + } + + q = glm::cross(s, e1); + v = f * glm::dot(direction, q); + + if (v < 0.0 || u + v > 1.0) { + return false; + } + + // at this stage we can compute t to find out where the intersection point is on the line + t = f * glm::dot(e2,q); + + // ray intersection + if (t > 0.00001) { + distance = t; + return true; + } else { + // this means that there is a line intersection but not a ray intersection + return false; + } + return false; +} + + // Do line segments (r1p1.x, r1p1.y)--(r1p2.x, r1p2.y) and (r2p1.x, r2p1.y)--(r2p2.x, r2p2.y) intersect? // from: http://ptspts.blogspot.com/2010/06/how-to-determine-if-two-line-segments.html bool doLineSegmentsIntersect(glm::vec2 r1p1, glm::vec2 r1p2, glm::vec2 r2p1, glm::vec2 r2p2) { diff --git a/libraries/shared/src/GeometryUtil.h b/libraries/shared/src/GeometryUtil.h index b521a79771..f439352ca8 100644 --- a/libraries/shared/src/GeometryUtil.h +++ b/libraries/shared/src/GeometryUtil.h @@ -76,6 +76,22 @@ bool findRaySphereIntersection(const glm::vec3& origin, const glm::vec3& directi bool findRayCapsuleIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& start, const glm::vec3& end, float radius, float& distance); +bool findRayTrianlgeIntersection(const glm::vec3& origin, const glm::vec3& direction, + const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& distance); + +class Triangle { +public: + glm::vec3 v0; + glm::vec3 v1; + glm::vec3 v2; +}; + +inline bool findRayTrianlgeIntersection(const glm::vec3& origin, const glm::vec3& direction, + const Triangle& triangle, float& distance) { + return findRayTrianlgeIntersection(origin, direction, triangle.v0, triangle.v1, triangle.v2, distance); +} + + bool doLineSegmentsIntersect(glm::vec2 r1p1, glm::vec2 r1p2, glm::vec2 r2p1, glm::vec2 r2p2); bool isOnSegment(float xi, float yi, float xj, float yj, float xk, float yk); int computeDirection(float xi, float yi, float xj, float yj, float xk, float yk); From 0ccbb98bdee1985567b24a39c38fc0cd05368890 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 5 Dec 2014 15:03:35 -0800 Subject: [PATCH 07/21] more work on improved model picking --- libraries/entities/src/EntityTreeElement.cpp | 26 +++++++++++++++++--- libraries/octree/src/OctreeElement.cpp | 10 ++++++-- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index e0ebe47412..c452dab5cb 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -478,10 +478,19 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con void** intersectedObject, float distanceToElementCube) { // only called if we do intersect our bounding cube, but find if we actually intersect with entities... + + qDebug() << "EntityTreeElement::findDetailedRayIntersection()...."; + qDebug() << " origin:" << origin; + qDebug() << " distance:" << distance; + qDebug() << " number of entities:" << _entityItems->size(); + int entityNumber = 0; QList::iterator entityItr = _entityItems->begin(); QList::const_iterator entityEnd = _entityItems->end(); bool somethingIntersected = false; + + //float bestEntityDistance = distance; + while(entityItr != entityEnd) { EntityItem* entity = (*entityItr); @@ -489,9 +498,16 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con float localDistance; BoxFace localFace; + qDebug() << "EntityTreeElement::findDetailedRayIntersection()...."; + qDebug() << " checking entity[" << entityNumber << "]:" << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); + qDebug() << " checking the AABox:" << entityBox; + // if the ray doesn't intersect with our cube, we can stop searching! if (entityBox.findRayIntersection(origin, direction, localDistance, localFace)) { + qDebug() << " AABox for entity intersects!"; + qDebug() << " localDistance:" << localDistance; + // extents is the entity relative, scaled, centered extents of the entity glm::mat4 rotation = glm::mat4_cast(entity->getRotation()); glm::mat4 translation = glm::translate(entity->getPosition()); @@ -509,12 +525,10 @@ 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 // and testing intersection there. - qDebug() << "EntityTreeElement::findDetailedRayIntersection()...."; - qDebug() << " origin:" << origin; - qDebug() << " checking entity:" << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); - qDebug() << " distance:" << distance; + qDebug() << " checking the entityFrameBox:" << entityFrameBox; if (entityFrameBox.findRayIntersection(entityFrameOrigin, entityFrameDirection, localDistance, localFace)) { + qDebug() << " entityFrameBox intersects!"; qDebug() << " localDistance:" << localDistance; if (localDistance < distance) { @@ -559,7 +573,11 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con } ++entityItr; + entityNumber++; } + + qDebug() << " EntityTreeElement::findDetailedRayIntersection().... returning somethingIntersected:" << somethingIntersected << "keepSearching:" << keepSearching; + return somethingIntersected; } diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index e085298c33..330624f4b9 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -1343,9 +1343,12 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 float distanceToElementDetails = distance; BoxFace localFace; + AACube debugCube = cube; + debugCube.scale((float)TREE_SCALE); + qDebug() << "OctreeElement::findRayIntersection()...."; qDebug() << " origin:" << origin; - qDebug() << " checking element:" << cube; + qDebug() << " checking element:" << debugCube << "in meters"; qDebug() << " distance:" << distance; // if the ray doesn't intersect with our cube, we can stop searching! @@ -1359,6 +1362,7 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 // by default, we only allow intersections with leaves with content if (!canRayIntersect()) { + qDebug() << " NOT canRayIntersect() -- no point in calling detailed..."; return false; // we don't intersect with non-leaves, and we keep searching } @@ -1367,9 +1371,10 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 // if the distance to the element cube is not less than the current best distance, then it's not possible // for any details inside the cube to be closer so we don't need to consider them. - if (distanceToElementCube < distance) { + if (cube.contains(origin) || distanceToElementCube < distance) { qDebug() << " distanceToElementCube < distance:" << (distanceToElementCube < distance); + qDebug() << " cube.contains(origin):" << (cube.contains(origin)); qDebug() << " continue.... call... findDetailedRayIntersection()..."; //qDebug() << " distanceToElementCube < distance -- continue.... call... findDetailedRayIntersection()..."; @@ -1403,6 +1408,7 @@ bool OctreeElement::findDetailedRayIntersection(const glm::vec3& origin, const g if (intersectedObject) { *intersectedObject = this; } + qDebug() << " OctreeElement::findDetailedRayIntersection().... hasContent() -- done searching..."; keepSearching = false; return true; // we did intersect } From ae647d39d0f62c94de93ec1bb85d01cfd0fb0292 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 5 Dec 2014 16:14:18 -0800 Subject: [PATCH 08/21] fix models with registrations other than 0,0,0 --- interface/src/renderer/Model.cpp | 24 ++++++++++++++++---- libraries/entities/src/EntityTreeElement.cpp | 4 ++++ libraries/octree/src/OctreeElement.cpp | 4 ++++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 6b398284a3..a259e42117 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -543,10 +543,10 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g qDebug() << " modelExtents:" << modelExtents; glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum; - glm::vec3 corner = dimensions * _registrationPoint; // since we're going to do the ray picking in the model frame of reference - AABox overlayFrameBox(corner, dimensions); + glm::vec3 corner = -(dimensions * _registrationPoint); // since we're going to do the ray picking in the model frame of reference + AABox modelFrameBox(corner, dimensions); - qDebug() << " overlayFrameBox:" << overlayFrameBox; + qDebug() << " modelFrameBox:" << modelFrameBox; glm::vec3 modelFrameOrigin = glm::vec3(worldToModelMatrix * glm::vec4(origin, 1.0f)); glm::vec3 modelFrameDirection = glm::vec3(worldToModelMatrix * glm::vec4(direction, 0.0f)); @@ -555,7 +555,9 @@ 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 // and testing intersection there. - if (overlayFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face)) { + if (modelFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face)) { + + qDebug() << " modelFrameBox.findRayIntersection() HITS!!!"; float bestDistance = std::numeric_limits::max(); float bestTriangleDistance = std::numeric_limits::max(); @@ -566,14 +568,21 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g int subMeshIndex = 0; const FBXGeometry& geometry = _geometry->getFBXGeometry(); + + qDebug() << " Checking mesh boxes...."; // If we hit the models box, then consider the submeshes... foreach(const AABox& subMeshBox, _calculatedMeshBoxes) { - qDebug() << "subMeshBox[" << subMeshIndex <<"]:" << subMeshBox; + qDebug() << " subMeshBox[" << subMeshIndex <<"]:" << subMeshBox; if (subMeshBox.findRayIntersection(origin, direction, distanceToSubMesh, subMeshFace)) { + qDebug() << " subMeshBox[" << subMeshIndex <<"].findRayIntersection() HITS!"; + qDebug() << " subMeshBox[" << subMeshIndex <<"].distanceToSubMesh:" << distanceToSubMesh; + qDebug() << " bestDistance:" << bestDistance; if (distanceToSubMesh < bestDistance) { + qDebug() << " distanceToSubMesh < bestDistance !! looks like a good match!"; + if (pickAgainstTriangles) { if (!_calculatedMeshTrianglesValid) { recalcuateMeshBoxes(); @@ -599,6 +608,8 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g intersectedSomething = true; face = subMeshFace; extraInfo = geometry.getModelNameOfMesh(subMeshIndex); + } else { + qDebug() << " distanceToSubMesh >= bestDistance !! TOO FAR AWAY!"; } } subMeshIndex++; @@ -607,6 +618,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g // if we were asked to pick against triangles, and we didn't hit one, then we // do not consider this model to be hit at all. if (pickAgainstTriangles && !someTriangleHit) { + qDebug() << "pickAgainstTriangles && !someTriangleHit --- call it a NON-HIT!"; intersectedSomething = false; } qDebug() << "pickAgainstTriangles:" << pickAgainstTriangles; @@ -626,6 +638,8 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g } return intersectedSomething; + } else { + qDebug() << "modelFrameBox.findRayIntersection()... DID NOT INTERSECT..."; } return intersectedSomething; diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index c452dab5cb..aea278adf6 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -553,6 +553,8 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con face = localFace; *intersectedObject = (void*)entity; somethingIntersected = true; + } else { + qDebug() << " localDistance >= distance... TOO FAR AWAY"; } } } else { @@ -566,6 +568,8 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con face = localFace; *intersectedObject = (void*)entity; somethingIntersected = true; + } else { + qDebug() << " localDistance >= distance... TOO FAR AWAY"; } } } diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index 330624f4b9..9f6e0530a8 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -1391,6 +1391,10 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 qDebug() << " distance:" << distance << " -- THIS ONE IS GOOD -------"; return true; + } else { + qDebug() << " distanceToElementDetails:" << distanceToElementDetails; + qDebug() << " distance:" << distance; + qDebug() << " distanceToElementDetails >= distance -- THIS ONE IS NOT SELECTED even though it INTERSECTED -------"; } } } From f1c6e2d1a23db6b3c276565110c6c3c0fa8fca69 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 5 Dec 2014 19:52:48 -0800 Subject: [PATCH 09/21] more debugging --- interface/src/Application.cpp | 17 ++++++++ .../entities/RenderableModelEntityItem.cpp | 2 + interface/src/renderer/Model.cpp | 39 +++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 44f83102e2..863bca8a85 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -434,6 +434,23 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : #endif this->installEventFilter(this); + + + + + qDebug() << "------------------------------------------------------------"; + qDebug() << " test findRayTrianlgeIntersection()...."; + float distanceA; + bool testA = findRayTrianlgeIntersection(glm::vec3(0.5,0.5,1), glm::vec3(0,0,-1), glm::vec3(0,0,0), glm::vec3(1,0,0), glm::vec3(0,1,0), distanceA); + qDebug() << " testA:" << testA; + qDebug() << " distanceA:" << distanceA; + + float distanceB; + bool testB = findRayTrianlgeIntersection(glm::vec3(0.5,0.5,1), glm::vec3(0,0,-1), glm::vec3(0,0,0), glm::vec3(0,1,0), glm::vec3(1,0,0), distanceB); + qDebug() << " testB:" << testB; + qDebug() << " distanceB:" << distanceB; + qDebug() << "------------------------------------------------------------"; + } void Application::aboutToQuit() { diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index 6bc6f52782..e2fd50ceee 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -262,6 +262,8 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori void** intersectedObject) const { qDebug() << "RenderableModelEntityItem::findDetailedRayIntersection()...."; + qDebug() << " this.id:" << getEntityItemID(); + qDebug() << " this.modelURL:" << getModelURL(); qDebug() << " origin:" << origin; glm::vec3 originInMeters = origin * (float)TREE_SCALE; qDebug() << " originInMeters:" << originInMeters; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index a259e42117..3606a17cf8 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -584,6 +584,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g qDebug() << " distanceToSubMesh < bestDistance !! looks like a good match!"; if (pickAgainstTriangles) { + qDebug() << " subMeshBox[" << subMeshIndex <<"] --- check triangles!!"; if (!_calculatedMeshTrianglesValid) { recalcuateMeshBoxes(); } @@ -596,9 +597,15 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g float thisTriangleDistance; if (findRayTrianlgeIntersection(origin, direction, triangle, thisTriangleDistance)) { + qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- HITS!!"; + qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] thisTriangleDistance:" << thisTriangleDistance; + qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] bestTriangleDistance:" << bestTriangleDistance; if (thisTriangleDistance < bestTriangleDistance) { bestTriangleDistance = thisTriangleDistance; someTriangleHit = true; + qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- WOOT! BEST DISTANCE!"; + } else { + qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- not best distance???"; } } } @@ -611,6 +618,38 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g } else { qDebug() << " distanceToSubMesh >= bestDistance !! TOO FAR AWAY!"; } + } else { + // TODO: this needs to be deleted... there shouldn't be any reason to run this here... if the mesh's bounding box + // doesn't intersect, then how can any of it's triangles!!!! + + qDebug() << " subMeshBox[" << subMeshIndex <<"].findRayIntersection() MISSES???"; + if (pickAgainstTriangles) { + qDebug() << " subMeshBox[" << subMeshIndex <<"] --- check triangles anyway!!"; + if (!_calculatedMeshTrianglesValid) { + recalcuateMeshBoxes(); + } + // check our triangles here.... + const QVector& meshTriangles = _calculatedMeshTriangles[subMeshIndex]; + int t = 0; + foreach (const Triangle& triangle, meshTriangles) { + //qDebug() << "triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2; + t++; + + float thisTriangleDistance; + if (findRayTrianlgeIntersection(origin, direction, triangle, thisTriangleDistance)) { + qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- HITS!!"; + qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] thisTriangleDistance:" << thisTriangleDistance; + qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] bestTriangleDistance:" << bestTriangleDistance; + if (thisTriangleDistance < bestTriangleDistance) { + bestTriangleDistance = thisTriangleDistance; + someTriangleHit = true; + qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- WOOT! BEST DISTANCE!"; + } else { + qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- not best distance???"; + } + } + } + } } subMeshIndex++; } From 1fec69698ec66db629413af7b1288737fb7715a6 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 5 Dec 2014 23:23:21 -0800 Subject: [PATCH 10/21] get the triangle picking for submeshes working, remove some debug --- .../entities/RenderableModelEntityItem.cpp | 16 +- interface/src/renderer/Model.cpp | 200 ++++++++++-------- interface/src/renderer/Model.h | 1 + libraries/entities/src/EntityTreeElement.cpp | 44 ++-- libraries/octree/src/OctreeElement.cpp | 34 +-- libraries/shared/src/GeometryUtil.cpp | 8 +- 6 files changed, 169 insertions(+), 134 deletions(-) diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index e2fd50ceee..37efeb98ee 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -174,7 +174,9 @@ void RenderableModelEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("model->render"); bool dontRenderAsScene = true; // Menu::getInstance()->isOptionChecked(MenuOption::DontRenderEntitiesAsScene); if (dontRenderAsScene) { - _model->render(alpha, modelRenderMode, args); + if (!_model->renderTriangleProxies()) { + _model->render(alpha, modelRenderMode, args); + } } else { _model->renderInScene(alpha, args); } @@ -261,12 +263,12 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject) const { - qDebug() << "RenderableModelEntityItem::findDetailedRayIntersection()...."; - qDebug() << " this.id:" << getEntityItemID(); - qDebug() << " this.modelURL:" << getModelURL(); - qDebug() << " origin:" << origin; + //qDebug() << "RenderableModelEntityItem::findDetailedRayIntersection()...."; + //qDebug() << " this.id:" << getEntityItemID(); + //qDebug() << " this.modelURL:" << getModelURL(); + //qDebug() << " origin:" << origin; glm::vec3 originInMeters = origin * (float)TREE_SCALE; - qDebug() << " originInMeters:" << originInMeters; + //qDebug() << " originInMeters:" << originInMeters; QString extraInfo; float localDistance; @@ -276,7 +278,7 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori // NOTE: findRayIntersectionAgainstSubMeshes() does work in meters, but we're expected to return // results in tree scale. distance = localDistance / (float)TREE_SCALE; - qDebug() << " --hit this mode -- returning distance:" << distance; + //qDebug() << " --hit this mode -- returning distance:" << distance; } return intersectsModel; // we only got here if we intersected our non-aabox diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 3606a17cf8..8f684440da 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -516,6 +516,61 @@ void Model::setJointStates(QVector states) { _boundingRadius = radius; } +bool Model::renderTriangleProxies() { + if (!isActive()) { + return false; + } + if (_calculatedMeshTrianglesValid) { + int color = 0; + foreach (const QVector& meshTriangles, _calculatedMeshTriangles) { + switch(color) { + case 0: glColor3ub( 0, 0, 255); break; + case 1: glColor3ub( 0, 255, 0); break; + case 2: glColor3ub( 0, 255, 255); break; + case 3: glColor3ub(255, 0, 0); break; + case 4: glColor3ub(255, 0, 255); break; + case 5: glColor3ub(255, 255, 0); break; + case 6: glColor3ub( 0, 0, 128); break; + case 7: glColor3ub( 0, 128, 0); break; + case 8: glColor3ub( 0, 128, 128); break; + case 9: glColor3ub(128, 0, 0); break; + case 10: glColor3ub(128, 0, 128); break; + case 11: glColor3ub(128, 128, 0); break; + case 12: glColor3ub(128, 128, 255); break; + case 13: glColor3ub(128, 255, 128); break; + case 14: glColor3ub(128, 255, 255); break; + case 15: glColor3ub(255, 128, 128); break; + case 16: glColor3ub(255, 128, 255); break; + case 17: glColor3ub(255, 255, 128); break; + default: glColor3ub(255,255, 255); break; + } + + if (_calculatedMeshBoxes.size() > color) { + const AABox& box = _calculatedMeshBoxes[color]; + glm::vec3 center = box.calcCenter(); + glm::vec3 dimensions = box.getDimensions(); + glPushMatrix(); + glTranslatef(center.x, center.y, center.z); + glScalef(dimensions.x, dimensions.y, dimensions.z); + Application::getInstance()->getDeferredLightingEffect()->renderWireCube(1.0f); + glPopMatrix(); + } + + + glBegin(GL_TRIANGLES); + foreach (const Triangle& triangle, meshTriangles) { + //qDebug() << "triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2; + glVertex3f( triangle.v0.x, triangle.v0.y, triangle.v0.z); + glVertex3f( triangle.v1.x, triangle.v1.y, triangle.v1.z); + glVertex3f( triangle.v2.x, triangle.v2.y, triangle.v2.z); + } + glEnd(); + color++; + } + } + return _calculatedMeshTrianglesValid; +} + bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face, QString& extraInfo) { @@ -528,9 +583,9 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g bool pickAgainstTriangles = Menu::getInstance()->isOptionChecked(MenuOption::PickAgainstModelTriangles); - qDebug() << "Model::findRayIntersectionAgainstSubMeshes()..."; - qDebug() << " origin:" << origin; - qDebug() << " direction:" << direction; + //qDebug() << "Model::findRayIntersectionAgainstSubMeshes()..."; + //qDebug() << " origin:" << origin; + //qDebug() << " direction:" << direction; // extents is the entity relative, scaled, centered extents of the entity glm::vec3 position = _translation; @@ -540,24 +595,24 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix); Extents modelExtents = getMeshExtents(); // NOTE: unrotated - qDebug() << " modelExtents:" << modelExtents; + //qDebug() << " modelExtents:" << modelExtents; glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum; glm::vec3 corner = -(dimensions * _registrationPoint); // since we're going to do the ray picking in the model frame of reference AABox modelFrameBox(corner, dimensions); - qDebug() << " modelFrameBox:" << modelFrameBox; + //qDebug() << " modelFrameBox:" << modelFrameBox; glm::vec3 modelFrameOrigin = glm::vec3(worldToModelMatrix * glm::vec4(origin, 1.0f)); glm::vec3 modelFrameDirection = glm::vec3(worldToModelMatrix * glm::vec4(direction, 0.0f)); - qDebug() << " modelFrameOrigin:" << modelFrameOrigin; - qDebug() << " modelFrameDirection:" << modelFrameDirection; + //qDebug() << " modelFrameOrigin:" << modelFrameOrigin; + //qDebug() << " modelFrameDirection:" << modelFrameDirection; // we can use the AABox's ray intersection by mapping our origin and direction into the model frame // and testing intersection there. if (modelFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face)) { - qDebug() << " modelFrameBox.findRayIntersection() HITS!!!"; + //qDebug() << " modelFrameBox.findRayIntersection() HITS!!!"; float bestDistance = std::numeric_limits::max(); float bestTriangleDistance = std::numeric_limits::max(); @@ -569,22 +624,23 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g const FBXGeometry& geometry = _geometry->getFBXGeometry(); - qDebug() << " Checking mesh boxes...."; - + //qDebug() << " Checking mesh boxes...."; + // If we hit the models box, then consider the submeshes... foreach(const AABox& subMeshBox, _calculatedMeshBoxes) { - qDebug() << " subMeshBox[" << subMeshIndex <<"]:" << subMeshBox; + //qDebug() << " subMeshBox[" << subMeshIndex <<"]:" << subMeshBox; if (subMeshBox.findRayIntersection(origin, direction, distanceToSubMesh, subMeshFace)) { - qDebug() << " subMeshBox[" << subMeshIndex <<"].findRayIntersection() HITS!"; - qDebug() << " subMeshBox[" << subMeshIndex <<"].distanceToSubMesh:" << distanceToSubMesh; - qDebug() << " bestDistance:" << bestDistance; + //qDebug() << " subMeshBox[" << subMeshIndex <<"].findRayIntersection() HITS!"; + //qDebug() << " subMeshBox[" << subMeshIndex <<"].distanceToSubMesh:" << distanceToSubMesh; + //qDebug() << " bestDistance:" << bestDistance; if (distanceToSubMesh < bestDistance) { - qDebug() << " distanceToSubMesh < bestDistance !! looks like a good match!"; + //qDebug() << " distanceToSubMesh < bestDistance !! looks like a good match!"; if (pickAgainstTriangles) { - qDebug() << " subMeshBox[" << subMeshIndex <<"] --- check triangles!!"; + someTriangleHit = false; + //qDebug() << " subMeshBox[" << subMeshIndex <<"] --- check triangles!!"; if (!_calculatedMeshTrianglesValid) { recalcuateMeshBoxes(); } @@ -592,93 +648,59 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g const QVector& meshTriangles = _calculatedMeshTriangles[subMeshIndex]; int t = 0; foreach (const Triangle& triangle, meshTriangles) { - //qDebug() << "triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2; + //qDebug() << "checking triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2; t++; float thisTriangleDistance; if (findRayTrianlgeIntersection(origin, direction, triangle, thisTriangleDistance)) { - qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- HITS!!"; - qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] thisTriangleDistance:" << thisTriangleDistance; - qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] bestTriangleDistance:" << bestTriangleDistance; - if (thisTriangleDistance < bestTriangleDistance) { + //qDebug() << "---- HIT triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2 << " -----"; + //qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- HITS!!"; + //qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] thisTriangleDistance:" << thisTriangleDistance; + //qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] bestTriangleDistance:" << bestTriangleDistance; + if (thisTriangleDistance < bestDistance) { bestTriangleDistance = thisTriangleDistance; someTriangleHit = true; - qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- WOOT! BEST DISTANCE!"; + + bestDistance = thisTriangleDistance; + intersectedSomething = true; + face = subMeshFace; + extraInfo = geometry.getModelNameOfMesh(subMeshIndex); + + //qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- WOOT! BEST DISTANCE!"; } else { - qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- not best distance???"; + //qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- not best distance???"; } } } + } else { + // this is the non-triangle picking case... + bestDistance = distanceToSubMesh; + intersectedSomething = true; + face = subMeshFace; + extraInfo = geometry.getModelNameOfMesh(subMeshIndex); } - - bestDistance = distanceToSubMesh; - intersectedSomething = true; - face = subMeshFace; - extraInfo = geometry.getModelNameOfMesh(subMeshIndex); } else { - qDebug() << " distanceToSubMesh >= bestDistance !! TOO FAR AWAY!"; + //qDebug() << " distanceToSubMesh >= bestDistance !! TOO FAR AWAY!"; } - } else { - // TODO: this needs to be deleted... there shouldn't be any reason to run this here... if the mesh's bounding box - // doesn't intersect, then how can any of it's triangles!!!! - - qDebug() << " subMeshBox[" << subMeshIndex <<"].findRayIntersection() MISSES???"; - if (pickAgainstTriangles) { - qDebug() << " subMeshBox[" << subMeshIndex <<"] --- check triangles anyway!!"; - if (!_calculatedMeshTrianglesValid) { - recalcuateMeshBoxes(); - } - // check our triangles here.... - const QVector& meshTriangles = _calculatedMeshTriangles[subMeshIndex]; - int t = 0; - foreach (const Triangle& triangle, meshTriangles) { - //qDebug() << "triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2; - t++; - - float thisTriangleDistance; - if (findRayTrianlgeIntersection(origin, direction, triangle, thisTriangleDistance)) { - qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- HITS!!"; - qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] thisTriangleDistance:" << thisTriangleDistance; - qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] bestTriangleDistance:" << bestTriangleDistance; - if (thisTriangleDistance < bestTriangleDistance) { - bestTriangleDistance = thisTriangleDistance; - someTriangleHit = true; - qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- WOOT! BEST DISTANCE!"; - } else { - qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- not best distance???"; - } - } - } - } - } + } subMeshIndex++; } - // if we were asked to pick against triangles, and we didn't hit one, then we - // do not consider this model to be hit at all. - if (pickAgainstTriangles && !someTriangleHit) { - qDebug() << "pickAgainstTriangles && !someTriangleHit --- call it a NON-HIT!"; - intersectedSomething = false; - } - qDebug() << "pickAgainstTriangles:" << pickAgainstTriangles; - qDebug() << "someTriangleHit:" << someTriangleHit; - qDebug() << "bestTriangleDistance:" << bestTriangleDistance; - qDebug() << "bestDistance:" << bestDistance; + //qDebug() << "pickAgainstTriangles:" << pickAgainstTriangles; + //qDebug() << "someTriangleHit:" << someTriangleHit; + //qDebug() << "bestTriangleDistance:" << bestTriangleDistance; + //qDebug() << "bestDistance:" << bestDistance; + //qDebug() << "intersectedSomething:" << intersectedSomething; if (intersectedSomething) { - qDebug() << " --- we hit this model --- "; - - if (pickAgainstTriangles) { - distance = bestTriangleDistance; - } else { - distance = bestDistance; - } - qDebug() << "distance:" << distance; + //qDebug() << " --- we hit this model --- "; + distance = bestDistance; + //qDebug() << "distance:" << distance; } return intersectedSomething; } else { - qDebug() << "modelFrameBox.findRayIntersection()... DID NOT INTERSECT..."; + //qDebug() << "modelFrameBox.findRayIntersection()... DID NOT INTERSECT..."; } return intersectedSomething; @@ -689,12 +711,14 @@ void Model::recalcuateMeshBoxes() { bool calculatedMeshTrianglesNeeded = pickAgainstTriangles && !_calculatedMeshTrianglesValid; if (!_calculatedMeshBoxesValid || calculatedMeshTrianglesNeeded) { - qDebug() << "Model::recalcuateMeshBoxes()"; + qDebug() << "************************************************************************************************"; + qDebug() << "Model::recalcuateMeshBoxes() -------------------------------------------------------------------"; PerformanceTimer perfTimer("calculatedMeshBoxes"); const FBXGeometry& geometry = _geometry->getFBXGeometry(); int numberOfMeshes = geometry.meshes.size(); _calculatedMeshBoxes.resize(numberOfMeshes); _calculatedMeshTriangles.clear(); + _calculatedMeshTriangles.resize(numberOfMeshes); for (int i = 0; i < numberOfMeshes; i++) { const FBXMesh& mesh = geometry.meshes.at(i); Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents); @@ -731,8 +755,14 @@ void Model::recalcuateMeshBoxes() { glm::vec3 v2 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i2], 1.0f))); glm::vec3 v3 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i3], 1.0f))); - Triangle tri1 = { v0, v1, v3 }; - Triangle tri2 = { v1, v2, v3 }; + // Sam's + //Triangle tri1 = { v0, v1, v3 }; + //Triangle tri2 = { v1, v2, v3 }; + + // triangle 0 1 2 + // triangle 2 3 0 + Triangle tri1 = { v0, v1, v2 }; + Triangle tri2 = { v2, v3, v0 }; //qDebug() << "quad["<< q <<"].t1 :" << v0 << ", "<< v1 << ", " << v3; //qDebug() << "quad["<< q <<"].t2 :" << v1 << ", "<< v2 << ", " << v3; @@ -764,7 +794,7 @@ void Model::recalcuateMeshBoxes() { } } - _calculatedMeshTriangles.push_back(thisMeshTriangles); + _calculatedMeshTriangles[i] = thisMeshTriangles; qDebug() << "------------------------------------------------------------------------------"; } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 406622e6a8..4145b7b3d9 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -89,6 +89,7 @@ public: enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE }; bool render(float alpha = 1.0f, RenderMode mode = DEFAULT_RENDER_MODE, RenderArgs* args = NULL); + bool renderTriangleProxies(); // Scene rendering support static void startScene(RenderArgs::RenderSide renderSide); diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index aea278adf6..ac65245f4b 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -479,10 +479,10 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con // only called if we do intersect our bounding cube, but find if we actually intersect with entities... - qDebug() << "EntityTreeElement::findDetailedRayIntersection()...."; - qDebug() << " origin:" << origin; - qDebug() << " distance:" << distance; - qDebug() << " number of entities:" << _entityItems->size(); + //qDebug() << "EntityTreeElement::findDetailedRayIntersection()...."; + //qDebug() << " origin:" << origin; + //qDebug() << " distance:" << distance; + //qDebug() << " number of entities:" << _entityItems->size(); int entityNumber = 0; QList::iterator entityItr = _entityItems->begin(); @@ -498,15 +498,15 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con float localDistance; BoxFace localFace; - qDebug() << "EntityTreeElement::findDetailedRayIntersection()...."; - qDebug() << " checking entity[" << entityNumber << "]:" << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); - qDebug() << " checking the AABox:" << entityBox; + //qDebug() << "EntityTreeElement::findDetailedRayIntersection()...."; + //qDebug() << " checking entity[" << entityNumber << "]:" << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); + //qDebug() << " checking the AABox:" << entityBox; // if the ray doesn't intersect with our cube, we can stop searching! if (entityBox.findRayIntersection(origin, direction, localDistance, localFace)) { - qDebug() << " AABox for entity intersects!"; - qDebug() << " localDistance:" << localDistance; + //qDebug() << " AABox for entity intersects!"; + //qDebug() << " localDistance:" << localDistance; // extents is the entity relative, scaled, centered extents of the entity glm::mat4 rotation = glm::mat4_cast(entity->getRotation()); @@ -525,51 +525,51 @@ 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 // and testing intersection there. - qDebug() << " checking the entityFrameBox:" << entityFrameBox; + //qDebug() << " checking the entityFrameBox:" << entityFrameBox; if (entityFrameBox.findRayIntersection(entityFrameOrigin, entityFrameDirection, localDistance, localFace)) { - qDebug() << " entityFrameBox intersects!"; - qDebug() << " localDistance:" << localDistance; + //qDebug() << " entityFrameBox intersects!"; + //qDebug() << " localDistance:" << localDistance; if (localDistance < distance) { - qDebug() << " localDistance < distance... continue..."; + //qDebug() << " localDistance < distance... continue..."; // now ask the entity if we actually intersect if (entity->supportsDetailedRayIntersection()) { - qDebug() << " entity->supportsDetailedRayIntersection()...."; + //qDebug() << " entity->supportsDetailedRayIntersection()...."; if (entity->findDetailedRayIntersection(origin, direction, keepSearching, element, localDistance, localFace, intersectedObject)) { - qDebug() << " localDistance (detailed):" << localDistance; + //qDebug() << " localDistance (detailed):" << localDistance; if (localDistance < distance) { - qDebug() << " localDistance < distance..."; - qDebug() << " CHOOSING THIS ONE ---> " << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); + //qDebug() << " localDistance < distance..."; + //qDebug() << " CHOOSING THIS ONE ---> " << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); distance = localDistance; face = localFace; *intersectedObject = (void*)entity; somethingIntersected = true; } else { - qDebug() << " localDistance >= distance... TOO FAR AWAY"; + //qDebug() << " localDistance >= distance... TOO FAR AWAY"; } } } else { // if the entity type doesn't support a detailed intersection, then just return the non-AABox results if (localDistance < distance) { - qDebug() << " localDistance < distance..."; - qDebug() << " CHOOSING THIS ONE ---> " << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); + //qDebug() << " localDistance < distance..."; + //qDebug() << " CHOOSING THIS ONE ---> " << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); distance = localDistance; face = localFace; *intersectedObject = (void*)entity; somethingIntersected = true; } else { - qDebug() << " localDistance >= distance... TOO FAR AWAY"; + //qDebug() << " localDistance >= distance... TOO FAR AWAY"; } } } @@ -580,7 +580,7 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con entityNumber++; } - qDebug() << " EntityTreeElement::findDetailedRayIntersection().... returning somethingIntersected:" << somethingIntersected << "keepSearching:" << keepSearching; + //qDebug() << " EntityTreeElement::findDetailedRayIntersection().... returning somethingIntersected:" << somethingIntersected << "keepSearching:" << keepSearching; return somethingIntersected; } diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index 9f6e0530a8..e3ff06b2d3 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -1346,23 +1346,23 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 AACube debugCube = cube; debugCube.scale((float)TREE_SCALE); - qDebug() << "OctreeElement::findRayIntersection()...."; - qDebug() << " origin:" << origin; - qDebug() << " checking element:" << debugCube << "in meters"; - qDebug() << " distance:" << distance; + //qDebug() << "OctreeElement::findRayIntersection()...."; + //qDebug() << " origin:" << origin; + //qDebug() << " checking element:" << debugCube << "in meters"; + //qDebug() << " distance:" << distance; // if the ray doesn't intersect with our cube, we can stop searching! if (!cube.findRayIntersection(origin, direction, distanceToElementCube, localFace)) { - qDebug() << " didn't intersect cube... done searching..."; + //qDebug() << " didn't intersect cube... done searching..."; keepSearching = false; // no point in continuing to search return false; // we did not intersect } - qDebug() << " distanceToElementCube:" << distanceToElementCube; + //qDebug() << " distanceToElementCube:" << distanceToElementCube; // by default, we only allow intersections with leaves with content if (!canRayIntersect()) { - qDebug() << " NOT canRayIntersect() -- no point in calling detailed..."; + //qDebug() << " NOT canRayIntersect() -- no point in calling detailed..."; return false; // we don't intersect with non-leaves, and we keep searching } @@ -1373,28 +1373,28 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 // for any details inside the cube to be closer so we don't need to consider them. if (cube.contains(origin) || distanceToElementCube < distance) { - qDebug() << " distanceToElementCube < distance:" << (distanceToElementCube < distance); - qDebug() << " cube.contains(origin):" << (cube.contains(origin)); - qDebug() << " continue.... call... findDetailedRayIntersection()..."; + //qDebug() << " distanceToElementCube < distance:" << (distanceToElementCube < distance); + //qDebug() << " cube.contains(origin):" << (cube.contains(origin)); + //qDebug() << " continue.... call... findDetailedRayIntersection()..."; //qDebug() << " distanceToElementCube < distance -- continue.... call... findDetailedRayIntersection()..."; if (findDetailedRayIntersection(origin, direction, keepSearching, element, distanceToElementDetails, face, intersectedObject, distanceToElementCube)) { - qDebug() << " findDetailedRayIntersection() -- intersected something"; + //qDebug() << " findDetailedRayIntersection() -- intersected something"; if (distanceToElementDetails < distance) { - qDebug() << " distanceToElementDetails < distance -- THIS ONE IS GOOD -------"; + //qDebug() << " distanceToElementDetails < distance -- THIS ONE IS GOOD -------"; distance = distanceToElementDetails; face = localFace; - qDebug() << " distance:" << distance << " -- THIS ONE IS GOOD -------"; + //qDebug() << " distance:" << distance << " -- THIS ONE IS GOOD -------"; return true; } else { - qDebug() << " distanceToElementDetails:" << distanceToElementDetails; - qDebug() << " distance:" << distance; - qDebug() << " distanceToElementDetails >= distance -- THIS ONE IS NOT SELECTED even though it INTERSECTED -------"; + //qDebug() << " distanceToElementDetails:" << distanceToElementDetails; + //qDebug() << " distance:" << distance; + //qDebug() << " distanceToElementDetails >= distance -- THIS ONE IS NOT SELECTED even though it INTERSECTED -------"; } } } @@ -1412,7 +1412,7 @@ bool OctreeElement::findDetailedRayIntersection(const glm::vec3& origin, const g if (intersectedObject) { *intersectedObject = this; } - qDebug() << " OctreeElement::findDetailedRayIntersection().... hasContent() -- done searching..."; + //qDebug() << " OctreeElement::findDetailedRayIntersection().... hasContent() -- done searching..."; keepSearching = false; return true; // we did intersect } diff --git a/libraries/shared/src/GeometryUtil.cpp b/libraries/shared/src/GeometryUtil.cpp index c064630f83..f44c954a3a 100644 --- a/libraries/shared/src/GeometryUtil.cpp +++ b/libraries/shared/src/GeometryUtil.cpp @@ -252,6 +252,7 @@ bool findRayCapsuleIntersection(const glm::vec3& origin, const glm::vec3& direct return true; } + bool findRayTrianlgeIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& distance) { @@ -264,7 +265,8 @@ bool findRayTrianlgeIntersection(const glm::vec3& origin, const glm::vec3& direc h = glm::cross(direction, e2); a = glm::dot(e1, h); - if (a > -0.00001 && a < 0.00001) { + if (a > EPSILON && a < EPSILON) { + qDebug() << "if (a > EPSILON && a < EPSILON)..."; return false; } @@ -287,17 +289,17 @@ bool findRayTrianlgeIntersection(const glm::vec3& origin, const glm::vec3& direc t = f * glm::dot(e2,q); // ray intersection - if (t > 0.00001) { + if (t > EPSILON) { distance = t; return true; } else { // this means that there is a line intersection but not a ray intersection + qDebug() << "if (t <= EPSILON)..."; return false; } return false; } - // Do line segments (r1p1.x, r1p1.y)--(r1p2.x, r1p2.y) and (r2p1.x, r2p1.y)--(r2p2.x, r2p2.y) intersect? // from: http://ptspts.blogspot.com/2010/06/how-to-determine-if-two-line-segments.html bool doLineSegmentsIntersect(glm::vec2 r1p1, glm::vec2 r1p2, glm::vec2 r2p1, glm::vec2 r2p2) { From ec907d1d1da54eb00fec1791e8dae64edd1dea1f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 09:44:30 -0800 Subject: [PATCH 11/21] removed debug --- libraries/shared/src/GeometryUtil.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/shared/src/GeometryUtil.cpp b/libraries/shared/src/GeometryUtil.cpp index f44c954a3a..e2736f8502 100644 --- a/libraries/shared/src/GeometryUtil.cpp +++ b/libraries/shared/src/GeometryUtil.cpp @@ -266,7 +266,6 @@ bool findRayTrianlgeIntersection(const glm::vec3& origin, const glm::vec3& direc a = glm::dot(e1, h); if (a > EPSILON && a < EPSILON) { - qDebug() << "if (a > EPSILON && a < EPSILON)..."; return false; } @@ -294,7 +293,6 @@ bool findRayTrianlgeIntersection(const glm::vec3& origin, const glm::vec3& direc return true; } else { // this means that there is a line intersection but not a ray intersection - qDebug() << "if (t <= EPSILON)..."; return false; } return false; From 303274a554d8876da4330395d1c8b2d9813ad7cc Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 10:59:48 -0800 Subject: [PATCH 12/21] tweaks and debug cleanup --- .../entities/RenderableModelEntityItem.cpp | 6 +-- interface/src/renderer/Model.cpp | 41 ++++--------------- interface/src/renderer/Model.h | 6 +-- 3 files changed, 14 insertions(+), 39 deletions(-) diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index 37efeb98ee..c5f5f0c98a 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -172,11 +172,9 @@ void RenderableModelEntityItem::render(RenderArgs* args) { // TODO: this is the majority of model render time. And rendering of a cube model vs the basic Box render // is significantly more expensive. Is there a way to call this that doesn't cost us as much? PerformanceTimer perfTimer("model->render"); - bool dontRenderAsScene = true; // Menu::getInstance()->isOptionChecked(MenuOption::DontRenderEntitiesAsScene); + bool dontRenderAsScene = Menu::getInstance()->isOptionChecked(MenuOption::DontRenderEntitiesAsScene); if (dontRenderAsScene) { - if (!_model->renderTriangleProxies()) { - _model->render(alpha, modelRenderMode, args); - } + _model->render(alpha, modelRenderMode, args); } else { _model->renderInScene(alpha, args); } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 8f684440da..a59a76709a 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -571,8 +571,8 @@ bool Model::renderTriangleProxies() { return _calculatedMeshTrianglesValid; } -bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, QString& extraInfo) { +bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, + BoxFace& face, QString& extraInfo, bool pickAgainstTriangles) { bool intersectedSomething = false; @@ -581,8 +581,6 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g return intersectedSomething; } - bool pickAgainstTriangles = Menu::getInstance()->isOptionChecked(MenuOption::PickAgainstModelTriangles); - //qDebug() << "Model::findRayIntersectionAgainstSubMeshes()..."; //qDebug() << " origin:" << origin; //qDebug() << " direction:" << direction; @@ -706,13 +704,10 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g return intersectedSomething; } -void Model::recalcuateMeshBoxes() { - bool pickAgainstTriangles = Menu::getInstance()->isOptionChecked(MenuOption::PickAgainstModelTriangles); +void Model::recalcuateMeshBoxes(bool pickAgainstTriangles) { bool calculatedMeshTrianglesNeeded = pickAgainstTriangles && !_calculatedMeshTrianglesValid; if (!_calculatedMeshBoxesValid || calculatedMeshTrianglesNeeded) { - qDebug() << "************************************************************************************************"; - qDebug() << "Model::recalcuateMeshBoxes() -------------------------------------------------------------------"; PerformanceTimer perfTimer("calculatedMeshBoxes"); const FBXGeometry& geometry = _geometry->getFBXGeometry(); int numberOfMeshes = geometry.meshes.size(); @@ -723,16 +718,9 @@ void Model::recalcuateMeshBoxes() { const FBXMesh& mesh = geometry.meshes.at(i); Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents); - qDebug() << "mesh.meshExtents["< thisMeshTriangles; for (int j = 0; j < mesh.parts.size(); j++) { const FBXMeshPart& part = mesh.parts.at(j); @@ -742,7 +730,6 @@ void Model::recalcuateMeshBoxes() { if (part.quadIndices.size() > 0) { int numberOfQuads = part.quadIndices.size() / INDICES_PER_QUAD; - qDebug() << "numberOfQuads:" << numberOfQuads; int vIndex = 0; for (int q = 0; q < numberOfQuads; q++) { int i0 = part.quadIndices[vIndex++]; @@ -755,18 +742,14 @@ void Model::recalcuateMeshBoxes() { glm::vec3 v2 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i2], 1.0f))); glm::vec3 v3 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i3], 1.0f))); - // Sam's - //Triangle tri1 = { v0, v1, v3 }; - //Triangle tri2 = { v1, v2, v3 }; + // Sam's recommended triangle slices + Triangle tri1 = { v0, v1, v3 }; + Triangle tri2 = { v1, v2, v3 }; - // triangle 0 1 2 - // triangle 2 3 0 - Triangle tri1 = { v0, v1, v2 }; - Triangle tri2 = { v2, v3, v0 }; + // NOTE: Random guy on the internet's recommended triangle slices + //Triangle tri1 = { v0, v1, v2 }; + //Triangle tri2 = { v2, v3, v0 }; - //qDebug() << "quad["<< q <<"].t1 :" << v0 << ", "<< v1 << ", " << v3; - //qDebug() << "quad["<< q <<"].t2 :" << v1 << ", "<< v2 << ", " << v3; - thisMeshTriangles.push_back(tri1); thisMeshTriangles.push_back(tri2); } @@ -774,7 +757,6 @@ void Model::recalcuateMeshBoxes() { if (part.triangleIndices.size() > 0) { int numberOfTris = part.triangleIndices.size() / INDICES_PER_TRIANGLE; - qDebug() << "numberOfTris:" << numberOfTris; int vIndex = 0; for (int t = 0; t < numberOfTris; t++) { int i0 = part.triangleIndices[vIndex++]; @@ -787,17 +769,12 @@ void Model::recalcuateMeshBoxes() { Triangle tri = { v0, v1, v2 }; - //qDebug() << "triangle["<< t <<"] :" << v0 << ", " << v1 << ", " << v2; - thisMeshTriangles.push_back(tri); } } } - _calculatedMeshTriangles[i] = thisMeshTriangles; - qDebug() << "------------------------------------------------------------------------------"; } - } _calculatedMeshBoxesValid = true; _calculatedMeshTrianglesValid = pickAgainstTriangles; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 4145b7b3d9..69dc6344ad 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -197,8 +197,8 @@ public: Q_INVOKABLE void setTextureWithNameToURL(const QString& name, const QUrl& url) { _geometry->setTextureWithNameToURL(name, url); } - bool findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, QString& extraInfo); + bool findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, + BoxFace& face, QString& extraInfo, bool pickAgainstTriangles = false); protected: QSharedPointer _geometry; @@ -371,7 +371,7 @@ private: QVector< QVector > _calculatedMeshTriangles; // world coordinate triangles for all sub meshes bool _calculatedMeshTrianglesValid; - void recalcuateMeshBoxes(); + void recalcuateMeshBoxes(bool pickAgainstTriangles = false); void segregateMeshGroups(); // used to calculate our list of translucent vs opaque meshes From 7ea85073f4397faba010fd4ff5f3afbaabc8e3fc Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 11:45:49 -0800 Subject: [PATCH 13/21] introduce precision picking in API form --- examples/developerMenuItems.js | 6 ++-- examples/editModels.js | 2 +- interface/src/Menu.h | 2 ++ interface/src/entities/EntityTreeRenderer.cpp | 17 ++++++--- interface/src/entities/EntityTreeRenderer.h | 3 +- .../entities/RenderableLightEntityItem.cpp | 2 +- .../src/entities/RenderableLightEntityItem.h | 2 +- .../entities/RenderableModelEntityItem.cpp | 29 ++++++++------- .../src/entities/RenderableModelEntityItem.h | 2 +- interface/src/renderer/Model.cpp | 2 +- libraries/entities/src/EntityItem.h | 2 +- .../entities/src/EntityScriptingInterface.cpp | 11 +++--- .../entities/src/EntityScriptingInterface.h | 7 ++-- libraries/entities/src/EntityTreeElement.cpp | 4 +-- libraries/entities/src/EntityTreeElement.h | 2 +- libraries/entities/src/SphereEntityItem.cpp | 2 +- libraries/entities/src/SphereEntityItem.h | 2 +- libraries/entities/src/TextEntityItem.cpp | 2 +- libraries/entities/src/TextEntityItem.h | 2 +- libraries/octree/src/Octree.cpp | 8 +++-- libraries/octree/src/Octree.h | 4 ++- libraries/octree/src/OctreeElement.cpp | 35 +++---------------- libraries/octree/src/OctreeElement.h | 4 +-- 23 files changed, 74 insertions(+), 78 deletions(-) diff --git a/examples/developerMenuItems.js b/examples/developerMenuItems.js index 0d2c4895ea..34bd3b3a75 100644 --- a/examples/developerMenuItems.js +++ b/examples/developerMenuItems.js @@ -19,15 +19,17 @@ function setupMenus() { if (!Menu.menuExists("Developer > Entities")) { Menu.addMenu("Developer > Entities"); Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Bounds", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Triangles", isCheckable: true, isChecked: false }); Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Element Bounds", isCheckable: true, isChecked: false }); Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Element Children", isCheckable: true, isChecked: false }); - Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Disable Light Entities", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Do Precision Picking", isCheckable: true, isChecked: false }); Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Attempt to Reduce Material Switches", isCheckable: true, isChecked: false }); Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Attempt Render Entities as Scene", isCheckable: true, isChecked: false }); - Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Pick Against Model Triangles", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Do Precision Picking", isCheckable: true, isChecked: false }); Menu.addMenu("Developer > Entities > Culling"); Menu.addMenuItem({ menuName: "Developer > Entities > Culling", menuItemName: "Don't Cull Out Of View Mesh Parts", isCheckable: true, isChecked: false }); Menu.addMenuItem({ menuName: "Developer > Entities > Culling", menuItemName: "Don't Cull Too Small Mesh Parts", isCheckable: true, isChecked: false }); + Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Disable Light Entities", isCheckable: true, isChecked: false }); } } diff --git a/examples/editModels.js b/examples/editModels.js index 8e3503b9b2..60ca9b6ca6 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -2554,7 +2554,7 @@ function mousePressEvent(event) { var pickRay = Camera.computePickRay(event.x, event.y); Vec3.print("[Mouse] Looking at: ", pickRay.origin); - var foundIntersection = Entities.findRayIntersection(pickRay); + var foundIntersection = Entities.findRayIntersection(pickRay, true); // we want precision picking here if(!foundIntersection.accurate) { return; diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 520c83177e..3f8a50af01 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -367,6 +367,7 @@ namespace MenuOption { const QString DontCullTooSmallMeshParts = "Don't Cull Too Small Mesh Parts"; const QString DontReduceMaterialSwitches = "Don't Attempt to Reduce Material Switches"; const QString DontRenderEntitiesAsScene = "Don't Render Entities as Scene"; + const QString DontDoPrecisionPicking = "Don't Do Precision Picking"; const QString DecreaseAvatarSize = "Decrease Avatar Size"; const QString DecreaseVoxelSize = "Decrease Voxel Size"; const QString DisableActivityLogger = "Disable Activity Logger"; @@ -378,6 +379,7 @@ namespace MenuOption { const QString DisplayHandTargets = "Show Hand Targets"; const QString DisplayHermiteData = "Display Hermite Data"; const QString DisplayModelBounds = "Display Model Bounds"; + const QString DisplayModelTriangles = "Display Model Triangles"; const QString DisplayModelElementChildProxies = "Display Model Element Children"; const QString DisplayModelElementProxy = "Display Model Element Bounds"; const QString DisplayTimingDetails = "Display Timing Details"; diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index 5aacd36a12..c6a6464438 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -650,7 +650,8 @@ PickRay EntityTreeRenderer::computePickRay(float x, float y) { } -RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType) { +RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType, + bool precisionPicking) { RayToEntityIntersectionResult result; if (_tree) { EntityTree* entityTree = static_cast(_tree); @@ -658,7 +659,8 @@ RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(cons OctreeElement* element; EntityItem* intersectedEntity = NULL; result.intersects = entityTree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face, - (void**)&intersectedEntity, lockType, &result.accurate); + (void**)&intersectedEntity, lockType, &result.accurate, + precisionPicking); if (result.intersects && intersectedEntity) { result.entityID = intersectedEntity->getEntityItemID(); result.properties = intersectedEntity->getProperties(); @@ -710,7 +712,9 @@ QScriptValueList EntityTreeRenderer::createEntityArgs(const EntityItemID& entity void EntityTreeRenderer::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent"); PickRay ray = computePickRay(event->x(), event->y()); - RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock); + + bool precisionPicking = !Menu::getInstance()->isOptionChecked(MenuOption::DontDoPrecisionPicking); + RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking); if (rayPickResult.intersects) { //qDebug() << "mousePressEvent over entity:" << rayPickResult.entityID; emit mousePressOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); @@ -734,7 +738,8 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event, unsigned int device void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { PerformanceTimer perfTimer("EntityTreeRenderer::mouseReleaseEvent"); PickRay ray = computePickRay(event->x(), event->y()); - RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock); + bool precisionPicking = !Menu::getInstance()->isOptionChecked(MenuOption::DontDoPrecisionPicking); + RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking); if (rayPickResult.intersects) { //qDebug() << "mouseReleaseEvent over entity:" << rayPickResult.entityID; emit mouseReleaseOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); @@ -768,7 +773,9 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event, unsigned int deviceI PerformanceTimer perfTimer("EntityTreeRenderer::mouseMoveEvent"); PickRay ray = computePickRay(event->x(), event->y()); - RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::TryLock); + + bool precisionPicking = false; // for mouse moves we do not do precision picking + RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::TryLock, precisionPicking); if (rayPickResult.intersects) { QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID); diff --git a/interface/src/entities/EntityTreeRenderer.h b/interface/src/entities/EntityTreeRenderer.h index 0042dd495f..40df81b46c 100644 --- a/interface/src/entities/EntityTreeRenderer.h +++ b/interface/src/entities/EntityTreeRenderer.h @@ -117,7 +117,8 @@ private: QList _releasedModels; void renderProxies(const EntityItem* entity, RenderArgs* args); PickRay computePickRay(float x, float y); - RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType); + RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType, + bool precisionPicking); EntityItemID _currentHoverOverEntityID; EntityItemID _currentClickingOnEntityID; diff --git a/interface/src/entities/RenderableLightEntityItem.cpp b/interface/src/entities/RenderableLightEntityItem.cpp index 91b2d35106..77dbb5da0b 100644 --- a/interface/src/entities/RenderableLightEntityItem.cpp +++ b/interface/src/entities/RenderableLightEntityItem.cpp @@ -93,7 +93,7 @@ void RenderableLightEntityItem::render(RenderArgs* args) { bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) const { + void** intersectedObject, bool precisionPicking) const { // TODO: this isn't really correct because we don't know if we actually live in the main tree of the applications's // EntityTreeRenderer. But we probably do. Technically we could be on the clipboard and someone might be trying to diff --git a/interface/src/entities/RenderableLightEntityItem.h b/interface/src/entities/RenderableLightEntityItem.h index 40fa31a4ce..2113f486cc 100644 --- a/interface/src/entities/RenderableLightEntityItem.h +++ b/interface/src/entities/RenderableLightEntityItem.h @@ -37,7 +37,7 @@ public: virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) const; + void** intersectedObject, bool precisionPicking) const; }; diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index c5f5f0c98a..2dd889538a 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -173,10 +173,18 @@ void RenderableModelEntityItem::render(RenderArgs* args) { // is significantly more expensive. Is there a way to call this that doesn't cost us as much? PerformanceTimer perfTimer("model->render"); bool dontRenderAsScene = Menu::getInstance()->isOptionChecked(MenuOption::DontRenderEntitiesAsScene); - if (dontRenderAsScene) { - _model->render(alpha, modelRenderMode, args); - } else { - _model->renderInScene(alpha, args); + bool displayModelTriangles = Menu::getInstance()->isOptionChecked(MenuOption::DisplayModelTriangles); + bool rendered = false; + if (displayModelTriangles) { + rendered = _model->renderTriangleProxies(); + } + + if (!rendered) { + if (dontRenderAsScene) { + _model->render(alpha, modelRenderMode, args); + } else { + _model->renderInScene(alpha, args); + } } } else { // if we couldn't get a model, then just draw a cube @@ -259,24 +267,21 @@ EntityItemProperties RenderableModelEntityItem::getProperties() const { bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) const { + void** intersectedObject, bool precisionPicking) const { - //qDebug() << "RenderableModelEntityItem::findDetailedRayIntersection()...."; - //qDebug() << " this.id:" << getEntityItemID(); - //qDebug() << " this.modelURL:" << getModelURL(); - //qDebug() << " origin:" << origin; glm::vec3 originInMeters = origin * (float)TREE_SCALE; - //qDebug() << " originInMeters:" << originInMeters; QString extraInfo; float localDistance; - bool intersectsModel = _model->findRayIntersectionAgainstSubMeshes(originInMeters, direction, localDistance, face, extraInfo); + qDebug() << "RenderableModelEntityItem::findDetailedRayIntersection() precisionPicking:" << precisionPicking; + + bool intersectsModel = _model->findRayIntersectionAgainstSubMeshes(originInMeters, direction, + localDistance, face, extraInfo, precisionPicking); if (intersectsModel) { // NOTE: findRayIntersectionAgainstSubMeshes() does work in meters, but we're expected to return // results in tree scale. distance = localDistance / (float)TREE_SCALE; - //qDebug() << " --hit this mode -- returning distance:" << distance; } return intersectsModel; // we only got here if we intersected our non-aabox diff --git a/interface/src/entities/RenderableModelEntityItem.h b/interface/src/entities/RenderableModelEntityItem.h index 9ed85beeaa..e187b944d8 100644 --- a/interface/src/entities/RenderableModelEntityItem.h +++ b/interface/src/entities/RenderableModelEntityItem.h @@ -54,7 +54,7 @@ public: virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) const; + void** intersectedObject, bool precisionPicking) const; Model* getModel(EntityTreeRenderer* renderer); private: diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index a59a76709a..ea075227cc 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -640,7 +640,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g someTriangleHit = false; //qDebug() << " subMeshBox[" << subMeshIndex <<"] --- check triangles!!"; if (!_calculatedMeshTrianglesValid) { - recalcuateMeshBoxes(); + recalcuateMeshBoxes(pickAgainstTriangles); } // check our triangles here.... const QVector& meshTriangles = _calculatedMeshTriangles[subMeshIndex]; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 7dbcaed8fc..22d956886a 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -138,7 +138,7 @@ public: virtual bool supportsDetailedRayIntersection() const { return false; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) const { return true; } + void** intersectedObject, bool precisionPicking) const { return true; } // attributes applicable to all entity types EntityTypes::EntityType getType() const { return _type; } diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 575a6c1a78..7e09e97f6f 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -196,16 +196,17 @@ QVector EntityScriptingInterface::findEntities(const glm::vec3& ce return result; } -RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersection(const PickRay& ray) { - return findRayIntersectionWorker(ray, Octree::TryLock); +RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersection(const PickRay& ray, bool precisionPicking) { + return findRayIntersectionWorker(ray, Octree::TryLock, precisionPicking); } -RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionBlocking(const PickRay& ray) { - return findRayIntersectionWorker(ray, Octree::Lock); +RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionBlocking(const PickRay& ray, bool precisionPicking) { + return findRayIntersectionWorker(ray, Octree::Lock, precisionPicking); } RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionWorker(const PickRay& ray, - Octree::lockType lockType) { + Octree::lockType lockType, + bool precisionPicking) { RayToEntityIntersectionResult result; if (_entityTree) { OctreeElement* element; diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index da0c6c9f1a..1233af678d 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -90,11 +90,11 @@ public slots: /// If the scripting context has visible voxels, this will determine a ray intersection, the results /// may be inaccurate if the engine is unable to access the visible voxels, in which case result.accurate /// will be false. - Q_INVOKABLE RayToEntityIntersectionResult findRayIntersection(const PickRay& ray); + Q_INVOKABLE RayToEntityIntersectionResult findRayIntersection(const PickRay& ray, bool precisionPicking = false); /// If the scripting context has visible voxels, this will determine a ray intersection, and will block in /// order to return an accurate result - Q_INVOKABLE RayToEntityIntersectionResult findRayIntersectionBlocking(const PickRay& ray); + Q_INVOKABLE RayToEntityIntersectionResult findRayIntersectionBlocking(const PickRay& ray, bool precisionPicking = false); Q_INVOKABLE void setLightsArePickable(bool value); Q_INVOKABLE bool getLightsArePickable() const; @@ -124,7 +124,8 @@ private: void queueEntityMessage(PacketType packetType, EntityItemID entityID, const EntityItemProperties& properties); /// actually does the work of finding the ray intersection, can be called in locking mode or tryLock mode - RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType); + RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType, + bool precisionPicking); uint32_t _nextCreatorTokenID; EntityTree* _entityTree; diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index ac65245f4b..058b4503aa 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -475,7 +475,7 @@ bool EntityTreeElement::bestFitBounds(const glm::vec3& minPoint, const glm::vec3 bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject, 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... @@ -540,7 +540,7 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con //qDebug() << " entity->supportsDetailedRayIntersection()...."; if (entity->findDetailedRayIntersection(origin, direction, keepSearching, element, localDistance, - localFace, intersectedObject)) { + localFace, intersectedObject, precisionPicking)) { //qDebug() << " localDistance (detailed):" << localDistance; diff --git a/libraries/entities/src/EntityTreeElement.h b/libraries/entities/src/EntityTreeElement.h index e59b35189f..4fbe9db323 100644 --- a/libraries/entities/src/EntityTreeElement.h +++ b/libraries/entities/src/EntityTreeElement.h @@ -137,7 +137,7 @@ public: virtual bool canRayIntersect() const { return hasEntities(); } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject, float distanceToElementCube); + void** intersectedObject, bool precisionPicking, float distanceToElementCube); virtual bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject) const; diff --git a/libraries/entities/src/SphereEntityItem.cpp b/libraries/entities/src/SphereEntityItem.cpp index 12fdd7a8c4..1960d9623e 100644 --- a/libraries/entities/src/SphereEntityItem.cpp +++ b/libraries/entities/src/SphereEntityItem.cpp @@ -96,7 +96,7 @@ void SphereEntityItem::recalculateCollisionShape() { bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) const { + void** intersectedObject, bool precisionPicking) const { // NOTE: origin and direction are in tree units. But our _sphereShape is in meters, so we need to // do a little math to make these match each other. diff --git a/libraries/entities/src/SphereEntityItem.h b/libraries/entities/src/SphereEntityItem.h index bb4f41726c..5769498229 100644 --- a/libraries/entities/src/SphereEntityItem.h +++ b/libraries/entities/src/SphereEntityItem.h @@ -59,7 +59,7 @@ public: virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) const; + void** intersectedObject, bool precisionPicking) const; protected: virtual void recalculateCollisionShape(); diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index 17ef33ee1c..f8f518a581 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -118,7 +118,7 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) const { + void** intersectedObject, bool precisionPicking) const { RayIntersectionInfo rayInfo; rayInfo._rayStart = origin; diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index a3d323aefd..c980969bb1 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -44,7 +44,7 @@ public: virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) const; + void** intersectedObject, bool precisionPicking) const; static const QString DEFAULT_TEXT; void setText(const QString& value) { _text = value; } diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index f13f832920..1a432c8e59 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -693,13 +693,14 @@ public: BoxFace& face; void** intersectedObject; bool found; + bool precisionPicking; }; bool findRayIntersectionOp(OctreeElement* element, void* extraData) { RayArgs* args = static_cast(extraData); bool keepSearching = true; if (element->findRayIntersection(args->origin, args->direction, keepSearching, - args->element, args->distance, args->face, args->intersectedObject)) { + args->element, args->distance, args->face, args->intersectedObject, args->precisionPicking)) { args->found = true; } return keepSearching; @@ -707,8 +708,9 @@ bool findRayIntersectionOp(OctreeElement* element, void* extraData) { bool Octree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, - Octree::lockType lockType, bool* accurateResult) { - RayArgs args = { origin / (float)(TREE_SCALE), direction, element, distance, face, intersectedObject, false}; + Octree::lockType lockType, bool* accurateResult, bool precisionPicking) { + RayArgs args = { origin / (float)(TREE_SCALE), direction, element, distance, face, + intersectedObject, false, precisionPicking}; distance = FLT_MAX; bool gotLock = false; diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 4ac7e22d90..cde8565ca2 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -298,7 +298,9 @@ public: bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElement*& node, float& distance, BoxFace& face, void** intersectedObject = NULL, - Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL); + Octree::lockType lockType = Octree::TryLock, + bool* accurateResult = NULL, + bool precisionPicking = false); bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject = NULL, Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL); diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index e3ff06b2d3..29f1d52926 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -1334,7 +1334,7 @@ void OctreeElement::notifyUpdateHooks() { bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject) { + void** intersectedObject, bool precisionPicking) { keepSearching = true; // assume that we will continue searching after this. @@ -1346,55 +1346,28 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 AACube debugCube = cube; debugCube.scale((float)TREE_SCALE); - //qDebug() << "OctreeElement::findRayIntersection()...."; - //qDebug() << " origin:" << origin; - //qDebug() << " checking element:" << debugCube << "in meters"; - //qDebug() << " distance:" << distance; - // if the ray doesn't intersect with our cube, we can stop searching! if (!cube.findRayIntersection(origin, direction, distanceToElementCube, localFace)) { - //qDebug() << " didn't intersect cube... done searching..."; keepSearching = false; // no point in continuing to search return false; // we did not intersect } - //qDebug() << " distanceToElementCube:" << distanceToElementCube; - // by default, we only allow intersections with leaves with content if (!canRayIntersect()) { - //qDebug() << " NOT canRayIntersect() -- no point in calling detailed..."; return false; // we don't intersect with non-leaves, and we keep searching } - // we did hit this element, so calculate appropriate distances - //localDistance *= TREE_SCALE; - // if the distance to the element cube is not less than the current best distance, then it's not possible // for any details inside the cube to be closer so we don't need to consider them. if (cube.contains(origin) || distanceToElementCube < distance) { - //qDebug() << " distanceToElementCube < distance:" << (distanceToElementCube < distance); - //qDebug() << " cube.contains(origin):" << (cube.contains(origin)); - //qDebug() << " continue.... call... findDetailedRayIntersection()..."; - //qDebug() << " distanceToElementCube < distance -- continue.... call... findDetailedRayIntersection()..."; + if (findDetailedRayIntersection(origin, direction, keepSearching, element, distanceToElementDetails, + face, intersectedObject, precisionPicking, distanceToElementCube)) { - if (findDetailedRayIntersection(origin, direction, keepSearching, - element, distanceToElementDetails, face, intersectedObject, distanceToElementCube)) { - - //qDebug() << " findDetailedRayIntersection() -- intersected something"; if (distanceToElementDetails < distance) { - //qDebug() << " distanceToElementDetails < distance -- THIS ONE IS GOOD -------"; - distance = distanceToElementDetails; face = localFace; - - //qDebug() << " distance:" << distance << " -- THIS ONE IS GOOD -------"; - return true; - } else { - //qDebug() << " distanceToElementDetails:" << distanceToElementDetails; - //qDebug() << " distance:" << distance; - //qDebug() << " distanceToElementDetails >= distance -- THIS ONE IS NOT SELECTED even though it INTERSECTED -------"; } } } @@ -1403,7 +1376,7 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 bool OctreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject, float distanceToElementCube) { + void** intersectedObject, bool precisionPicking, float distanceToElementCube) { // we did hit this element, so calculate appropriate distances if (hasContent()) { diff --git a/libraries/octree/src/OctreeElement.h b/libraries/octree/src/OctreeElement.h index 9161a9b171..3bd13a2f3c 100644 --- a/libraries/octree/src/OctreeElement.h +++ b/libraries/octree/src/OctreeElement.h @@ -119,11 +119,11 @@ public: virtual bool canRayIntersect() const { return isLeaf(); } virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& node, float& distance, BoxFace& face, - void** intersectedObject = NULL); + void** intersectedObject = NULL, bool precisionPicking = false); virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject, float distanceToElementCube); + void** intersectedObject, bool precisionPicking, float distanceToElementCube); virtual bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject) const; From 3bb16ce831bf06e283c589c51f6106a2c271eff8 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 12:03:46 -0800 Subject: [PATCH 14/21] properly wire up precision picking in JS api --- interface/src/renderer/Model.cpp | 12 ++++++++---- interface/src/renderer/Model.h | 2 +- libraries/entities/src/EntityScriptingInterface.cpp | 5 ++++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index ea075227cc..81ac44872d 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -574,6 +574,7 @@ bool Model::renderTriangleProxies() { bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face, QString& extraInfo, bool pickAgainstTriangles) { +//qDebug() << "Model::findRayIntersectionAgainstSubMeshes() pickAgainstTriangles:" << pickAgainstTriangles; bool intersectedSomething = false; // if we aren't active, we can't ray pick yet... @@ -640,13 +641,13 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g someTriangleHit = false; //qDebug() << " subMeshBox[" << subMeshIndex <<"] --- check triangles!!"; if (!_calculatedMeshTrianglesValid) { - recalcuateMeshBoxes(pickAgainstTriangles); + recalculateMeshBoxes(pickAgainstTriangles); } // check our triangles here.... const QVector& meshTriangles = _calculatedMeshTriangles[subMeshIndex]; int t = 0; foreach (const Triangle& triangle, meshTriangles) { - //qDebug() << "checking triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2; + // qDebug() << "checking triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2; t++; float thisTriangleDistance; @@ -704,8 +705,11 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g return intersectedSomething; } -void Model::recalcuateMeshBoxes(bool pickAgainstTriangles) { +// TODO: we seem to call this too often when things haven't actually changed... look into optimizing this +void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { + //qDebug() << "recalculateMeshBoxes() pickAgainstTriangles:" << pickAgainstTriangles; bool calculatedMeshTrianglesNeeded = pickAgainstTriangles && !_calculatedMeshTrianglesValid; + //qDebug() << "recalculateMeshBoxes() calculatedMeshTrianglesNeeded:" << calculatedMeshTrianglesNeeded; if (!_calculatedMeshBoxesValid || calculatedMeshTrianglesNeeded) { PerformanceTimer perfTimer("calculatedMeshBoxes"); @@ -787,7 +791,7 @@ void Model::renderSetup(RenderArgs* args) { // 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) { - recalcuateMeshBoxes(); + recalculateMeshBoxes(); } // set up dilated textures on first render after load/simulate diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 69dc6344ad..43b04b7a46 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -371,7 +371,7 @@ private: QVector< QVector > _calculatedMeshTriangles; // world coordinate triangles for all sub meshes bool _calculatedMeshTrianglesValid; - void recalcuateMeshBoxes(bool pickAgainstTriangles = false); + void recalculateMeshBoxes(bool pickAgainstTriangles = false); void segregateMeshGroups(); // used to calculate our list of translucent vs opaque meshes diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 7e09e97f6f..26870ad9bb 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -207,12 +207,15 @@ RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionBlock RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType, bool precisionPicking) { + + RayToEntityIntersectionResult result; if (_entityTree) { OctreeElement* element; EntityItem* intersectedEntity = NULL; result.intersects = _entityTree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face, - (void**)&intersectedEntity, lockType, &result.accurate); + (void**)&intersectedEntity, lockType, &result.accurate, + precisionPicking); if (result.intersects && intersectedEntity) { result.entityID = intersectedEntity->getEntityItemID(); result.properties = intersectedEntity->getProperties(); From a03984a561a78d21387f4b27dc9d0c6576acefdb Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 14:59:50 -0800 Subject: [PATCH 15/21] removed some debug code --- interface/src/Application.cpp | 17 ----------------- .../src/entities/RenderableModelEntityItem.cpp | 2 +- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 863bca8a85..44f83102e2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -434,23 +434,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : #endif this->installEventFilter(this); - - - - - qDebug() << "------------------------------------------------------------"; - qDebug() << " test findRayTrianlgeIntersection()...."; - float distanceA; - bool testA = findRayTrianlgeIntersection(glm::vec3(0.5,0.5,1), glm::vec3(0,0,-1), glm::vec3(0,0,0), glm::vec3(1,0,0), glm::vec3(0,1,0), distanceA); - qDebug() << " testA:" << testA; - qDebug() << " distanceA:" << distanceA; - - float distanceB; - bool testB = findRayTrianlgeIntersection(glm::vec3(0.5,0.5,1), glm::vec3(0,0,-1), glm::vec3(0,0,0), glm::vec3(0,1,0), glm::vec3(1,0,0), distanceB); - qDebug() << " testB:" << testB; - qDebug() << " distanceB:" << distanceB; - qDebug() << "------------------------------------------------------------"; - } void Application::aboutToQuit() { diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index 2dd889538a..51f46ff30c 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -273,7 +273,7 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori QString extraInfo; float localDistance; - qDebug() << "RenderableModelEntityItem::findDetailedRayIntersection() precisionPicking:" << precisionPicking; + //qDebug() << "RenderableModelEntityItem::findDetailedRayIntersection() precisionPicking:" << precisionPicking; bool intersectsModel = _model->findRayIntersectionAgainstSubMeshes(originInMeters, direction, localDistance, face, extraInfo, precisionPicking); From c8e648c4d724b86aea1284a3867b560d80114d79 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 15:00:29 -0800 Subject: [PATCH 16/21] removed unused menu item --- interface/src/Menu.h | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 3f8a50af01..138828d3e8 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -434,7 +434,6 @@ namespace MenuOption { const QString OldVoxelCullingMode = "Old Voxel Culling Mode"; const QString Pair = "Pair"; const QString PasteToVoxel = "Paste to Voxel..."; - const QString PickAgainstModelTriangles = "Pick Against Model Triangles"; const QString PipelineWarnings = "Log Render Pipeline Warnings"; const QString Preferences = "Preferences..."; const QString Quit = "Quit"; From 1a1fb18ba11cb966855441dd8a70a56d44f0bb8e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 15:03:26 -0800 Subject: [PATCH 17/21] removed dead code --- interface/src/renderer/Model.cpp | 47 -------------------------------- 1 file changed, 47 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 81ac44872d..91bb4735fd 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -556,10 +556,8 @@ bool Model::renderTriangleProxies() { glPopMatrix(); } - glBegin(GL_TRIANGLES); foreach (const Triangle& triangle, meshTriangles) { - //qDebug() << "triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2; glVertex3f( triangle.v0.x, triangle.v0.y, triangle.v0.z); glVertex3f( triangle.v1.x, triangle.v1.y, triangle.v1.z); glVertex3f( triangle.v2.x, triangle.v2.y, triangle.v2.z); @@ -574,7 +572,6 @@ bool Model::renderTriangleProxies() { bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face, QString& extraInfo, bool pickAgainstTriangles) { -//qDebug() << "Model::findRayIntersectionAgainstSubMeshes() pickAgainstTriangles:" << pickAgainstTriangles; bool intersectedSomething = false; // if we aren't active, we can't ray pick yet... @@ -582,10 +579,6 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g return intersectedSomething; } - //qDebug() << "Model::findRayIntersectionAgainstSubMeshes()..."; - //qDebug() << " origin:" << origin; - //qDebug() << " direction:" << direction; - // extents is the entity relative, scaled, centered extents of the entity glm::vec3 position = _translation; glm::mat4 rotation = glm::mat4_cast(_rotation); @@ -594,25 +587,18 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix); Extents modelExtents = getMeshExtents(); // NOTE: unrotated - //qDebug() << " modelExtents:" << modelExtents; glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum; glm::vec3 corner = -(dimensions * _registrationPoint); // since we're going to do the ray picking in the model frame of reference AABox modelFrameBox(corner, dimensions); - //qDebug() << " modelFrameBox:" << modelFrameBox; - glm::vec3 modelFrameOrigin = glm::vec3(worldToModelMatrix * glm::vec4(origin, 1.0f)); glm::vec3 modelFrameDirection = glm::vec3(worldToModelMatrix * glm::vec4(direction, 0.0f)); - //qDebug() << " modelFrameOrigin:" << modelFrameOrigin; - //qDebug() << " modelFrameDirection:" << modelFrameDirection; // we can use the AABox's ray intersection by mapping our origin and direction into the model frame // and testing intersection there. if (modelFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face)) { - //qDebug() << " modelFrameBox.findRayIntersection() HITS!!!"; - float bestDistance = std::numeric_limits::max(); float bestTriangleDistance = std::numeric_limits::max(); bool someTriangleHit = false; @@ -623,23 +609,13 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g const FBXGeometry& geometry = _geometry->getFBXGeometry(); - //qDebug() << " Checking mesh boxes...."; - // If we hit the models box, then consider the submeshes... foreach(const AABox& subMeshBox, _calculatedMeshBoxes) { - //qDebug() << " subMeshBox[" << subMeshIndex <<"]:" << subMeshBox; if (subMeshBox.findRayIntersection(origin, direction, distanceToSubMesh, subMeshFace)) { - //qDebug() << " subMeshBox[" << subMeshIndex <<"].findRayIntersection() HITS!"; - //qDebug() << " subMeshBox[" << subMeshIndex <<"].distanceToSubMesh:" << distanceToSubMesh; - //qDebug() << " bestDistance:" << bestDistance; if (distanceToSubMesh < bestDistance) { - - //qDebug() << " distanceToSubMesh < bestDistance !! looks like a good match!"; - if (pickAgainstTriangles) { someTriangleHit = false; - //qDebug() << " subMeshBox[" << subMeshIndex <<"] --- check triangles!!"; if (!_calculatedMeshTrianglesValid) { recalculateMeshBoxes(pickAgainstTriangles); } @@ -647,15 +623,10 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g const QVector& meshTriangles = _calculatedMeshTriangles[subMeshIndex]; int t = 0; foreach (const Triangle& triangle, meshTriangles) { - // qDebug() << "checking triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2; t++; float thisTriangleDistance; if (findRayTrianlgeIntersection(origin, direction, triangle, thisTriangleDistance)) { - //qDebug() << "---- HIT triangle["<< t <<"] :" << triangle.v0 << ", "<< triangle.v1 << ", " << triangle.v2 << " -----"; - //qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- HITS!!"; - //qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] thisTriangleDistance:" << thisTriangleDistance; - //qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] bestTriangleDistance:" << bestTriangleDistance; if (thisTriangleDistance < bestDistance) { bestTriangleDistance = thisTriangleDistance; someTriangleHit = true; @@ -664,10 +635,6 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g intersectedSomething = true; face = subMeshFace; extraInfo = geometry.getModelNameOfMesh(subMeshIndex); - - //qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- WOOT! BEST DISTANCE!"; - } else { - //qDebug() << " subMeshBox[" << subMeshIndex <<"].triangle[" << t <<"] --- not best distance???"; } } } @@ -678,28 +645,16 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g face = subMeshFace; extraInfo = geometry.getModelNameOfMesh(subMeshIndex); } - } else { - //qDebug() << " distanceToSubMesh >= bestDistance !! TOO FAR AWAY!"; } } subMeshIndex++; } - //qDebug() << "pickAgainstTriangles:" << pickAgainstTriangles; - //qDebug() << "someTriangleHit:" << someTriangleHit; - //qDebug() << "bestTriangleDistance:" << bestTriangleDistance; - //qDebug() << "bestDistance:" << bestDistance; - //qDebug() << "intersectedSomething:" << intersectedSomething; - if (intersectedSomething) { - //qDebug() << " --- we hit this model --- "; distance = bestDistance; - //qDebug() << "distance:" << distance; } return intersectedSomething; - } else { - //qDebug() << "modelFrameBox.findRayIntersection()... DID NOT INTERSECT..."; } return intersectedSomething; @@ -707,9 +662,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g // TODO: we seem to call this too often when things haven't actually changed... look into optimizing this void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { - //qDebug() << "recalculateMeshBoxes() pickAgainstTriangles:" << pickAgainstTriangles; bool calculatedMeshTrianglesNeeded = pickAgainstTriangles && !_calculatedMeshTrianglesValid; - //qDebug() << "recalculateMeshBoxes() calculatedMeshTrianglesNeeded:" << calculatedMeshTrianglesNeeded; if (!_calculatedMeshBoxesValid || calculatedMeshTrianglesNeeded) { PerformanceTimer perfTimer("calculatedMeshBoxes"); From 08092e7abe2eaca2aa4bc97bac932a2adc6ab3c0 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 15:06:00 -0800 Subject: [PATCH 18/21] removed dead code --- libraries/entities/src/EntityTreeElement.cpp | 39 -------------------- 1 file changed, 39 deletions(-) diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 058b4503aa..70def167a2 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -478,11 +478,6 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con void** intersectedObject, bool precisionPicking, float distanceToElementCube) { // only called if we do intersect our bounding cube, but find if we actually intersect with entities... - - //qDebug() << "EntityTreeElement::findDetailedRayIntersection()...."; - //qDebug() << " origin:" << origin; - //qDebug() << " distance:" << distance; - //qDebug() << " number of entities:" << _entityItems->size(); int entityNumber = 0; QList::iterator entityItr = _entityItems->begin(); @@ -498,16 +493,9 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con float localDistance; BoxFace localFace; - //qDebug() << "EntityTreeElement::findDetailedRayIntersection()...."; - //qDebug() << " checking entity[" << entityNumber << "]:" << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); - //qDebug() << " checking the AABox:" << entityBox; - // if the ray doesn't intersect with our cube, we can stop searching! if (entityBox.findRayIntersection(origin, direction, localDistance, localFace)) { - //qDebug() << " AABox for entity intersects!"; - //qDebug() << " localDistance:" << localDistance; - // extents is the entity relative, scaled, centered extents of the entity glm::mat4 rotation = glm::mat4_cast(entity->getRotation()); glm::mat4 translation = glm::translate(entity->getPosition()); @@ -525,51 +513,27 @@ 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 // and testing intersection there. - //qDebug() << " checking the entityFrameBox:" << entityFrameBox; - if (entityFrameBox.findRayIntersection(entityFrameOrigin, entityFrameDirection, localDistance, localFace)) { - //qDebug() << " entityFrameBox intersects!"; - //qDebug() << " localDistance:" << localDistance; - if (localDistance < distance) { - //qDebug() << " localDistance < distance... continue..."; - // now ask the entity if we actually intersect if (entity->supportsDetailedRayIntersection()) { - - //qDebug() << " entity->supportsDetailedRayIntersection()...."; - if (entity->findDetailedRayIntersection(origin, direction, keepSearching, element, localDistance, localFace, intersectedObject, precisionPicking)) { - //qDebug() << " localDistance (detailed):" << localDistance; - if (localDistance < distance) { - - //qDebug() << " localDistance < distance..."; - //qDebug() << " CHOOSING THIS ONE ---> " << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); - distance = localDistance; face = localFace; *intersectedObject = (void*)entity; somethingIntersected = true; - } else { - //qDebug() << " localDistance >= distance... TOO FAR AWAY"; } } } else { // if the entity type doesn't support a detailed intersection, then just return the non-AABox results if (localDistance < distance) { - - //qDebug() << " localDistance < distance..."; - //qDebug() << " CHOOSING THIS ONE ---> " << entity->getEntityItemID() << "-" << qPrintable(EntityTypes::getEntityTypeName(entity->getType())); - distance = localDistance; face = localFace; *intersectedObject = (void*)entity; somethingIntersected = true; - } else { - //qDebug() << " localDistance >= distance... TOO FAR AWAY"; } } } @@ -579,9 +543,6 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con ++entityItr; entityNumber++; } - - //qDebug() << " EntityTreeElement::findDetailedRayIntersection().... returning somethingIntersected:" << somethingIntersected << "keepSearching:" << keepSearching; - return somethingIntersected; } From 7011162c70e0ccbb442d94de95d4beb863f773e6 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 15:07:02 -0800 Subject: [PATCH 19/21] removed dead code --- libraries/octree/src/OctreeElement.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index 29f1d52926..c6938ff1f6 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -1385,7 +1385,6 @@ bool OctreeElement::findDetailedRayIntersection(const glm::vec3& origin, const g if (intersectedObject) { *intersectedObject = this; } - //qDebug() << " OctreeElement::findDetailedRayIntersection().... hasContent() -- done searching..."; keepSearching = false; return true; // we did intersect } From 8dd1a2815f625d43ce1b2f6884a63fdb01d259c9 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 15:43:17 -0800 Subject: [PATCH 20/21] use precision picking in newEditEntities --- examples/newEditEntities.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index ef1be8fef9..606ff5955a 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -465,7 +465,7 @@ function rayPlaneIntersection(pickRay, point, normal) { function findClickedEntity(event) { var pickRay = Camera.computePickRay(event.x, event.y); - var foundIntersection = Entities.findRayIntersection(pickRay); + var foundIntersection = Entities.findRayIntersection(pickRay, true); // want precision picking if (!foundIntersection.accurate) { return null; From d698594899a669b9b69f4f4fb61d7380f80274cd Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Dec 2014 19:39:02 -0800 Subject: [PATCH 21/21] use common findRayTriangleIntersection --- interface/src/MetavoxelSystem.cpp | 25 +---------- interface/src/renderer/Model.cpp | 2 +- libraries/shared/src/GeometryUtil.cpp | 62 +++++++++------------------ libraries/shared/src/GeometryUtil.h | 6 +-- 4 files changed, 25 insertions(+), 70 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index ebf2188b4d..87060d7dfa 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -21,6 +21,7 @@ #include +#include #include #include @@ -1095,30 +1096,6 @@ VoxelBuffer::VoxelBuffer(const QVector& vertices, const QVector _materials(materials) { } -static bool findRayTriangleIntersection(const glm::vec3& origin, const glm::vec3& direction, - const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& distance) { - glm::vec3 firstSide = v0 - v1; - glm::vec3 secondSide = v2 - v1; - glm::vec3 normal = glm::cross(secondSide, firstSide); - float dividend = glm::dot(normal, v1) - glm::dot(origin, normal); - if (dividend > 0.0f) { - return false; // origin below plane - } - float divisor = glm::dot(normal, direction); - if (divisor > -EPSILON) { - return false; - } - float t = dividend / divisor; - glm::vec3 point = origin + direction * t; - if (glm::dot(normal, glm::cross(point - v1, firstSide)) > 0.0f && - glm::dot(normal, glm::cross(secondSide, point - v1)) > 0.0f && - glm::dot(normal, glm::cross(point - v0, v2 - v0)) > 0.0f) { - distance = t; - return true; - } - return false; -} - bool VoxelBuffer::findFirstRayIntersection(const glm::vec3& entry, const glm::vec3& origin, const glm::vec3& direction, float& distance) const { float highest = _size - 1.0f; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 91bb4735fd..71f5129a1e 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -626,7 +626,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g t++; float thisTriangleDistance; - if (findRayTrianlgeIntersection(origin, direction, triangle, thisTriangleDistance)) { + if (findRayTriangleIntersection(origin, direction, triangle, thisTriangleDistance)) { if (thisTriangleDistance < bestDistance) { bestTriangleDistance = thisTriangleDistance; someTriangleHit = true; diff --git a/libraries/shared/src/GeometryUtil.cpp b/libraries/shared/src/GeometryUtil.cpp index e2736f8502..5376883438 100644 --- a/libraries/shared/src/GeometryUtil.cpp +++ b/libraries/shared/src/GeometryUtil.cpp @@ -252,48 +252,26 @@ bool findRayCapsuleIntersection(const glm::vec3& origin, const glm::vec3& direct return true; } - -bool findRayTrianlgeIntersection(const glm::vec3& origin, const glm::vec3& direction, - const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& distance) { - - glm::vec3 e1, e2, h, s, q; - float a, f, u, v, t; - - e1 = v1 - v0; - e2 = v2 - v0; - - h = glm::cross(direction, e2); - a = glm::dot(e1, h); - - if (a > EPSILON && a < EPSILON) { - return false; - } - - f = 1/a; - s = origin - v0; - u = f * glm::dot(s,h); - - if (u < 0.0 || u > 1.0) { - return false; - } - - q = glm::cross(s, e1); - v = f * glm::dot(direction, q); - - if (v < 0.0 || u + v > 1.0) { - return false; - } - - // at this stage we can compute t to find out where the intersection point is on the line - t = f * glm::dot(e2,q); - - // ray intersection - if (t > EPSILON) { - distance = t; - return true; - } else { - // this means that there is a line intersection but not a ray intersection - return false; +bool findRayTriangleIntersection(const glm::vec3& origin, const glm::vec3& direction, + const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& distance) { + glm::vec3 firstSide = v0 - v1; + glm::vec3 secondSide = v2 - v1; + glm::vec3 normal = glm::cross(secondSide, firstSide); + float dividend = glm::dot(normal, v1) - glm::dot(origin, normal); + if (dividend > 0.0f) { + return false; // origin below plane + } + float divisor = glm::dot(normal, direction); + if (divisor > -EPSILON) { + return false; + } + float t = dividend / divisor; + glm::vec3 point = origin + direction * t; + if (glm::dot(normal, glm::cross(point - v1, firstSide)) > 0.0f && + glm::dot(normal, glm::cross(secondSide, point - v1)) > 0.0f && + glm::dot(normal, glm::cross(point - v0, v2 - v0)) > 0.0f) { + distance = t; + return true; } return false; } diff --git a/libraries/shared/src/GeometryUtil.h b/libraries/shared/src/GeometryUtil.h index f439352ca8..a6889ef73e 100644 --- a/libraries/shared/src/GeometryUtil.h +++ b/libraries/shared/src/GeometryUtil.h @@ -76,7 +76,7 @@ bool findRaySphereIntersection(const glm::vec3& origin, const glm::vec3& directi bool findRayCapsuleIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& start, const glm::vec3& end, float radius, float& distance); -bool findRayTrianlgeIntersection(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); class Triangle { @@ -86,9 +86,9 @@ public: glm::vec3 v2; }; -inline bool findRayTrianlgeIntersection(const glm::vec3& origin, const glm::vec3& direction, +inline bool findRayTriangleIntersection(const glm::vec3& origin, const glm::vec3& direction, const Triangle& triangle, float& distance) { - return findRayTrianlgeIntersection(origin, direction, triangle.v0, triangle.v1, triangle.v2, distance); + return findRayTriangleIntersection(origin, direction, triangle.v0, triangle.v1, triangle.v2, distance); }