mirror of
https://github.com/Linloir/SceneEditor.git
synced 2025-12-18 16:08:11 +08:00
[CORE][ADD] Hit Test
This commit is contained in:
parent
db04a46510
commit
98a1321af2
@ -5,15 +5,17 @@
|
|||||||
class HitRecord {
|
class HitRecord {
|
||||||
private:
|
private:
|
||||||
bool _hitted;
|
bool _hitted;
|
||||||
|
float _t;
|
||||||
glm::vec3 _position = glm::vec3(0.0f);
|
glm::vec3 _position = glm::vec3(0.0f);
|
||||||
glm::vec3 _normal = glm::vec3(0.0f);
|
glm::vec3 _normal = glm::vec3(0.0f);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HitRecord() : _hitted(false) {}
|
HitRecord() : _hitted(false), _t(std::numeric_limits<float>::max()) {}
|
||||||
HitRecord(glm::vec3 position, glm::vec3 normal) : _hitted(true), _position(position), _normal(normal) {}
|
HitRecord(float t, glm::vec3 position, glm::vec3 normal) : _hitted(true), _t(t), _position(position), _normal(normal) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline bool hitted() const { return _hitted; }
|
inline bool hitted() const { return _hitted; }
|
||||||
|
inline float t() const { return _t; }
|
||||||
inline glm::vec3 position() const { return _position; }
|
inline glm::vec3 position() const { return _position; }
|
||||||
inline glm::vec3 normal() const { return _normal; }
|
inline glm::vec3 normal() const { return _normal; }
|
||||||
};
|
};
|
||||||
|
|||||||
@ -83,7 +83,7 @@ HitRecord Mesh::hit(const Ray& ray) const {
|
|||||||
// Hit
|
// Hit
|
||||||
glm::vec3 normal = glm::normalize(glm::cross(edge1, edge2));
|
glm::vec3 normal = glm::normalize(glm::cross(edge1, edge2));
|
||||||
glm::vec3 hitPoint = ray.origin() + t * ray.direction();
|
glm::vec3 hitPoint = ray.origin() + t * ray.direction();
|
||||||
return HitRecord(hitPoint, normal);
|
return HitRecord(t, hitPoint, normal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return HitRecord();
|
return HitRecord();
|
||||||
|
|||||||
@ -11,6 +11,8 @@
|
|||||||
SceneViewer::SceneViewer(QWidget* parent)
|
SceneViewer::SceneViewer(QWidget* parent)
|
||||||
: QOpenGLWidget(parent)
|
: QOpenGLWidget(parent)
|
||||||
{
|
{
|
||||||
|
// Set mouse tracking
|
||||||
|
setMouseTracking(true);
|
||||||
// OpenGL initialize
|
// OpenGL initialize
|
||||||
QSurfaceFormat format;
|
QSurfaceFormat format;
|
||||||
format.setProfile(QSurfaceFormat::CoreProfile);
|
format.setProfile(QSurfaceFormat::CoreProfile);
|
||||||
@ -57,6 +59,33 @@ void SceneViewer::extractShaderResorce(const QString& shaderName) {
|
|||||||
QFile::setPermissions(shaderTempPath, QFile::ReadOwner | QFile::WriteOwner);
|
QFile::setPermissions(shaderTempPath, QFile::ReadOwner | QFile::WriteOwner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SceneViewer::hitTest(const Ray& ray) {
|
||||||
|
HitRecord newRecord = HitRecord();
|
||||||
|
Renderable* newObject = nullptr;
|
||||||
|
int newObjectIndex = -1;
|
||||||
|
for (int i = 0; i < _objects.size(); i++) {
|
||||||
|
Logger::debug("Testing object " + std::to_string(i));
|
||||||
|
Renderable* obj = _objects[i];
|
||||||
|
HitRecord hitRecord = obj->hit(ray);
|
||||||
|
if (hitRecord.hitted()) {
|
||||||
|
Logger::debug("Hitted object " + std::to_string(i));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Logger::debug("Missed object " + std::to_string(i));
|
||||||
|
}
|
||||||
|
if (hitRecord.hitted() && hitRecord.t() < newRecord.t()) {
|
||||||
|
newRecord = hitRecord;
|
||||||
|
newObject = obj;
|
||||||
|
newObjectIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (newRecord.hitted()) {
|
||||||
|
Logger::debug("Hit test hitted object with index " + std::to_string(newObjectIndex));
|
||||||
|
}
|
||||||
|
_hitRecord = newRecord;
|
||||||
|
_hoveredObject = newObject;
|
||||||
|
}
|
||||||
|
|
||||||
void SceneViewer::initializeGL() {
|
void SceneViewer::initializeGL() {
|
||||||
initializeOpenGLFunctions();
|
initializeOpenGLFunctions();
|
||||||
|
|
||||||
@ -95,10 +124,10 @@ void SceneViewer::initializeGL() {
|
|||||||
|
|
||||||
Model* model = new Model("E:\\Repositories\\CollegeProjects\\CGAssignments\\FinalProject\\Models\\backpack\\backpack.obj");
|
Model* model = new Model("E:\\Repositories\\CollegeProjects\\CGAssignments\\FinalProject\\Models\\backpack\\backpack.obj");
|
||||||
Renderable* backpack = new Renderable(model);
|
Renderable* backpack = new Renderable(model);
|
||||||
|
backpack->move(glm::vec3(-5.0f, -2.0f, -2.0f));
|
||||||
_objects.push_back(backpack);
|
_objects.push_back(backpack);
|
||||||
|
|
||||||
Renderable* backpack2 = new Renderable(model);
|
Renderable* backpack2 = new Renderable(model);
|
||||||
backpack2->move(glm::vec3(-5.0f, -2.0f, -2.0f));
|
|
||||||
backpack2->makeLight();
|
backpack2->makeLight();
|
||||||
backpack2->originalLight()->setIdealDistance(500);
|
backpack2->originalLight()->setIdealDistance(500);
|
||||||
_objects.push_back(backpack2);
|
_objects.push_back(backpack2);
|
||||||
@ -173,9 +202,6 @@ void SceneViewer::mousePressEvent(QMouseEvent* event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SceneViewer::mouseMoveEvent(QMouseEvent* event) {
|
void SceneViewer::mouseMoveEvent(QMouseEvent* event) {
|
||||||
if (event->buttons() != Qt::NoButton) {
|
|
||||||
Logger::debug("Mouse moved with offset: " + std::to_string(event->x() - _lastMousePosition.x()) + ", " + std::to_string(event->y() - _lastMousePosition.y()));
|
|
||||||
}
|
|
||||||
// Check the type of button pressed
|
// Check the type of button pressed
|
||||||
switch (event->buttons()) {
|
switch (event->buttons()) {
|
||||||
case Qt::LeftButton: {
|
case Qt::LeftButton: {
|
||||||
@ -212,6 +238,14 @@ void SceneViewer::mouseMoveEvent(QMouseEvent* event) {
|
|||||||
Logger::debug("Center at: " + std::to_string(_rotateCenter.x) + ", " + std::to_string(_rotateCenter.y) + ", " + std::to_string(_rotateCenter.z));
|
Logger::debug("Center at: " + std::to_string(_rotateCenter.x) + ", " + std::to_string(_rotateCenter.y) + ", " + std::to_string(_rotateCenter.z));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Qt::NoButton: {
|
||||||
|
// If no button pressed, do hit test and move the current object if selected
|
||||||
|
float relX = (float)event->x() / (float)width();
|
||||||
|
float relY = 1 - (float)event->y() / (float)height();
|
||||||
|
Ray ray = _camera.generateRay(glm::vec2(relX, relY), (float)width() / (float)height());
|
||||||
|
hitTest(ray);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
Logger::warning("Unknown mouse button input");
|
Logger::warning("Unknown mouse button input");
|
||||||
Logger::warning("Mouse button: " + std::to_string(event->buttons()));
|
Logger::warning("Mouse button: " + std::to_string(event->buttons()));
|
||||||
@ -236,29 +270,3 @@ void SceneViewer::wheelEvent(QWheelEvent* event) {
|
|||||||
// Update the view
|
// Update the view
|
||||||
parentWidget()->update();
|
parentWidget()->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneViewer::showEvent(QShowEvent* event) {
|
|
||||||
// Call show event of super class
|
|
||||||
QOpenGLWidget::showEvent(event);
|
|
||||||
|
|
||||||
if (_initialized) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//// Create mask for rounded corner
|
|
||||||
//QPainterPath mask;
|
|
||||||
//mask.addRoundedRect(rect(), _cornerRadius, _cornerRadius);
|
|
||||||
//setMask(mask.toFillPolygon().toPolygon());
|
|
||||||
|
|
||||||
_initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SceneViewer::resizeEvent(QResizeEvent* event) {
|
|
||||||
// Call resize event of super class
|
|
||||||
QOpenGLWidget::resizeEvent(event);
|
|
||||||
|
|
||||||
//// Create mask for rounded corner
|
|
||||||
//QPainterPath mask;
|
|
||||||
//mask.addRoundedRect(rect(), _cornerRadius, _cornerRadius);
|
|
||||||
//setMask(mask.toFillPolygon().toPolygon());
|
|
||||||
}
|
|
||||||
|
|||||||
@ -37,9 +37,14 @@ private:
|
|||||||
// Rotate center
|
// Rotate center
|
||||||
glm::vec3 _rotateCenter = glm::vec3(0.0f, 0.0f, 0.0f);
|
glm::vec3 _rotateCenter = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
// User preferences
|
||||||
|
bool _stickToSurface = false; // whether to rotate the object to the normal of the hitted surface
|
||||||
|
|
||||||
// User Interaction flags section---------------------
|
// User Interaction flags section---------------------
|
||||||
QPoint _lastMousePosition;
|
QPoint _lastMousePosition;
|
||||||
|
Renderable* _hoveredObject = nullptr;
|
||||||
Renderable* _selectedObject = nullptr;
|
Renderable* _selectedObject = nullptr;
|
||||||
|
HitRecord _hitRecord;
|
||||||
|
|
||||||
// UI interface control
|
// UI interface control
|
||||||
const int _cornerRadius = 10;
|
const int _cornerRadius = 10;
|
||||||
@ -51,6 +56,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void extractShaderResorce(const QString& shaderName);
|
void extractShaderResorce(const QString& shaderName);
|
||||||
|
void hitTest(const Ray& ray);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// OpenGL functions
|
// OpenGL functions
|
||||||
@ -62,8 +68,4 @@ protected:
|
|||||||
virtual void mousePressEvent(QMouseEvent* event) override;
|
virtual void mousePressEvent(QMouseEvent* event) override;
|
||||||
virtual void mouseMoveEvent(QMouseEvent* event) override;
|
virtual void mouseMoveEvent(QMouseEvent* event) override;
|
||||||
virtual void wheelEvent(QWheelEvent* event) override;
|
virtual void wheelEvent(QWheelEvent* event) override;
|
||||||
|
|
||||||
// UI update events
|
|
||||||
virtual void showEvent(QShowEvent* event) override;
|
|
||||||
virtual void resizeEvent(QResizeEvent* event) override;
|
|
||||||
};
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user