more work on improved model picking

This commit is contained in:
ZappoMan 2014-12-04 16:43:12 -08:00
parent 5ec9a9b6ed
commit 37ffa48fa3
3 changed files with 18 additions and 377 deletions

View file

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

View file

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

View file

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