Skip to content

Commit 73adaf6

Browse files
committed
Added qml2DRaycastingEngine to the project.
1 parent 8dd9c7c commit 73adaf6

22 files changed

+786
-50
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ Demo | Description | Screenshot
1212
**cvVideo** | A C++/OpenCV/Qt example on how to display video files with configurable Aspect Ratio. | <img src="cvVideo/screenshot.gif" width="200"/>
1313
**cvWatershedSegmentation** | [Stackoverflow answer](https://stackoverflow.com/a/25851951/176769) that uses C++/OpenCV's watershed segmentation with distance transform to segment beans. | <img src="cvWatershedSegmentation/screenshot.jpg" width="200"/>
1414
**ipcQtGesture** | A C++/Qt application that uses the old *Intel® Perceptual Computing SDK 2013* for gesture recognition. Windows only. | No image available
15-
**qmlRayCasting2D** | A QML implementation of 2D raycasting from [Daniel Shiffman](https://www.youtube.com/watch?v=TOEi6T2mtHo). | <img src="qmlRayCasting2D/screenshot.gif" width="200"/>
16-
**qmlBattery** | A Qt/QML Battery element that displays the amount of energy left as horizontal bars according to the charge. On this demo, the charge is set dynamically and randomly from the C++ side. | <img src="qmlBattery/screenshot.gif" width="200"/>
15+
**qml2DRaycasting** | A QML implementation of 2D raycasting based on [Daniel Shiffman](https://www.youtube.com/watch?v=TOEi6T2mtHo) coding challenge. | <img src="qml2DRaycasting/screenshot.gif" width="200"/>
16+
**qml2DRaycastingEngine** | A QML implementation of 2D raycasting engine inspired by [Daniel Shiffman](https://www.youtube.com/watch?v=vYgIKn7iDH8) coding challenge. | <img src="qml2DRaycastingEngine/screenshot.gif" width="200"/>
17+
**qmlBattery** | A Qt/QML Battery element that displays the amount of energy left as horizontal bars according to the charge. On this demo, the charge is set dynamically and randomly from the C++ side. | <img src="qmlBattery/screenshot.gif" height="195"/>
1718
**qtArduinoSerial** | An C++/Qt example on how to print data from a serial (COM) port connected to Arduino. | No image available
1819
**qtFPSvsTIMEAnimation** | A C++/Qt implementation of FPS-based and Time-based animation techniques, as explained by [Steven Lambert](http://blog.sklambert.com/using-time-based-animation-implement/) | <img src="qtFPSvsTIMEAnimation/screenshot.gif" width="180"/>
1920
**qtKinectVideo** | C++/Qt application based on "Color Basics" from Kinect for Windows SDK 1.8. This demo shows how to display the Color Stream. | No image available

qmlRayCasting2D/Boundary.qml renamed to qml2DRaycasting/Boundary.qml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Item {
66
property vector2d b: Qt.vector2d(0, 0)
77

88
function show(ctx) {
9-
Draw.line(ctx, a.x, a.y, b.x, b.y, Qt.rgba(255, 255, 255, 1));
9+
Draw.line(ctx, a.x, a.y, b.x, b.y, Qt.rgba(255, 255, 255, 1), 1);
1010

1111
//console.log("Boundary.show: a=" + a);
1212
//console.log("Boundary.show: b=" + b);

qmlRayCasting2D/Particle.qml renamed to qml2DRaycasting/Particle.qml

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,26 @@ Item {
88
id: particle
99

1010
property var pos: Qt.vector2d(0, 0)
11-
property var rays: createListOfRays()
12-
property var numRays: 30; // the amount of light rays that this particle emits
11+
property var numRays: 32; // default value: the amount of light rays that this particle emits
12+
property var rays: createListOfRays(numRays)
1313

14-
function show(ctx) {
15-
Draw.circle(ctx, pos.x, pos.y, 4, "white");
14+
property int size: 5
15+
property var color: "white"
16+
property var lightColor: "yellow"
1617

18+
function show(ctx) {
1719
for (let i = 0; i < rays.length; ++i)
1820
rays[i].show(ctx);
21+
22+
Draw.circle(ctx, pos.x, pos.y, particle.size, particle.color);
1923
}
2024

21-
// createListOfRays: returns a list of QML components of type Ray
22-
function createListOfRays() {
23-
var list = new Array(numRays);
24-
const incSize = 360 / numRays;
25+
// createListOfRays: returns a list of QML items of type Ray
26+
function createListOfRays(size) {
27+
// preallocate improves performance? var list = new Array(size);
28+
var list = [];
29+
30+
const incSize = 360 / size;
2531

2632
for (let i = 0, x = 0; i < 360; i += incSize, ++x) {
2733
var component = Qt.createComponent("Ray.qml");
@@ -67,7 +73,7 @@ Item {
6773

6874
// check if the point of intersection exists
6975
if (pt)
70-
Draw.line(ctx, particle.pos.x, particle.pos.y, pt.x, pt.y, "yellow");
76+
Draw.line(ctx, particle.pos.x, particle.pos.y, pt.x, pt.y, particle.lightColor);
7177
}
7278
}
7379

@@ -95,7 +101,7 @@ Item {
95101
}
96102

97103
if (closestIntersectionPt)
98-
Draw.line(ctx, particle.pos.x, particle.pos.y, closestIntersectionPt.x, closestIntersectionPt.y, "yellow");
104+
Draw.line(ctx, particle.pos.x, particle.pos.y, closestIntersectionPt.x, closestIntersectionPt.y, particle.lightColor);
99105
}
100106
}
101107

File renamed without changes.

qmlRayCasting2D/Ray.qml renamed to qml2DRaycasting/Ray.qml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Item {
1212
property vector2d pos: Qt.vector2d(0, 0) // starting position of the ray
1313
property vector2d dir: fromAngle(angle) // unit vector that guides the direction of the light
1414

15-
property var raySize: 8 // size of the ray for debugging purposes
15+
property var raySize: 16 // size of the ray for debugging purposes
1616

1717
// show: draw the light of ray on the screen (red)
1818
function show(ctx) {

qml2DRaycasting/draw.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// helper functions for drawing inside Canvas
2+
3+
function line(ctx, x1, y1, x2, y2, color, lineWidth=1) {
4+
ctx.save();
5+
ctx.beginPath();
6+
ctx.lineWidth = lineWidth;
7+
ctx.strokeStyle = color;
8+
ctx.moveTo(x1, y1);
9+
ctx.lineTo(x2, y2);
10+
ctx.closePath();
11+
ctx.stroke();
12+
ctx.restore();
13+
}
14+
15+
function circle(ctx, x, y, radius, color) {
16+
ctx.save();
17+
ctx.beginPath()
18+
ctx.strokeStyle = color;
19+
ctx.fillStyle = color;
20+
ctx.arc(x, y, radius, 0, 360, false);
21+
ctx.fill();
22+
ctx.closePath()
23+
ctx.restore();
24+
}
25+
26+
function rect(ctx, x, y, w, h, color, border=true) {
27+
ctx.save();
28+
ctx.beginPath()
29+
30+
ctx.rect(x, y, w, h);
31+
ctx.fillStyle = color;
32+
ctx.fill();
33+
34+
if (!border) {
35+
ctx.lineWidth = 1;
36+
ctx.strokeStyle = color;
37+
}
38+
39+
ctx.stroke();
40+
ctx.closePath()
41+
ctx.restore();
42+
}
43+
44+
function text(ctx, text, x, y, color, font="20px sans-serif") {
45+
ctx.save();
46+
ctx.font = font;
47+
ctx.fillStyle = color;
48+
ctx.fillText(qsTr(text), x, y);
49+
ctx.stroke();
50+
ctx.restore();
51+
}
File renamed without changes.

qmlRayCasting2D/main.qml renamed to qml2DRaycasting/main.qml

Lines changed: 72 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,38 @@ import "draw.js" as Draw
77

88
Window {
99
id: window
10-
width: 600
11-
height: 600
10+
width: 800
11+
height: 800
1212
visible: true
13-
title: qsTr("2D Raytracing")
13+
title: qsTr("2D Raycasting")
1414
color: "black"
1515

16+
property bool showFps: true
17+
property int frameCounter: 0
18+
property real fps: 0.0
19+
1620
Canvas {
1721
id: canvas
1822
anchors.fill: parent
1923

24+
// change default render target to FBO: utilizes OpenGL hardware acceleration rather than rendering into system memory
25+
renderTarget: Canvas.FramebufferObject
26+
27+
// change default render strategy to Threaded: context will defer graphics commands to a private rendering thread
28+
renderStrategy: Canvas.Threaded
29+
30+
// store latest mouse move coordinates
2031
property vector2d mousePoint: Qt.vector2d(0, 0)
21-
property var walls: createListOfWalls();
32+
33+
// specify wall size and create walls
2234
property int numWalls: 5
35+
property var walls: createListOfWalls(numWalls);
2336

2437
// a single light particle that emits rays on all directions
2538
Particle {
2639
id: particle
2740
pos: Qt.vector2d(canvas.mousePoint.x, canvas.mousePoint.y)
28-
numRays: 200
41+
numRays: 64
2942
}
3043

3144
// drawing procedure
@@ -50,21 +63,49 @@ Window {
5063
// find if any of these rays in the particle are able to intercept the boundary
5164
//particle.lookWall(walls[0], ctx);
5265
particle.look(walls, ctx);
66+
67+
// increment frame counter
68+
window.frameCounter++;
5369
}
5470

55-
// refresh the canvas automatically every 33 milliseconds
71+
// try to refresh the canvas every 5ms
5672
Timer {
57-
interval: 33
73+
interval: 5
5874
running: true
5975
repeat: true
60-
onTriggered: canvas.requestPaint()
76+
77+
property double startTime: 0.0
78+
property double elapsedTime: 0.0
79+
property double msPerFrame: 0.0
80+
81+
onTriggered: {
82+
if (startTime === 0)
83+
startTime = new Date().getTime();
84+
85+
elapsedTime = new Date().getTime() - startTime;
86+
87+
if (elapsedTime >= 1000) {
88+
// compute FPS
89+
msPerFrame = elapsedTime / window.frameCounter;
90+
window.fps = 1000 / msPerFrame;
91+
92+
// reset start time and fps count
93+
startTime = 0;
94+
window.frameCounter = 0;
95+
}
96+
97+
// trigger canvas.onPaint()
98+
canvas.requestPaint()
99+
100+
//console.log("FPS:" + fps);
101+
}
61102
}
62103

63104
// createListOfWalls: creates a list of random walls on the screen
64-
function createListOfWalls() {
65-
var list = new Array(canvas.numWalls);
105+
function createListOfWalls(size) {
106+
var list = new Array(size);
66107

67-
for (let i = 0; i < canvas.numWalls; ++i) {
108+
for (let i = 0; i < size; ++i) {
68109
var component = Qt.createComponent("Boundary.qml");
69110
if (component === null) {
70111
console.log("Canvas !!! error creating component");
@@ -102,4 +143,24 @@ Window {
102143
canvas.mousePoint.y = mouse.y;
103144
}
104145
}
146+
147+
Item {
148+
focus: true
149+
150+
Keys.onPressed: {
151+
if (event.key === Qt.Key_F) {
152+
console.log("onPressed: F");
153+
showFps = !showFps;
154+
event.accepted = true;
155+
}
156+
}
157+
}
158+
159+
160+
Text {
161+
anchors.right: parent.right
162+
color: "lime"
163+
text: qsTr("FPS: " + window.fps.toFixed(1))
164+
visible: window.showFps
165+
}
105166
}
File renamed without changes.
File renamed without changes.

qml2DRaycastingEngine/Boundary.qml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import QtQuick 2.0
2+
import "draw.js" as Draw
3+
4+
Item {
5+
id: wall
6+
property vector2d a: Qt.vector2d(0, 0)
7+
property vector2d b: Qt.vector2d(0, 0)
8+
property var color: "cyan"
9+
10+
function show(ctx) {
11+
Draw.line(ctx, a.x, a.y, b.x, b.y, wall.color, 1);
12+
13+
//console.log("Boundary.show: a=" + a);
14+
//console.log("Boundary.show: b=" + b);
15+
}
16+
17+
Component.onCompleted: {
18+
console.log("Boundary constructed: a=" + a + " b=" + b);
19+
}
20+
}

0 commit comments

Comments
 (0)