Compare commits
26 Commits
d43b49a12f
...
failed-fac
| Author | SHA1 | Date | |
|---|---|---|---|
| 1be782b88d | |||
| 3444e9e183 | |||
| fdd972b286 | |||
| 768eed2f39 | |||
| 41639882db | |||
| fa6e4662a6 | |||
| a7ad78e103 | |||
| 0798cd2a6c | |||
| ce6975cc44 | |||
| b9860f3de0 | |||
| 6e729183ef | |||
| d5d430e80d | |||
| 95b4db5191 | |||
| e2dfdf1600 | |||
| 2333a7cdb5 | |||
| 8a75dab453 | |||
| 6396e49f9b | |||
| 22efad4684 | |||
| d40ae7e670 | |||
| 2fb73d91ef | |||
| a6d46a8280 | |||
| c28c080009 | |||
| 405e151f12 | |||
| 5e20822df4 | |||
| 34ecee0fa2 | |||
| 7010d221d0 |
19
README.md
Normal file
19
README.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Unnamed CAD Software
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
### Building
|
||||||
|
|
||||||
|
On Debian 12:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ sudo apt install cmake qt6-base-dev qt6-svg-dev libtbb-dev
|
||||||
|
$ sudo apt install libocct-foundation-dev libocct-modeling-data-dev libocct-modeling-algorithms-dev libocct-visualization-dev
|
||||||
|
|
||||||
|
$ mkdir build
|
||||||
|
$ cd build/
|
||||||
|
$ cmake ..
|
||||||
|
$ make
|
||||||
|
|
||||||
|
$ ./OpenCAD
|
||||||
|
```
|
||||||
42
icons/home.svg
Normal file
42
icons/home.svg
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
class="size-6"
|
||||||
|
version="1.1"
|
||||||
|
id="svg2"
|
||||||
|
sodipodi:docname="home.svg"
|
||||||
|
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview2"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:zoom="14.574147"
|
||||||
|
inkscape:cx="6.9643869"
|
||||||
|
inkscape:cy="8.6797532"
|
||||||
|
inkscape:window-width="1440"
|
||||||
|
inkscape:window-height="831"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg2" />
|
||||||
|
<path
|
||||||
|
d="M11.47 3.841a.75.75 0 0 1 1.06 0l8.69 8.69a.75.75 0 1 0 1.06-1.061l-8.689-8.69a2.25 2.25 0 0 0-3.182 0l-8.69 8.69a.75.75 0 1 0 1.061 1.06l8.69-8.689Z"
|
||||||
|
id="path1"
|
||||||
|
style="fill:#ffffff" />
|
||||||
|
<path
|
||||||
|
d="m12 5.432 8.159 8.159c.03.03.06.058.091.086v6.198c0 1.035-.84 1.875-1.875 1.875H15a.75.75 0 0 1-.75-.75v-4.5a.75.75 0 0 0-.75-.75h-3a.75.75 0 0 0-.75.75V21a.75.75 0 0 1-.75.75H5.625a1.875 1.875 0 0 1-1.875-1.875v-6.198a2.29 2.29 0 0 0 .091-.086L12 5.432Z"
|
||||||
|
id="path2"
|
||||||
|
style="fill:#ffffff" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -7,11 +7,14 @@
|
|||||||
<file>icons/circle.svg</file>
|
<file>icons/circle.svg</file>
|
||||||
<file>icons/save-sketch.svg</file>
|
<file>icons/save-sketch.svg</file>
|
||||||
<file>icons/cursor.svg</file>
|
<file>icons/cursor.svg</file>
|
||||||
|
<file>icons/home.svg</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/shaders">
|
<qresource prefix="/shaders">
|
||||||
<file alias="simple.vert">src/shaders/simple.vert</file>
|
<file alias="simple.vert">src/shaders/simple.vert</file>
|
||||||
<file alias="simple.frag">src/shaders/simple.frag</file>
|
<file alias="simple.frag">src/shaders/simple.frag</file>
|
||||||
<file alias="texture.vert">src/shaders/texture.vert</file>
|
<file alias="texture.vert">src/shaders/texture.vert</file>
|
||||||
<file alias="texture.frag">src/shaders/texture.frag</file>
|
<file alias="texture.frag">src/shaders/texture.frag</file>
|
||||||
|
<file alias="lit.vert">src/shaders/lit.vert</file>
|
||||||
|
<file alias="lit.frag">src/shaders/lit.frag</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
@@ -158,6 +158,9 @@ void ApplicationController::addCircle(const gp_Pnt& center, double radius)
|
|||||||
|
|
||||||
void ApplicationController::endSketch()
|
void ApplicationController::endSketch()
|
||||||
{
|
{
|
||||||
|
if (m_activeSketch) {
|
||||||
|
m_activeSketch->buildShape();
|
||||||
|
}
|
||||||
m_activeSketch = nullptr;
|
m_activeSketch = nullptr;
|
||||||
setActiveTool(ToolType::None);
|
setActiveTool(ToolType::None);
|
||||||
emit sketchModeEnded();
|
emit sketchModeEnded();
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ void Camera::mouseMoveEvent(QMouseEvent* event, int viewportHeight)
|
|||||||
int dx = event->pos().x() - m_lastPos.x();
|
int dx = event->pos().x() - m_lastPos.x();
|
||||||
int dy = event->pos().y() - m_lastPos.y();
|
int dy = event->pos().y() - m_lastPos.y();
|
||||||
|
|
||||||
if (event->buttons() & Qt::MiddleButton) {
|
if ((event->buttons() & Qt::MiddleButton) || (event->buttons() == (Qt::LeftButton | Qt::RightButton))) {
|
||||||
if (QApplication::keyboardModifiers() & Qt::ShiftModifier) {
|
if (QApplication::keyboardModifiers() & Qt::ShiftModifier) {
|
||||||
// Pan
|
// Pan
|
||||||
if (viewportHeight == 0) viewportHeight = 1;
|
if (viewportHeight == 0) viewportHeight = 1;
|
||||||
@@ -269,6 +269,70 @@ void Camera::animateToPlaneView(int plane)
|
|||||||
animGroup->start(QAbstractAnimation::DeleteWhenStopped);
|
animGroup->start(QAbstractAnimation::DeleteWhenStopped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Camera::animateToHomeView()
|
||||||
|
{
|
||||||
|
auto* animGroup = new QParallelAnimationGroup(this);
|
||||||
|
|
||||||
|
const float full_circle = 360.0f * 16.0f;
|
||||||
|
|
||||||
|
float currentXRot = xRotation();
|
||||||
|
float targetXRot = 30 * 16;
|
||||||
|
float diffX = targetXRot - currentXRot;
|
||||||
|
diffX = fmod(diffX, full_circle);
|
||||||
|
if (diffX > full_circle / 2.0f) {
|
||||||
|
diffX -= full_circle;
|
||||||
|
} else if (diffX < -full_circle / 2.0f) {
|
||||||
|
diffX += full_circle;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* xRotAnim = new QPropertyAnimation(this, "xRotation");
|
||||||
|
xRotAnim->setDuration(300);
|
||||||
|
xRotAnim->setStartValue(currentXRot);
|
||||||
|
xRotAnim->setEndValue(currentXRot + diffX);
|
||||||
|
xRotAnim->setEasingCurve(QEasingCurve::InOutQuad);
|
||||||
|
animGroup->addAnimation(xRotAnim);
|
||||||
|
|
||||||
|
float currentYRot = yRotation();
|
||||||
|
float targetYRot = -45 * 16;
|
||||||
|
float diffY = targetYRot - currentYRot;
|
||||||
|
diffY = fmod(diffY, full_circle);
|
||||||
|
if (diffY > full_circle / 2.0f) {
|
||||||
|
diffY -= full_circle;
|
||||||
|
} else if (diffY < -full_circle / 2.0f) {
|
||||||
|
diffY += full_circle;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* yRotAnim = new QPropertyAnimation(this, "yRotation");
|
||||||
|
yRotAnim->setDuration(300);
|
||||||
|
yRotAnim->setStartValue(currentYRot);
|
||||||
|
yRotAnim->setEndValue(currentYRot + diffY);
|
||||||
|
yRotAnim->setEasingCurve(QEasingCurve::InOutQuad);
|
||||||
|
animGroup->addAnimation(yRotAnim);
|
||||||
|
|
||||||
|
auto* panXAnim = new QPropertyAnimation(this, "panX");
|
||||||
|
panXAnim->setDuration(300);
|
||||||
|
panXAnim->setStartValue(panX());
|
||||||
|
panXAnim->setEndValue(0.0f);
|
||||||
|
panXAnim->setEasingCurve(QEasingCurve::InOutQuad);
|
||||||
|
animGroup->addAnimation(panXAnim);
|
||||||
|
|
||||||
|
auto* panYAnim = new QPropertyAnimation(this, "panY");
|
||||||
|
panYAnim->setDuration(300);
|
||||||
|
panYAnim->setStartValue(panY());
|
||||||
|
panYAnim->setEndValue(0.0f);
|
||||||
|
panYAnim->setEasingCurve(QEasingCurve::InOutQuad);
|
||||||
|
animGroup->addAnimation(panYAnim);
|
||||||
|
|
||||||
|
auto* zoomAnim = new QPropertyAnimation(this, "zoom");
|
||||||
|
zoomAnim->setDuration(300);
|
||||||
|
zoomAnim->setStartValue(zoom());
|
||||||
|
zoomAnim->setEndValue(-20.0f);
|
||||||
|
zoomAnim->setEasingCurve(QEasingCurve::InOutQuad);
|
||||||
|
animGroup->addAnimation(zoomAnim);
|
||||||
|
|
||||||
|
animGroup->start(QAbstractAnimation::DeleteWhenStopped);
|
||||||
|
}
|
||||||
|
|
||||||
void Camera::startRotation(const QVector3D& pivot)
|
void Camera::startRotation(const QVector3D& pivot)
|
||||||
{
|
{
|
||||||
m_rotationPivot = pivot;
|
m_rotationPivot = pivot;
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public:
|
|||||||
|
|
||||||
void animateToPlaneView(int plane);
|
void animateToPlaneView(int plane);
|
||||||
void animateRestoreState();
|
void animateRestoreState();
|
||||||
|
void animateToHomeView();
|
||||||
|
|
||||||
void startRotation(const QVector3D& pivot);
|
void startRotation(const QVector3D& pivot);
|
||||||
void stopRotation();
|
void stopRotation();
|
||||||
|
|||||||
@@ -2,8 +2,24 @@
|
|||||||
#include "SketchObject.h"
|
#include "SketchObject.h"
|
||||||
#include "SketchLine.h"
|
#include "SketchLine.h"
|
||||||
#include "SketchRectangle.h"
|
#include "SketchRectangle.h"
|
||||||
|
#include "SketchCircle.h"
|
||||||
|
|
||||||
|
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||||
|
#include <BRepBuilderAPI_MakeWire.hxx>
|
||||||
|
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||||
|
#include <BRep_Builder.hxx>
|
||||||
|
#include <TopoDS_Compound.hxx>
|
||||||
|
#include <TopoDS.hxx>
|
||||||
|
#include <gp_Circ.hxx>
|
||||||
|
#include <gp_Ax2.hxx>
|
||||||
|
#include <TopExp_Explorer.hxx>
|
||||||
|
#include <ShapeAnalysis_FreeBounds.hxx>
|
||||||
|
#include <gp_Pln.hxx>
|
||||||
|
#include <BRepOffsetAPI_MakeFilling.hxx>
|
||||||
|
#include <GeomAbs_Shape.hxx>
|
||||||
|
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
SketchFeature::SketchFeature(const QString& name)
|
SketchFeature::SketchFeature(const QString& name)
|
||||||
: Feature(name)
|
: Feature(name)
|
||||||
@@ -35,6 +51,119 @@ const TopoDS_Shape& SketchFeature::shape() const
|
|||||||
return m_shape;
|
return m_shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SketchFeature::buildShape()
|
||||||
|
{
|
||||||
|
m_shape.Nullify();
|
||||||
|
QList<TopoDS_Edge> lineEdges;
|
||||||
|
QList<TopoDS_Face> faces;
|
||||||
|
|
||||||
|
gp_Pln sketchPlane;
|
||||||
|
switch (m_plane) {
|
||||||
|
case SketchPlane::XY: sketchPlane = gp_Pln(gp::Origin(), gp::DY()); break;
|
||||||
|
case SketchPlane::XZ: sketchPlane = gp_Pln(gp::Origin(), gp::DZ()); break;
|
||||||
|
case SketchPlane::YZ: sketchPlane = gp_Pln(gp::Origin(), gp::DX()); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (SketchObject* obj : m_objects) {
|
||||||
|
if (auto line = dynamic_cast<SketchLine*>(obj)) {
|
||||||
|
BRepBuilderAPI_MakeEdge makeEdge(line->startPoint(), line->endPoint());
|
||||||
|
if (makeEdge.IsDone()) {
|
||||||
|
lineEdges.append(makeEdge.Edge());
|
||||||
|
}
|
||||||
|
} else if (auto rect = dynamic_cast<SketchRectangle*>(obj)) {
|
||||||
|
const gp_Pnt& c1 = rect->corner1();
|
||||||
|
const gp_Pnt& c2 = rect->corner2();
|
||||||
|
gp_Pnt other_corner1, other_corner2;
|
||||||
|
|
||||||
|
if (m_plane == SketchPlane::XY) {
|
||||||
|
other_corner1.SetCoord(c2.X(), c1.Y(), c1.Z());
|
||||||
|
other_corner2.SetCoord(c1.X(), c1.Y(), c2.Z());
|
||||||
|
} else if (m_plane == SketchPlane::XZ) {
|
||||||
|
other_corner1.SetCoord(c2.X(), c1.Y(), c1.Z());
|
||||||
|
other_corner2.SetCoord(c1.X(), c2.Y(), c1.Z());
|
||||||
|
} else { // YZ
|
||||||
|
other_corner1.SetCoord(c1.X(), c2.Y(), c1.Z());
|
||||||
|
other_corner2.SetCoord(c1.X(), c1.Y(), c2.Z());
|
||||||
|
}
|
||||||
|
|
||||||
|
BRepBuilderAPI_MakeEdge me1(c1, other_corner1);
|
||||||
|
BRepBuilderAPI_MakeEdge me2(other_corner1, c2);
|
||||||
|
BRepBuilderAPI_MakeEdge me3(c2, other_corner2);
|
||||||
|
BRepBuilderAPI_MakeEdge me4(other_corner2, c1);
|
||||||
|
if (me1.IsDone() && me2.IsDone() && me3.IsDone() && me4.IsDone()) {
|
||||||
|
BRepBuilderAPI_MakeWire wireBuilder(me1.Edge(), me2.Edge(), me3.Edge(), me4.Edge());
|
||||||
|
if (wireBuilder.IsDone()) {
|
||||||
|
BRepBuilderAPI_MakeFace faceBuilder(sketchPlane, wireBuilder.Wire());
|
||||||
|
if (faceBuilder.IsDone()) {
|
||||||
|
faces.append(faceBuilder.Face());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (auto circle = dynamic_cast<SketchCircle*>(obj)) {
|
||||||
|
const gp_Pnt& center = circle->center();
|
||||||
|
double radius = circle->radius();
|
||||||
|
gp_Dir normal;
|
||||||
|
switch (m_plane) {
|
||||||
|
case SketchPlane::XY: normal = gp::DY(); break;
|
||||||
|
case SketchPlane::XZ: normal = gp::DZ(); break;
|
||||||
|
case SketchPlane::YZ: normal = gp::DX(); break;
|
||||||
|
}
|
||||||
|
gp_Ax2 axis(center, normal);
|
||||||
|
gp_Circ circ(axis, radius);
|
||||||
|
BRepBuilderAPI_MakeEdge makeEdge(circ);
|
||||||
|
if (makeEdge.IsDone()) {
|
||||||
|
TopoDS_Edge edge = makeEdge.Edge();
|
||||||
|
BRepBuilderAPI_MakeWire wireBuilder(edge);
|
||||||
|
if(wireBuilder.IsDone()) {
|
||||||
|
BRepBuilderAPI_MakeFace faceBuilder(sketchPlane, wireBuilder.Wire());
|
||||||
|
if (faceBuilder.IsDone()) {
|
||||||
|
faces.append(faceBuilder.Face());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lineEdges.isEmpty()) {
|
||||||
|
qDebug() << "buildShape: processing" << lineEdges.size() << "line edges";
|
||||||
|
|
||||||
|
BRepOffsetAPI_MakeFilling faceMaker;
|
||||||
|
for (const TopoDS_Edge& edge : lineEdges) {
|
||||||
|
faceMaker.Add(edge, GeomAbs_C0);
|
||||||
|
}
|
||||||
|
faceMaker.Build();
|
||||||
|
|
||||||
|
if (faceMaker.IsDone()) {
|
||||||
|
TopExp_Explorer explorer(faceMaker.Shape(), TopAbs_FACE);
|
||||||
|
int facesAdded = 0;
|
||||||
|
for (; explorer.More(); explorer.Next()) {
|
||||||
|
faces.append(TopoDS::Face(explorer.Current()));
|
||||||
|
facesAdded++;
|
||||||
|
}
|
||||||
|
qDebug() << "buildShape: added" << facesAdded << "face(s) using MakeFilling";
|
||||||
|
} else {
|
||||||
|
qDebug() << "buildShape: MakeFilling failed";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "buildShape: total faces created:" << faces.size();
|
||||||
|
if (faces.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (faces.size() == 1) {
|
||||||
|
m_shape = faces.first();
|
||||||
|
} else {
|
||||||
|
TopoDS_Compound compound;
|
||||||
|
BRep_Builder builder;
|
||||||
|
builder.MakeCompound(compound);
|
||||||
|
for (const auto& face : faces) {
|
||||||
|
builder.Add(compound, face);
|
||||||
|
}
|
||||||
|
m_shape = compound;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SketchFeature::addObject(SketchObject* object)
|
void SketchFeature::addObject(SketchObject* object)
|
||||||
{
|
{
|
||||||
m_objects.append(object);
|
m_objects.append(object);
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ public:
|
|||||||
|
|
||||||
const TopoDS_Shape& shape() const;
|
const TopoDS_Shape& shape() const;
|
||||||
|
|
||||||
|
void buildShape();
|
||||||
|
|
||||||
void addObject(SketchObject* object);
|
void addObject(SketchObject* object);
|
||||||
const QList<SketchObject*>& objects() const;
|
const QList<SketchObject*>& objects() const;
|
||||||
|
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ GridParams getGridParams(float distance)
|
|||||||
} else if (distance > 50.0f) {
|
} else if (distance > 50.0f) {
|
||||||
return { 5.0f, 25.0f, 1000 };
|
return { 5.0f, 25.0f, 1000 };
|
||||||
} else if (distance > 10.0f) {
|
} else if (distance > 10.0f) {
|
||||||
return { 1.0f, 5.0f, 100 };
|
return { 1.0f, 5.0f, 1000 };
|
||||||
} else { // zoomed in
|
} else { // zoomed in
|
||||||
return { 0.2f, 1.0f, 10 };
|
return { 0.2f, 1.0f, 1000 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@@ -1,12 +1,30 @@
|
|||||||
#include "ViewCube.h"
|
#include "ViewCube.h"
|
||||||
|
#include <QGuiApplication>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
#include <QOpenGLShaderProgram>
|
#include <QOpenGLShaderProgram>
|
||||||
#include <QOpenGLTexture>
|
#include <QOpenGLTexture>
|
||||||
|
#include <QScreen>
|
||||||
|
#include <QSvgRenderer>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
QRect getHomeButtonRect(int widgetWidth) {
|
||||||
|
const int viewCubeSize = 150; // logical pixels
|
||||||
|
const int buttonSize = 24;
|
||||||
|
const int buttonOffsetX = 16;
|
||||||
|
const int buttonOffsetY = 16;
|
||||||
|
|
||||||
|
const int viewCubeX = widgetWidth - viewCubeSize;
|
||||||
|
|
||||||
|
return QRect(viewCubeX + buttonOffsetX, buttonOffsetY, buttonSize, buttonSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ViewCube::ViewCube()
|
ViewCube::ViewCube()
|
||||||
{
|
{
|
||||||
|
m_homeButtonRenderer = new QSvgRenderer(QString(":/icons/home.svg"));
|
||||||
for (int i = 0; i < 6; ++i) {
|
for (int i = 0; i < 6; ++i) {
|
||||||
m_faceTextures[i] = nullptr;
|
m_faceTextures[i] = nullptr;
|
||||||
}
|
}
|
||||||
@@ -18,6 +36,7 @@ ViewCube::~ViewCube()
|
|||||||
delete m_faceTextures[i];
|
delete m_faceTextures[i];
|
||||||
}
|
}
|
||||||
delete m_textureShaderProgram;
|
delete m_textureShaderProgram;
|
||||||
|
delete m_homeButtonRenderer;
|
||||||
m_cubeVbo.destroy();
|
m_cubeVbo.destroy();
|
||||||
m_cubeVao.destroy();
|
m_cubeVao.destroy();
|
||||||
m_axesVbo.destroy();
|
m_axesVbo.destroy();
|
||||||
@@ -32,17 +51,30 @@ void ViewCube::initializeGL()
|
|||||||
setupBuffers();
|
setupBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewCube::paintGL(QOpenGLShaderProgram* simpleShader, int simpleShaderColorLoc, const QMatrix4x4& viewMatrix, int width, int height)
|
void ViewCube::paintGL(QOpenGLShaderProgram* simpleShader, int simpleShaderColorLoc, const QMatrix4x4& viewMatrix, int width, int height, const QPoint& mousePos)
|
||||||
{
|
{
|
||||||
int viewCubeSize = 150;
|
int viewCubeSize = 150 * QGuiApplication::primaryScreen()->devicePixelRatio();
|
||||||
glViewport(width - viewCubeSize, height - viewCubeSize, viewCubeSize, viewCubeSize);
|
glViewport(width - viewCubeSize, height - viewCubeSize, viewCubeSize, viewCubeSize);
|
||||||
|
|
||||||
|
QRect viewCubeRect(width - viewCubeSize, 0, viewCubeSize, viewCubeSize);
|
||||||
|
QPoint physicalMousePos = mousePos * QGuiApplication::primaryScreen()->devicePixelRatio();
|
||||||
|
|
||||||
|
m_isHovered = viewCubeRect.contains(physicalMousePos);
|
||||||
|
|
||||||
|
float opacity = m_isHovered ? 1.0f : 0.5f;
|
||||||
|
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
glClear(GL_DEPTH_BUFFER_BIT);
|
glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
QMatrix4x4 viewCubeProjection;
|
QMatrix4x4 viewCubeProjection;
|
||||||
viewCubeProjection.ortho(-2, 2, -2, 2, -10, 10);
|
viewCubeProjection.ortho(-2, 2, -2, 2, -10, 10);
|
||||||
|
|
||||||
drawViewCube(viewCubeProjection, viewMatrix);
|
drawViewCube(viewCubeProjection, viewMatrix, opacity);
|
||||||
drawAxes(simpleShader, simpleShaderColorLoc, viewCubeProjection, viewMatrix);
|
drawAxes(simpleShader, simpleShaderColorLoc, viewCubeProjection, viewMatrix);
|
||||||
|
|
||||||
|
glDisable(GL_BLEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewCube::createFaceTextures()
|
void ViewCube::createFaceTextures()
|
||||||
@@ -144,7 +176,7 @@ void ViewCube::setupBuffers()
|
|||||||
m_axesVbo.release();
|
m_axesVbo.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewCube::drawViewCube(const QMatrix4x4& projection, const QMatrix4x4& view)
|
void ViewCube::drawViewCube(const QMatrix4x4& projection, const QMatrix4x4& view, float opacity)
|
||||||
{
|
{
|
||||||
if (!m_textureShaderProgram || !m_textureShaderProgram->isLinked()) return;
|
if (!m_textureShaderProgram || !m_textureShaderProgram->isLinked()) return;
|
||||||
|
|
||||||
@@ -153,6 +185,7 @@ void ViewCube::drawViewCube(const QMatrix4x4& projection, const QMatrix4x4& view
|
|||||||
m_textureShaderProgram->setUniformValue("projectionMatrix", projection);
|
m_textureShaderProgram->setUniformValue("projectionMatrix", projection);
|
||||||
m_textureShaderProgram->setUniformValue("modelViewMatrix", view);
|
m_textureShaderProgram->setUniformValue("modelViewMatrix", view);
|
||||||
m_textureShaderProgram->setUniformValue("texture_diffuse1", 0);
|
m_textureShaderProgram->setUniformValue("texture_diffuse1", 0);
|
||||||
|
m_textureShaderProgram->setUniformValue("opacity", opacity);
|
||||||
|
|
||||||
QOpenGLVertexArrayObject::Binder vaoBinder(&m_cubeVao);
|
QOpenGLVertexArrayObject::Binder vaoBinder(&m_cubeVao);
|
||||||
for (int i = 0; i < 6; ++i) {
|
for (int i = 0; i < 6; ++i) {
|
||||||
@@ -193,3 +226,27 @@ void ViewCube::drawAxes(QOpenGLShaderProgram* simpleShader, int colorLoc, const
|
|||||||
|
|
||||||
glLineWidth(1.0f);
|
glLineWidth(1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ViewCube::paint2D(QPainter& painter, int widgetWidth, int widgetHeight)
|
||||||
|
{
|
||||||
|
if (!m_isHovered) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_homeButtonRect = getHomeButtonRect(widgetWidth);
|
||||||
|
|
||||||
|
if (m_homeButtonRenderer && m_homeButtonRenderer->isValid()) {
|
||||||
|
m_homeButtonRenderer->render(&painter, m_homeButtonRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ViewCube::handleMousePress(const QPoint& pos, int widgetWidth, int widgetHeight)
|
||||||
|
{
|
||||||
|
if (!m_isHovered) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect homeButtonRect = getHomeButtonRect(widgetWidth);
|
||||||
|
|
||||||
|
return homeButtonRect.contains(pos);
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,9 +5,12 @@
|
|||||||
#include <QMatrix4x4>
|
#include <QMatrix4x4>
|
||||||
#include <QOpenGLVertexArrayObject>
|
#include <QOpenGLVertexArrayObject>
|
||||||
#include <QOpenGLBuffer>
|
#include <QOpenGLBuffer>
|
||||||
|
#include <QPoint>
|
||||||
|
|
||||||
class QOpenGLShaderProgram;
|
class QOpenGLShaderProgram;
|
||||||
class QOpenGLTexture;
|
class QOpenGLTexture;
|
||||||
|
class QPainter;
|
||||||
|
class QSvgRenderer;
|
||||||
|
|
||||||
class ViewCube : protected QOpenGLFunctions
|
class ViewCube : protected QOpenGLFunctions
|
||||||
{
|
{
|
||||||
@@ -16,15 +19,21 @@ public:
|
|||||||
~ViewCube();
|
~ViewCube();
|
||||||
|
|
||||||
void initializeGL();
|
void initializeGL();
|
||||||
void paintGL(QOpenGLShaderProgram* simpleShader, int simpleShaderColorLoc, const QMatrix4x4& viewMatrix, int width, int height);
|
void paintGL(QOpenGLShaderProgram* simpleShader, int simpleShaderColorLoc, const QMatrix4x4& viewMatrix, int width, int height, const QPoint& mousePos);
|
||||||
|
void paint2D(QPainter& painter, int widgetWidth, int widgetHeight);
|
||||||
|
bool handleMousePress(const QPoint& pos, int widgetWidth, int widgetHeight);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createFaceTextures();
|
void createFaceTextures();
|
||||||
void initShaders();
|
void initShaders();
|
||||||
void setupBuffers();
|
void setupBuffers();
|
||||||
void drawViewCube(const QMatrix4x4& projection, const QMatrix4x4& view);
|
void drawViewCube(const QMatrix4x4& projection, const QMatrix4x4& view, float opacity);
|
||||||
void drawAxes(QOpenGLShaderProgram* simpleShader, int colorLoc, const QMatrix4x4& projection, const QMatrix4x4& view);
|
void drawAxes(QOpenGLShaderProgram* simpleShader, int colorLoc, const QMatrix4x4& projection, const QMatrix4x4& view);
|
||||||
|
|
||||||
|
bool m_isHovered = false;
|
||||||
|
QRect m_homeButtonRect;
|
||||||
|
QSvgRenderer* m_homeButtonRenderer = nullptr;
|
||||||
|
|
||||||
QOpenGLTexture* m_faceTextures[6];
|
QOpenGLTexture* m_faceTextures[6];
|
||||||
|
|
||||||
QOpenGLShaderProgram* m_textureShaderProgram = nullptr;
|
QOpenGLShaderProgram* m_textureShaderProgram = nullptr;
|
||||||
|
|||||||
@@ -30,6 +30,15 @@
|
|||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include <BRepMesh_IncrementalMesh.hxx>
|
||||||
|
#include <TopExp_Explorer.hxx>
|
||||||
|
#include <TopoDS.hxx>
|
||||||
|
#include <TopoDS_Face.hxx>
|
||||||
|
#include <Poly_Triangulation.hxx>
|
||||||
|
#include <BRep_Tool.hxx>
|
||||||
|
#include <gp_Dir.hxx>
|
||||||
|
#include <gp_Trsf.hxx>
|
||||||
|
|
||||||
struct PntComparator {
|
struct PntComparator {
|
||||||
bool operator()(const gp_Pnt& a, const gp_Pnt& b) const {
|
bool operator()(const gp_Pnt& a, const gp_Pnt& b) const {
|
||||||
// A tolerance is needed for floating point comparisons
|
// A tolerance is needed for floating point comparisons
|
||||||
@@ -72,6 +81,7 @@ ViewportWidget::~ViewportWidget()
|
|||||||
{
|
{
|
||||||
makeCurrent();
|
makeCurrent();
|
||||||
delete m_shaderProgram;
|
delete m_shaderProgram;
|
||||||
|
delete m_litShaderProgram;
|
||||||
delete m_viewCube;
|
delete m_viewCube;
|
||||||
delete m_sketchGrid;
|
delete m_sketchGrid;
|
||||||
m_vbo.destroy();
|
m_vbo.destroy();
|
||||||
@@ -114,8 +124,10 @@ void ViewportWidget::initializeGL()
|
|||||||
|
|
||||||
void ViewportWidget::paintGL()
|
void ViewportWidget::paintGL()
|
||||||
{
|
{
|
||||||
|
const qreal retinaScale = devicePixelRatio();
|
||||||
|
|
||||||
// Main scene rendering
|
// Main scene rendering
|
||||||
glViewport(0, 0, width(), height());
|
glViewport(0, 0, width() * retinaScale, height() * retinaScale);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
if (!m_shaderProgram || !m_shaderProgram->isLinked()) {
|
if (!m_shaderProgram || !m_shaderProgram->isLinked()) {
|
||||||
@@ -189,9 +201,9 @@ void ViewportWidget::paintGL()
|
|||||||
QMatrix4x4 viewCubeModel;
|
QMatrix4x4 viewCubeModel;
|
||||||
viewCubeModel.rotate(m_camera->xRotation() / 16.0f, 1, 0, 0);
|
viewCubeModel.rotate(m_camera->xRotation() / 16.0f, 1, 0, 0);
|
||||||
viewCubeModel.rotate(m_camera->yRotation() / 16.0f, 0, 1, 0);
|
viewCubeModel.rotate(m_camera->yRotation() / 16.0f, 0, 1, 0);
|
||||||
m_viewCube->paintGL(m_shaderProgram, m_colorLoc, viewCubeModel, width(), height());
|
m_viewCube->paintGL(m_shaderProgram, m_colorLoc, viewCubeModel, width() * retinaScale, height() * retinaScale, m_currentMousePos);
|
||||||
|
|
||||||
glViewport(0, 0, width(), height());
|
glViewport(0, 0, width() * retinaScale, height() * retinaScale);
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
|
|
||||||
@@ -200,6 +212,7 @@ void ViewportWidget::paintGL()
|
|||||||
m_sketchGrid->paintAxisLabels(painter, static_cast<SketchGrid::SketchPlane>(m_currentPlane), model, projection);
|
m_sketchGrid->paintAxisLabels(painter, static_cast<SketchGrid::SketchPlane>(m_currentPlane), model, projection);
|
||||||
}
|
}
|
||||||
m_featureBrowser->paint(painter, width(), height());
|
m_featureBrowser->paint(painter, width(), height());
|
||||||
|
m_viewCube->paint2D(painter, width(), height());
|
||||||
|
|
||||||
|
|
||||||
if (m_activeSketchTool) {
|
if (m_activeSketchTool) {
|
||||||
@@ -228,6 +241,12 @@ void ViewportWidget::mousePressEvent(QMouseEvent *event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (event->button() == Qt::LeftButton) {
|
if (event->button() == Qt::LeftButton) {
|
||||||
|
if (m_viewCube->handleMousePress(event->pos(), width(), height())) {
|
||||||
|
m_camera->animateToHomeView();
|
||||||
|
update();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_isSelectingPlane) {
|
if (m_isSelectingPlane) {
|
||||||
if (m_highlightedPlane != SketchPlane::NONE) {
|
if (m_highlightedPlane != SketchPlane::NONE) {
|
||||||
emit planeSelected(m_highlightedPlane);
|
emit planeSelected(m_highlightedPlane);
|
||||||
@@ -585,6 +604,9 @@ void ViewportWidget::drawSketch(const SketchFeature* sketch)
|
|||||||
|
|
||||||
if (!lineVertices.isEmpty()) {
|
if (!lineVertices.isEmpty()) {
|
||||||
m_vbo.allocate(lineVertices.constData(), lineVertices.size() * sizeof(GLfloat));
|
m_vbo.allocate(lineVertices.constData(), lineVertices.size() * sizeof(GLfloat));
|
||||||
|
m_shaderProgram->enableAttributeArray(0);
|
||||||
|
m_shaderProgram->setAttributeBuffer(0, GL_FLOAT, 0, 3, 0);
|
||||||
|
m_shaderProgram->disableAttributeArray(1);
|
||||||
glDrawArrays(GL_LINES, 0, lineVertices.size() / 3);
|
glDrawArrays(GL_LINES, 0, lineVertices.size() / 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,13 +662,88 @@ void ViewportWidget::drawSketch(const SketchFeature* sketch)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw faces
|
||||||
|
if (!sketch->shape().IsNull()) {
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
BRepMesh_IncrementalMesh(sketch->shape(), 0.1, Standard_False, 0.5, Standard_True); // Linear deflection, compute normals
|
||||||
|
|
||||||
|
QVector<GLfloat> faceData;
|
||||||
|
TopExp_Explorer explorer(sketch->shape(), TopAbs_FACE);
|
||||||
|
for (; explorer.More(); explorer.Next()) {
|
||||||
|
TopoDS_Face face = TopoDS::Face(explorer.Current());
|
||||||
|
TopLoc_Location location;
|
||||||
|
Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation(face, location);
|
||||||
|
|
||||||
|
if (!triangulation.IsNull()) {
|
||||||
|
gp_Trsf locTrsf = location.Transformation();
|
||||||
|
|
||||||
|
if (triangulation->HasNormals()) {
|
||||||
|
for (int i = 1; i <= triangulation->NbTriangles(); ++i) {
|
||||||
|
const Poly_Triangle& triangle = triangulation->Triangle(i);
|
||||||
|
for (int j = 1; j <= 3; ++j) {
|
||||||
|
int nodeIdx = triangle.Value(j);
|
||||||
|
gp_Pnt p = triangulation->Node(nodeIdx).Transformed(location);
|
||||||
|
gp_Dir n = triangulation->Normal(nodeIdx);
|
||||||
|
n.Transform(locTrsf);
|
||||||
|
|
||||||
|
if (face.Orientation() == TopAbs_REVERSED) {
|
||||||
|
n.Reverse();
|
||||||
|
}
|
||||||
|
faceData << p.X() << p.Y() << p.Z();
|
||||||
|
faceData << n.X() << n.Y() << n.Z();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 1; i <= triangulation->NbTriangles(); ++i) {
|
||||||
|
const Poly_Triangle& triangle = triangulation->Triangle(i);
|
||||||
|
gp_Pnt p1 = triangulation->Node(triangle.Value(1)).Transformed(location);
|
||||||
|
gp_Pnt p2 = triangulation->Node(triangle.Value(2)).Transformed(location);
|
||||||
|
gp_Pnt p3 = triangulation->Node(triangle.Value(3)).Transformed(location);
|
||||||
|
|
||||||
|
QVector3D v1(p1.X(), p1.Y(), p1.Z());
|
||||||
|
QVector3D v2(p2.X(), p2.Y(), p2.Z());
|
||||||
|
QVector3D v3(p3.X(), p3.Y(), p3.Z());
|
||||||
|
QVector3D faceNormal = QVector3D::crossProduct(v2 - v1, v3 - v1).normalized();
|
||||||
|
if (face.Orientation() == TopAbs_REVERSED) {
|
||||||
|
faceNormal = -faceNormal;
|
||||||
|
}
|
||||||
|
faceData << p1.X() << p1.Y() << p1.Z() << faceNormal.x() << faceNormal.y() << faceNormal.z();
|
||||||
|
faceData << p2.X() << p2.Y() << p2.Z() << faceNormal.x() << faceNormal.y() << faceNormal.z();
|
||||||
|
faceData << p3.X() << p3.Y() << p3.Z() << faceNormal.x() << faceNormal.y() << faceNormal.z();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!faceData.isEmpty()) {
|
||||||
|
m_litShaderProgram->bind();
|
||||||
|
m_litShaderProgram->setUniformValue(m_litProjMatrixLoc, projection);
|
||||||
|
m_litShaderProgram->setUniformValue(m_litMvMatrixLoc, m_camera->modelViewMatrix());
|
||||||
|
m_litShaderProgram->setUniformValue(m_litNormalMatrixLoc, m_camera->modelViewMatrix().normalMatrix());
|
||||||
|
|
||||||
|
m_vbo.bind();
|
||||||
|
m_vbo.allocate(faceData.constData(), faceData.size() * sizeof(GLfloat));
|
||||||
|
|
||||||
|
m_litShaderProgram->enableAttributeArray(0);
|
||||||
|
m_litShaderProgram->setAttributeBuffer(0, GL_FLOAT, 0, 3, 6 * sizeof(GLfloat));
|
||||||
|
m_litShaderProgram->enableAttributeArray(1);
|
||||||
|
m_litShaderProgram->setAttributeBuffer(1, GL_FLOAT, 3 * sizeof(GLfloat), 3, 6 * sizeof(GLfloat));
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, faceData.size() / 6);
|
||||||
|
m_litShaderProgram->disableAttributeArray(1);
|
||||||
|
m_shaderProgram->bind(); // rebind simple shader for subsequent draws
|
||||||
|
m_shaderProgram->setAttributeBuffer(0, GL_FLOAT, 0, 3, 0);
|
||||||
|
}
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
}
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewportWidget::initShaders()
|
void ViewportWidget::initShaders()
|
||||||
{
|
{
|
||||||
|
// Simple shader for lines and grids
|
||||||
m_shaderProgram = new QOpenGLShaderProgram(this);
|
m_shaderProgram = new QOpenGLShaderProgram(this);
|
||||||
|
|
||||||
if (!m_shaderProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/simple.vert")) {
|
if (!m_shaderProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/simple.vert")) {
|
||||||
qCritical() << "Vertex shader compilation failed:" << m_shaderProgram->log();
|
qCritical() << "Vertex shader compilation failed:" << m_shaderProgram->log();
|
||||||
return;
|
return;
|
||||||
@@ -659,10 +756,27 @@ void ViewportWidget::initShaders()
|
|||||||
qCritical() << "Shader program linking failed:" << m_shaderProgram->log();
|
qCritical() << "Shader program linking failed:" << m_shaderProgram->log();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_projMatrixLoc = m_shaderProgram->uniformLocation("projectionMatrix");
|
m_projMatrixLoc = m_shaderProgram->uniformLocation("projectionMatrix");
|
||||||
m_mvMatrixLoc = m_shaderProgram->uniformLocation("modelViewMatrix");
|
m_mvMatrixLoc = m_shaderProgram->uniformLocation("modelViewMatrix");
|
||||||
m_colorLoc = m_shaderProgram->uniformLocation("objectColor");
|
m_colorLoc = m_shaderProgram->uniformLocation("objectColor");
|
||||||
|
|
||||||
|
// Lit shader for faces
|
||||||
|
m_litShaderProgram = new QOpenGLShaderProgram(this);
|
||||||
|
if (!m_litShaderProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/lit.vert")) {
|
||||||
|
qCritical() << "Lit vertex shader compilation failed:" << m_litShaderProgram->log();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!m_litShaderProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/lit.frag")) {
|
||||||
|
qCritical() << "Lit fragment shader compilation failed:" << m_litShaderProgram->log();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!m_litShaderProgram->link()) {
|
||||||
|
qCritical() << "Lit shader program linking failed:" << m_litShaderProgram->log();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_litProjMatrixLoc = m_litShaderProgram->uniformLocation("projectionMatrix");
|
||||||
|
m_litMvMatrixLoc = m_litShaderProgram->uniformLocation("modelViewMatrix");
|
||||||
|
m_litNormalMatrixLoc = m_litShaderProgram->uniformLocation("normalMatrix");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewportWidget::drawSelectionPlanes()
|
void ViewportWidget::drawSelectionPlanes()
|
||||||
@@ -677,6 +791,9 @@ void ViewportWidget::drawSelectionPlanes()
|
|||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
m_vbo.bind();
|
m_vbo.bind();
|
||||||
|
m_shaderProgram->enableAttributeArray(0);
|
||||||
|
m_shaderProgram->setAttributeBuffer(0, GL_FLOAT, 0, 3, 0);
|
||||||
|
m_shaderProgram->disableAttributeArray(1);
|
||||||
QVector<GLfloat> vertices;
|
QVector<GLfloat> vertices;
|
||||||
|
|
||||||
auto drawPlane = [&](const QVector<GLfloat>& quadVerts, bool highlighted) {
|
auto drawPlane = [&](const QVector<GLfloat>& quadVerts, bool highlighted) {
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ private:
|
|||||||
|
|
||||||
QMatrix4x4 projection;
|
QMatrix4x4 projection;
|
||||||
QOpenGLShaderProgram* m_shaderProgram = nullptr;
|
QOpenGLShaderProgram* m_shaderProgram = nullptr;
|
||||||
|
QOpenGLShaderProgram* m_litShaderProgram = nullptr;
|
||||||
QOpenGLVertexArrayObject m_vao;
|
QOpenGLVertexArrayObject m_vao;
|
||||||
QOpenGLBuffer m_vbo;
|
QOpenGLBuffer m_vbo;
|
||||||
|
|
||||||
@@ -104,6 +105,11 @@ private:
|
|||||||
int m_projMatrixLoc = -1;
|
int m_projMatrixLoc = -1;
|
||||||
int m_mvMatrixLoc = -1;
|
int m_mvMatrixLoc = -1;
|
||||||
int m_colorLoc = -1;
|
int m_colorLoc = -1;
|
||||||
|
|
||||||
|
// Lit shader uniform locations
|
||||||
|
int m_litProjMatrixLoc = -1;
|
||||||
|
int m_litMvMatrixLoc = -1;
|
||||||
|
int m_litNormalMatrixLoc = -1;
|
||||||
Camera* m_camera = nullptr;
|
Camera* m_camera = nullptr;
|
||||||
ViewCube* m_viewCube;
|
ViewCube* m_viewCube;
|
||||||
SketchGrid* m_sketchGrid = nullptr;
|
SketchGrid* m_sketchGrid = nullptr;
|
||||||
|
|||||||
33
src/shaders/lit.frag
Normal file
33
src/shaders/lit.frag
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#version 330 core
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
in vec3 FragPos;
|
||||||
|
in vec3 Normal;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 viewPos = vec3(0.0, 0.0, 0.0); // View position is origin in view space
|
||||||
|
vec3 lightPos = vec3(0.0, 10.0, 5.0); // Light position in view space
|
||||||
|
vec3 lightColor = vec3(1.0, 1.0, 1.0);
|
||||||
|
vec3 objectColor = vec3(0.5, 0.5, 1.0);
|
||||||
|
|
||||||
|
// Ambient
|
||||||
|
float ambientStrength = 0.3;
|
||||||
|
vec3 ambient = ambientStrength * lightColor;
|
||||||
|
|
||||||
|
// Diffuse
|
||||||
|
vec3 norm = normalize(Normal);
|
||||||
|
vec3 lightDir = normalize(lightPos - FragPos);
|
||||||
|
float diff = max(dot(norm, lightDir), 0.0);
|
||||||
|
vec3 diffuse = diff * lightColor;
|
||||||
|
|
||||||
|
// Specular
|
||||||
|
float specularStrength = 0.5;
|
||||||
|
vec3 viewDir = normalize(viewPos - FragPos);
|
||||||
|
vec3 reflectDir = reflect(-lightDir, norm);
|
||||||
|
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
|
||||||
|
vec3 specular = specularStrength * spec * lightColor;
|
||||||
|
|
||||||
|
vec3 result = (ambient + diffuse + specular) * objectColor;
|
||||||
|
FragColor = vec4(result, 1.0);
|
||||||
|
}
|
||||||
17
src/shaders/lit.vert
Normal file
17
src/shaders/lit.vert
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#version 330 core
|
||||||
|
layout (location = 0) in vec3 aPos;
|
||||||
|
layout (location = 1) in vec3 aNormal;
|
||||||
|
|
||||||
|
out vec3 FragPos;
|
||||||
|
out vec3 Normal;
|
||||||
|
|
||||||
|
uniform mat4 modelViewMatrix;
|
||||||
|
uniform mat4 projectionMatrix;
|
||||||
|
uniform mat3 normalMatrix;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragPos = vec3(modelViewMatrix * vec4(aPos, 1.0));
|
||||||
|
Normal = normalMatrix * aNormal;
|
||||||
|
gl_Position = projectionMatrix * modelViewMatrix * vec4(aPos, 1.0);
|
||||||
|
}
|
||||||
@@ -5,8 +5,10 @@ out vec4 FragColor;
|
|||||||
in vec2 TexCoord;
|
in vec2 TexCoord;
|
||||||
|
|
||||||
uniform sampler2D texture_diffuse1;
|
uniform sampler2D texture_diffuse1;
|
||||||
|
uniform float opacity;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
FragColor = texture(texture_diffuse1, TexCoord);
|
vec4 texColor = texture(texture_diffuse1, TexCoord);
|
||||||
|
FragColor = vec4(texColor.rgb, texColor.a * opacity);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user