mirror of
https://github.com/Linloir/SceneEditor.git
synced 2025-12-16 23:18:12 +08:00
[CORE][ADD] Hit Test
This commit is contained in:
parent
db04a46510
commit
98a1321af2
@ -5,15 +5,17 @@
|
||||
class HitRecord {
|
||||
private:
|
||||
bool _hitted;
|
||||
float _t;
|
||||
glm::vec3 _position = glm::vec3(0.0f);
|
||||
glm::vec3 _normal = glm::vec3(0.0f);
|
||||
|
||||
public:
|
||||
HitRecord() : _hitted(false) {}
|
||||
HitRecord(glm::vec3 position, glm::vec3 normal) : _hitted(true), _position(position), _normal(normal) {}
|
||||
HitRecord() : _hitted(false), _t(std::numeric_limits<float>::max()) {}
|
||||
HitRecord(float t, glm::vec3 position, glm::vec3 normal) : _hitted(true), _t(t), _position(position), _normal(normal) {}
|
||||
|
||||
public:
|
||||
inline bool hitted() const { return _hitted; }
|
||||
inline float t() const { return _t; }
|
||||
inline glm::vec3 position() const { return _position; }
|
||||
inline glm::vec3 normal() const { return _normal; }
|
||||
};
|
||||
|
||||
@ -83,7 +83,7 @@ HitRecord Mesh::hit(const Ray& ray) const {
|
||||
// Hit
|
||||
glm::vec3 normal = glm::normalize(glm::cross(edge1, edge2));
|
||||
glm::vec3 hitPoint = ray.origin() + t * ray.direction();
|
||||
return HitRecord(hitPoint, normal);
|
||||
return HitRecord(t, hitPoint, normal);
|
||||
}
|
||||
}
|
||||
return HitRecord();
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
SceneViewer::SceneViewer(QWidget* parent)
|
||||
: QOpenGLWidget(parent)
|
||||
{
|
||||
// Set mouse tracking
|
||||
setMouseTracking(true);
|
||||
// OpenGL initialize
|
||||
QSurfaceFormat format;
|
||||
format.setProfile(QSurfaceFormat::CoreProfile);
|
||||
@ -57,6 +59,33 @@ void SceneViewer::extractShaderResorce(const QString& shaderName) {
|
||||
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() {
|
||||
initializeOpenGLFunctions();
|
||||
|
||||
@ -95,10 +124,10 @@ void SceneViewer::initializeGL() {
|
||||
|
||||
Model* model = new Model("E:\\Repositories\\CollegeProjects\\CGAssignments\\FinalProject\\Models\\backpack\\backpack.obj");
|
||||
Renderable* backpack = new Renderable(model);
|
||||
backpack->move(glm::vec3(-5.0f, -2.0f, -2.0f));
|
||||
_objects.push_back(backpack);
|
||||
|
||||
Renderable* backpack2 = new Renderable(model);
|
||||
backpack2->move(glm::vec3(-5.0f, -2.0f, -2.0f));
|
||||
backpack2->makeLight();
|
||||
backpack2->originalLight()->setIdealDistance(500);
|
||||
_objects.push_back(backpack2);
|
||||
@ -173,9 +202,6 @@ void SceneViewer::mousePressEvent(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
|
||||
switch (event->buttons()) {
|
||||
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));
|
||||
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: {
|
||||
Logger::warning("Unknown mouse button input");
|
||||
Logger::warning("Mouse button: " + std::to_string(event->buttons()));
|
||||
@ -236,29 +270,3 @@ void SceneViewer::wheelEvent(QWheelEvent* event) {
|
||||
// Update the view
|
||||
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
|
||||
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---------------------
|
||||
QPoint _lastMousePosition;
|
||||
Renderable* _hoveredObject = nullptr;
|
||||
Renderable* _selectedObject = nullptr;
|
||||
HitRecord _hitRecord;
|
||||
|
||||
// UI interface control
|
||||
const int _cornerRadius = 10;
|
||||
@ -51,6 +56,7 @@ public:
|
||||
|
||||
private:
|
||||
void extractShaderResorce(const QString& shaderName);
|
||||
void hitTest(const Ray& ray);
|
||||
|
||||
protected:
|
||||
// OpenGL functions
|
||||
@ -62,8 +68,4 @@ protected:
|
||||
virtual void mousePressEvent(QMouseEvent* event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent* 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